From ad33756d6190df4f1aad9b6468b0b59086e916b5 Mon Sep 17 00:00:00 2001 From: zhangxiaoyu Date: Tue, 19 Jul 2022 15:23:34 +0800 Subject: [PATCH] refactor patch code of attach and seccomp Signed-off-by: zhangxiaoyu --- src/lxc/attach.c | 517 +++++++++++++++++++++++++++++++++++++++ src/lxc/lsm/nop.c | 14 ++ src/lxc/seccomp.c | 555 ++++++++++++++++++++++++++++++++++++++++++ src/lxc/storage/zfs.c | 9 + 4 files changed, 1095 insertions(+) diff --git a/src/lxc/attach.c b/src/lxc/attach.c index 38e16f2..8a2c52a 100644 --- a/src/lxc/attach.c +++ b/src/lxc/attach.c @@ -49,6 +49,25 @@ #include #endif +#ifdef HAVE_ISULAD +#include "exec_commands.h" + +typedef enum { + ATTACH_INIT, + ATTACH_TIMEOUT, + ATTACH_MAX, +} attach_timeout_t; + +static volatile attach_timeout_t g_attach_timeout_state = ATTACH_INIT; + +struct attach_timeout_conf { + int64_t timeout; + unsigned long long start_time; + pid_t pid; +}; + +#endif + lxc_log_define(attach, lxc); /* Define default options if no options are supplied by the user. */ @@ -630,6 +649,9 @@ struct attach_clone_payload { struct lxc_proc_context_info *init_ctx; lxc_attach_exec_t exec_function; void *exec_payload; +#ifdef HAVE_ISULAD + struct lxc_terminal *terminal; +#endif }; static void lxc_put_attach_clone_payload(struct attach_clone_payload *p) @@ -642,6 +664,48 @@ static void lxc_put_attach_clone_payload(struct attach_clone_payload *p) } } +#ifdef HAVE_ISULAD +static int isulad_set_attach_pipes(struct lxc_terminal *terminal) +{ + int ret = 0; + if (terminal->pipes[0][1] >= 0) { + close(terminal->pipes[0][1]); + terminal->pipes[0][1] = -1; + } + + if (terminal->pipes[0][0] >= 0) { + ret = dup2(terminal->pipes[0][0], STDIN_FILENO); + if (ret < 0) + goto out; + } + + if (terminal->pipes[1][0] >= 0) { + close(terminal->pipes[1][0]); + terminal->pipes[1][0] = -1; + } + + if (terminal->pipes[1][1] >= 0) { + ret = dup2(terminal->pipes[1][1], STDOUT_FILENO); + if (ret < 0) + goto out; + } + if (terminal->pipes[2][0] >= 0) { + close(terminal->pipes[2][0]); + terminal->pipes[2][0] = -1; + } + + if (terminal->pipes[2][1] >= 0) { + ret = dup2(terminal->pipes[2][1], STDERR_FILENO); + if (ret < 0) + goto out; + } + + setsid(); +out: + return ret; +} +#endif + static int attach_child_main(struct attach_clone_payload *payload) { int lsm_fd, ret; @@ -654,6 +718,31 @@ static int attach_child_main(struct attach_clone_payload *payload) bool needs_lsm = (options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label; +#ifdef HAVE_ISULAD + int msg_fd = -1; + sigset_t mask; + + /*isulad: record errpipe fd*/ + msg_fd = init_ctx->container->lxc_conf->errpipe[1]; + init_ctx->container->lxc_conf->errpipe[1] = -1; + /*isulad: set system umask */ + umask(init_ctx->container->lxc_conf->umask); + + /*isulad: restore default signal handlers and unblock all signals*/ + for (int i = 1; i < NSIG; i++) + signal(i, SIG_DFL); + + ret = sigfillset(&mask); + if (ret < 0) { + SYSERROR("Failed to fill signal mask"); + goto on_error;; + } + ret = sigprocmask(SIG_UNBLOCK, &mask, NULL); + if (ret < 0) { + SYSERROR("Failed to set signal mask"); + goto on_error; + } +#endif /* A description of the purpose of this functionality is provided in the * lxc-attach(1) manual page. We have to remount here and not in the @@ -695,6 +784,28 @@ static int attach_child_main(struct attach_clone_payload *payload) TRACE("Dropped capabilities"); } +#ifdef HAVE_ISULAD + /* isulad: set workdir */ + if (options->initial_cwd || init_ctx->container->lxc_conf->init_cwd) { + char *init_cwd; + init_cwd = options->initial_cwd ? options->initial_cwd : init_ctx->container->lxc_conf->init_cwd; + /* try to create workdir if not exist */ + struct stat st; + if (stat(init_cwd, &st) < 0 && mkdir_p(init_cwd, 0750) < 0) { + SYSERROR("Try to create directory \"%s\" as workdir failed when attach", init_cwd); + lxc_write_error_message(msg_fd, "Try to create directory \"%s\" as workdir failed when attach: %s", + init_cwd, strerror(errno)); + goto on_error; + } + if (chdir(init_cwd)) { + SYSERROR("Could not change directory to \"%s\" when attach", init_cwd); + lxc_write_error_message(msg_fd, "Could not change directory to \"%s\" when attach: %s", + init_cwd, strerror(errno)); + goto on_error; + } + } +#endif + /* Always set the environment (specify (LXC_ATTACH_KEEP_ENV, NULL, NULL) * if you want this to be a no-op). */ @@ -736,8 +847,10 @@ static int attach_child_main(struct attach_clone_payload *payload) goto on_error; } +#ifndef HAVE_ISULAD if (!lxc_setgroups(0, NULL) && errno != EPERM) goto on_error; +#endif if (options->namespaces & CLONE_NEWUSER) { /* Check whether nsuid 0 has a mapping. */ @@ -770,6 +883,13 @@ static int attach_child_main(struct attach_clone_payload *payload) else new_gid = ns_root_gid; +#ifdef HAVE_ISULAD + // isulad: set env home in container + if (lxc_setup_env_home(new_uid) < 0) { + goto on_error; + } +#endif + if ((init_ctx->container && init_ctx->container->lxc_conf && init_ctx->container->lxc_conf->no_new_privs) || (options->attach_flags & LXC_ATTACH_NO_NEW_PRIVS)) { @@ -810,10 +930,12 @@ static int attach_child_main(struct attach_clone_payload *payload) goto on_error; } +#ifndef HAVE_ISULAD close(payload->ipc_socket); payload->ipc_socket = -EBADF; lxc_proc_put_context_info(init_ctx); payload->init_ctx = NULL; +#endif /* The following is done after the communication socket is shut down. * That way, all errors that might (though unlikely) occur up until this @@ -856,6 +978,24 @@ static int attach_child_main(struct attach_clone_payload *payload) } if (options->attach_flags & LXC_ATTACH_TERMINAL) { +#ifdef HAVE_ISULAD + /* isulad: dup2 pipe[0][0] to container stdin, pipe[1][1] to container stdout, pipe[2][1] to container stderr */ + if (payload->terminal->disable_pty) { + ret = isulad_set_attach_pipes(payload->terminal); + if (ret < 0) { + SYSERROR("Failed to prepare terminal file pipes"); + goto on_error; + } + } + + if(!payload->terminal->disable_pty && payload->terminal_pts_fd >= 0) { + ret = lxc_terminal_prepare_login(payload->terminal_pts_fd); + if (ret < 0) { + SYSERROR("Failed to prepare terminal file descriptor %d", payload->terminal_pts_fd); + goto on_error; + } + } +#else ret = lxc_terminal_prepare_login(payload->terminal_pts_fd); if (ret < 0) { SYSERROR("Failed to prepare terminal file descriptor %d", payload->terminal_pts_fd); @@ -863,6 +1003,7 @@ static int attach_child_main(struct attach_clone_payload *payload) } TRACE("Prepared terminal file descriptor %d", payload->terminal_pts_fd); +#endif } /* Avoid unnecessary syscalls. */ @@ -872,6 +1013,17 @@ static int attach_child_main(struct attach_clone_payload *payload) if (new_gid == ns_root_gid) new_gid = LXC_INVALID_GID; +#ifdef HAVE_ISULAD + if (prctl(PR_SET_KEEPCAPS, 1) < 0) { + SYSERROR("Failed to keep permitted capabilities"); + goto on_error; + } + + if (!lxc_setgroups(init_ctx->container->lxc_conf->init_groups_len, + init_ctx->container->lxc_conf->init_groups)) + goto on_error; +#endif + /* Make sure that the processes STDIO is correctly owned by the user that we are switching to */ ret = fix_stdio_permissions(new_uid); if (ret) @@ -880,21 +1032,63 @@ static int attach_child_main(struct attach_clone_payload *payload) if (!lxc_switch_uid_gid(new_uid, new_gid)) goto on_error; +#ifdef HAVE_ISULAD + if (prctl(PR_SET_KEEPCAPS, 0) < 0) { + SYSERROR("Failed to clear permitted capabilities"); + goto on_error; + } + + if (lxc_drop_caps(init_ctx->container->lxc_conf) != 0) { + ERROR("Failed to drop caps."); + goto on_error; + } + + close(payload->ipc_socket); + payload->ipc_socket = -EBADF; + lxc_proc_put_context_info(init_ctx); + payload->init_ctx = NULL; + _exit(payload->exec_function(payload->exec_payload, msg_fd)); +#else /* We're done, so we can now do whatever the user intended us to do. */ _exit(payload->exec_function(payload->exec_payload)); +#endif on_error: lxc_put_attach_clone_payload(payload); _exit(EXIT_FAILURE); } +#ifdef HAVE_ISULAD +static int lxc_attach_terminal(struct lxc_conf *conf, + struct lxc_terminal *terminal, lxc_attach_options_t *options) +#else static int lxc_attach_terminal(struct lxc_conf *conf, struct lxc_terminal *terminal) +#endif { int ret; lxc_terminal_init(terminal); +#ifdef HAVE_ISULAD + /* isulad: if we pass fifo in option, use them as init fifos */ + if (options->init_fifo[0]) { + free(terminal->init_fifo[0]); + terminal->init_fifo[0] = safe_strdup(options->init_fifo[0]); + } + if (options->init_fifo[1]) { + free(terminal->init_fifo[1]); + terminal->init_fifo[1] = safe_strdup(options->init_fifo[1]); + } + if (options->init_fifo[2]) { + free(terminal->init_fifo[2]); + terminal->init_fifo[2] = safe_strdup(options->init_fifo[2]); + } + + terminal->disable_pty = options->disable_pty; + terminal->open_stdin = options->open_stdin; +#endif + ret = lxc_terminal_create(terminal); if (ret < 0) return log_error(-1, "Failed to create terminal"); @@ -952,9 +1146,126 @@ static inline void lxc_attach_terminal_close_log(struct lxc_terminal *terminal) close_prot_errno_disarm(terminal->log_fd); } +#ifdef HAVE_ISULAD +/* isulad: attach timeout thread function */ +static void* wait_attach_timeout(void *arg) +{ + struct attach_timeout_conf *conf = (struct attach_timeout_conf *)arg; + + if (!conf || conf->timeout < 1) + goto out; + sleep(conf->timeout); + if (lxc_process_alive(conf->pid, conf->start_time)) { + g_attach_timeout_state = ATTACH_TIMEOUT; + if (kill(conf->pid, SIGKILL) < 0) { + ERROR("Failed to send signal %d to pid %d", SIGKILL, conf->pid); + } + } + +out: + free(conf); + return ((void *)0); +} + +/* isulad: create attach timeout thread */ +static int create_attach_timeout_thread(int64_t attach_timeout, pid_t pid) +{ + int ret = 0; + pthread_t ptid; + pthread_attr_t attr; + struct attach_timeout_conf *timeout_conf = NULL; + + timeout_conf = malloc(sizeof(struct attach_timeout_conf)); + if (timeout_conf == NULL) { + ERROR("Failed to malloc attach timeout conf"); + ret = -1; + goto out; + } + + memset(timeout_conf, 0, sizeof(struct attach_timeout_conf)); + timeout_conf->timeout = attach_timeout; + timeout_conf->pid = pid; + timeout_conf->start_time = lxc_get_process_startat(pid); + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + ret = pthread_create(&ptid, &attr, wait_attach_timeout, timeout_conf); + pthread_attr_destroy(&attr); + if (ret != 0) { + ERROR("Create attach wait timeout thread failed"); + free(timeout_conf); + goto out; + } + +out: + return ret; +} + +static int attach_signal_handler(int fd, uint32_t events, void *data, + struct lxc_epoll_descr *descr) +{ + int ret; + siginfo_t info; + struct signalfd_siginfo siginfo; + pid_t *pid = data; + + ret = lxc_read_nointr(fd, &siginfo, sizeof(siginfo)); + if (ret < 0) + return log_error(LXC_MAINLOOP_ERROR, "Failed to read signal info from signal file descriptor %d", fd); + + if (ret != sizeof(siginfo)) + return log_error(LXC_MAINLOOP_ERROR, "Unexpected size for struct signalfd_siginfo"); + + /* Check whether init is running. */ + info.si_pid = 0; + ret = waitid(P_PID, *pid, &info, WEXITED | WNOWAIT | WNOHANG); + if (ret == 0 && info.si_pid == *pid) { + return log_warn(LXC_MAINLOOP_CLOSE, "Container attach init process %d exited", *pid); + } + + return LXC_MAINLOOP_CONTINUE; +} + +static int isulad_setup_signal_fd(sigset_t *oldmask) +{ + int ret; + sigset_t mask; + const int signals[] = {SIGBUS, SIGILL, SIGSEGV, SIGWINCH, SIGTERM}; + + /* Block everything except serious error signals. */ + ret = sigfillset(&mask); + if (ret < 0) + return -EBADF; + + for (int sig = 0; sig < (sizeof(signals) / sizeof(signals[0])); sig++) { + ret = sigdelset(&mask, signals[sig]); + if (ret < 0) + return -EBADF; + } + + ret = pthread_sigmask(SIG_BLOCK, &mask, oldmask); + if (ret < 0) + return log_error_errno(-EBADF, errno, + "Failed to set signal mask"); + + ret = signalfd(-1, &mask, SFD_CLOEXEC); + if (ret < 0) + return log_error_errno(-EBADF, + errno, "Failed to create signal file descriptor"); + + TRACE("Created signal file descriptor %d", ret); + + return ret; +} + +int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, + void *exec_payload, lxc_attach_options_t *options, + pid_t *attached_process, char **err_msg) +#else int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, void *exec_payload, lxc_attach_options_t *options, pid_t *attached_process) +#endif { int i, ret, status; int ipc_sockets[2]; @@ -966,6 +1277,13 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, struct lxc_conf *conf; char *name, *lxcpath; struct attach_clone_payload payload = {0}; +#ifdef HAVE_ISULAD + struct lxc_exec_command_handler exec_command; + const char *suffix = options->suffix; + + exec_command.maincmd_fd = -1; + exec_command.terminal = &terminal; +#endif ret = access("/proc/self/ns", X_OK); if (ret) @@ -1017,6 +1335,14 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, if (!conf) return log_error_errno(-EINVAL, EINVAL, "Missing container confifg"); +#ifdef HAVE_ISULAD + // always switch uid and gid for attach + if (options->uid == -1) + options->uid = init_ctx->container->lxc_conf->init_uid; + if (options->gid == -1) + options->gid = init_ctx->container->lxc_conf->init_gid; +#endif + if (!fetch_seccomp(init_ctx->container, options)) WARN("Failed to get seccomp policy"); @@ -1090,7 +1416,11 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, } if (options->attach_flags & LXC_ATTACH_TERMINAL) { +#ifdef HAVE_ISULAD + ret = lxc_attach_terminal(conf, &terminal, options); +#else ret = lxc_attach_terminal(conf, &terminal); +#endif if (ret < 0) { ERROR("Failed to setup new terminal"); free(cwd); @@ -1099,6 +1429,12 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, } terminal.log_fd = options->log_fd; +#ifdef HAVE_ISULAD + if (suffix != NULL) { + exec_command.maincmd_fd = lxc_exec_cmd_init(name, lxcpath, suffix); + exec_command.terminal = &terminal; + } +#endif } else { lxc_terminal_init(&terminal); } @@ -1139,10 +1475,40 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, ret = socketpair(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); if (ret < 0) { SYSERROR("Could not set up required IPC mechanism for attaching"); +#ifdef HAVE_ISULAD + if (options->attach_flags & LXC_ATTACH_TERMINAL) { + lxc_terminal_delete(&terminal); + lxc_terminal_conf_free(&terminal); + if (exec_command.maincmd_fd != -1) { + close(exec_command.maincmd_fd); + } + lxc_exec_unix_sock_delete(name, suffix); + } +#endif + free(cwd); + lxc_proc_put_context_info(init_ctx); + return -1; + } + +#ifdef HAVE_ISULAD + /* isulad: pipdfd for get error message of child or grandchild process. */ + if (pipe2(conf->errpipe, O_CLOEXEC) != 0) { + SYSERROR("Failed to init errpipe"); + if (options->attach_flags & LXC_ATTACH_TERMINAL) { + lxc_terminal_delete(&terminal); + lxc_terminal_conf_free(&terminal); + if (exec_command.maincmd_fd != -1) { + close(exec_command.maincmd_fd); + } + lxc_exec_unix_sock_delete(name, suffix); + } + close(ipc_sockets[0]); + close(ipc_sockets[1]); free(cwd); lxc_proc_put_context_info(init_ctx); return -1; } +#endif /* Create intermediate subprocess, two reasons: * 1. We can't setns() in the child itself, since we want to make @@ -1154,6 +1520,18 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, pid = fork(); if (pid < 0) { SYSERROR("Failed to create first subprocess"); +#ifdef HAVE_ISULAD + if (options->attach_flags & LXC_ATTACH_TERMINAL) { + lxc_terminal_delete(&terminal); + lxc_terminal_conf_free(&terminal); + if (exec_command.maincmd_fd != -1) { + close(exec_command.maincmd_fd); + } + lxc_exec_unix_sock_delete(name, suffix); + } + close(ipc_sockets[0]); + close(ipc_sockets[1]); +#endif free(cwd); lxc_proc_put_context_info(init_ctx); return -1; @@ -1163,10 +1541,35 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, int ret_parent = -1; pid_t to_cleanup_pid = pid; struct lxc_epoll_descr descr = {0}; +#ifdef HAVE_ISULAD + int isulad_sigfd; + sigset_t isulad_oldmask; + struct lxc_epoll_descr isulad_descr = {0}; +#endif /* close unneeded file descriptors */ close(ipc_sockets[1]); free(cwd); +#ifdef HAVE_ISULAD + /* isulad: close errpipe */ + close(conf->errpipe[1]); + conf->errpipe[1] = -1; + /* isulad: close pipe after clone */ + if (terminal.pipes[0][0] >= 0) { + close(terminal.pipes[0][0]); + terminal.pipes[0][0] = -1; + } + + if (terminal.pipes[1][1] >= 0) { + close(terminal.pipes[1][1]); + terminal.pipes[1][1] = -1; + } + + if (terminal.pipes[2][1] >= 0) { + close(terminal.pipes[2][1]); + terminal.pipes[2][1] = -1; + } +#endif lxc_proc_close_ns_fd(init_ctx); if (options->attach_flags & LXC_ATTACH_TERMINAL) lxc_attach_terminal_close_pts(&terminal); @@ -1200,7 +1603,11 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, /* Setup resource limits */ if (!lxc_list_empty(&conf->limits)) { +#ifdef HAVE_ISULAD + ret = setup_resource_limits(&conf->limits, pid, -1); +#else ret = setup_resource_limits(&conf->limits, pid); +#endif if (ret < 0) goto on_error; } @@ -1210,9 +1617,28 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, if (ret < 0) goto on_error; +#ifdef HAVE_ISULAD + ret = lxc_attach_terminal_mainloop_init(&terminal, &isulad_descr); + if (ret < 0) + goto on_error; + + if (suffix != NULL) { + (void)lxc_exec_cmd_mainloop_add(&descr, &exec_command); + } +#endif TRACE("Initialized terminal mainloop"); } +#ifdef HAVE_ISULAD + /* The signal fd has to be created before forking otherwise if the child + * process exits before we setup the signal fd, the event will be lost + * and the command will be stuck. + */ + isulad_sigfd = isulad_setup_signal_fd(&isulad_oldmask); + if (isulad_sigfd < 0) + goto close_mainloop; +#endif + /* Let the child process know to go ahead. */ status = 0; ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status)); @@ -1290,6 +1716,34 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, *attached_process = attached_pid; +#ifdef HAVE_ISULAD + if (options->timeout > 0) { + ret = create_attach_timeout_thread(options->timeout, *attached_process); + if (ret) { + ERROR("Failed to create attach timeout thread for container."); + goto close_mainloop; + } + } + /* isulad: read error msg from pipe */ + ssize_t size_read; + char errbuf[BUFSIZ + 1] = {0}; + pid_t tmp_pid = *attached_process; + + size_read = read(conf->errpipe[0], errbuf, BUFSIZ); + if (size_read > 0) { + if (err_msg) + *err_msg = safe_strdup(errbuf); + goto close_mainloop; + } + if (options->attach_flags & LXC_ATTACH_TERMINAL) { + ret = lxc_mainloop_add_handler(&descr, isulad_sigfd, attach_signal_handler, &tmp_pid); + if (ret < 0) { + ERROR("Failed to add signal handler for %d to mainloop", tmp_pid); + goto close_mainloop; + } + } +#endif + /* Now shut down communication with child, we're done. */ shutdown(ipc_sockets[0], SHUT_RDWR); close(ipc_sockets[0]); @@ -1298,17 +1752,44 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, ret_parent = 0; to_cleanup_pid = -1; +#ifdef HAVE_ISULAD + // iSulad: close stdin pipe if we do not want open_stdin with container stdin + if (!terminal.open_stdin) { + if (terminal.pipes[0][1] > 0) { + close(terminal.pipes[0][1]); + terminal.pipes[0][1] = -1; + } + } +#endif if (options->attach_flags & LXC_ATTACH_TERMINAL) { +#ifdef HAVE_ISULAD + ret = isulad_safe_mainloop(&descr, -1); +#else ret = lxc_mainloop(&descr, -1); +#endif if (ret < 0) { ret_parent = -1; to_cleanup_pid = attached_pid; } } +#ifdef HAVE_ISULAD + // do lxc_mainloop to make sure we do not lose any output + (void)isulad_safe_mainloop(&isulad_descr, 100); + if (g_attach_timeout_state == ATTACH_TIMEOUT && err_msg != NULL && *err_msg == NULL) { + *err_msg = safe_strdup("Attach exceeded timeout"); + } +#endif close_mainloop: +#ifdef HAVE_ISULAD + if (options->attach_flags & LXC_ATTACH_TERMINAL) { + lxc_mainloop_close(&isulad_descr); + lxc_mainloop_close(&descr); + } +#else if (options->attach_flags & LXC_ATTACH_TERMINAL) lxc_mainloop_close(&descr); +#endif on_error: if (ipc_sockets[0] >= 0) { @@ -1322,6 +1803,12 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, if (options->attach_flags & LXC_ATTACH_TERMINAL) { lxc_terminal_delete(&terminal); lxc_terminal_conf_free(&terminal); +#ifdef HAVE_ISULAD + if (exec_command.maincmd_fd != -1) { + close(exec_command.maincmd_fd); + } + lxc_exec_unix_sock_delete(name, suffix); +#endif } lxc_proc_put_context_info(init_ctx); @@ -1331,10 +1818,21 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, /* close unneeded file descriptors */ close_prot_errno_disarm(ipc_sockets[0]); +#ifdef HAVE_ISULAD + /* isulad: close errpipe */ + close(conf->errpipe[0]); + conf->errpipe[0] = -1; +#endif + if (options->attach_flags & LXC_ATTACH_TERMINAL) { lxc_attach_terminal_close_ptmx(&terminal); lxc_attach_terminal_close_peer(&terminal); lxc_attach_terminal_close_log(&terminal); +#ifdef HAVE_ISULAD + if (exec_command.maincmd_fd != -1) { + close(exec_command.maincmd_fd); + } +#endif } /* Wait for the parent to have setup cgroups. */ @@ -1380,6 +1878,9 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, payload.terminal_pts_fd = terminal.pts; payload.exec_function = exec_function; payload.exec_payload = exec_payload; +#ifdef HAVE_ISULAD + payload.terminal = &terminal; +#endif pid = lxc_raw_clone(CLONE_PARENT, NULL); if (pid < 0) { @@ -1390,7 +1891,11 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, } if (pid == 0) { +#ifdef HAVE_ISULAD + if (options->attach_flags & LXC_ATTACH_TERMINAL && terminal.tty_state) { +#else if (options->attach_flags & LXC_ATTACH_TERMINAL) { +#endif ret = pthread_sigmask(SIG_SETMASK, &terminal.tty_state->oldmask, NULL); if (ret < 0) { @@ -1430,7 +1935,11 @@ int lxc_attach(struct lxc_container *container, lxc_attach_exec_t exec_function, _exit(EXIT_SUCCESS); } +#ifdef HAVE_ISULAD +int lxc_attach_run_command(void *payload, int msg_fd) +#else int lxc_attach_run_command(void *payload) +#endif { int ret = -1; lxc_attach_command_t *cmd = payload; @@ -1446,11 +1955,19 @@ int lxc_attach_run_command(void *payload) break; } } +#ifdef HAVE_ISULAD + /* isulad: write error messages */ + lxc_write_error_message(msg_fd, "exec: \"%s\": %s.", cmd->program, strerror(errno)); +#endif return log_error_errno(ret, errno, "Failed to exec \"%s\"", cmd->program); } +#ifdef HAVE_ISULAD +int lxc_attach_run_shell(void* payload, int msg_fd) +#else int lxc_attach_run_shell(void* payload) +#endif { __do_free char *buf = NULL; uid_t uid; diff --git a/src/lxc/lsm/nop.c b/src/lxc/lsm/nop.c index 5b345b9..188945d 100644 --- a/src/lxc/lsm/nop.c +++ b/src/lxc/lsm/nop.c @@ -24,11 +24,25 @@ static int nop_enabled(void) return 0; } +#ifdef HAVE_ISULAD +static int nop_file_label_set(const char *path, const char *label) { + return 0; +} + +static int nop_relabel(const char *path, const char *label, bool shared) { + return 0; +} +#endif + static struct lsm_drv nop_drv = { .name = "nop", .enabled = nop_enabled, .process_label_get = nop_process_label_get, .process_label_set = nop_process_label_set, +#ifdef HAVE_ISULAD + .file_label_set = nop_file_label_set, + .relabel = nop_relabel, +#endif }; struct lsm_drv *lsm_nop_drv_init(void) diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c index 7820db8..a6e6d42 100644 --- a/src/lxc/seccomp.c +++ b/src/lxc/seccomp.c @@ -351,8 +351,13 @@ int get_hostarch(void) return lxc_seccomp_arch_unknown; } +#ifdef HAVE_ISULAD +scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, + uint32_t default_policy_action, uint32_t *architectures) +#else scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, uint32_t default_policy_action, bool *needs_merge) +#endif { int ret; uint32_t arch; @@ -476,9 +481,17 @@ scmp_filter_ctx get_new_ctx(enum lxc_hostarch_t n_arch, } TRACE("Removed native arch from main seccomp context"); +#ifdef HAVE_ISULAD + *architectures = arch; +#else *needs_merge = true; +#endif } else { +#ifdef HAVE_ISULAD + *architectures = SCMP_ARCH_NATIVE; +#else *needs_merge = false; +#endif TRACE("Arch %d already present in main seccomp context", (int)n_arch); } @@ -510,7 +523,11 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx, if (ret < 0) { errno = -ret; SYSERROR("Failed loading rule to reject force umount"); +#ifdef HAVE_ISULAD + return true; +#else return false; +#endif } INFO("Set seccomp rule to reject force umounts"); @@ -519,24 +536,42 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx, nr = seccomp_syscall_resolve_name(line); if (nr == __NR_SCMP_ERROR) { +#ifdef HAVE_ISULAD + DEBUG("Failed to resolve syscall \"%s\"", line); + DEBUG("This syscall will NOT be handled by seccomp"); +#else WARN("Failed to resolve syscall \"%s\"", line); WARN("This syscall will NOT be handled by seccomp"); +#endif return true; } if (nr < 0) { +#ifdef HAVE_ISULAD + DEBUG("Got negative return value %d for syscall \"%s\"", nr, line); + DEBUG("This syscall will NOT be handled by seccomp"); +#else WARN("Got negative return value %d for syscall \"%s\"", nr, line); WARN("This syscall will NOT be handled by seccomp"); +#endif return true; } memset(&arg_cmp, 0, sizeof(arg_cmp)); for (i = 0; i < rule->args_num; i++) { +#ifdef HAVE_ISULAD + DEBUG("arg_cmp[%d]: SCMP_CMP(%u, %llu, %llu, %llu)", i, + rule->args_value[i].index, + (long long unsigned int)rule->args_value[i].op, + (long long unsigned int)rule->args_value[i].mask, + (long long unsigned int)rule->args_value[i].value); +#else INFO("arg_cmp[%d]: SCMP_CMP(%u, %llu, %llu, %llu)", i, rule->args_value[i].index, (long long unsigned int)rule->args_value[i].op, (long long unsigned int)rule->args_value[i].mask, (long long unsigned int)rule->args_value[i].value); +#endif if (SCMP_CMP_MASKED_EQ == rule->args_value[i].op) arg_cmp[i] = SCMP_CMP(rule->args_value[i].index, @@ -553,14 +588,43 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx, rule->args_num, arg_cmp); if (ret < 0) { errno = -ret; +#ifdef HAVE_ISULAD + DEBUG("Failed loading rule for %s (nr %d action %d (%s))", + line, nr, rule->action, get_action_name(rule->action)); + return true; +#else SYSERROR("Failed loading rule for %s (nr %d action %d (%s))", line, nr, rule->action, get_action_name(rule->action)); return false; +#endif } return true; } +#ifdef HAVE_ISULAD +#define SCMP_ARCH_INDEX_MAX 3 + +struct scmp_ctx_info { + uint32_t architectures[SCMP_ARCH_INDEX_MAX]; + enum lxc_hostarch_t lxc_arch[SCMP_ARCH_INDEX_MAX]; + scmp_filter_ctx contexts[SCMP_ARCH_INDEX_MAX]; + bool needs_merge[SCMP_ARCH_INDEX_MAX]; +}; + +static int get_arch_index(enum lxc_hostarch_t arch, struct scmp_ctx_info *ctx) +{ + int i; + + for (i = 0; i < SCMP_ARCH_INDEX_MAX; i++) { + if (ctx->lxc_arch[i] == arch) + return i; + } + + return -1; +} +#endif + /* * v2 consists of * [x86] @@ -575,6 +639,494 @@ bool do_resolve_add_rule(uint32_t arch, char *line, scmp_filter_ctx ctx, * write * close */ +#ifdef HAVE_ISULAD +static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_conf *conf) +{ + int ret; + char *p; + enum lxc_hostarch_t cur_rule_arch, native_arch; + bool blacklist = false; + uint32_t default_policy_action = -1, default_rule_action = -1; + struct seccomp_v2_rule rule; + struct scmp_ctx_info ctx; + + if (strncmp(line, "blacklist", 9) == 0) + blacklist = true; + else if (strncmp(line, "whitelist", 9) != 0) { + ERROR("Bad seccomp policy style \"%s\"", line); + return -1; + } + + p = strchr(line, ' '); + if (p) { + default_policy_action = get_v2_default_action(p + 1); + if (default_policy_action == -2) + return -1; + } + + /* for blacklist, allow any syscall which has no rule */ + if (blacklist) { + if (default_policy_action == -1) + default_policy_action = SCMP_ACT_ALLOW; + + if (default_rule_action == -1) + default_rule_action = SCMP_ACT_KILL; + } else { + if (default_policy_action == -1) + default_policy_action = SCMP_ACT_KILL; + + if (default_rule_action == -1) + default_rule_action = SCMP_ACT_ALLOW; + } + + memset(&ctx, 0, sizeof(ctx)); + ctx.architectures[0] = SCMP_ARCH_NATIVE; + ctx.architectures[1] = SCMP_ARCH_NATIVE; + ctx.architectures[2] = SCMP_ARCH_NATIVE; + native_arch = get_hostarch(); + cur_rule_arch = native_arch; + if (native_arch == lxc_seccomp_arch_amd64) { + cur_rule_arch = lxc_seccomp_arch_all; + + ctx.lxc_arch[0] = lxc_seccomp_arch_i386; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_i386, + default_policy_action, &ctx.architectures[0]); + if (!ctx.contexts[0]) + goto bad; + + ctx.lxc_arch[1] = lxc_seccomp_arch_x32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_x32, + default_policy_action, &ctx.architectures[1]); + if (!ctx.contexts[1]) + goto bad; + + ctx.lxc_arch[2] = lxc_seccomp_arch_amd64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_amd64, + default_policy_action, &ctx.architectures[2]); + if (!ctx.contexts[2]) + goto bad; +#ifdef SCMP_ARCH_PPC + } else if (native_arch == lxc_seccomp_arch_ppc64) { + cur_rule_arch = lxc_seccomp_arch_all; + + ctx.lxc_arch[0] = lxc_seccomp_arch_ppc; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_ppc, + default_policy_action, &ctx.architectures[0]); + if (!ctx.contexts[0]) + goto bad; + + ctx.lxc_arch[1] = lxc_seccomp_arch_ppc64; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_ppc64, + default_policy_action, &ctx.architectures[1]); + if (!ctx.contexts[1]) + goto bad; +#endif +#ifdef SCMP_ARCH_ARM + } else if (native_arch == lxc_seccomp_arch_arm64) { + cur_rule_arch = lxc_seccomp_arch_all; + + ctx.lxc_arch[0] = lxc_seccomp_arch_arm; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_arm, + default_policy_action, &ctx.architectures[0]); + if (!ctx.contexts[0]) + goto bad; + +#ifdef SCMP_ARCH_AARCH64 + ctx.lxc_arch[1] = lxc_seccomp_arch_arm64; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_arm64, + default_policy_action, &ctx.architectures[1]); + if (!ctx.contexts[1]) + goto bad; +#endif +#endif +#ifdef SCMP_ARCH_MIPS + } else if (native_arch == lxc_seccomp_arch_mips64) { + cur_rule_arch = lxc_seccomp_arch_all; + + ctx.lxc_arch[0] = lxc_seccomp_arch_mips; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_mips, + default_policy_action, &ctx.architectures[0]); + if (!ctx.contexts[0]) + goto bad; + + ctx.lxc_arch[1] = lxc_seccomp_arch_mips64n32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_mips64n32, + default_policy_action, &ctx.architectures[1]); + if (!ctx.contexts[1]) + goto bad; + + ctx.lxc_arch[2] = lxc_seccomp_arch_mips64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_mips64, + default_policy_action, &ctx.architectures[2]); + if (!ctx.contexts[2]) + goto bad; + } else if (native_arch == lxc_seccomp_arch_mipsel64) { + cur_rule_arch = lxc_seccomp_arch_all; + ctx.lxc_arch[0] = lxc_seccomp_arch_mipsel; + ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_mipsel, + default_policy_action, &ctx.architectures[0]); + if (!ctx.contexts[0]) + goto bad; + + ctx.lxc_arch[1] = lxc_seccomp_arch_mipsel64n32; + ctx.contexts[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32, + default_policy_action, &ctx.architectures[1]); + if (!ctx.contexts[1]) + goto bad; + + ctx.lxc_arch[2] = lxc_seccomp_arch_mipsel64; + ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_mipsel64, + default_policy_action, &ctx.architectures[2]); + if (!ctx.contexts[2]) + goto bad; +#endif + } + + if (default_policy_action != SCMP_ACT_KILL) { + ret = seccomp_reset(conf->seccomp.seccomp_ctx, default_policy_action); + if (ret != 0) { + ERROR("Error re-initializing Seccomp"); + return -1; + } + + ret = seccomp_attr_set(conf->seccomp.seccomp_ctx, SCMP_FLTATR_CTL_NNP, 0); + if (ret < 0) { + errno = -ret; + SYSERROR("Failed to turn off no-new-privs"); + return -1; + } + +#ifdef SCMP_FLTATR_ATL_TSKIP + ret = seccomp_attr_set(conf->seccomp.seccomp_ctx, SCMP_FLTATR_ATL_TSKIP, 1); + if (ret < 0) { + errno = -ret; + SYSWARN("Failed to turn on seccomp nop-skip, continuing"); + } +#endif + } + + while (getline(&line, line_bufsz, f) != -1) { + if (line[0] == '#') + continue; + + if (line[0] == '\0') + continue; + + remove_trailing_newlines(line); + + DEBUG("Processing \"%s\"", line); + + if (line[0] == '[') { + /* Read the architecture for next set of rules. */ + if (strcmp(line, "[x86]") == 0 || + strcmp(line, "[X86]") == 0) { + if (native_arch != lxc_seccomp_arch_i386 && + native_arch != lxc_seccomp_arch_amd64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_i386; + } else if (strcmp(line, "[x32]") == 0 || + strcmp(line, "[X32]") == 0) { + if (native_arch != lxc_seccomp_arch_amd64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_x32; + } else if (strcmp(line, "[X86_64]") == 0 || + strcmp(line, "[x86_64]") == 0) { + if (native_arch != lxc_seccomp_arch_amd64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_amd64; + } else if (strcmp(line, "[all]") == 0 || + strcmp(line, "[ALL]") == 0) { + cur_rule_arch = lxc_seccomp_arch_all; + } +#ifdef SCMP_ARCH_ARM + else if (strcmp(line, "[arm]") == 0 || + strcmp(line, "[ARM]") == 0) { + if (native_arch != lxc_seccomp_arch_arm && + native_arch != lxc_seccomp_arch_arm64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_arm; + } +#endif +#ifdef SCMP_ARCH_AARCH64 + else if (strcmp(line, "[arm64]") == 0 || + strcmp(line, "[ARM64]") == 0) { + if (native_arch != lxc_seccomp_arch_arm64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_arm64; + } +#endif +#ifdef SCMP_ARCH_PPC64LE + else if (strcmp(line, "[ppc64le]") == 0 || + strcmp(line, "[PPC64LE]") == 0) { + if (native_arch != lxc_seccomp_arch_ppc64le) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_ppc64le; + } +#endif +#ifdef SCMP_ARCH_PPC64 + else if (strcmp(line, "[ppc64]") == 0 || + strcmp(line, "[PPC64]") == 0) { + if (native_arch != lxc_seccomp_arch_ppc64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_ppc64; + } +#endif +#ifdef SCMP_ARCH_PPC + else if (strcmp(line, "[ppc]") == 0 || + strcmp(line, "[PPC]") == 0) { + if (native_arch != lxc_seccomp_arch_ppc && + native_arch != lxc_seccomp_arch_ppc64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_ppc; + } +#endif +#ifdef SCMP_ARCH_MIPS + else if (strcmp(line, "[mips64]") == 0 || + strcmp(line, "[MIPS64]") == 0) { + if (native_arch != lxc_seccomp_arch_mips64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_mips64; + } else if (strcmp(line, "[mips64n32]") == 0 || + strcmp(line, "[MIPS64N32]") == 0) { + if (native_arch != lxc_seccomp_arch_mips64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_mips64n32; + } else if (strcmp(line, "[mips]") == 0 || + strcmp(line, "[MIPS]") == 0) { + if (native_arch != lxc_seccomp_arch_mips && + native_arch != lxc_seccomp_arch_mips64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_mips; + } else if (strcmp(line, "[mipsel64]") == 0 || + strcmp(line, "[MIPSEL64]") == 0) { + if (native_arch != lxc_seccomp_arch_mipsel64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_mipsel64; + } else if (strcmp(line, "[mipsel64n32]") == 0 || + strcmp(line, "[MIPSEL64N32]") == 0) { + if (native_arch != lxc_seccomp_arch_mipsel64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_mipsel64n32; + } else if (strcmp(line, "[mipsel]") == 0 || + strcmp(line, "[MIPSEL]") == 0) { + if (native_arch != lxc_seccomp_arch_mipsel && + native_arch != lxc_seccomp_arch_mipsel64) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_mipsel; + } +#endif +#ifdef SCMP_ARCH_S390X + else if (strcmp(line, "[s390x]") == 0 || + strcmp(line, "[S390X]") == 0) { + if (native_arch != lxc_seccomp_arch_s390x) { + cur_rule_arch = lxc_seccomp_arch_unknown; + continue; + } + + cur_rule_arch = lxc_seccomp_arch_s390x; + } +#endif + else { + goto bad_arch; + } + + continue; + } + + /* irrelevant arch - i.e. arm on i386 */ + if (cur_rule_arch == lxc_seccomp_arch_unknown) + continue; + + memset(&rule, 0, sizeof(rule)); + /* read optional action which follows the syscall */ + ret = parse_v2_rules(line, default_rule_action, &rule); + if (ret != 0) { + ERROR("Failed to interpret seccomp rule"); + goto bad_rule; + } + + if (cur_rule_arch == native_arch) { + /* add for native arch */ + if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, + conf->seccomp.seccomp_ctx, &rule)) + goto bad_rule; + + DEBUG("Added native rule for arch %d for %s action %d(%s)", + SCMP_ARCH_NATIVE, line, rule.action, + get_action_name(rule.action)); + } else if (cur_rule_arch != lxc_seccomp_arch_all) { + /* add for compat specified arch */ + int arch_index = get_arch_index(cur_rule_arch, &ctx); + if (arch_index < 0) + goto bad_arch; + + if (!do_resolve_add_rule(ctx.architectures[arch_index], line, + ctx.contexts[arch_index], &rule)) + goto bad_rule; + + DEBUG("Added compat rule for arch %d for %s action %d(%s)", + ctx.architectures[arch_index], line, rule.action, + get_action_name(rule.action)); + ctx.needs_merge[arch_index] = true; + } else { + /* add for all compat archs */ + if (!do_resolve_add_rule(SCMP_ARCH_NATIVE, line, + conf->seccomp.seccomp_ctx, &rule)) + goto bad_rule; + + DEBUG("Added native rule for arch %d for %s action %d(%s)", + SCMP_ARCH_NATIVE, line, rule.action, + get_action_name(rule.action)); + + if (ctx.architectures[0] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(ctx.architectures[0], line, + ctx.contexts[0], &rule)) + goto bad_rule; + + DEBUG("Added compat rule for arch %d for %s action %d(%s)", + ctx.architectures[0], line, rule.action, + get_action_name(rule.action)); + ctx.needs_merge[0] = true; + } + + if (ctx.architectures[1] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(ctx.architectures[1], line, + ctx.contexts[1], &rule)) + goto bad_rule; + + DEBUG("Added compat rule for arch %d for %s action %d(%s)", + ctx.architectures[1], line, rule.action, + get_action_name(rule.action)); + ctx.needs_merge[1] = true; + } + + if (ctx.architectures[2] != SCMP_ARCH_NATIVE) { + if (!do_resolve_add_rule(ctx.architectures[2], line, + ctx.contexts[2], &rule)) + goto bad_rule; + + DEBUG("Added native rule for arch %d for %s action %d(%s)", + ctx.architectures[2], line, rule.action, + get_action_name(rule.action)); + ctx.needs_merge[2] = true; + } + } + + } + + INFO("Merging compat seccomp contexts into main context"); + if (ctx.contexts[0]) { + if (ctx.needs_merge[0]) { + ret = seccomp_merge(conf->seccomp.seccomp_ctx, ctx.contexts[0]); + if (ret < 0) { + ERROR("%s - Failed to merge first compat seccomp " + "context into main context", strerror(-ret)); + goto bad; + } + + TRACE("Merged first compat seccomp context into main context"); + } else { + seccomp_release(ctx.contexts[0]); + ctx.contexts[0] = NULL; + } + } + + if (ctx.contexts[1]) { + if (ctx.needs_merge[1]) { + ret = seccomp_merge(conf->seccomp.seccomp_ctx, ctx.contexts[1]); + if (ret < 0) { + ERROR("%s - Failed to merge second compat seccomp " + "context into main context", strerror(-ret)); + goto bad; + } + + TRACE("Merged second compat seccomp context into main context"); + } else { + seccomp_release(ctx.contexts[1]); + ctx.contexts[1] = NULL; + } + } + + if (ctx.contexts[2]) { + if (ctx.needs_merge[2]) { + ret = seccomp_merge(conf->seccomp.seccomp_ctx, ctx.contexts[2]); + if (ret < 0) { + ERROR("%s - Failed to merge third compat seccomp " + "context into main context", strerror(-ret)); + goto bad; + } + + TRACE("Merged third compat seccomp context into main context"); + } else { + seccomp_release(ctx.contexts[2]); + ctx.contexts[2] = NULL; + } + } + + free(line); + return 0; + +bad_arch: + ERROR("Unsupported architecture \"%s\"", line); + +bad_rule: +bad: + if (ctx.contexts[0]) + seccomp_release(ctx.contexts[0]); + + if (ctx.contexts[1]) + seccomp_release(ctx.contexts[1]); + + if (ctx.contexts[2]) + seccomp_release(ctx.contexts[2]); + + free(line); + + return -1; +} +#else static int parse_config_v2(FILE *f, char *line, size_t *line_bufsz, struct lxc_conf *conf) { int ret; @@ -1067,6 +1619,7 @@ bad: return -1; } +#endif #else /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf) { @@ -1288,6 +1841,7 @@ void lxc_seccomp_free(struct lxc_seccomp *seccomp) seccomp_notify_free(seccomp->notifier.req_buf, seccomp->notifier.rsp_buf); seccomp->notifier.req_buf = NULL; seccomp->notifier.rsp_buf = NULL; + free_disarm(seccomp->notifier.cookie); #endif } @@ -1498,6 +2052,7 @@ void seccomp_conf_init(struct lxc_conf *conf) sizeof(conf->seccomp.notifier.proxy_addr)); conf->seccomp.notifier.req_buf = NULL; conf->seccomp.notifier.rsp_buf = NULL; + conf->seccomp.notifier.cookie = NULL; #endif } diff --git a/src/lxc/storage/zfs.c b/src/lxc/storage/zfs.c index ee9e32d..903937a 100644 --- a/src/lxc/storage/zfs.c +++ b/src/lxc/storage/zfs.c @@ -167,13 +167,22 @@ int zfs_mount(struct lxc_storage *bdev) const char *src; char cmd_output[PATH_MAX] = {0}; +#ifdef HAVE_ISULAD + unsigned long pflags = 0; +#endif + if (strcmp(bdev->type, "zfs")) return -22; if (!bdev->src || !bdev->dest) return -22; +#ifdef HAVE_ISULAD + ret = parse_mntopts(bdev->mntopts, &mntflags, &pflags, &mntdata); +#else ret = parse_mntopts(bdev->mntopts, &mntflags, &mntdata); +#endif + if (ret < 0) { ERROR("Failed to parse mount options"); return -22; -- 2.25.1