diff options
author | Florian Weimer <fweimer@redhat.com> | 2017-11-17 22:11:28 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2017-11-17 22:11:28 +0100 |
commit | ce003e5d4cd94c5380699b0dadeaaf825813afbe (patch) | |
tree | 54634638fd8470347ab02e16b1645772091780aa /support | |
parent | e7df6c5c79458dc042a8c967bafa6e8eca88ae0d (diff) | |
download | glibc-ce003e5d4cd94c5380699b0dadeaaf825813afbe.zip glibc-ce003e5d4cd94c5380699b0dadeaaf825813afbe.tar.gz glibc-ce003e5d4cd94c5380699b0dadeaaf825813afbe.tar.bz2 |
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 <jrnieder@gmail.com>
Diffstat (limited to 'support')
-rw-r--r-- | support/support_become_root.c | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/support/support_become_root.c b/support/support_become_root.c index 3fa0bd4..5086570 100644 --- a/support/support_become_root.c +++ b/support/support_become_root.c @@ -18,18 +18,69 @@ #include <support/namespace.h> +#include <fcntl.h> #include <sched.h> #include <stdio.h> +#include <string.h> +#include <support/check.h> +#include <support/xunistd.h> #include <unistd.h> +#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) { |