From: Serge Hallyn Date: Tue, 3 Jun 2014 03:03:58 +0000 (-0500) Subject: execute: don't bind mount init.lxc.static if lxc-init is in the container X-Git-Tag: lxc-1.1.0.alpha1~73 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9d9c111c6106ab53b96a5ce6010fa20c47900e35;p=thirdparty%2Flxc.git execute: don't bind mount init.lxc.static if lxc-init is in the container 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 Acked-by: Stéphane Graber --- diff --git a/.gitignore b/.gitignore index 8145f81c9..a69ffdea9 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 8beded29c..9fa4858b9 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 4ebc214ab..b78bcbfc0 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 b076ce741..173afa866 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 691e56ca9..050102ce6 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);