1518 lines
43 KiB
Diff
1518 lines
43 KiB
Diff
From ad33756d6190df4f1aad9b6468b0b59086e916b5 Mon Sep 17 00:00:00 2001
|
|
From: zhangxiaoyu <zhangxiaoyu58@huawei.com>
|
|
Date: Tue, 19 Jul 2022 15:23:34 +0800
|
|
Subject: [PATCH] refactor patch code of attach and seccomp
|
|
|
|
Signed-off-by: zhangxiaoyu <zhangxiaoyu58@huawei.com>
|
|
---
|
|
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 <sys/personality.h>
|
|
#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
|
|
|