[lxc-devel] [PATCH 4/6] execute: don't bind mount init.lxc.static if lxc-init is in the container

Serge Hallyn serge.hallyn at ubuntu.com
Tue Jun 3 03:03:58 UTC 2014


Move choose_init into utils.c so we can re-use it.  Make it and on_path
accept an optional rootfs argument to prepend to the paths when checking
whether the file exists.

Also add lxc.init.static to .gitignore

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 .gitignore        |   1 +
 src/lxc/conf.c    |  13 +++++--
 src/lxc/execute.c |  86 +-----------------------------------------
 src/lxc/utils.c   | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/lxc/utils.h   |   3 +-
 5 files changed, 122 insertions(+), 91 deletions(-)

diff --git a/.gitignore b/.gitignore
index 8145f81..a69ffde 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,7 @@ templates/lxc-ubuntu
 templates/lxc-ubuntu-cloud
 
 src/lxc/init.lxc
+src/lxc/init.lxc.static
 src/lxc/lxc-attach
 src/lxc/lxc-autostart
 src/lxc/lxc-cgroup
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 8beded2..9fa4858 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3246,14 +3246,14 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
 	enum idtype type;
 	char *buf = NULL, *pos, *cmdpath = NULL;
 
-	cmdpath = on_path("newuidmap");
+	cmdpath = on_path("newuidmap", NULL);
 	if (cmdpath) {
 		use_shadow = 1;
 		free(cmdpath);
 	}
 
 	if (!use_shadow) {
-		cmdpath = on_path("newgidmap");
+		cmdpath = on_path("newgidmap", NULL);
 		if (cmdpath) {
 			use_shadow = 1;
 			free(cmdpath);
@@ -3814,7 +3814,14 @@ static void remount_all_slave(void)
 void lxc_execute_bind_init(struct lxc_conf *conf)
 {
 	int ret;
-	char path[PATH_MAX], destpath[PATH_MAX];
+	char path[PATH_MAX], destpath[PATH_MAX], *p;
+
+	/* If init exists in the container, don't bind mount a static one */
+	p = choose_init(conf->rootfs.mount);
+	if (p) {
+		free(p);
+		return;
+	}
 
 	ret = snprintf(path, PATH_MAX, SBINDIR "/init.lxc.static");
 	if (ret < 0 || ret >= PATH_MAX) {
diff --git a/src/lxc/execute.c b/src/lxc/execute.c
index 4ebc214..b78bcbf 100644
--- a/src/lxc/execute.c
+++ b/src/lxc/execute.c
@@ -39,90 +39,6 @@ struct execute_args {
 	int quiet;
 };
 
-/* historically lxc-init has been under /usr/lib/lxc and under
- * /usr/lib/$ARCH/lxc.  It now lives as $prefix/sbin/init.lxc.
- */
-static char *choose_init(void)
-{
-	char *retv = NULL;
-	int ret, env_set = 0;
-	struct stat mystat;
-
-	if (!getenv("PATH")) {
-		if (setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 0))
-			SYSERROR("Failed to setenv");
-		env_set = 1;
-	}
-
-	retv = on_path("init.lxc");
-
-	if (env_set) {
-		if (unsetenv("PATH"))
-			SYSERROR("Failed to unsetenv");
-	}
-
-	if (retv)
-		return retv;
-
-	retv = malloc(PATH_MAX);
-	if (!retv)
-		return NULL;
-
-	ret = snprintf(retv, PATH_MAX, SBINDIR "/init.lxc");
-	if (ret < 0 || ret >= PATH_MAX) {
-		ERROR("pathname too long");
-		goto out1;
-	}
-
-	ret = stat(retv, &mystat);
-	if (ret == 0)
-		return retv;
-
-	ret = snprintf(retv, PATH_MAX, LXCINITDIR "/lxc/lxc-init");
-	if (ret < 0 || ret >= PATH_MAX) {
-		ERROR("pathname too long");
-		goto out1;
-	}
-
-	ret = stat(retv, &mystat);
-	if (ret == 0)
-		return retv;
-
-	ret = snprintf(retv, PATH_MAX, "/usr/lib/lxc/lxc-init");
-	if (ret < 0 || ret >= PATH_MAX) {
-		ERROR("pathname too long");
-		goto out1;
-	}
-	ret = stat(retv, &mystat);
-	if (ret == 0)
-		return retv;
-	ret = snprintf(retv, PATH_MAX, "/sbin/lxc-init");
-	if (ret < 0 || ret >= PATH_MAX) {
-		ERROR("pathname too long");
-		goto out1;
-	}
-	ret = stat(retv, &mystat);
-	if (ret == 0)
-		return retv;
-
-	/*
-	 * Last resort, look for the statically compiled init.lxc which we
-	 * hopefully bind-mounted in
-	 */
-	ret = snprintf(retv, PATH_MAX, "/init.lxc.static");
-	if (ret < 0 || ret >= PATH_MAX) {
-		WARN("Nonsense - name /lxc.init.static too long");
-		goto out1;
-	}
-	ret = stat(retv, &mystat);
-	if (ret == 0)
-		return retv;
-
-out1:
-	free(retv);
-	return NULL;
-}
-
 static int execute_start(struct lxc_handler *handler, void* data)
 {
 	int j, i = 0;
@@ -146,7 +62,7 @@ static int execute_start(struct lxc_handler *handler, void* data)
 	if (!argv)
 		goto out1;
 
-	initpath = choose_init();
+	initpath = choose_init(NULL);
 	if (!initpath) {
 		ERROR("Failed to find an lxc-init");
 		goto out2;
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index b076ce7..173afa8 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1272,7 +1272,7 @@ int detect_ramfs_rootfs(void)
 	return 0;
 }
 
-char *on_path(char *cmd) {
+char *on_path(char *cmd, const char *rootfs) {
 	char *path = NULL;
 	char *entry = NULL;
 	char *saveptr = NULL;
@@ -1289,7 +1289,10 @@ char *on_path(char *cmd) {
 
 	entry = strtok_r(path, ":", &saveptr);
 	while (entry) {
-		ret = snprintf(cmdpath, MAXPATHLEN, "%s/%s", entry, cmd);
+		if (rootfs)
+			ret = snprintf(cmdpath, MAXPATHLEN, "%s/%s/%s", rootfs, entry, cmd);
+		else
+			ret = snprintf(cmdpath, MAXPATHLEN, "%s/%s", entry, cmd);
 
 		if (ret < 0 || ret >= MAXPATHLEN)
 			goto next_loop;
@@ -1313,3 +1316,106 @@ bool file_exists(const char *f)
 
 	return stat(f, &statbuf) == 0;
 }
+
+/* historically lxc-init has been under /usr/lib/lxc and under
+ * /usr/lib/$ARCH/lxc.  It now lives as $prefix/sbin/init.lxc.
+ */
+char *choose_init(const char *rootfs)
+{
+	char *retv = NULL;
+	int ret, env_set = 0;
+	struct stat mystat;
+
+	if (!getenv("PATH")) {
+		if (setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", 0))
+			SYSERROR("Failed to setenv");
+		env_set = 1;
+	}
+
+	retv = on_path("init.lxc", rootfs);
+
+	if (env_set) {
+		if (unsetenv("PATH"))
+			SYSERROR("Failed to unsetenv");
+	}
+
+	if (retv)
+		return retv;
+
+	retv = malloc(PATH_MAX);
+	if (!retv)
+		return NULL;
+
+	if (rootfs)
+		ret = snprintf(retv, PATH_MAX, "%s/%s/init.lxc", rootfs, SBINDIR);
+	else
+		ret = snprintf(retv, PATH_MAX, SBINDIR "/init.lxc");
+	if (ret < 0 || ret >= PATH_MAX) {
+		ERROR("pathname too long");
+		goto out1;
+	}
+
+	ret = stat(retv, &mystat);
+	if (ret == 0)
+		return retv;
+
+	if (rootfs)
+		ret = snprintf(retv, PATH_MAX, "%s/%s/lxc/lxc-init", rootfs, LXCINITDIR);
+	else
+		ret = snprintf(retv, PATH_MAX, LXCINITDIR "/lxc/lxc-init");
+	if (ret < 0 || ret >= PATH_MAX) {
+		ERROR("pathname too long");
+		goto out1;
+	}
+
+	ret = stat(retv, &mystat);
+	if (ret == 0)
+		return retv;
+
+	if (rootfs)
+		ret = snprintf(retv, PATH_MAX, "%s/usr/lib/lxc/lxc-init", rootfs);
+	else
+		ret = snprintf(retv, PATH_MAX, "/usr/lib/lxc/lxc-init");
+	if (ret < 0 || ret >= PATH_MAX) {
+		ERROR("pathname too long");
+		goto out1;
+	}
+	ret = stat(retv, &mystat);
+	if (ret == 0)
+		return retv;
+
+	if (rootfs)
+		ret = snprintf(retv, PATH_MAX, "%s/sbin/lxc-init", rootfs);
+	else
+		ret = snprintf(retv, PATH_MAX, "/sbin/lxc-init");
+	if (ret < 0 || ret >= PATH_MAX) {
+		ERROR("pathname too long");
+		goto out1;
+	}
+	ret = stat(retv, &mystat);
+	if (ret == 0)
+		return retv;
+
+	/*
+	 * Last resort, look for the statically compiled init.lxc which we
+	 * hopefully bind-mounted in.
+	 * If we are called during container setup, and we get to this point,
+	 * then the init.lxc.static from the host will need to be bind-mounted
+	 * in.  So we return NULL here to indicate that.
+	 */
+	if (rootfs)
+		goto out1;
+
+	ret = snprintf(retv, PATH_MAX, "/init.lxc.static");
+	if (ret < 0 || ret >= PATH_MAX) {
+		WARN("Nonsense - name /lxc.init.static too long");
+		goto out1;
+	}
+	ret = stat(retv, &mystat);
+	if (ret == 0)
+		return retv;
+
+out1:
+	free(retv);
+	return NULL;
+}
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 691e56c..050102c 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -279,5 +279,6 @@ uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval);
 
 int detect_shared_rootfs(void);
 int detect_ramfs_rootfs(void);
-char *on_path(char *cmd);
+char *on_path(char *cmd, const char *rootfs);
 bool file_exists(const char *f);
+char *choose_init(const char *rootfs);
-- 
2.0.0



More information about the lxc-devel mailing list