diff --git a/tests/host_tools/test_syscalls.c b/tests/host_tools/test_syscalls.c new file mode 100644 index 00000000000..6a58edf0983 --- /dev/null +++ b/tests/host_tools/test_syscalls.c @@ -0,0 +1,77 @@ +// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +// This is used by `test_seccomp_validate.py` + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +void install_bpf_filter(char *bpf_file) { + int fd = open(bpf_file, O_RDONLY); + if (fd == -1) { + perror("open"); + exit(EXIT_FAILURE); + } + struct stat sb; + if (fstat(fd, &sb) == -1) { + perror("stat"); + exit(EXIT_FAILURE); + } + size_t size = sb.st_size; + size_t insn_len = size / sizeof(struct sock_filter); + struct sock_filter *filterbuf = (struct sock_filter*)malloc(size); + if (read(fd, filterbuf, size) == -1) { + perror("read"); + exit(EXIT_FAILURE); + } + + /* Install seccomp filter */ + struct sock_fprog prog = { + .len = (unsigned short)(insn_len), + .filter = filterbuf, + }; + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + perror("prctl(NO_NEW_PRIVS)"); + exit(EXIT_FAILURE); + } + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { + perror("prctl(SECCOMP)"); + exit(EXIT_FAILURE); + } +} + + +int main(int argc, char **argv) { + /* parse arguments */ + if (argc < 3) { + fprintf(stderr, "Usage: %s BPF_FILE ARG0..\n", argv[0]); + exit(EXIT_FAILURE); + } + char *bpf_file = argv[1]; + long syscall_id = atoi(argv[2]); + long arg0, arg1, arg2, arg3; + arg0 = arg1 = arg2 = arg3 = 0; + if (argc > 3) arg0 = atoi(argv[3]); + if (argc > 4) arg1 = atoi(argv[4]); + if (argc > 5) arg2 = atoi(argv[5]); + if (argc > 6) arg3 = atoi(argv[6]); + + /* read seccomp filter from file */ + if (strcmp(bpf_file, "/dev/null") != 0) { + install_bpf_filter(bpf_file); + } + + long res = syscall(syscall_id, arg0, arg1, arg2, arg3); + printf("%ld\n", res); + return EXIT_SUCCESS; +} diff --git a/tests/integration_tests/security/test_seccomp_validate.py b/tests/integration_tests/security/test_seccomp_validate.py new file mode 100644 index 00000000000..ea27caa01ba --- /dev/null +++ b/tests/integration_tests/security/test_seccomp_validate.py @@ -0,0 +1,134 @@ +# Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Test that validates that seccompiler filters work as expected""" + +import json +import platform +import struct +from pathlib import Path + +import pytest +import seccomp + +from framework import utils +from host_tools import cargo_build + +ARCH = platform.machine() + + +@pytest.fixture(scope="session") +def bin_test_syscall(test_fc_session_root_path): + """Build a simple vsock client/server application.""" + test_syscall_bin = Path(test_fc_session_root_path) / "test_syscall" + cargo_build.gcc_compile("host_tools/test_syscalls.c", test_syscall_bin) + assert test_syscall_bin.exists() + yield test_syscall_bin + + +class BpfMapReader: + """ + Simple reader for the files that seccompiler-bin produces + + The files are serialized with bincode[1] in format that is easy to parse. + + sock_filter = + BpfProgram = Vec + BpfMap = BTreeMap(str, BpfProgram) + str = Vec + + [1] https://github.com/bincode-org/bincode/blob/trunk/docs/spec.md + """ + + INSN_FMT = "