From: Christian Brauner Date: Tue, 29 Jun 2021 08:32:31 +0000 (+0200) Subject: execute: ensure parent is notified about child exec and close all unneeded fds X-Git-Tag: lxc-5.0.0~150^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=734a677ed22e8adfbcbc66b30763f9da9279cc39;p=thirdparty%2Flxc.git execute: ensure parent is notified about child exec and close all unneeded fds lxc_container_init() creates the container payload process as it's child so lxc_container_init() itself never really exits and thus the parent isn't notified about the child exec'ing since the sync file descriptor is never closed. Make sure it's closed to notify the parent about the child's exec. In addition we're currently leaking all file descriptors associated with the handler into the stub init. Make sure that all file descriptors other than stderr are closed. Signed-off-by: Christian Brauner --- diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 625e80955..cdefc2ad5 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -22,8 +22,10 @@ #include "list.h" #include "lxcseccomp.h" #include "memory_utils.h" +#include "namespace.h" #include "ringbuf.h" #include "start.h" +#include "state.h" #include "storage/storage.h" #include "string_utils.h" #include "syscall_wrappers.h" diff --git a/src/lxc/initutils.c b/src/lxc/initutils.c index 21a7c1a05..f5e41804d 100644 --- a/src/lxc/initutils.c +++ b/src/lxc/initutils.c @@ -429,6 +429,46 @@ static void interrupt_handler(int sig) was_interrupted = sig; } +static int close_inherited(void) +{ + int fddir; + DIR *dir; + struct dirent *direntp; + +restart: + dir = opendir("/proc/self/fd"); + if (!dir) + return -errno; + + fddir = dirfd(dir); + + while ((direntp = readdir(dir))) { + int fd, ret; + + if (strcmp(direntp->d_name, ".") == 0) + continue; + + if (strcmp(direntp->d_name, "..") == 0) + continue; + + ret = lxc_safe_int(direntp->d_name, &fd); + if (ret < 0) + continue; + + if (fd == STDERR_FILENO || fd == fddir) + break; + + if (close(fd)) + return -errno; + + closedir(dir); + goto restart; + } + + closedir(dir); + return 0; +} + __noreturn int lxc_container_init(int argc, char *const *argv, bool quiet) { int i, logfd, ret; @@ -565,9 +605,22 @@ __noreturn int lxc_container_init(int argc, char *const *argv, bool quiet) exit(EXIT_FAILURE); } - /* No need of other inherited fds but stderr. */ - close(STDIN_FILENO); - close(STDOUT_FILENO); + ret = close_range(STDERR_FILENO + 1, UINT_MAX, CLOSE_RANGE_UNSHARE); + if (ret) { + /* + * Fallback to close_inherited() when the syscall is not + * available or when CLOSE_RANGE_UNSHARE isn't supported. + * On a regular kernel CLOSE_RANGE_UNSHARE should always be + * available but openSUSE Leap 15.3 seems to have a partial + * backport without CLOSE_RANGE_UNSHARE support. + */ + if (errno == ENOSYS || errno == EINVAL) + ret = close_inherited(); + } + if (ret) { + fprintf(stderr, "Aborting attach to prevent leaking file descriptors into container\n"); + exit(EXIT_FAILURE); + } for (;;) { int status;