[lxc-devel] [lxc/master] execute: don't bind in lxc.init.static
tych0 on Github
lxc-bot at linuxcontainers.org
Wed May 9 15:55:39 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 768 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180509/298a72ff/attachment.bin>
-------------- next part --------------
From 0077e205dc6a774893c489cfb5c96ee9af275e34 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho at tycho.ws>
Date: Wed, 9 May 2018 15:47:00 +0000
Subject: [PATCH] execute: don't bind in lxc.init.static
Instead of bind mounting in the init and execing it, let's just use
fexecve. There are at least two reasons to prefer this:
* We don't pollute the users rootfs (even if only temporarily). Even if we
remove the file, it still changes the mtime of /tmp (or wherever we would
bind it), which users who are sensitive to any changes in the rootfs will
see.
* It allows us to get rid of a whole bunch of code.
Signed-off-by: Tycho Andersen <tycho at tycho.ws>
---
src/lxc/cmd/lxc_init.c | 28 ----------------
src/lxc/conf.c | 75 ++++++++---------------------------------
src/lxc/execute.c | 9 ++---
src/lxc/start.h | 2 +-
src/lxc/utils.c | 90 --------------------------------------------------
src/lxc/utils.h | 1 -
6 files changed, 17 insertions(+), 188 deletions(-)
diff --git a/src/lxc/cmd/lxc_init.c b/src/lxc/cmd/lxc_init.c
index 228a2eb8b..a16745dcd 100644
--- a/src/lxc/cmd/lxc_init.c
+++ b/src/lxc/cmd/lxc_init.c
@@ -192,32 +192,6 @@ static void kill_children(pid_t pid)
fclose(f);
}
-static void remove_self(void)
-{
- int ret;
- ssize_t n;
- char path[MAXPATHLEN] = {0};
-
- n = readlink("/proc/self/exe", path, sizeof(path));
- if (n < 0 || n >= MAXPATHLEN) {
- SYSERROR("Failed to readlink \"/proc/self/exe\"");
- return;
- }
- path[n] = '\0';
-
- ret = umount2(path, MNT_DETACH);
- if (ret < 0) {
- SYSERROR("Failed to unmount \"%s\"", path);
- return;
- }
-
- ret = unlink(path);
- if (ret < 0) {
- SYSERROR("Failed to unlink \"%s\"", path);
- return;
- }
-}
-
int main(int argc, char *argv[])
{
int i, ret;
@@ -317,8 +291,6 @@ int main(int argc, char *argv[])
}
}
- remove_self();
-
pid = fork();
if (pid < 0)
exit(EXIT_FAILURE);
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 253331160..5c6483cc7 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3203,64 +3203,6 @@ void remount_all_slave(void)
free(line);
}
-static int lxc_execute_bind_init(struct lxc_handler *handler)
-{
- int ret;
- char *p;
- char path[PATH_MAX], destpath[PATH_MAX];
- struct lxc_conf *conf = handler->conf;
-
- /* If init exists in the container, don't bind mount a static one */
- p = choose_init(conf->rootfs.mount);
- if (p) {
- char *old = p;
-
- p = strdup(old + strlen(conf->rootfs.mount));
- free(old);
- if (!p)
- return -ENOMEM;
-
- INFO("Found existing init at \"%s\"", p);
- goto out;
- }
-
- ret = snprintf(path, PATH_MAX, SBINDIR "/init.lxc.static");
- if (ret < 0 || ret >= PATH_MAX)
- return -1;
-
- if (!file_exists(path)) {
- ERROR("The file \"%s\" does not exist on host", path);
- return -1;
- }
-
- ret = snprintf(destpath, PATH_MAX, "%s" P_tmpdir "%s", conf->rootfs.mount, "/.lxc-init");
- if (ret < 0 || ret >= PATH_MAX)
- return -1;
-
- if (!file_exists(destpath)) {
- ret = mknod(destpath, S_IFREG | 0000, 0);
- if (ret < 0 && errno != EEXIST) {
- SYSERROR("Failed to create dummy \"%s\" file as bind mount target", destpath);
- return -1;
- }
- }
-
- ret = safe_mount(path, destpath, "none", MS_BIND, NULL, conf->rootfs.mount);
- if (ret < 0) {
- SYSERROR("Failed to bind mount lxc.init.static into container");
- return -1;
- }
-
- p = strdup(destpath + strlen(conf->rootfs.mount));
- if (!p)
- return -ENOMEM;
-
- INFO("Bind mounted lxc.init.static into container at \"%s\"", path);
-out:
- ((struct execute_args *)handler->data)->init_path = p;
- return 0;
-}
-
/* This does the work of remounting / if it is shared, calling the container
* pre-mount hooks, and mounting the rootfs.
*/
@@ -3391,11 +3333,22 @@ int lxc_setup(struct lxc_handler *handler)
return -1;
if (lxc_conf->is_execute) {
- ret = lxc_execute_bind_init(handler);
- if (ret < 0) {
- ERROR("Failed to bind-mount the lxc init system");
+ int fd;
+ char path[PATH_MAX];
+
+ ret = snprintf(path, PATH_MAX, SBINDIR "/init.lxc.static");
+ if (ret < 0 || ret >= PATH_MAX) {
+ ERROR("Path to init.lxc.static too long");
return -1;
}
+
+ fd = open(path, O_PATH | O_CLOEXEC);
+ if (fd < 0) {
+ SYSERROR("Unable to open lxc.init.static");
+ return -1;
+ }
+
+ ((struct execute_args *)handler->data)->init_fd = fd;
}
/* Now mount only cgroups, if wanted. Before, /sys could not have been
diff --git a/src/lxc/execute.c b/src/lxc/execute.c
index b436b6a3f..2da338028 100644
--- a/src/lxc/execute.c
+++ b/src/lxc/execute.c
@@ -66,12 +66,7 @@ static int execute_start(struct lxc_handler *handler, void* data)
goto out1;
}
- if (!my_args->init_path) {
- ERROR("Init path missing");
- goto out2;
- }
-
- argv[i++] = my_args->init_path;
+ argv[i++] = "lxc-init";
argv[i++] = "-n";
argv[i++] = (char *)handler->name;
@@ -117,7 +112,7 @@ static int execute_start(struct lxc_handler *handler, void* data)
NOTICE("Exec'ing \"%s\"", my_args->argv[0]);
- execvp(argv[0], argv);
+ fexecve(my_args->init_fd, argv, environ);
SYSERROR("Failed to exec %s", argv[0]);
out3:
diff --git a/src/lxc/start.h b/src/lxc/start.h
index 5455ca5f3..c83b91e2b 100644
--- a/src/lxc/start.h
+++ b/src/lxc/start.h
@@ -135,7 +135,7 @@ struct lxc_handler {
};
struct execute_args {
- char *init_path;
+ int init_fd;
char *const *argv;
int quiet;
};
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index 3d0f8641c..c1910edeb 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -1290,96 +1290,6 @@ bool cgns_supported(void)
return file_exists("/proc/self/ns/cgroup");
}
-/* 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;
- const char *empty = "",
- *tmp;
- int ret, env_set = 0;
-
- 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)
- tmp = rootfs;
- else
- tmp = empty;
-
- ret = snprintf(retv, PATH_MAX, "%s/%s/%s", tmp, SBINDIR, "/init.lxc");
- if (ret < 0 || ret >= PATH_MAX) {
- ERROR("pathname too long");
- goto out1;
- }
- if (access(retv, X_OK) == 0)
- return retv;
-
- ret = snprintf(retv, PATH_MAX, "%s/%s/%s", tmp, LXCINITDIR, "/lxc/lxc-init");
- if (ret < 0 || ret >= PATH_MAX) {
- ERROR("pathname too long");
- goto out1;
- }
- if (access(retv, X_OK) == 0)
- return retv;
-
- ret = snprintf(retv, PATH_MAX, "%s/usr/lib/lxc/lxc-init", tmp);
- if (ret < 0 || ret >= PATH_MAX) {
- ERROR("pathname too long");
- goto out1;
- }
- if (access(retv, X_OK) == 0)
- return retv;
-
- ret = snprintf(retv, PATH_MAX, "%s/sbin/lxc-init", tmp);
- if (ret < 0 || ret >= PATH_MAX) {
- ERROR("pathname too long");
- goto out1;
- }
- if (access(retv, X_OK) == 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;
- }
- if (access(retv, X_OK) == 0)
- return retv;
-
-out1:
- free(retv);
- return NULL;
-}
-
int print_to_file(const char *file, const char *content)
{
FILE *f;
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 62f087311..061c10255 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -506,7 +506,6 @@ extern bool detect_ramfs_rootfs(void);
extern char *on_path(const char *cmd, const char *rootfs);
extern bool file_exists(const char *f);
extern bool cgns_supported(void);
-extern char *choose_init(const char *rootfs);
extern int print_to_file(const char *file, const char *content);
extern bool switch_to_ns(pid_t pid, const char *ns);
extern int is_dir(const char *path);
More information about the lxc-devel
mailing list