Merge pull request #20777 from benzea/benzea/fix-seccomp-filter

seccomp: Always install filters for native architecture
This commit is contained in:
Yu Watanabe 2021-10-01 15:12:55 +09:00 committed by GitHub
commit 1924f26d2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 100 additions and 9 deletions

View file

@ -1789,6 +1789,10 @@ int seccomp_restrict_archs(Set *archs) {
for (unsigned i = 0; seccomp_local_archs[i] != SECCOMP_LOCAL_ARCH_END; ++i) {
uint32_t arch = seccomp_local_archs[i];
/* See above comment, our "native" architecture is never blocked. */
if (arch == seccomp_arch_native())
continue;
/* That architecture might have already been blocked by a previous call to seccomp_restrict_archs. */
if (arch == SECCOMP_LOCAL_ARCH_BLOCKED)
continue;

View file

@ -713,8 +713,10 @@ static void test_exec_systemcallfilter(Manager *m) {
test(m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED);
test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
test(m, "exec-systemcallfilter-not-failing3.service", 0, CLD_EXITED);
test(m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED);
test(m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED);
test(m, "exec-systemcallfilter-failing3.service", SIGSYS, CLD_KILLED);
r = find_executable("python3", NULL);
if (r < 0) {

View file

@ -890,6 +890,66 @@ static void test_load_syscall_filter_set_raw(void) {
assert_se(wait_for_terminate_and_check("syscallrawseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_native_syscalls_filtered(void) {
pid_t pid;
log_info("/* %s */", __func__);
if (!is_seccomp_available()) {
log_notice("Seccomp not available, skipping %s", __func__);
return;
}
if (!have_seccomp_privs()) {
log_notice("Not privileged, skipping %s", __func__);
return;
}
pid = fork();
assert_se(pid >= 0);
if (pid == 0) {
_cleanup_set_free_ Set *arch_s = NULL;
_cleanup_hashmap_free_ Hashmap *s = NULL;
/* Passing "native" or an empty set is equivalent, just do both here. */
assert_se(arch_s = set_new(NULL));
assert_se(seccomp_restrict_archs(arch_s) >= 0);
assert_se(set_put(arch_s, SCMP_ARCH_NATIVE) >= 0);
assert_se(seccomp_restrict_archs(arch_s) >= 0);
assert_se(access("/", F_OK) >= 0);
assert_se(poll(NULL, 0, 0) == 0);
assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, scmp_act_kill_process(), true) >= 0);
assert_se(access("/", F_OK) >= 0);
assert_se(poll(NULL, 0, 0) == 0);
assert_se(s = hashmap_new(NULL));
#if defined __NR_access && __NR_access >= 0
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(-1)) >= 0);
log_debug("has access()");
#endif
#if defined __NR_faccessat && __NR_faccessat >= 0
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0);
log_debug("has faccessat()");
#endif
#if defined __NR_faccessat2 && __NR_faccessat2 >= 0
assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat2 + 1), INT_TO_PTR(-1)) >= 0);
log_debug("has faccessat2()");
#endif
assert_se(!hashmap_isempty(s));
assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN), true) >= 0);
assert_se(access("/", F_OK) < 0);
assert_se(errno == EUCLEAN);
_exit(EXIT_SUCCESS);
}
assert_se(wait_for_terminate_and_check("nativeseccomp", pid, WAIT_LOG) == EXIT_SUCCESS);
}
static void test_lock_personality(void) {
unsigned long current;
pid_t pid;
@ -1171,6 +1231,7 @@ int main(int argc, char *argv[]) {
test_memory_deny_write_execute_shmat();
test_restrict_archs();
test_load_syscall_filter_set_raw();
test_native_syscalls_filtered();
test_lock_personality();
test_restrict_suid_sgid();

View file

@ -0,0 +1,9 @@
[Unit]
Description=Test for SystemCallFilter
[Service]
ExecStart=/bin/sh -c '/bin/echo "This should not be seen"'
Type=oneshot
LimitCORE=0
SystemCallArchitectures=native
SystemCallFilter=~write open execve fexecve execveat exit_group close mmap munmap fstat DONOTEXIST

View file

@ -0,0 +1,8 @@
[Unit]
Description=Test for SystemCallFilter
[Service]
ExecStart=/bin/sh -c 'echo "Foo bar"'
Type=oneshot
SystemCallArchitectures=native
SystemCallFilter=

View file

@ -4,6 +4,13 @@
set -eux
set -o pipefail
ARGS=()
if [[ -v ASAN_OPTIONS || -v UBSAN_OPTIONS ]]; then
# If we're running under sanitizers, we need to use a less restrictive
# profile, otherwise LSan syscall would get blocked by seccomp
ARGS+=(--profile=trusted)
fi
export SYSTEMD_LOG_LEVEL=debug
mkdir -p /run/systemd/system/systemd-portabled.service.d/
cat <<EOF >/run/systemd/system/systemd-portabled.service.d/override.conf
@ -11,7 +18,7 @@ cat <<EOF >/run/systemd/system/systemd-portabled.service.d/override.conf
Environment=SYSTEMD_LOG_LEVEL=debug
EOF
portablectl attach --now --runtime /usr/share/minimal_0.raw app0
portablectl "${ARGS[@]}" attach --now --runtime /usr/share/minimal_0.raw app0
systemctl is-active app0.service
systemctl is-active app0-foo.service
@ -21,7 +28,7 @@ systemctl is-active app0-bar.service && exit 1
set -e
set -o pipefail
portablectl reattach --now --runtime /usr/share/minimal_1.raw app0
portablectl "${ARGS[@]}" reattach --now --runtime /usr/share/minimal_1.raw app0
systemctl is-active app0.service
systemctl is-active app0-bar.service
@ -42,7 +49,7 @@ portablectl list | grep -q -F "No images."
unsquashfs -dest /tmp/minimal_0 /usr/share/minimal_0.raw
unsquashfs -dest /tmp/minimal_1 /usr/share/minimal_1.raw
portablectl attach --copy=symlink --now --runtime /tmp/minimal_0 app0
portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime /tmp/minimal_0 app0
systemctl is-active app0.service
systemctl is-active app0-foo.service
@ -52,7 +59,7 @@ systemctl is-active app0-bar.service && exit 1
set -e
set -o pipefail
portablectl reattach --now --enable --runtime /tmp/minimal_1 app0
portablectl "${ARGS[@]}" reattach --now --enable --runtime /tmp/minimal_1 app0
systemctl is-active app0.service
systemctl is-active app0-bar.service
@ -68,21 +75,21 @@ portablectl detach --now --enable --runtime /tmp/minimal_1 app0
portablectl list | grep -q -F "No images."
portablectl attach --now --runtime --extension /usr/share/app0.raw /usr/share/minimal_0.raw app0
portablectl "${ARGS[@]}" attach --now --runtime --extension /usr/share/app0.raw /usr/share/minimal_0.raw app0
systemctl is-active app0.service
portablectl reattach --now --runtime --extension /usr/share/app0.raw /usr/share/minimal_1.raw app0
portablectl "${ARGS[@]}" reattach --now --runtime --extension /usr/share/app0.raw /usr/share/minimal_1.raw app0
systemctl is-active app0.service
portablectl detach --now --runtime --extension /usr/share/app0.raw /usr/share/minimal_1.raw app0
portablectl attach --now --runtime --extension /usr/share/app1.raw /usr/share/minimal_0.raw app1
portablectl "${ARGS[@]}" attach --now --runtime --extension /usr/share/app1.raw /usr/share/minimal_0.raw app1
systemctl is-active app1.service
portablectl reattach --now --runtime --extension /usr/share/app1.raw /usr/share/minimal_1.raw app1
portablectl "${ARGS[@]}" reattach --now --runtime --extension /usr/share/app1.raw /usr/share/minimal_1.raw app1
systemctl is-active app1.service
@ -95,7 +102,7 @@ mount /usr/share/app1.raw /tmp/app1
mount /usr/share/minimal_0.raw /tmp/rootdir
mount -t overlay overlay -o lowerdir=/tmp/app1:/tmp/rootdir /tmp/overlay
portablectl attach --copy=symlink --now --runtime /tmp/overlay app1
portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime /tmp/overlay app1
systemctl is-active app1.service