]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
lxc-attach: User namespaces: Use init's user & group id when attaching
authorChristian Seiler <christian@iwakd.de>
Wed, 6 Mar 2013 19:43:52 +0000 (20:43 +0100)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 6 Mar 2013 20:30:30 +0000 (14:30 -0600)
When attaching to a container with a user namespace, try to detect the
user and group ids of init via /proc and attach as that same user. Only
if that is unsuccessful, fall back to (0, 0).

Signed-off-by: Christian Seiler <christian@iwakd.de>
src/lxc/attach.c
src/lxc/attach.h
src/lxc/lxc_attach.c

index ad7d319cbb25e9072bf062c0bc3912ed72b1e1a6..6b89763ccb2b456f332bda4448da79b5b155a214 100644 (file)
@@ -428,3 +428,50 @@ char *lxc_attach_getpwshell(uid_t uid)
                exit(-1);
        }
 }
+
+void lxc_attach_get_init_uidgid(uid_t* init_uid, gid_t* init_gid)
+{
+       FILE *proc_file;
+       char proc_fn[MAXPATHLEN];
+       char *line = NULL;
+       size_t line_bufsz = 0;
+       int ret;
+       long value = -1;
+       uid_t uid = (uid_t)-1;
+       gid_t gid = (gid_t)-1;
+
+       /* read capabilities */
+       snprintf(proc_fn, MAXPATHLEN, "/proc/%d/status", 1);
+
+       proc_file = fopen(proc_fn, "r");
+       if (!proc_file)
+               return;
+
+       while (getline(&line, &line_bufsz, proc_file) != -1) {
+               /* format is: real, effective, saved set user, fs
+                * we only care about real uid
+                */
+               ret = sscanf(line, "Uid: %ld", &value);
+               if (ret != EOF && ret > 0) {
+                       uid = (uid_t) value;
+               } else {
+                       ret = sscanf(line, "Gid: %ld", &value);
+                       if (ret != EOF && ret > 0)
+                               gid = (gid_t) value;
+               }
+               if (uid != (uid_t)-1 && gid != (gid_t)-1)
+                       break;
+       }
+
+       fclose(proc_file);
+       free(line);
+
+       /* only override arguments if we found something */
+       if (uid != (uid_t)-1)
+               *init_uid = uid;
+       if (gid != (gid_t)-1)
+               *init_gid = gid;
+
+       /* TODO: we should also parse supplementary groups and use
+        * setgroups() to set them */
+}
index f448b1e65d4ff7cb000e0740a1603114d3529e88..ef5d87bf10838df16cabffa5fa6eac4def26b911 100644 (file)
@@ -40,4 +40,6 @@ extern int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx);
 
 extern char *lxc_attach_getpwshell(uid_t uid);
 
+extern void lxc_attach_get_init_uidgid(uid_t* init_uid, gid_t* init_gid);
+
 #endif
index 69ebfaccaa04df86e0916e36ee598babada17e04..1622cb12f73fc67b275e05800709e6141c70c812 100644 (file)
@@ -418,13 +418,20 @@ int main(int argc, char *argv[])
                lxc_sync_fini(handler);
 
                if (namespace_flags & CLONE_NEWUSER) {
-                       /* XXX FIXME this should get the uid of the container init and setuid to that */
-                       /* XXX FIXME or perhaps try to map in the lxc-attach caller's uid? */
-                       if (setgid(0)) {
+                       uid_t init_uid = 0;
+                       gid_t init_gid = 0;
+
+                       /* ignore errors, we will fall back to root in that case
+                        * (/proc was not mounted etc.)
+                        */
+                       lxc_attach_get_init_uidgid(&init_uid, &init_gid);
+
+                       /* try to set the uid/gid combination */
+                       if (setgid(init_gid)) {
                                SYSERROR("switching to container gid");
                                return -1;
                        }
-                       if (setuid(0)) {
+                       if (setuid(init_uid)) {
                                SYSERROR("switching to container uid");
                                return -1;
                        }