The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/2341

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
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 <ty...@tycho.ws>
From fcc7bf2940b912dee51c1062e66893a2d7726f10 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <ty...@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 <ty...@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;
 };
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to