runc/patch/0091-runc-cve-2019-5736-workaround-if-memfd_create.patch

208 lines
4.9 KiB
Diff
Raw Normal View History

From 621c01059536ec167da8c9d5571e8bf860b4dadb Mon Sep 17 00:00:00 2001
From: wangfengtu <wangfengtu@huawei.com>
Date: Wed, 13 Feb 2019 05:26:38 -0500
Subject: [PATCH 91/94] runc: cve-2019-5736: workaround if
memfd_create and O_TMPFILE not work
[Changelog]: create tmpfile using mkostemp when memfd_create and
O_TMPFILE not work
[Author]: git
Change-Id: I785295b19759487ddaa5e0dcb5c11e4aa9ace838
Signed-off-by: sdu.liu <sdu.liu@huawei.com>
Signed-off-by: wangfengtu <wangfengtu@huawei.com>
---
libcontainer/nsenter/cloned_binary.c | 117 +++++++++++++++++++++++++----------
script/runc-euleros.spec | 2 +-
2 files changed, 87 insertions(+), 32 deletions(-)
diff --git a/libcontainer/nsenter/cloned_binary.c b/libcontainer/nsenter/cloned_binary.c
index c8a42c2..e59d434 100644
--- a/libcontainer/nsenter/cloned_binary.c
+++ b/libcontainer/nsenter/cloned_binary.c
@@ -71,6 +71,14 @@ int memfd_create(const char *name, unsigned int flags)
(F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)
#endif
+enum clone_type
+{
+ USING_MEMFD = 0,
+ USING_UNAMED_FILE,
+ USING_TMPFILE,
+};
+
+
static void *must_realloc(void *ptr, size_t size)
{
void *old = ptr;
@@ -80,6 +88,23 @@ static void *must_realloc(void *ptr, size_t size)
return ptr;
}
+static int get_clone_type()
+{
+ int memfd = 0;
+#ifdef HAVE_MEMFD_CREATE
+ memfd = memfd_create(RUNC_MEMFD_COMMENT, MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ if (memfd > 0 || memfd == 0) {
+ close(memfd);
+ return USING_MEMFD;
+ }
+#else
+#ifdef O_TMPFILE
+ return USING_UNAMED_FILE;
+#endif
+#endif
+ return USING_TMPFILE;
+}
+
/*
* Verify whether we are currently in a self-cloned program (namely, is
* /proc/self/exe a memfd). F_GET_SEALS will only succeed for memfds (or rather
@@ -87,21 +112,23 @@ static void *must_realloc(void *ptr, size_t size)
*/
static int is_self_cloned(void)
{
- int fd, ret, is_cloned = 0;
+ int fd, ret, type, is_cloned = 0;
fd = open("/proc/self/exe", O_RDONLY|O_CLOEXEC);
if (fd < 0)
return -ENOTRECOVERABLE;
+ type = get_clone_type();
+
+ if (type == USING_MEMFD) {
+ ret = fcntl(fd, F_GET_SEALS);
+ is_cloned = (ret == RUNC_MEMFD_SEALS);
+ } else {
+ struct stat statbuf = {0};
+ ret = fstat(fd, &statbuf);
+ if (ret >= 0)
+ is_cloned = (statbuf.st_nlink == 0);
+ }
-#ifdef HAVE_MEMFD_CREATE
- ret = fcntl(fd, F_GET_SEALS);
- is_cloned = (ret == RUNC_MEMFD_SEALS);
-#else
- struct stat statbuf = {0};
- ret = fstat(fd, &statbuf);
- if (ret >= 0)
- is_cloned = (statbuf.st_nlink == 0);
-#endif
close(fd);
return is_cloned;
}
@@ -198,16 +225,37 @@ error:
return -EINVAL;
}
+
static int clone_binary(void)
{
int binfd, memfd;
ssize_t sent = 0;
+ char template[] = "/tmp/runc.XXXXXX";
+ int type = 0;
+ char *tmpfile = NULL;
+
+ type = get_clone_type();
+ switch (type) {
+ case USING_MEMFD:
+ memfd = memfd_create(RUNC_MEMFD_COMMENT, MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ break;
+ case USING_UNAMED_FILE:
+ memfd = open("/tmp", O_TMPFILE | O_EXCL | O_RDWR | O_CLOEXEC, 0711);
+ break;
+ case USING_TMPFILE:
+ memfd = mkostemp(template,O_EXCL | O_RDWR | O_CLOEXEC);
+ if (memfd < 0) {
+ goto error;
+ }
+ tmpfile = template;
+ if (fchmod(memfd, 0711)) {
+ goto error;
+ }
+ break;
+ default:
+ return -ENOTRECOVERABLE;
+ }
-#ifdef HAVE_MEMFD_CREATE
- memfd = memfd_create(RUNC_MEMFD_COMMENT, MFD_CLOEXEC | MFD_ALLOW_SEALING);
-#else
- memfd = open("/tmp", O_TMPFILE | O_EXCL | O_RDWR | O_CLOEXEC, 0711);
-#endif
if (memfd < 0)
return -ENOTRECOVERABLE;
@@ -220,29 +268,36 @@ static int clone_binary(void)
if (sent < 0)
goto error;
-#ifdef HAVE_MEMFD_CREATE
- int err = fcntl(memfd, F_ADD_SEALS, RUNC_MEMFD_SEALS);
- if (err < 0)
- goto error;
-#else
+ if (type == USING_MEMFD) {
+ int err = fcntl(memfd, F_ADD_SEALS, RUNC_MEMFD_SEALS);
+ if (err < 0)
+ goto error;
+ } else {
/* Need to re-open "memfd" as read-only to avoid execve(2) giving -EXTBUSY. */
- int newfd;
- char *fdpath = NULL;
+ int newfd;
+ char *fdpath = NULL;
- if (asprintf(&fdpath, "/proc/self/fd/%d", memfd) < 0)
- goto error;
- newfd = open(fdpath, O_RDONLY | O_CLOEXEC);
- free(fdpath);
- if (newfd < 0)
- goto error;
+ if (asprintf(&fdpath, "/proc/self/fd/%d", memfd) < 0)
+ goto error;
+ newfd = open(fdpath, O_RDONLY | O_CLOEXEC);
+ free(fdpath);
+ if (newfd < 0)
+ goto error;
+ close(memfd);
- close(memfd);
- memfd = newfd;
-#endif
+ memfd = newfd;
+ }
+
+ if(tmpfile) {
+ remove(tmpfile);
+ }
return memfd;
error:
close(memfd);
+ if(tmpfile) {
+ remove(tmpfile);
+ }
return -EIO;
}
diff --git a/script/runc-euleros.spec b/script/runc-euleros.spec
index 2448078..b577d1a 100644
--- a/script/runc-euleros.spec
+++ b/script/runc-euleros.spec
@@ -2,7 +2,7 @@
Name: docker-runc
Version: 1.0.0.rc3
-Release: 20%{?dist}
+Release: 21%{?dist}
Summary: runc is a CLI tool for spawning and running containers according to the OCF specification
License: ASL 2.0
--
2.7.4.3