[lxc-devel] [PATCH 2/3] lxc-attach: User namespaces: Use init's user & group id when attaching

Christian Seiler christian at iwakd.de
Mon Mar 4 19:20:23 UTC 2013


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 at iwakd.de>
---
 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 af3d7a0..7845dda 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -275,3 +275,56 @@ int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx)
 
 	return 0;
 }
+
+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 4d4f719..fc630e2 100644
--- a/src/lxc/attach.h
+++ b/src/lxc/attach.h
@@ -38,4 +38,6 @@ extern int lxc_attach_to_ns(pid_t other_pid, int which);
 extern int lxc_attach_remount_sys_proc();
 extern int lxc_attach_drop_privs(struct lxc_proc_context_info *ctx);
 
+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 292b5b5..6095b54 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 could be 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





More information about the lxc-devel mailing list