The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/7168
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) === Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From 51d0971bf2c8aab88992eab0ccc098137496df86 Mon Sep 17 00:00:00 2001 From: Christian Brauner <christian.brau...@ubuntu.com> Date: Fri, 10 Apr 2020 11:06:35 +0200 Subject: [PATCH] forkexec: close all inherited fds Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com> --- lxd/main_forkexec.go | 85 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/lxd/main_forkexec.go b/lxd/main_forkexec.go index ea2451e8df..3d69fa80ad 100644 --- a/lxd/main_forkexec.go +++ b/lxd/main_forkexec.go @@ -122,6 +122,86 @@ static int fd_cloexec(int fd, bool cloexec) return 0; } +static int safe_int(const char *numstr, int *converted) +{ + char *err = NULL; + signed long int sli; + + errno = 0; + sli = strtol(numstr, &err, 0); + if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN)) + return -ERANGE; + + if (errno != 0 && sli == 0) + return -EINVAL; + + if (err == numstr || *err != '\0') + return -EINVAL; + + if (sli > INT_MAX || sli < INT_MIN) + return -ERANGE; + + *converted = (int)sli; + return 0; +} + +static inline bool match_stdfds(int fd) +{ + return (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO); +} + +static int close_inherited(int *fds_to_ignore, size_t len_fds) +{ + 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; + size_t i; + + if (strcmp(direntp->d_name, ".") == 0) + continue; + + if (strcmp(direntp->d_name, "..") == 0) + continue; + + ret = safe_int(direntp->d_name, &fd); + if (ret < 0) + continue; + + for (i = 0; i < len_fds; i++) + if (fds_to_ignore[i] == fd) + break; + + if (fd == fddir || (i < len_fds && fd == fds_to_ignore[i])) + continue; + + if (match_stdfds(fd)) + continue; + + close(fd); + closedir(dir); + goto restart; + } + + closedir(dir); + return 0; +} + +#define EXEC_STDIN_FD 3 +#define EXEC_STDOUT_FD 4 +#define EXEC_STDERR_FD 5 +#define EXEC_PIPE_FD 6 +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + // We use a separate function because cleanup macros are called during stack // unwinding if I'm not mistaken and if the compiler knows it exits it won't // call them. That's not a problem since we're exiting but I just like to be on @@ -129,7 +209,7 @@ static int fd_cloexec(int fd, bool cloexec) // tell the compiler to not inline us. __attribute__ ((noinline)) static int __forkexec(void) { - __do_close int status_pipe = 6; + __do_close int status_pipe = EXEC_PIPE_FD; __do_free_string_list char **argvp = NULL, **envvp = NULL; call_cleaner(lxc_container_put) struct lxc_container *c = NULL; const char *config_path = NULL, *lxcpath = NULL, *name = NULL; @@ -138,6 +218,7 @@ __attribute__ ((noinline)) static int __forkexec(void) lxc_attach_command_t command = { .program = NULL, }; + int fds_to_ignore[] = {EXEC_STDIN_FD, EXEC_STDOUT_FD, EXEC_STDERR_FD, EXEC_PIPE_FD}; int ret; pid_t pid; uid_t uid; @@ -191,6 +272,8 @@ __attribute__ ((noinline)) static int __forkexec(void) if (!argvp || !*argvp) return log_error(EXIT_FAILURE, "No command specified"); + close_inherited(fds_to_ignore, ARRAY_SIZE(fds_to_ignore)); + ret = fd_cloexec(status_pipe, true); if (ret) return EXIT_FAILURE;
_______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel