[lxc-devel] [PATCH 7/5] lxc-destroy: support unprivileged use

Serge Hallyn serge.hallyn at ubuntu.com
Thu Jul 25 21:58:20 UTC 2013


Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 src/lxc/conf.c         | 24 ++++++++++++++++++++++++
 src/lxc/conf.h         |  1 +
 src/lxc/lxc_destroy.c  |  7 -------
 src/lxc/lxccontainer.c | 15 ++++++++++++---
 4 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index a47d4bd..a84c2ad 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -2825,6 +2825,30 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
 	return wait_for_pid(pid);
 }
 
+int do_mapped_rmdir(char *path, struct lxc_conf *conf)
+{
+	char buf[4096], *p = buf;
+	int hostuid = geteuid(), nsuid = find_unmapped_nsuid(conf);
+	struct lxc_list *it;
+
+	/* lxc-usernsexec -m b:$nsuid:$hostuid <... all container mappings>  \
+	 * rm -rf --one-file-system path */
+	p += snprintf(buf, 4095, "lxc-usernsexec -m u:%d:%d:1", nsuid, hostuid);
+
+	lxc_list_for_each(it, &conf->id_map) {
+		struct id_map *map = it->elem;
+		p += snprintf(p, p-buf, " -m %c:%d:%d:%d",
+			      map->idtype == ID_TYPE_UID ? 'u' : 'g',
+			      (int)map->nsid, (int)map->hostid, (int)map->range);
+	}
+	p += snprintf(p, p-buf, " -- rm -rf --one-file-system %s", path);
+	if (p - buf >= 4096) {
+		ERROR("lxc-usernsexec directory removal command too long");
+		return -1;
+	}
+	return system(buf);
+}
+
 int ttys_shift_ids(struct lxc_conf *c)
 {
 	int i;
diff --git a/src/lxc/conf.h b/src/lxc/conf.h
index c285950..e3565bd 100644
--- a/src/lxc/conf.h
+++ b/src/lxc/conf.h
@@ -336,5 +336,6 @@ extern uid_t get_mapped_rootid(struct lxc_conf *conf);
 extern int find_unmapped_nsuid(struct lxc_conf *conf);
 extern bool hostid_is_mapped(int id, struct lxc_conf *conf);
 extern int chown_mapped_root(char *path, struct lxc_conf *conf);
+extern int do_mapped_rmdir(char *path, struct lxc_conf *conf);
 extern int ttys_shift_ids(struct lxc_conf *c);
 #endif
diff --git a/src/lxc/lxc_destroy.c b/src/lxc/lxc_destroy.c
index 9a1b11f..114c911 100644
--- a/src/lxc/lxc_destroy.c
+++ b/src/lxc/lxc_destroy.c
@@ -64,13 +64,6 @@ int main(int argc, char *argv[])
 {
 	struct lxc_container *c;
 
-	/* this is a short term test.  We'll probably want to check for
-	 * write access to lxcpath instead */
-	if (geteuid()) {
-		fprintf(stderr, "%s must be run as root\n", argv[0]);
-		exit(1);
-	}
-
 	if (lxc_arguments_parse(&my_args, argc, argv))
 		exit(1);
 
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index ee0b1ff..3dae2b8 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -1467,6 +1467,9 @@ static bool lxcapi_destroy(struct lxc_container *c)
 {
 	struct bdev *r = NULL;
 	bool ret = false;
+	const char *p1 = lxcapi_get_config_path(c);
+	char *path = alloca(strlen(p1) + strlen(c->name) + 2);
+	sprintf(path, "%s/%s", p1, c->name);
 
 	if (!c || !lxcapi_is_defined(c))
 		return false;
@@ -1480,6 +1483,15 @@ static bool lxcapi_destroy(struct lxc_container *c)
 		goto out;
 	}
 
+	if (geteuid() != 0) {
+		/*
+		 * container is one big dir, and we have to shell out
+		 * to have permission to remove it.  So do it in one
+		 * big shot
+		 */
+		return do_mapped_rmdir(path, c->lxc_conf) == 0;
+	}
+
 	if (c->lxc_conf && c->lxc_conf->rootfs.path && c->lxc_conf->rootfs.mount)
 		r = bdev_init(c->lxc_conf->rootfs.path, c->lxc_conf->rootfs.mount, NULL);
 	if (r) {
@@ -1489,9 +1501,6 @@ static bool lxcapi_destroy(struct lxc_container *c)
 		}
 	}
 
-	const char *p1 = lxcapi_get_config_path(c);
-	char *path = alloca(strlen(p1) + strlen(c->name) + 2);
-	sprintf(path, "%s/%s", p1, c->name);
 	if (lxc_rmdir_onedev(path) < 0) {
 		ERROR("Error destroying container directory for %s", c->name);
 		goto out;
-- 
1.8.3.2





More information about the lxc-devel mailing list