]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf: write "deny" to /proc/[pid]/setgroups
authorChristian Brauner <christian.brauner@ubuntu.com>
Wed, 3 Jan 2018 15:28:40 +0000 (16:28 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 4 Jan 2018 10:57:09 +0000 (11:57 +0100)
When fully unprivileged users run a container that only maps their own {g,u}id
and they do not have access to setuid new{g,u}idmap binaries we will write the
idmapping directly. This however requires us to write "deny" to
/proc/[pid]/setgroups otherwise any write to /proc/[pid]/gid_map will be
denied.

On a sidenote, this patch enables fully unprivileged containers. If you now set
lxc.net.[i].type = empty no privilege whatsoever is required to run a container.

Enhances #2033.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Cc: Felix Abecassis <fabecassis@nvidia.com>
Cc: Jonathan Calmels <jcalmels@nvidia.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/cgroups/cgfsng.c
src/lxc/conf.c
src/lxc/conf.h
src/lxc/start.c

index 28ddc827d922bed4f32fbcea26abad2e5f7ed6ff..68520f4c8887fd1eb9f0c5e5510ca2a2f067cd7b 100644 (file)
@@ -1284,7 +1284,7 @@ static int rmdir_wrapper(void *data)
                SYSERROR("Failed to setgid to 0");
        if (setresuid(nsuid, nsuid, nsuid) < 0)
                SYSERROR("Failed to setuid to 0");
-       if (setgroups(0, NULL) < 0)
+       if (setgroups(0, NULL) < 0 && errno != EPERM)
                SYSERROR("Failed to clear groups");
 
        return cgroup_rmdir(arg->path);
@@ -1481,7 +1481,7 @@ static int chown_cgroup_wrapper(void *data)
                SYSERROR("Failed to setgid to 0");
        if (setresuid(nsuid, nsuid, nsuid) < 0)
                SYSERROR("Failed to setuid to 0");
-       if (setgroups(0, NULL) < 0)
+       if (setgroups(0, NULL) < 0 && errno != EPERM)
                SYSERROR("Failed to clear groups");
 
        destuid = get_ns_uid(arg->origuid);
index 9a036090709c52bc196d664b7b329c979baf6b4f..1f303454addf0d9589409e6252005ae89eb72cac 100644 (file)
@@ -2627,28 +2627,54 @@ struct lxc_conf *lxc_conf_init(void)
 }
 
 int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
-                           size_t buf_size)
+                    size_t buf_size)
 {
        char path[MAXPATHLEN];
        int fd, ret;
 
+       if (geteuid() != 0 && idtype == ID_TYPE_GID) {
+               size_t buflen;
+
+               ret = snprintf(path, MAXPATHLEN, "/proc/%d/setgroups", pid);
+               if (ret < 0 || ret >= MAXPATHLEN) {
+                       ERROR("Failed to create string");
+                       return -E2BIG;
+               }
+
+               fd = open(path, O_WRONLY);
+               if (fd < 0 && errno != ENOENT) {
+                       SYSERROR("Failed to open \"%s\"", path);
+                       return -1;
+               }
+
+               buflen = sizeof("deny\n") - 1;
+               errno = 0;
+               ret = lxc_write_nointr(fd, "deny\n", buflen);
+               if (ret != buflen) {
+                       SYSERROR("Failed to write \"deny\" to \"/proc/%d/setgroups\"", pid);
+                       close(fd);
+                       return -1;
+               }
+               close(fd);
+       }
+
        ret = snprintf(path, MAXPATHLEN, "/proc/%d/%cid_map", pid,
                       idtype == ID_TYPE_UID ? 'u' : 'g');
        if (ret < 0 || ret >= MAXPATHLEN) {
-               ERROR("failed to create path \"%s\"", path);
+               ERROR("Failed to create string");
                return -E2BIG;
        }
 
        fd = open(path, O_WRONLY);
        if (fd < 0) {
-               SYSERROR("failed to open \"%s\"", path);
+               SYSERROR("Failed to open \"%s\"", path);
                return -1;
        }
 
        errno = 0;
        ret = lxc_write_nointr(fd, buf, buf_size);
        if (ret != buf_size) {
-               SYSERROR("failed to write %cid mapping to \"%s\"",
+               SYSERROR("Failed to write %cid mapping to \"%s\"",
                         idtype == ID_TYPE_UID ? 'u' : 'g', path);
                close(fd);
                return -1;
index 37123822037dc874f7fea9f7ab329027f3c04a53..806a15733137971839a7e13315425f83cbf1f97e 100644 (file)
@@ -410,7 +410,7 @@ struct lxc_conf {
        struct lxc_list procs;
 };
 
-int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
+extern int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
                            size_t buf_size);
 
 #ifdef HAVE_TLS
index d5b6f56e70707f35c9f2eb8a969aef96d4308c21..e2ca11455274d71e6d920b62358b0bb5f60d67a3 100644 (file)
@@ -1014,7 +1014,7 @@ static int do_start(void *data)
                 * user namespace.
                 */
                ret = lxc_setgroups(0, NULL);
-               if (ret < 0)
+               if (ret < 0 && (handler->am_root || errno != EPERM))
                        goto out_warn_father;
 
                if (!handler->am_root) {