X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fexecute.c;h=d2e5b740b7f4e282c3331fd1371700edd1a11ddc;hb=c0467cf387548dc98c0254f63553d862b35a84e5;hp=4317afad8ad0531fcb6d373e5c6078e574a0d6f1;hpb=5ce70e5bcd62e89b52485961c3699312ee4a7e0e;p=elogind.git diff --git a/src/core/execute.c b/src/core/execute.c index 4317afad8..d2e5b740b 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -38,15 +38,23 @@ #include #include #include -#include #include #include +#ifdef HAVE_SECCOMP +#include + +#include "set.h" +#endif #undef basename #ifdef HAVE_PAM #include #endif +#ifdef HAVE_SELINUX +#include +#endif + #include "execute.h" #include "strv.h" #include "macro.h" @@ -63,11 +71,11 @@ #include "utmp-wtmp.h" #include "def.h" #include "path-util.h" -#include "syscall-list.h" #include "env-util.h" #include "fileio.h" #include "unit.h" #include "async.h" +#include "selinux-util.h" #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC) #define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC) @@ -928,57 +936,32 @@ static void rename_process_from_path(const char *path) { rename_process(process_name); } -static int apply_seccomp(uint32_t *syscall_filter) { - static const struct sock_filter header[] = { - VALIDATE_ARCHITECTURE, - EXAMINE_SYSCALL - }; - static const struct sock_filter footer[] = { - _KILL_PROCESS - }; - - int i; - unsigned n; - struct sock_filter *f; - struct sock_fprog prog = {}; - - assert(syscall_filter); +#ifdef HAVE_SECCOMP +static int apply_seccomp(ExecContext *c) { + uint32_t action = SCMP_ACT_ALLOW; + Iterator i; + void *id; - /* First: count the syscalls to check for */ - for (i = 0, n = 0; i < syscall_max(); i++) - if (syscall_filter[i >> 4] & (1 << (i & 31))) - n++; - - /* Second: build the filter program from a header the syscall - * matches and the footer */ - f = alloca(sizeof(struct sock_filter) * (ELEMENTSOF(header) + 2*n + ELEMENTSOF(footer))); - memcpy(f, header, sizeof(header)); - - for (i = 0, n = 0; i < syscall_max(); i++) - if (syscall_filter[i >> 4] & (1 << (i & 31))) { - struct sock_filter item[] = { - BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, INDEX_TO_SYSCALL(i), 0, 1), - BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) - }; + assert(c); - assert_cc(ELEMENTSOF(item) == 2); + c->syscall_filter = seccomp_init(c->syscall_filter_default_action); + if (!c->syscall_filter) + return -1; - f[ELEMENTSOF(header) + 2*n] = item[0]; - f[ELEMENTSOF(header) + 2*n+1] = item[1]; + if (c->syscall_filter_default_action == SCMP_ACT_ALLOW) + action = SCMP_ACT_KILL; - n++; + SET_FOREACH(id, c->filtered_syscalls, i) { + int r = seccomp_rule_add(c->syscall_filter, action, PTR_TO_INT(id) - 1, 0); + if (r < 0) { + log_error("Failed to add syscall filter"); + return r; } + } - memcpy(f + (ELEMENTSOF(header) + 2*n), footer, sizeof(footer)); - - /* Third: install the filter */ - prog.len = ELEMENTSOF(header) + ELEMENTSOF(footer) + 2*n; - prog.filter = f; - if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) - return -errno; - - return 0; + return seccomp_load(c->syscall_filter); } +#endif static void do_idle_pipe_dance(int idle_pipe[4]) { assert(idle_pipe); @@ -1427,7 +1410,8 @@ int exec_spawn(ExecCommand *command, !strv_isempty(context->read_only_dirs) || !strv_isempty(context->inaccessible_dirs) || context->mount_flags != 0 || - (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir))) { + (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir)) || + context->private_devices) { char *tmp = NULL, *var = NULL; @@ -1450,6 +1434,7 @@ int exec_spawn(ExecCommand *command, context->inaccessible_dirs, tmp, var, + context->private_devices, context->mount_flags); if (err < 0) { @@ -1555,13 +1540,34 @@ int exec_spawn(ExecCommand *command, goto fail_child; } - if (context->syscall_filter) { - err = apply_seccomp(context->syscall_filter); +#ifdef HAVE_SECCOMP + if (context->filtered_syscalls) { + err = apply_seccomp(context); if (err < 0) { r = EXIT_SECCOMP; goto fail_child; } } +#endif +#ifdef HAVE_SELINUX + if (context->selinux_context && use_selinux()) { + bool ignore; + char* c; + + c = context->selinux_context; + if (c[0] == '-') { + c++; + ignore = true; + } else + ignore = false; + + err = setexeccon(c); + if (err < 0 && !ignore) { + r = EXIT_SELINUX_CONTEXT; + goto fail_child; + } + } +#endif } err = build_environment(context, n_fds, watchdog_usec, home, username, shell, &our_env); @@ -1720,8 +1726,23 @@ void exec_context_done(ExecContext *c) { free(c->utmp_id); c->utmp_id = NULL; + free(c->selinux_context); + c->selinux_context = NULL; + free(c->syscall_filter); c->syscall_filter = NULL; + + free(c->syscall_filter_string); + c->syscall_filter_string = NULL; + +#ifdef HAVE_SECCOMP + if (c->syscall_filter) { + seccomp_release(c->syscall_filter); + c->syscall_filter = NULL; + } + set_free(c->filtered_syscalls); + c->filtered_syscalls = NULL; +#endif } void exec_command_done(ExecCommand *c) { @@ -1896,6 +1917,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { "%sNonBlocking: %s\n" "%sPrivateTmp: %s\n" "%sPrivateNetwork: %s\n" + "%sPrivateDevices: %s\n" "%sIgnoreSIGPIPE: %s\n", prefix, c->umask, prefix, c->working_directory ? c->working_directory : "/", @@ -1903,6 +1925,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { prefix, yes_no(c->non_blocking), prefix, yes_no(c->private_tmp), prefix, yes_no(c->private_network), + prefix, yes_no(c->private_devices), prefix, yes_no(c->ignore_sigpipe)); STRV_FOREACH(e, c->environment) @@ -2087,6 +2110,11 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { fprintf(f, "%sUtmpIdentifier: %s\n", prefix, c->utmp_id); + + if (c->selinux_context) + fprintf(f, + "%sSELinuxContext: %s\n", + prefix, c->selinux_context); } void exec_status_start(ExecStatus *s, pid_t pid) {