208 lines
4.9 KiB
Diff
208 lines
4.9 KiB
Diff
|
|
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
|
||
|
|
|