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). --- src/lxc/attach.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/attach.h | 2 ++ src/lxc/lxc_attach.c | 15 ++++++++++---- 3 files changed, 66 insertions(+), 4 deletions(-)
diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 88356e1..399ec36 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -479,3 +479,56 @@ struct passwd *lxc_attach_getpwuid(uid_t uid) exit(-1); } } + +int 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 -1; + + 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 */ + + /* at least some entries were not found, we return error */ + if (uid == (uid_t)-1 || gid == (gid_t)-1) + return -1; + + return 0; +} diff --git a/src/lxc/attach.h b/src/lxc/attach.h index 90e693a..1e9b87e 100644 --- a/src/lxc/attach.h +++ b/src/lxc/attach.h @@ -41,4 +41,6 @@ extern int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx); struct passwd; extern struct passwd *lxc_attach_getpwuid(uid_t uid); +extern int lxc_attach_get_init_uidgid(uid_t* init_uid, gid_t* init_gid); + #endif diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c index 9c86ffe..cdc1601 100644 --- a/src/lxc/lxc_attach.c +++ b/src/lxc/lxc_attach.c @@ -417,13 +417,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.) + */ + (void) 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; } -- 1.7.10.4 ------------------------------------------------------------------------------ Symantec Endpoint Protection 12 positioned as A LEADER in The Forrester Wave(TM): Endpoint Security, Q1 2013 and "remains a good choice" in the endpoint security space. For insight on selecting the right partner to tackle endpoint security challenges, access the full report. http://p.sf.net/sfu/symantec-dev2dev _______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel