|
38 | 38 | #include <linux/fs.h> |
39 | 39 | #include <linux/oom.h> |
40 | 40 | #include <sys/poll.h> |
| 41 | +#include <linux/seccomp-bpf.h> |
41 | 42 |
|
42 | 43 | #ifdef HAVE_PAM |
43 | 44 | #include <security/pam_appl.h> |
|
60 | 61 | #include "def.h" |
61 | 62 | #include "loopback-setup.h" |
62 | 63 | #include "path-util.h" |
| 64 | +#include "syscall-list.h" |
63 | 65 |
|
64 | 66 | #define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC) |
65 | 67 |
|
@@ -924,6 +926,59 @@ static void rename_process_from_path(const char *path) { |
924 | 926 | rename_process(process_name); |
925 | 927 | } |
926 | 928 |
|
| 929 | +static int apply_seccomp(uint32_t *syscall_filter) { |
| 930 | + static const struct sock_filter header[] = { |
| 931 | + VALIDATE_ARCHITECTURE, |
| 932 | + EXAMINE_SYSCALL |
| 933 | + }; |
| 934 | + static const struct sock_filter footer[] = { |
| 935 | + _KILL_PROCESS |
| 936 | + }; |
| 937 | + |
| 938 | + int i; |
| 939 | + unsigned n; |
| 940 | + struct sock_filter *f; |
| 941 | + struct sock_fprog prog; |
| 942 | + |
| 943 | + assert(syscall_filter); |
| 944 | + |
| 945 | + /* First: count the syscalls to check for */ |
| 946 | + for (i = 0, n = 0; i < syscall_max(); i++) |
| 947 | + if (syscall_filter[i >> 4] & (1 << (i & 31))) |
| 948 | + n++; |
| 949 | + |
| 950 | + /* Second: build the filter program from a header the syscall |
| 951 | + * matches and the footer */ |
| 952 | + f = alloca(sizeof(struct sock_filter) * (ELEMENTSOF(header) + 2*n + ELEMENTSOF(footer))); |
| 953 | + memcpy(f, header, sizeof(header)); |
| 954 | + |
| 955 | + for (i = 0, n = 0; i < syscall_max(); i++) |
| 956 | + if (syscall_filter[i >> 4] & (1 << (i & 31))) { |
| 957 | + struct sock_filter item[] = { |
| 958 | + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, i, 0, 1), |
| 959 | + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) |
| 960 | + }; |
| 961 | + |
| 962 | + assert_cc(ELEMENTSOF(item) == 2); |
| 963 | + |
| 964 | + f[ELEMENTSOF(header) + 2*n] = item[0]; |
| 965 | + f[ELEMENTSOF(header) + 2*n+1] = item[1]; |
| 966 | + |
| 967 | + n++; |
| 968 | + } |
| 969 | + |
| 970 | + memcpy(f + (ELEMENTSOF(header) + 2*n), footer, sizeof(footer)); |
| 971 | + |
| 972 | + /* Third: install the filter */ |
| 973 | + zero(prog); |
| 974 | + prog.len = ELEMENTSOF(header) + ELEMENTSOF(footer) + 2*n; |
| 975 | + prog.filter = f; |
| 976 | + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) |
| 977 | + return -errno; |
| 978 | + |
| 979 | + return 0; |
| 980 | +} |
| 981 | + |
927 | 982 | int exec_spawn(ExecCommand *command, |
928 | 983 | char **argv, |
929 | 984 | const ExecContext *context, |
@@ -1355,6 +1410,21 @@ int exec_spawn(ExecCommand *command, |
1355 | 1410 | r = EXIT_CAPABILITIES; |
1356 | 1411 | goto fail_child; |
1357 | 1412 | } |
| 1413 | + |
| 1414 | + if (context->no_new_privileges) |
| 1415 | + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { |
| 1416 | + err = -errno; |
| 1417 | + r = EXIT_NO_NEW_PRIVILEGES; |
| 1418 | + goto fail_child; |
| 1419 | + } |
| 1420 | + |
| 1421 | + if (context->syscall_filter) { |
| 1422 | + err = apply_seccomp(context->syscall_filter); |
| 1423 | + if (err < 0) { |
| 1424 | + r = EXIT_SECCOMP; |
| 1425 | + goto fail_child; |
| 1426 | + } |
| 1427 | + } |
1358 | 1428 | } |
1359 | 1429 |
|
1360 | 1430 | if (!(our_env = new0(char*, 7))) { |
|
0 commit comments