]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
unshare: Fix --map-root-user to work on new kernels
authorEric W. Biederman <ebiederm@xmission.com>
Wed, 17 Dec 2014 23:06:03 +0000 (17:06 -0600)
committerKarel Zak <kzak@redhat.com>
Fri, 9 Jan 2015 09:32:33 +0000 (10:32 +0100)
In rare cases droping groups with setgroups(0, NULL) is an operation
that can grant a user additional privileges.  User namespaces were
allwoing that operation to unprivileged users and that had to be
fixed.

Update unshare --map-root-user to disable the setgroups operation
before setting the gid_map.

This is needed as after the security fix gid_map is restricted to
privileged users unless setgroups has been disabled.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
include/pathnames.h
sys-utils/unshare.c

index 0d21b980b131e5e5d07c3703786a60809caf999d..cbc93b76985e452f297f9d47358fb2997d0cb1ea 100644 (file)
@@ -93,6 +93,7 @@
 
 #define _PATH_PROC_UIDMAP      "/proc/self/uid_map"
 #define _PATH_PROC_GIDMAP      "/proc/self/gid_map"
+#define _PATH_PROC_SETGROUPS   "/proc/self/setgroups"
 
 #define _PATH_PROC_ATTR_CURRENT        "/proc/self/attr/current"
 #define _PATH_PROC_ATTR_EXEC   "/proc/self/attr/exec"
index fccdba2f659361db13482d77814efb06d0702a37..9fdce931f385cdd2ae0603675e81fdc54cbb99ac 100644 (file)
 #include "pathnames.h"
 #include "all-io.h"
 
+static void disable_setgroups(void)
+{
+       const char *file = _PATH_PROC_SETGROUPS;
+       const char *deny = "deny";
+       int fd;
+
+       fd = open(file, O_WRONLY);
+       if (fd < 0) {
+               if (errno == ENOENT)
+                       return;
+                err(EXIT_FAILURE, _("cannot open %s"), file);
+       }
+
+       if (write_all(fd, deny, strlen(deny)))
+               err(EXIT_FAILURE, _("write failed %s"), file);
+       close(fd);
+}
+
 static void map_id(const char *file, uint32_t from, uint32_t to)
 {
        char *buf;
@@ -181,6 +199,7 @@ int main(int argc, char *argv[])
        }
 
        if (maproot) {
+               disable_setgroups();
                map_id(_PATH_PROC_UIDMAP, 0, real_euid);
                map_id(_PATH_PROC_GIDMAP, 0, real_egid);
        }