From: Florian Weimer Date: Fri, 17 Nov 2017 21:11:28 +0000 (+0100) Subject: support_become_root: Enable file creation in user namespaces X-Git-Tag: glibc-2.27~476 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ce003e5d4cd94c5380699b0dadeaaf825813afbe;p=thirdparty%2Fglibc.git support_become_root: Enable file creation in user namespaces Without UID/GID maps, file creation will file with EOVERFLOW. This patch is based on DJ Delorie's work on container testing. Reviewed-by: Jonathan Nieder --- diff --git a/ChangeLog b/ChangeLog index 4ab52b2fd90..a5530971a0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2017-11-17 Florian Weimer + + support_become_root: Enable file creation in namespaces. + * support/support_become_root.c (setup_mapping): New function. + (support_become_root): Call it. + 2017-11-17 Joseph Myers * sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h (HWCAP_DCPOP): New diff --git a/support/support_become_root.c b/support/support_become_root.c index 3fa0bd4ac05..50865702516 100644 --- a/support/support_become_root.c +++ b/support/support_become_root.c @@ -18,18 +18,69 @@ #include +#include #include #include +#include +#include +#include #include +#ifdef CLONE_NEWUSER +/* The necessary steps to allow file creation in user namespaces. */ +static void +setup_uid_gid_mapping (uid_t original_uid, gid_t original_gid) +{ + int fd = open64 ("/proc/self/uid_map", O_WRONLY); + if (fd < 0) + { + printf ("warning: could not open /proc/self/uid_map: %m\n" + "warning: file creation may not be possible\n"); + return; + } + + /* We map our original UID to the same UID in the container so we + own our own files normally. Without that, file creation could + fail with EOVERFLOW (sic!). */ + char buf[100]; + int ret = snprintf (buf, sizeof (buf), "%llu %llu 1\n", + (unsigned long long) original_uid, + (unsigned long long) original_uid); + TEST_VERIFY_EXIT (ret < sizeof (buf)); + xwrite (fd, buf, ret); + xclose (fd); + + /* Disable setgroups before mapping groups, otherwise that would + fail with EPERM. */ + fd = xopen ("/proc/self/setgroups", O_WRONLY, 0); + xwrite (fd, "deny\n", strlen ("deny\n")); + xclose (fd); + + /* Now map our own GID, like we did for the user ID. */ + fd = xopen ("/proc/self/gid_map", O_WRONLY, 0); + ret = snprintf (buf, sizeof (buf), "%llu %llu 1\n", + (unsigned long long) original_gid, + (unsigned long long) original_gid); + TEST_VERIFY_EXIT (ret < sizeof (buf)); + xwrite (fd, buf, ret); + xclose (fd); +} +#endif /* CLONE_NEWUSER */ + bool support_become_root (void) { #ifdef CLONE_NEWUSER + uid_t original_uid = getuid (); + gid_t original_gid = getgid (); + if (unshare (CLONE_NEWUSER | CLONE_NEWNS) == 0) - /* Even if we do not have UID zero, we have extended privileges at - this point. */ - return true; + { + setup_uid_gid_mapping (original_uid, original_gid); + /* Even if we do not have UID zero, we have extended privileges at + this point. */ + return true; + } #endif if (setuid (0) != 0) {