[lxc-devel] [lxc/master] use execveat syscall to exec lxc-init if supported

tych0 on Github lxc-bot at linuxcontainers.org
Tue May 22 23:35:25 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 498 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180522/a9a6664d/attachment.bin>
-------------- next part --------------
From fcc7bf2940b912dee51c1062e66893a2d7726f10 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho at tycho.ws>
Date: Tue, 22 May 2018 23:33:17 +0000
Subject: [PATCH] use execveat syscall to exec lxc-init if supported

the execveat allows us to exec stuff via a fd so we don't have to bind
mount stuff in. see the comment about why we're using the syscall directly.

Signed-off-by: Tycho Andersen <tycho at tycho.ws>
---
 src/lxc/conf.c    | 47 +++++++++++++++++++++++++++++++++++++++++++----
 src/lxc/execute.c | 19 ++++++++++++-------
 src/lxc/start.h   |  1 +
 3 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 77c134e82..c87465c77 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -3259,6 +3259,7 @@ static int lxc_execute_bind_init(struct lxc_handler *handler)
 
 	INFO("Bind mounted lxc.init.static into container at \"%s\"", path);
 out:
+	((struct execute_args *)handler->data)->init_fd = -1;
 	((struct execute_args *)handler->data)->init_path = p;
 	return 0;
 }
@@ -3333,6 +3334,24 @@ static bool verify_start_hooks(struct lxc_conf *conf)
 	return true;
 }
 
+static bool execveat_supported(void)
+{
+#ifdef __NR_execveat
+	/*
+	 * We use the syscall here, because it was introduced in kernel 3.19,
+	 * while glibc got support for using the syscall much later, in 2.27.
+	 * We don't want to use glibc because it falls back to /proc, and the
+	 * container may not have /proc mounted depending on its configuration.
+	 */
+	syscall(__NR_execveat, -1, "", NULL, NULL, AT_EMPTY_PATH);
+	if (errno == ENOSYS)
+		return false;
+	return true;
+#else
+	return false;
+#endif
+}
+
 int lxc_setup(struct lxc_handler *handler)
 {
 	int ret;
@@ -3393,10 +3412,30 @@ 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");
-			return -1;
+		if (execveat_supported()) {
+			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;
+			((struct execute_args *)handler->data)->init_path = NULL;
+		} else {
+			ret = lxc_execute_bind_init(handler);
+			if (ret < 0) {
+				ERROR("Failed to bind-mount the lxc init system");
+				return -1;
+			}
 		}
 	}
 
diff --git a/src/lxc/execute.c b/src/lxc/execute.c
index b436b6a3f..fdd639a2d 100644
--- a/src/lxc/execute.c
+++ b/src/lxc/execute.c
@@ -66,12 +66,10 @@ 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;
+	if (my_args->init_path)
+		argv[i++] = my_args->init_path;
+	else
+		argv[i++] = "lxc-init";
 
 	argv[i++] = "-n";
 	argv[i++] = (char *)handler->name;
@@ -117,7 +115,14 @@ static int execute_start(struct lxc_handler *handler, void* data)
 
 	NOTICE("Exec'ing \"%s\"", my_args->argv[0]);
 
-	execvp(argv[0], argv);
+	if (my_args->init_fd >= 0)
+#ifdef __NR_execveat
+		syscall(__NR_execveat, my_args->init_fd, "", argv, environ, AT_EMPTY_PATH);
+#else
+		ERROR("Set up execveat without syscall nr?");
+#endif
+	else
+		execvp(argv[0], argv);
 	SYSERROR("Failed to exec %s", argv[0]);
 
 out3:
diff --git a/src/lxc/start.h b/src/lxc/start.h
index 466dbf5f3..aaa731077 100644
--- a/src/lxc/start.h
+++ b/src/lxc/start.h
@@ -138,6 +138,7 @@ struct lxc_handler {
 
 struct execute_args {
 	char *init_path;
+	int init_fd;
 	char *const *argv;
 	int quiet;
 };


More information about the lxc-devel mailing list