From 86f5b73dda5b20a51af32ab5f951e5472edb40b8 Mon Sep 17 00:00:00 2001 From: Manabu Sugimoto Date: Mon, 3 Jan 2022 16:18:01 +0900 Subject: [PATCH] tests: Add tests for Rust bindings Add the regression tests (1-60) for the libseccomp crate that is Rust language bindings for the libseccomp library. You can run the tests as follows: ```sh $ sed -i "/^AC_INIT/ s/0.0.0/9.9.9/" configure.ac $ ./autogen.sh $ ./configure --prefix=$(pwd)/src/.libs --enable-rust $ make && make install $ make check-build $ cd tests && ./regression -m rust ``` Based on: #323 Signed-off-by: Manabu Sugimoto Signed-off-by: mayank --- .github/actions/setup/action.yml | 4 + .github/workflows/continuous-integration.yml | 15 +- Makefile.am | 4 +- configure.ac | 30 ++ tests/.gitignore | 4 + tests/Makefile.am | 34 ++ tests/regression | 24 +- tests/rust/01-sim-allow.rs | 17 + tests/rust/02-sim-basic.rs | 22 ++ tests/rust/03-sim-basic_chains.rs | 37 +++ tests/rust/04-sim-multilevel_chains.rs | 51 +++ tests/rust/05-sim-long_jumps.rs | 52 ++++ tests/rust/06-sim-actions.rs | 29 ++ tests/rust/07-sim-db_bug_looping.rs | 37 +++ tests/rust/08-sim-subtree_checks.rs | 160 ++++++++++ tests/rust/09-sim-syscall_priority_pre.rs | 35 +++ tests/rust/10-sim-syscall_priority_post.rs | 35 +++ tests/rust/11-basic-basic_errors.rs | 83 +++++ tests/rust/12-sim-basic_masked_ops.rs | 65 ++++ tests/rust/13-basic-attrs.rs | 69 ++++ tests/rust/14-sim-reset.rs | 21 ++ tests/rust/15-basic-resolver.rs | 85 +++++ tests/rust/16-sim-arch_basic.rs | 85 +++++ tests/rust/17-sim-arch_merge.rs | 53 ++++ tests/rust/18-sim-basic_allowlist.rs | 37 +++ tests/rust/19-sim-missing_syscalls.rs | 27 ++ tests/rust/20-live-basic_die.rs | 40 +++ tests/rust/21-live-basic_allow.rs | 43 +++ tests/rust/22-sim-basic_chains_array.rs | 37 +++ tests/rust/23-sim-arch_all_le_basic.rs | 52 ++++ tests/rust/24-live-arg_allow.rs | 55 ++++ tests/rust/25-sim-multilevel_chains_adv.rs | 32 ++ tests/rust/26-sim-arch_all_be_basic.rs | 51 +++ tests/rust/27-sim-bpf_blk_state.rs | 83 +++++ tests/rust/28-sim-arch_x86.rs | 23 ++ tests/rust/29-sim-pseudo_syscall.rs | 32 ++ tests/rust/30-sim-socket_syscalls.rs | 47 +++ tests/rust/31-basic-version_check.rs | 15 + tests/rust/32-live-tsync_allow.rs | 44 +++ tests/rust/33-sim-socket_syscalls_be.rs | 29 ++ tests/rust/34-sim-basic_denylist.rs | 40 +++ tests/rust/35-sim-negative_one.rs | 26 ++ tests/rust/36-sim-ipc_syscalls.rs | 40 +++ tests/rust/37-sim-ipc_syscalls_be.rs | 36 +++ tests/rust/38-basic-pfc_coverage.rs | 65 ++++ tests/rust/39-basic-api_level.rs | 54 ++++ tests/rust/40-sim-log.rs | 19 ++ tests/rust/41-sim-syscall_priority_arch.rs | 23 ++ tests/rust/42-sim-adv_chains.rs | 181 +++++++++++ tests/rust/43-sim-a2_order.rs | 115 +++++++ tests/rust/44-live-a2_order.rs | 125 ++++++++ tests/rust/45-sim-chain_code_coverage.rs | 74 +++++ tests/rust/46-sim-kill_process.rs | 31 ++ tests/rust/47-live-kill_process.rs | 51 +++ tests/rust/48-sim-32b_args.rs | 46 +++ tests/rust/49-sim-64b_comparisons.rs | 23 ++ tests/rust/50-sim-hash_collision.rs | 46 +++ tests/rust/51-live-user_notification.rs | 47 +++ tests/rust/52-basic-load.rs | 32 ++ tests/rust/53-sim-binary_tree.rs | 109 +++++++ tests/rust/54-live-binary_tree.rs | 87 ++++++ tests/rust/55-basic-pfc_binary_tree.rs | 93 ++++++ tests/rust/56-basic-iterate_syscalls.rs | 67 ++++ tests/rust/57-basic-rawsysrc.rs | 29 ++ tests/rust/58-live-tsync_notify.rs | 40 +++ tests/rust/59-basic-empty_binary_tree.rs | 19 ++ tests/rust/60-sim-precompute.rs | 23 ++ tests/rust/Cargo.lock | 311 +++++++++++++++++++ tests/rust/Cargo.toml | 257 +++++++++++++++ tests/rust/utils.rs | 113 +++++++ 70 files changed, 3914 insertions(+), 6 deletions(-) create mode 100644 tests/rust/01-sim-allow.rs create mode 100644 tests/rust/02-sim-basic.rs create mode 100644 tests/rust/03-sim-basic_chains.rs create mode 100644 tests/rust/04-sim-multilevel_chains.rs create mode 100644 tests/rust/05-sim-long_jumps.rs create mode 100644 tests/rust/06-sim-actions.rs create mode 100644 tests/rust/07-sim-db_bug_looping.rs create mode 100644 tests/rust/08-sim-subtree_checks.rs create mode 100644 tests/rust/09-sim-syscall_priority_pre.rs create mode 100644 tests/rust/10-sim-syscall_priority_post.rs create mode 100644 tests/rust/11-basic-basic_errors.rs create mode 100644 tests/rust/12-sim-basic_masked_ops.rs create mode 100644 tests/rust/13-basic-attrs.rs create mode 100644 tests/rust/14-sim-reset.rs create mode 100644 tests/rust/15-basic-resolver.rs create mode 100644 tests/rust/16-sim-arch_basic.rs create mode 100644 tests/rust/17-sim-arch_merge.rs create mode 100644 tests/rust/18-sim-basic_allowlist.rs create mode 100644 tests/rust/19-sim-missing_syscalls.rs create mode 100644 tests/rust/20-live-basic_die.rs create mode 100644 tests/rust/21-live-basic_allow.rs create mode 100644 tests/rust/22-sim-basic_chains_array.rs create mode 100644 tests/rust/23-sim-arch_all_le_basic.rs create mode 100644 tests/rust/24-live-arg_allow.rs create mode 100644 tests/rust/25-sim-multilevel_chains_adv.rs create mode 100644 tests/rust/26-sim-arch_all_be_basic.rs create mode 100644 tests/rust/27-sim-bpf_blk_state.rs create mode 100644 tests/rust/28-sim-arch_x86.rs create mode 100644 tests/rust/29-sim-pseudo_syscall.rs create mode 100644 tests/rust/30-sim-socket_syscalls.rs create mode 100644 tests/rust/31-basic-version_check.rs create mode 100644 tests/rust/32-live-tsync_allow.rs create mode 100644 tests/rust/33-sim-socket_syscalls_be.rs create mode 100644 tests/rust/34-sim-basic_denylist.rs create mode 100644 tests/rust/35-sim-negative_one.rs create mode 100644 tests/rust/36-sim-ipc_syscalls.rs create mode 100644 tests/rust/37-sim-ipc_syscalls_be.rs create mode 100644 tests/rust/38-basic-pfc_coverage.rs create mode 100644 tests/rust/39-basic-api_level.rs create mode 100644 tests/rust/40-sim-log.rs create mode 100644 tests/rust/41-sim-syscall_priority_arch.rs create mode 100644 tests/rust/42-sim-adv_chains.rs create mode 100644 tests/rust/43-sim-a2_order.rs create mode 100644 tests/rust/44-live-a2_order.rs create mode 100644 tests/rust/45-sim-chain_code_coverage.rs create mode 100644 tests/rust/46-sim-kill_process.rs create mode 100644 tests/rust/47-live-kill_process.rs create mode 100644 tests/rust/48-sim-32b_args.rs create mode 100644 tests/rust/49-sim-64b_comparisons.rs create mode 100644 tests/rust/50-sim-hash_collision.rs create mode 100644 tests/rust/51-live-user_notification.rs create mode 100644 tests/rust/52-basic-load.rs create mode 100644 tests/rust/53-sim-binary_tree.rs create mode 100644 tests/rust/54-live-binary_tree.rs create mode 100644 tests/rust/55-basic-pfc_binary_tree.rs create mode 100644 tests/rust/56-basic-iterate_syscalls.rs create mode 100644 tests/rust/57-basic-rawsysrc.rs create mode 100644 tests/rust/58-live-tsync_notify.rs create mode 100644 tests/rust/59-basic-empty_binary_tree.rs create mode 100644 tests/rust/60-sim-precompute.rs create mode 100644 tests/rust/Cargo.lock create mode 100644 tests/rust/Cargo.toml create mode 100644 tests/rust/utils.rs diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 94f6bbb1..a3bcce4d 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -37,4 +37,8 @@ runs: shell: bash - run: | ./autogen.sh + # Specify the tentative version of the libseccomp test library because some + # functions of the Rust bindings are restricted based on the version. + TEST_VERSION=9.9.9 + sed -i "/^AC_INIT/ s/0.0.0/$TEST_VERSION/" configure.ac shell: bash diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 2a3e2739..f7c69367 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -34,7 +34,11 @@ jobs: uses: ./.github/actions/setup - name: Build libseccomp run: | - ./configure --enable-python + ./configure --prefix=$(pwd)/src/.libs --enable-python --enable-rust + # make and make install are required to create a pkconfig because + # the Rust bindings need it for the compilation. + make + make install make check-build - name: Run tests run: | @@ -52,13 +56,18 @@ jobs: uses: ./.github/actions/setup - name: Build libseccomp run: | - ./configure --enable-python + ./configure --prefix=$(pwd)/src/.libs --enable-python --enable-rust + # make and make install are required to create a pkconfig because + # the Rust bindings need it for the compilation. + # This can be removed when the Rust bindings drop the version check by pkgconfig. + make + make install make check-build - name: Run live tests run: | LIBSECCOMP_TSTCFG_JOBS=0 \ LIBSECCOMP_TSTCFG_TYPE=live \ - LIBSECCOMP_TSTCFG_MODE_LIST=c make -C tests check + LIBSECCOMP_TSTCFG_MODE_LIST="c rust" make -C tests check scanbuild: name: Scan Build diff --git a/Makefile.am b/Makefile.am index 588e0238..4bf54374 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,8 +41,8 @@ AM_MAKEFLAGS_1 = AM_MAKEFLAGS_ = ${AM_MAKEFLAGS_0} AM_MAKEFLAGS = ${AM_MAKEFLAGS_@AM_V@} -# enable python during distcheck -AM_DISTCHECK_CONFIGURE_FLAGS = --enable-python +# enable python and rust during distcheck +AM_DISTCHECK_CONFIGURE_FLAGS = --enable-python --enable-rust check-build: all ${MAKE} ${AM_MAKEFLAGS} -C src check-build diff --git a/configure.ac b/configure.ac index f2f68621..a453953a 100644 --- a/configure.ac +++ b/configure.ac @@ -123,6 +123,36 @@ AC_DEFINE_UNQUOTED([ENABLE_PYTHON], [$(test "$enable_python" = "yes" && echo 1 || echo 0)], [Python bindings build flag.]) +dnl #### +dnl rustc checks +dnl #### +AC_CHECK_PROGS(rustc, rustc, "no") +AS_IF([test "$rustc" != no], [ + AS_ECHO("checking rustc version... $($rustc -V 2>&1 | cut -d' ' -f 2)") + RUSTC_VER_MAJ=$($rustc -V 2>&1 | cut -d' ' -f 2 | cut -d'.' -f 1); + RUSTC_VER_MIN=$($rustc -V 2>&1 | cut -d' ' -f 2 | cut -d'.' -f 2); +],[ + RUSTC_VER_MAJ=0 + RUSTC_VER_MIN=0 +]) + +dnl #### +dnl rust binding checks +dnl #### +AC_ARG_ENABLE([rust], + [AS_HELP_STRING([--enable-rust], + [build the rust bindings, requires rustc])]) +AS_IF([test "$enable_rust" = yes], [ + # rustc version check + AS_IF([test "$RUSTC_VER_MAJ" -eq 1 -a "$RUSTC_VER_MIN" -lt 63], [ + AC_MSG_ERROR([rust bindings require rustc 1.63 or higher]) + ]) +]) +AM_CONDITIONAL([ENABLE_RUST], [test "$enable_rust" = yes]) +AC_DEFINE_UNQUOTED([ENABLE_RUST], + [$(test "$enable_rust" = yes && echo 1 || echo 0)], + [Rust bindings build flag.]) + AC_CHECK_TOOL(GPERF, gperf) if test -z "$GPERF"; then AC_MSG_ERROR([please install gperf]) diff --git a/tests/.gitignore b/tests/.gitignore index de6efd1f..ce6720b8 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -68,3 +68,7 @@ util.pyc 58-live-tsync_notify 59-basic-empty_binary_tree 60-sim-precompute +/rust/target +/rust/utils/target +.crates.toml +.crates2.json diff --git a/tests/Makefile.am b/tests/Makefile.am index 07bea2e7..43c1c7fa 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -34,6 +34,32 @@ miniseq_LDADD = TESTS = regression +if ENABLE_RUST +rust_BINDINGS_TEST = yes +else +rust_BINDINGS_TEST = no +endif + +rust_TESTS_DIR = ./rust +rust_CARGO_TOML = Cargo.toml +rust_LINK_TYPE = static +rust_LIBSECCOMP_LIBRARY_DIR = ../src/.libs/lib +export LIBSECCOMP_LINK_TYPE =$(rust_LINK_TYPE) +export LIBSECCOMP_LIB_PATH =$(shell realpath $(rust_LIBSECCOMP_LIBRARY_DIR)) + +define check_rust_bindings + echo "Check format and lint for rust bindings"; \ + cargo fmt --manifest-path $(rust_TESTS_DIR)/$(rust_CARGO_TOML) -- --check || exit 1; \ + cargo clippy --manifest-path $(rust_TESTS_DIR)/$(rust_CARGO_TOML) \ + --all-targets --all-features -- -D warnings || exit 1; +endef + +define build_rust_bindings + echo "Build test programs for rust bindings"; \ + cargo build --manifest-path $(rust_TESTS_DIR)/$(rust_CARGO_TOML) || exit 1; \ + cargo install --quiet --root $(rust_TESTS_DIR) --path $(rust_TESTS_DIR) || exit 1; +endef + check_PROGRAMS = \ miniseq \ 01-sim-allow \ @@ -240,6 +266,14 @@ EXTRA_PROGRAMS = 00-test check-build: ${MAKE} ${AM_MAKEFLAGS} ${check_PROGRAMS} + @if [ "$(rust_BINDINGS_TEST)" = "yes" ]; then \ + $(call check_rust_bindings) \ + $(call build_rust_bindings) \ + fi clean-local: ${RM} -f 00-test *.pyc + if [ "$(rust_BINDINGS_TEST)" = "yes" ]; then \ + cargo clean --manifest-path $(rust_TESTS_DIR)/$(rust_CARGO_TOML); \ + ${RM} -rf $(rust_TESTS_DIR)/bin; \ + fi diff --git a/tests/regression b/tests/regression index ff2be56d..062f210b 100755 --- a/tests/regression +++ b/tests/regression @@ -62,6 +62,9 @@ GLBL_SYS_RESOLVER="../tools/scmp_sys_resolver" GLBL_SYS_SIM="../tools/scmp_bpf_sim" GLBL_SYS_API="../tools/scmp_api_level" +RUST_TESTS_DIR="./rust" +RUST_TESTS_BIN_DIR="${RUST_TESTS_DIR}/bin" + #### # functions @@ -104,7 +107,7 @@ optional arguments: -h show this help message and exit -j JOBS run up to JOBS test jobs in parallel can also be set via LIBSECCOMP_TSTCFG_JOBS env variable - -m MODE specified the test mode [c (default), python] + -m MODE specified the test mode [c (default), python, rust] can also be set via LIBSECCOMP_TSTCFG_MODE_LIST env variable -a specifies all tests are to be run -b BATCH_NAME specifies batch of tests to be run @@ -266,6 +269,8 @@ function run_test_command() { else cmd="$cmd /usr/bin/env python ${srcdir}/$2.py $3" fi + elif [[ $mode == "rust" ]]; then + cmd="${RUST_TESTS_BIN_DIR}/$2 $3" else cmd="$2 $3" fi @@ -871,6 +876,16 @@ function run_test() { # generate the test number string for the line of batch test data local testnumstr=$(generate_test_num "$1" $2 1) + # skip tests not yet supported for Rust bindings + if [[ "$mode" == "rust" ]]; then + if [[ ! -e "${RUST_TESTS_DIR}/${1}.rs" ]]; then + print_result $testnumstr "SKIPPED" \ + "(test not yet supported)" + stats_skipped=$(($stats_skipped+1)) + return + fi + fi + # ensure we only run tests which match the specified type match_csv_word "$type" "$4" local type_match=$? @@ -1115,6 +1130,9 @@ while getopts "ab:gj:l:m:s:t:T:vh" opt; do verify_deps python mode_list="$mode_list python" ;; + rust) + mode_list="$mode_list rust" + ;; *) usage exit 1 @@ -1160,6 +1178,10 @@ if [[ -z $mode_list ]]; then [[ "$(grep "ENABLE_PYTHON" ../configure.h | \ awk '{ print $3 }')" = "1" ]] && \ mode_list="$mode_list python" + # rust tests + [[ "$(grep "ENABLE_RUST" ../configure.h | \ + awk '{ print $3 }')" = "1" ]] && \ + mode_list="$mode_list rust" fi fi diff --git a/tests/rust/01-sim-allow.rs b/tests/rust/01-sim-allow.rs new file mode 100644 index 00000000..00926593 --- /dev/null +++ b/tests/rust/01-sim-allow.rs @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/02-sim-basic.rs b/tests/rust/02-sim-basic.rs new file mode 100644 index 00000000..89749818 --- /dev/null +++ b/tests/rust/02-sim-basic.rs @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("read")?)?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("write")?)?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/03-sim-basic_chains.rs b/tests/rust/03-sim-basic_chains.rs new file mode 100644 index 00000000..474ac1bd --- /dev/null +++ b/tests/rust/03-sim-basic_chains.rs @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::{stderr, stdin, stdout}; +use std::os::unix::io::AsRawFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg0 == stdin().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stdout().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stderr().as_raw_fd() as u64)], + )?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/04-sim-multilevel_chains.rs b/tests/rust/04-sim-multilevel_chains.rs new file mode 100644 index 00000000..f72c3afe --- /dev/null +++ b/tests/rust/04-sim-multilevel_chains.rs @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::{stderr, stdin, stdout}; +use std::os::unix::io::AsRawFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("openat")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[ + scmp_cmp!($arg0 == stdin().as_raw_fd() as u64), + scmp_cmp!($arg1 != 0), + scmp_cmp!($arg2 < libc::ssize_t::MAX as u64), + ], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[ + scmp_cmp!($arg0 == stdout().as_raw_fd() as u64), + scmp_cmp!($arg1 != 0), + scmp_cmp!($arg2 < libc::ssize_t::MAX as u64), + ], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[ + scmp_cmp!($arg0 == stderr().as_raw_fd() as u64), + scmp_cmp!($arg1 != 0), + scmp_cmp!($arg2 < libc::ssize_t::MAX as u64), + ], + )?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/05-sim-long_jumps.rs b/tests/rust/05-sim-long_jumps.rs new file mode 100644 index 00000000..a758d417 --- /dev/null +++ b/tests/rust/05-sim-long_jumps.rs @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("brk")?)?; + + // same syscall, many chains + for iter in 0..100 { + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("chdir")?, + &[ + scmp_cmp!($arg0 == iter), + scmp_cmp!($arg1 != 0), + scmp_cmp!($arg2 < libc::ssize_t::MAX as u64), + ], + )?; + } + + // many syscalls, same chain + let mut ctr = 0; + for iter in 0..10000 { + if ctr >= 100 { + break; + } + + let syscall = ScmpSyscall::from(iter); + if syscall == ScmpSyscall::from_name("chdir")? { + continue; + } + + if syscall.get_name().is_ok() { + ctx.add_rule_conditional(ScmpAction::Allow, iter, &[scmp_cmp!($arg0 != 0)])?; + ctr += 1; + } + } + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/06-sim-actions.rs b/tests/rust/06-sim-actions.rs new file mode 100644 index 00000000..0e27810d --- /dev/null +++ b/tests/rust/06-sim-actions.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + set_api(3)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("read")?)?; + ctx.add_rule(ScmpAction::Log, ScmpSyscall::from_name("rt_sigreturn")?)?; + ctx.add_rule( + ScmpAction::Errno(libc::EPERM), + ScmpSyscall::from_name("write")?, + )?; + ctx.add_rule(ScmpAction::Trap, ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Trace(1234), ScmpSyscall::from_name("openat")?)?; + ctx.add_rule(ScmpAction::KillProcess, ScmpSyscall::from_name("fstatfs")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/07-sim-db_bug_looping.rs b/tests/rust/07-sim-db_bug_looping.rs new file mode 100644 index 00000000..87a1228c --- /dev/null +++ b/tests/rust/07-sim-db_bug_looping.rs @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::{stdin, stdout}; +use std::os::unix::io::AsRawFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + // The next three add_rule_conditional_exact() calls for read must + // go together in this order to catch an infinite loop. + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg0 == stdout().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg1 == 0x0)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg0 == stdin().as_raw_fd() as u64)], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/08-sim-subtree_checks.rs b/tests/rust/08-sim-subtree_checks.rs new file mode 100644 index 00000000..0f009e78 --- /dev/null +++ b/tests/rust/08-sim-subtree_checks.rs @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + // The syscall and argument numbers are all fake to make the test + // simpler. + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 0), scmp_cmp!($arg1 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg1 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1001), + &[scmp_cmp!($arg1 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1001), + &[scmp_cmp!($arg0 == 0), scmp_cmp!($arg1 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1002), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 == 1), + scmp_cmp!($arg2 == 2), + scmp_cmp!($arg3 == 3), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1002), + &[scmp_cmp!($arg1 == 1), scmp_cmp!($arg2 == 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1003), + &[scmp_cmp!($arg1 == 1), scmp_cmp!($arg2 == 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1003), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 == 1), + scmp_cmp!($arg2 == 2), + scmp_cmp!($arg3 == 3), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1004), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 == 1), + scmp_cmp!($arg2 == 2), + scmp_cmp!($arg3 == 3), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1004), + &[scmp_cmp!($arg0 == 0), scmp_cmp!($arg1 == 11)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1004), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 == 1), + scmp_cmp!($arg2 == 2), + scmp_cmp!($arg3 == 33), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1004), + &[scmp_cmp!($arg1 == 1), scmp_cmp!($arg2 == 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1005), + &[scmp_cmp!($arg1 == 1), scmp_cmp!($arg2 == 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1005), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 == 1), + scmp_cmp!($arg2 == 2), + scmp_cmp!($arg3 == 3), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1005), + &[scmp_cmp!($arg0 == 0), scmp_cmp!($arg1 == 11)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1005), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 == 1), + scmp_cmp!($arg2 == 2), + scmp_cmp!($arg3 == 33), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1006), + &[scmp_cmp!($arg1 != 1), scmp_cmp!($arg2 == 0)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1006), + &[scmp_cmp!($arg1 == 1), scmp_cmp!($arg2 == 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1006), + &[scmp_cmp!($arg1 != 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Trap, + ScmpSyscall::from(1007), + &[scmp_cmp!($arg2 == 2), scmp_cmp!($arg3 == 3)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1007), + &[scmp_cmp!($arg2 == 2), scmp_cmp!($arg3 != 3)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1007), + &[scmp_cmp!($arg3 != 3)], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/09-sim-syscall_priority_pre.rs b/tests/rust/09-sim-syscall_priority_pre.rs new file mode 100644 index 00000000..1221d8d0 --- /dev/null +++ b/tests/rust/09-sim-syscall_priority_pre.rs @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + // The syscall and argument numbers are all fake to make the test + // simpler. + ctx.set_syscall_priority(1000, 3)?; + ctx.set_syscall_priority(1001, 2)?; + ctx.set_syscall_priority(1002, 1)?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 0), scmp_cmp!($arg1 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1001), + &[scmp_cmp!($arg0 == 0)], + )?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from(1002))?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/10-sim-syscall_priority_post.rs b/tests/rust/10-sim-syscall_priority_post.rs new file mode 100644 index 00000000..e2b14c54 --- /dev/null +++ b/tests/rust/10-sim-syscall_priority_post.rs @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + // The syscall and argument numbers are all fake to make the test + // simpler. + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 0), scmp_cmp!($arg1 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1001), + &[scmp_cmp!($arg0 == 0)], + )?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from(1002))?; + + ctx.set_syscall_priority(1000, 3)?; + ctx.set_syscall_priority(1001, 2)?; + ctx.set_syscall_priority(1002, 1)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/11-basic-basic_errors.rs b/tests/rust/11-basic-basic_errors.rs new file mode 100644 index 00000000..3ec078a4 --- /dev/null +++ b/tests/rust/11-basic-basic_errors.rs @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::error::SeccompErrno; +use libseccomp::*; +use nix::unistd::{sysconf, SysconfVar}; +use std::os::unix::io::FromRawFd; +use std::os::unix::prelude::OwnedFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + + // set_syscall_priority error + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + let mut e = ctx.set_syscall_priority(-10, 1).unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::EINVAL); + + // add_rule errors + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + e = ctx + .add_rule(ScmpAction::Allow, ScmpSyscall::from_name("read")?) + .unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::EACCES); + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + e = ctx + .add_rule_exact(ScmpAction::KillThread, ScmpSyscall::from(-10001)) + .unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::EDOM); + + // add_rule_exact error + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + ctx.remove_arch(ScmpArch::Native)?; + ctx.add_arch(ScmpArch::X86)?; + e = ctx + .add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from_name("socket")?, + &[scmp_cmp!($arg0 == 2)], + ) + .unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::EINVAL); + + // Errno values beyond MAX_ERRNO + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + e = ctx + .add_rule(ScmpAction::Errno(0xffff), ScmpSyscall::from(0)) + .unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::EINVAL); + + // export_pfc error + let ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + e = ctx + .export_pfc(unsafe { + OwnedFd::from_raw_fd((sysconf(SysconfVar::OPEN_MAX)?.unwrap() - 1) as i32) + }) + .unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::ECANCELED); + + // export_bpf error + let ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + e = ctx + .export_bpf(unsafe { + OwnedFd::from_raw_fd((sysconf(SysconfVar::OPEN_MAX)?.unwrap() - 1) as i32) + }) + .unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::ECANCELED); + + // seccomp notify errors + let api = get_api(); + if api >= 5 { + let ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + assert!(notify_id_valid(-1, 0).is_err()); + assert!(ctx.get_notify_fd().is_err()); + } + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/12-sim-basic_masked_ops.rs b/tests/rust/12-sim-basic_masked_ops.rs new file mode 100644 index 00000000..172e0185 --- /dev/null +++ b/tests/rust/12-sim-basic_masked_ops.rs @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + // The syscall and argument numbers are all fake to make the test + // simpler. + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 == 1), + scmp_cmp!($arg2 == 2), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 & 0x00ff == 1), + scmp_cmp!($arg2 == 2), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 & 0xffff == 11), + scmp_cmp!($arg2 == 2), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 & 0xffff == 111), + scmp_cmp!($arg2 == 2), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 & 0xff00 == 1000), + scmp_cmp!($arg2 == 2), + ], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/13-basic-attrs.rs b/tests/rust/13-basic-attrs.rs new file mode 100644 index 00000000..dde3117d --- /dev/null +++ b/tests/rust/13-basic-attrs.rs @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::error::SeccompErrno; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let val = u32::MAX; + + set_api(5)?; + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + // for ActDefault + assert_eq!(ctx.get_act_default()?, ScmpAction::Allow); + let e = ctx + .set_filter_attr(ScmpFilterAttr::ActDefault, val) + .unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::EACCES); + + // for ActBadArch + ctx.set_act_badarch(ScmpAction::Allow)?; + assert_eq!(ctx.get_act_badarch()?, ScmpAction::Allow); + + // for CtlNnp + ctx.set_ctl_nnp(false)?; + ctx.get_ctl_nnp()?; + + // for CtlTsync + if let Err(e) = ctx.set_ctl_tsync(true) { + assert_eq!(e.errno().unwrap(), SeccompErrno::EOPNOTSUPP); + } + assert!(ctx.get_ctl_tsync()?); + + // for ApiTskip + ctx.set_filter_attr(ScmpFilterAttr::ApiTskip, val)?; + ctx.get_filter_attr(ScmpFilterAttr::ApiTskip)?; + + // for CtlLog + ctx.set_ctl_log(true)?; + assert!(ctx.get_ctl_log()?); + + // for CtlSsb + ctx.set_ctl_ssb(true)?; + assert!(ctx.get_ctl_ssb()?); + + // for CtlOptimize + ctx.set_ctl_optimize(2)?; + assert_eq!(ctx.get_ctl_optimize()?, 2); + + // for ApiSysRawRc + ctx.set_api_sysrawrc(true)?; + assert!(ctx.get_api_sysrawrc()?); + + // for CtlWaitKill + // SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV has been available since Linux 5.19. + if check_api(7, ScmpVersion::from((2, 6, 0))).unwrap() { + ctx.set_ctl_waitkill(true)?; + assert!(ctx.get_ctl_waitkill()?); + } + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/14-sim-reset.rs b/tests/rust/14-sim-reset.rs new file mode 100644 index 00000000..06b6e07e --- /dev/null +++ b/tests/rust/14-sim-reset.rs @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("read")?)?; + ctx.reset(ScmpAction::KillThread)?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("write")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/15-basic-resolver.rs b/tests/rust/15-basic-resolver.rs new file mode 100644 index 00000000..bd49cd9d --- /dev/null +++ b/tests/rust/15-basic-resolver.rs @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; + +const ARCH_LIST: [ScmpArch; 23] = [ + ScmpArch::Native, + ScmpArch::X86, + ScmpArch::X8664, + ScmpArch::X32, + ScmpArch::Arm, + ScmpArch::Aarch64, + ScmpArch::Loongarch64, + ScmpArch::M68k, + ScmpArch::Mips, + ScmpArch::Mips64, + ScmpArch::Mips64N32, + ScmpArch::Mipsel, + ScmpArch::Mipsel64, + ScmpArch::Mipsel64N32, + ScmpArch::Ppc, + ScmpArch::Ppc64, + ScmpArch::Ppc64Le, + ScmpArch::S390, + ScmpArch::S390X, + ScmpArch::Parisc, + ScmpArch::Parisc64, + ScmpArch::Riscv64, + ScmpArch::Sh, +]; + +fn main() -> Result<()> { + assert_eq!(ScmpSyscall::from_name("open")?, ScmpSyscall::new("open")); + assert_eq!(ScmpSyscall::from_name("read")?, ScmpSyscall::new("read")); + assert!(ScmpSyscall::from_name("INVALID").is_err()); + assert_eq!( + ScmpSyscall::from_name_by_arch_rewrite("openat", ScmpArch::Native)?, + ScmpSyscall::new("openat") + ); + + for arch in ARCH_LIST { + assert!(ScmpSyscall::from_name("INVALID").is_err()); + assert!(ScmpSyscall::from(-1).get_name_by_arch(arch).is_err()); + + let nr_open = ScmpSyscall::from_name_by_arch("open", arch)?; + let nr_read = ScmpSyscall::from_name_by_arch("read", arch)?; + let nr_socket = ScmpSyscall::from_name_by_arch_rewrite("socket", arch)?; + let nr_shmctl = ScmpSyscall::from_name_by_arch_rewrite("shmctl", arch)?; + + let mut name = nr_open.get_name_by_arch(arch)?; + assert_eq!(name, "open"); + name = nr_read.get_name_by_arch(arch)?; + assert_eq!(name, "read"); + name = nr_socket.get_name_by_arch(arch)?; + assert!(name == "socket" || name == "socketcall"); + name = nr_shmctl.get_name_by_arch(arch)?; + assert!(name == "shmctl" || name == "ipc"); + + // socket pseudo-syscalls + if ScmpSyscall::from_name_by_arch("socketcall", arch)? > 0.into() { + for sys in -120..-100 { + ScmpSyscall::from(sys).get_name_by_arch(arch)?; + } + } + + // ipc pseudo-syscalls + if ScmpSyscall::from_name_by_arch("ipc", arch)? > 0.into() { + for sys in -204..-200 { + ScmpSyscall::from(sys).get_name_by_arch(arch)?; + } + for sys in -214..-210 { + ScmpSyscall::from(sys).get_name_by_arch(arch)?; + } + for sys in -224..-220 { + ScmpSyscall::from(sys).get_name_by_arch(arch)?; + } + } + } + Ok(()) +} diff --git a/tests/rust/16-sim-arch_basic.rs b/tests/rust/16-sim-arch_basic.rs new file mode 100644 index 00000000..a747cc7b --- /dev/null +++ b/tests/rust/16-sim-arch_basic.rs @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::{stderr, stdin, stdout}; +use std::os::unix::io::AsRawFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + // NOTE: not strictly necessary since we get the native arch by default + // but it serves as a good sanity check for the code and boosts + // our code coverage numbers + assert!(ctx.is_arch_present(ScmpArch::Native)?); + + ctx.remove_arch(ScmpArch::Native)?; + + // NOTE: we are using a different approach to test for the native arch + // to exercise slightly different code paths + assert!(!ctx.is_arch_present(ScmpArch::native())?); + + // NOTE: more sanity/coverage tests (see above) + ctx.add_arch(ScmpArch::Native)?; + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::X86)?; + ctx.add_arch(ScmpArch::X8664)?; + ctx.add_arch(ScmpArch::X32)?; + ctx.add_arch(ScmpArch::Arm)?; + ctx.add_arch(ScmpArch::Aarch64)?; + ctx.add_arch(ScmpArch::Loongarch64)?; + ctx.add_arch(ScmpArch::Mipsel)?; + ctx.add_arch(ScmpArch::Mipsel64)?; + ctx.add_arch(ScmpArch::Mipsel64N32)?; + ctx.add_arch(ScmpArch::Ppc64Le)?; + ctx.add_arch(ScmpArch::Riscv64)?; + ctx.add_arch(ScmpArch::Sh)?; + + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg0 == stdin().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stdout().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stderr().as_raw_fd() as u64)], + )?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("socket")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("connect")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shutdown")?)?; + + util_filter_output(&opts, &ctx)?; + + // not strictly necessary, but let's exercise the code paths + ctx.remove_arch(ScmpArch::X86)?; + ctx.remove_arch(ScmpArch::X8664)?; + ctx.remove_arch(ScmpArch::X32)?; + ctx.remove_arch(ScmpArch::Arm)?; + ctx.remove_arch(ScmpArch::Aarch64)?; + ctx.remove_arch(ScmpArch::Loongarch64)?; + ctx.remove_arch(ScmpArch::Mipsel)?; + ctx.remove_arch(ScmpArch::Mipsel64)?; + ctx.remove_arch(ScmpArch::Mipsel64N32)?; + ctx.remove_arch(ScmpArch::Ppc64Le)?; + ctx.remove_arch(ScmpArch::Riscv64)?; + ctx.remove_arch(ScmpArch::Sh)?; + + Ok(()) +} diff --git a/tests/rust/17-sim-arch_merge.rs b/tests/rust/17-sim-arch_merge.rs new file mode 100644 index 00000000..78737cfe --- /dev/null +++ b/tests/rust/17-sim-arch_merge.rs @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::{stderr, stdin, stdout}; +use std::os::unix::io::AsRawFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + + let mut ctx_32 = ScmpFilterContext::new(ScmpAction::KillThread)?; + let mut ctx_64 = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx_32.remove_arch(ScmpArch::Native)?; + ctx_64.remove_arch(ScmpArch::Native)?; + + ctx_32.add_arch(ScmpArch::X86)?; + ctx_64.add_arch(ScmpArch::X8664)?; + + ctx_32.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg0 == stdin().as_raw_fd() as u64)], + )?; + + ctx_32.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stdout().as_raw_fd() as u64)], + )?; + + ctx_32.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stderr().as_raw_fd() as u64)], + )?; + + ctx_32.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx_64.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("socket")?)?; + ctx_64.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("connect")?)?; + ctx_64.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shutdown")?)?; + + ctx_64.merge(ctx_32)?; + // NOTE: ctx_32 is no longer valid at this point + + util_filter_output(&opts, &ctx_64) +} diff --git a/tests/rust/18-sim-basic_allowlist.rs b/tests/rust/18-sim-basic_allowlist.rs new file mode 100644 index 00000000..474ac1bd --- /dev/null +++ b/tests/rust/18-sim-basic_allowlist.rs @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::{stderr, stdin, stdout}; +use std::os::unix::io::AsRawFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg0 == stdin().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stdout().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stderr().as_raw_fd() as u64)], + )?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/19-sim-missing_syscalls.rs b/tests/rust/19-sim-missing_syscalls.rs new file mode 100644 index 00000000..bee0ad39 --- /dev/null +++ b/tests/rust/19-sim-missing_syscalls.rs @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::error::SeccompErrno; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.remove_arch(ScmpArch::Native)?; + ctx.add_arch(ScmpArch::X86)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("tuxcall")?)?; + let e = ctx + .add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("tuxcall")?) + .unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::EDOM); + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/20-live-basic_die.rs b/tests/rust/20-live-basic_die.rs new file mode 100644 index 00000000..74659852 --- /dev/null +++ b/tests/rust/20-live-basic_die.rs @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::env; +use std::process; +use utils::*; + +fn main() -> Result<()> { + let args: Vec = env::args().collect(); + if args.len() < 2 { + process::exit(1); + } + + let action = util_action_parse(&args[1])?; + if action == ScmpAction::Trap { + util_trap_install()?; + } + + let mut ctx = ScmpFilterContext::new(action)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("exit_group")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("sigaltstack")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("munmap")?)?; + + ctx.load()?; + + let mut ret: i32 = util_file_write("/dev/null"); + if ret == 0 { + ret = 160; + } + + process::exit(ret); +} diff --git a/tests/rust/21-live-basic_allow.rs b/tests/rust/21-live-basic_allow.rs new file mode 100644 index 00000000..ed097442 --- /dev/null +++ b/tests/rust/21-live-basic_allow.rs @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::env; +use std::process; +use utils::*; + +fn main() -> Result<()> { + let args: Vec = env::args().collect(); + if args.len() < 2 { + process::exit(1); + } + + let action = util_action_parse(&args[1])?; + assert_eq!(action, ScmpAction::Allow); + util_trap_install()?; + + let mut ctx = ScmpFilterContext::new(ScmpAction::Trap)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("open")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("openat")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("write")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("exit_group")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("sigaltstack")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("munmap")?)?; + + ctx.load()?; + + let mut ret: i32 = util_file_write("/dev/null"); + if ret == 0 { + ret = 160; + } + + process::exit(ret); +} diff --git a/tests/rust/22-sim-basic_chains_array.rs b/tests/rust/22-sim-basic_chains_array.rs new file mode 100644 index 00000000..474ac1bd --- /dev/null +++ b/tests/rust/22-sim-basic_chains_array.rs @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::{stderr, stdin, stdout}; +use std::os::unix::io::AsRawFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg0 == stdin().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stdout().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stderr().as_raw_fd() as u64)], + )?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/23-sim-arch_all_le_basic.rs b/tests/rust/23-sim-arch_all_le_basic.rs new file mode 100644 index 00000000..3fa1a7e2 --- /dev/null +++ b/tests/rust/23-sim-arch_all_le_basic.rs @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::{stderr, stdin, stdout}; +use std::os::unix::io::AsRawFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::X86)?; + ctx.add_arch(ScmpArch::X8664)?; + ctx.add_arch(ScmpArch::X32)?; + ctx.add_arch(ScmpArch::Arm)?; + ctx.add_arch(ScmpArch::Aarch64)?; + ctx.add_arch(ScmpArch::Loongarch64)?; + ctx.add_arch(ScmpArch::Mipsel)?; + ctx.add_arch(ScmpArch::Mipsel64)?; + ctx.add_arch(ScmpArch::Mipsel64N32)?; + ctx.add_arch(ScmpArch::Ppc64Le)?; + ctx.add_arch(ScmpArch::Riscv64)?; + ctx.add_arch(ScmpArch::Sh)?; + + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg0 == stdin().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stdout().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stderr().as_raw_fd() as u64)], + )?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/24-live-arg_allow.rs b/tests/rust/24-live-arg_allow.rs new file mode 100644 index 00000000..7fd30b58 --- /dev/null +++ b/tests/rust/24-live-arg_allow.rs @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use nix::fcntl::{open, OFlag}; +use nix::sys::stat::Mode; +use nix::unistd::write; +use std::env; +use std::process; +use utils::*; + +fn main() -> Result<()> { + let args: Vec = env::args().collect(); + if args.len() < 2 { + process::exit(1); + } + + let action = util_action_parse(&args[1])?; + assert_eq!(action, ScmpAction::Allow); + util_trap_install()?; + + let fd = open( + "/dev/null", + OFlag::O_WRONLY | OFlag::O_CREAT, + Mode::S_IRUSR | Mode::S_IWUSR, + )?; + let buf = "testing"; + let buf_len = buf.len(); + + let mut ctx = ScmpFilterContext::new(ScmpAction::Trap)?; + + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == fd as u64)], + )?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("exit_group")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("sigaltstack")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("munmap")?)?; + + ctx.load()?; + + if write(fd, buf.as_bytes()) == Ok(buf_len) { + process::exit(160); + } else { + process::exit(util_errno()) + } +} diff --git a/tests/rust/25-sim-multilevel_chains_adv.rs b/tests/rust/25-sim-multilevel_chains_adv.rs new file mode 100644 index 00000000..a72f06c6 --- /dev/null +++ b/tests/rust/25-sim-multilevel_chains_adv.rs @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(10), + &[scmp_cmp!($arg0 == 11), scmp_cmp!($arg1 != 12)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(20), + &[ + scmp_cmp!($arg0 == 21), + scmp_cmp!($arg1 != 22), + scmp_cmp!($arg2 == 23), + ], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/26-sim-arch_all_be_basic.rs b/tests/rust/26-sim-arch_all_be_basic.rs new file mode 100644 index 00000000..155c5740 --- /dev/null +++ b/tests/rust/26-sim-arch_all_be_basic.rs @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::{stderr, stdin, stdout}; +use std::os::unix::io::AsRawFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::M68k)?; + ctx.add_arch(ScmpArch::Mips)?; + ctx.add_arch(ScmpArch::Mips64)?; + ctx.add_arch(ScmpArch::Mips64N32)?; + ctx.add_arch(ScmpArch::Parisc)?; + ctx.add_arch(ScmpArch::Parisc64)?; + ctx.add_arch(ScmpArch::Ppc)?; + ctx.add_arch(ScmpArch::Ppc64)?; + ctx.add_arch(ScmpArch::S390)?; + ctx.add_arch(ScmpArch::S390X)?; + ctx.add_arch(ScmpArch::Sheb)?; + + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg0 == stdin().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stdout().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stderr().as_raw_fd() as u64)], + )?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/27-sim-bpf_blk_state.rs b/tests/rust/27-sim-bpf_blk_state.rs new file mode 100644 index 00000000..fbaac975 --- /dev/null +++ b/tests/rust/27-sim-bpf_blk_state.rs @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 3)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 4)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 5)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 6)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 7)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 8)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 9)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 11)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 12)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 13)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 14)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 15)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 >= 16)], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/28-sim-arch_x86.rs b/tests/rust/28-sim-arch_x86.rs new file mode 100644 index 00000000..80c4e805 --- /dev/null +++ b/tests/rust/28-sim-arch_x86.rs @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + ctx.remove_arch(ScmpArch::Native)?; + // add x86-64 and x86 (in that order!) but explicitly leave out x32 + ctx.add_arch(ScmpArch::X8664)?; + ctx.add_arch(ScmpArch::X86)?; + ctx.add_rule(ScmpAction::Errno(1), ScmpSyscall::from_name("close")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/29-sim-pseudo_syscall.rs b/tests/rust/29-sim-pseudo_syscall.rs new file mode 100644 index 00000000..0c906b57 --- /dev/null +++ b/tests/rust/29-sim-pseudo_syscall.rs @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + // NOTE: we have to be careful here because some ABIs use syscall + // offsets which could interfere with our test, x86 is safe + ctx.remove_arch(ScmpArch::Native)?; + ctx.add_arch(ScmpArch::X86)?; + + // ScmpSyscall::from_name(sysmips) == 4294957190 (unsigned) + ctx.add_rule(ScmpAction::KillThread, ScmpSyscall::from_name("sysmips")?)?; + assert!(ctx + .add_rule_exact(ScmpAction::KillThread, ScmpSyscall::from_name("sysmips")?) + .is_err()); + // -10001 == 4294957295 (unsigned) + assert!(ctx + .add_rule_exact(ScmpAction::KillThread, ScmpSyscall::from(-10001)) + .is_err()); + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/30-sim-socket_syscalls.rs b/tests/rust/30-sim-socket_syscalls.rs new file mode 100644 index 00000000..c0eb119e --- /dev/null +++ b/tests/rust/30-sim-socket_syscalls.rs @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::X86)?; + ctx.add_arch(ScmpArch::X8664)?; + ctx.add_arch(ScmpArch::X32)?; + ctx.add_arch(ScmpArch::Ppc64Le)?; + ctx.add_arch(ScmpArch::Mipsel)?; + ctx.add_arch(ScmpArch::Sh)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("socket")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("bind")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("connect")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("listen")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("accept")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("getsockname")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("getpeername")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("socketpair")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("send")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("recv")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("sendto")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("recvfrom")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shutdown")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("setsockopt")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("getsockopt")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("sendmsg")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("recvmsg")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("accept4")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("sendmmsg")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("recvmmsg")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/31-basic-version_check.rs b/tests/rust/31-basic-version_check.rs new file mode 100644 index 00000000..88ab5db3 --- /dev/null +++ b/tests/rust/31-basic-version_check.rs @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; + +fn main() -> Result<()> { + assert!(ScmpVersion::current().is_ok()); + + Ok(()) +} diff --git a/tests/rust/32-live-tsync_allow.rs b/tests/rust/32-live-tsync_allow.rs new file mode 100644 index 00000000..9a3d55fd --- /dev/null +++ b/tests/rust/32-live-tsync_allow.rs @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::env; +use std::process; +use utils::*; + +fn main() -> Result<()> { + let args: Vec = env::args().collect(); + if args.len() < 2 { + process::exit(1); + } + let action = util_action_parse(&args[1])?; + assert_eq!(action, ScmpAction::Allow); + util_trap_install()?; + + let mut ctx = ScmpFilterContext::new(ScmpAction::Trap)?; + + ctx.set_ctl_tsync(true)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("open")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("openat")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("write")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("exit_group")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("sigaltstack")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("munmap")?)?; + + ctx.load()?; + + let mut ret: i32 = util_file_write("/dev/null"); + if ret == 0 { + ret = 160; + } + + process::exit(ret); +} diff --git a/tests/rust/33-sim-socket_syscalls_be.rs b/tests/rust/33-sim-socket_syscalls_be.rs new file mode 100644 index 00000000..b3c6d8db --- /dev/null +++ b/tests/rust/33-sim-socket_syscalls_be.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::S390)?; + ctx.add_arch(ScmpArch::S390X)?; + ctx.add_arch(ScmpArch::Ppc)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("socket")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("connect")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("accept")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("accept4")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shutdown")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/34-sim-basic_denylist.rs b/tests/rust/34-sim-basic_denylist.rs new file mode 100644 index 00000000..288ec1a1 --- /dev/null +++ b/tests/rust/34-sim-basic_denylist.rs @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::{stderr, stdin, stdout}; +use std::os::unix::io::AsRawFd; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg0 == stdin().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stdout().as_raw_fd() as u64)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::KillThread, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == stderr().as_raw_fd() as u64)], + )?; + ctx.add_rule_exact(ScmpAction::KillThread, ScmpSyscall::from_name("close")?)?; + ctx.add_rule_exact( + ScmpAction::KillThread, + ScmpSyscall::from_name("rt_sigreturn")?, + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/35-sim-negative_one.rs b/tests/rust/35-sim-negative_one.rs new file mode 100644 index 00000000..a948ead6 --- /dev/null +++ b/tests/rust/35-sim-negative_one.rs @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::X86)?; + ctx.add_arch(ScmpArch::X8664)?; + + ctx.set_filter_attr(ScmpFilterAttr::ApiTskip, 1)?; + ctx.set_syscall_priority(ScmpSyscall::from(-1), 100)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from(-1))?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/36-sim-ipc_syscalls.rs b/tests/rust/36-sim-ipc_syscalls.rs new file mode 100644 index 00000000..8e82b714 --- /dev/null +++ b/tests/rust/36-sim-ipc_syscalls.rs @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::X86)?; + ctx.add_arch(ScmpArch::X8664)?; + ctx.add_arch(ScmpArch::X32)?; + ctx.add_arch(ScmpArch::Ppc64Le)?; + ctx.add_arch(ScmpArch::Mipsel)?; + ctx.add_arch(ScmpArch::Sh)?; + ctx.add_arch(ScmpArch::Loongarch64)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("semop")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("semtimedop")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("semget")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("semctl")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("msgsnd")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("msgrcv")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("msgget")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("msgctl")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shmat")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shmdt")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shmget")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shmctl")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/37-sim-ipc_syscalls_be.rs b/tests/rust/37-sim-ipc_syscalls_be.rs new file mode 100644 index 00000000..9aa3a32f --- /dev/null +++ b/tests/rust/37-sim-ipc_syscalls_be.rs @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::S390)?; + ctx.add_arch(ScmpArch::S390X)?; + ctx.add_arch(ScmpArch::Ppc)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("semop")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("semtimedop")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("semget")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("semctl")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("msgsnd")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("msgrcv")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("msgget")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("msgctl")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shmat")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shmdt")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shmget")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("shmctl")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/38-basic-pfc_coverage.rs b/tests/rust/38-basic-pfc_coverage.rs new file mode 100644 index 00000000..39a5cec3 --- /dev/null +++ b/tests/rust/38-basic-pfc_coverage.rs @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::io::stdout; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + set_api(3)?; + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::X8664)?; + ctx.add_arch(ScmpArch::X86)?; + ctx.add_arch(ScmpArch::X32)?; + ctx.add_arch(ScmpArch::Arm)?; + ctx.add_arch(ScmpArch::Aarch64)?; + ctx.add_arch(ScmpArch::Mipsel)?; + ctx.add_arch(ScmpArch::Mipsel64)?; + ctx.add_arch(ScmpArch::Mipsel64N32)?; + ctx.add_arch(ScmpArch::Ppc64Le)?; + ctx.add_arch(ScmpArch::Riscv64)?; + + // NOTE: the syscalls and their arguments have been picked to achieve + // the highest possible code coverage, this is not a useful + // real world filter configuration + ctx.add_rule(ScmpAction::KillThread, ScmpSyscall::from_name("open")?)?; + ctx.add_rule_conditional( + ScmpAction::KillThread, + ScmpSyscall::from_name("read")?, + &[ + scmp_cmp!($arg0 == 0), + scmp_cmp!($arg1 >= 1), + scmp_cmp!($arg2 > 2), + scmp_cmp!($arg3 & 0x0f == 3), + ], + )?; + ctx.add_rule_conditional( + ScmpAction::Trap, + ScmpSyscall::from_name("write")?, + &[ + scmp_cmp!($arg0 != 0), + scmp_cmp!($arg1 <= 1), + scmp_cmp!($arg2 < 2), + ], + )?; + ctx.add_rule(ScmpAction::Errno(1), ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Trace(1), ScmpSyscall::from_name("exit")?)?; + ctx.add_rule(ScmpAction::KillThread, ScmpSyscall::from_name("fstat")?)?; + ctx.add_rule(ScmpAction::Log, ScmpSyscall::from_name("exit_group")?)?; + + // verify the prioritized, but no-rule, syscall + ctx.set_syscall_priority(ScmpSyscall::from_name("poll")?, 255)?; + + ctx.export_pfc(stdout())?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/39-basic-api_level.rs b/tests/rust/39-basic-api_level.rs new file mode 100644 index 00000000..cd1e1208 --- /dev/null +++ b/tests/rust/39-basic-api_level.rs @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::error::SeccompErrno; +use libseccomp::*; + +fn main() -> Result<()> { + let mut api: u32; + api = get_api(); + assert!(api >= 1); + + set_api(1)?; + api = get_api(); + assert!(api == 1); + + set_api(2)?; + api = get_api(); + assert!(api == 2); + + set_api(3)?; + api = get_api(); + assert!(api == 3); + + set_api(4)?; + api = get_api(); + assert!(api == 4); + + set_api(5)?; + api = get_api(); + assert!(api == 5); + + set_api(6)?; + api = get_api(); + assert!(api == 6); + + set_api(7)?; + api = get_api(); + assert!(api == 7); + + // Attempt to set a high, invalid API level + let e = set_api(1024).unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::EINVAL); + + // Ensure that the previously set API level didn't change + api = get_api(); + assert!(api == 7); + + Ok(()) +} diff --git a/tests/rust/40-sim-log.rs b/tests/rust/40-sim-log.rs new file mode 100644 index 00000000..1c835d64 --- /dev/null +++ b/tests/rust/40-sim-log.rs @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + + set_api(3)?; + let ctx = ScmpFilterContext::new(ScmpAction::Log)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/41-sim-syscall_priority_arch.rs b/tests/rust/41-sim-syscall_priority_arch.rs new file mode 100644 index 00000000..56da958f --- /dev/null +++ b/tests/rust/41-sim-syscall_priority_arch.rs @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.remove_arch(ScmpArch::Native)?; + ctx.add_arch(ScmpArch::X86)?; + + ctx.set_syscall_priority(ScmpSyscall::from_name("socket")?, 128)?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from_name("socket")?)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/42-sim-adv_chains.rs b/tests/rust/42-sim-adv_chains.rs new file mode 100644 index 00000000..c1d6b432 --- /dev/null +++ b/tests/rust/42-sim-adv_chains.rs @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::error::SeccompErrno; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1001), + &[scmp_cmp!($arg0 == 1), scmp_cmp!($arg1 == 2)], + )?; + ctx.add_rule_exact(ScmpAction::Allow, ScmpSyscall::from(1001))?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1002), + &[scmp_cmp!($arg0 == 1)], + )?; + let e = ctx + .add_rule_conditional_exact( + ScmpAction::Trap, + ScmpSyscall::from(1002), + &[scmp_cmp!($arg0 == 1)], + ) + .unwrap_err(); + assert_eq!(e.errno().unwrap(), SeccompErrno::EEXIST); + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1003), + &[scmp_cmp!($arg0 != 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Trap, + ScmpSyscall::from(1003), + &[scmp_cmp!($arg0 == 1)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1004), + &[scmp_cmp!($arg0 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Trap, + ScmpSyscall::from(1004), + &[scmp_cmp!($arg0 != 1)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1005), + &[scmp_cmp!($arg0 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1005), + &[scmp_cmp!($arg0 != 1)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1006), + &[scmp_cmp!($arg0 == 1), scmp_cmp!($arg1 == 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1006), + &[scmp_cmp!($arg0 == 1)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1007), + &[scmp_cmp!($arg0 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1007), + &[scmp_cmp!($arg0 == 1), scmp_cmp!($arg1 == 2)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1008), + &[scmp_cmp!($arg0 != 1), scmp_cmp!($arg1 != 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1008), + &[ + scmp_cmp!($arg0 != 1), + scmp_cmp!($arg1 != 2), + scmp_cmp!($arg2 != 3), + ], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1009), + &[scmp_cmp!($arg0 == 1), scmp_cmp!($arg1 != 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1009), + &[scmp_cmp!($arg0 != 1)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1010), + &[scmp_cmp!($arg0 != 1), scmp_cmp!($arg1 == 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1010), + &[scmp_cmp!($arg0 == 1)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1011), + &[scmp_cmp!($arg0 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1011), + &[scmp_cmp!($arg0 != 1), scmp_cmp!($arg2 == 1)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1012), + &[scmp_cmp!($arg0 & 0x0000 == 1)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1013), + &[scmp_cmp!($arg0 != 1), scmp_cmp!($arg1 != 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1013), + &[scmp_cmp!($arg0 < 1), scmp_cmp!($arg1 != 2)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1014), + &[scmp_cmp!($arg0 >= 1), scmp_cmp!($arg1 >= 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1014), + &[scmp_cmp!($arg0 != 1), scmp_cmp!($arg1 != 2)], + )?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1015), + &[scmp_cmp!($arg0 == 4), scmp_cmp!($arg1 == 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1015), + &[scmp_cmp!($arg0 == 4), scmp_cmp!($arg1 != 1)], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/43-sim-a2_order.rs b/tests/rust/43-sim-a2_order.rs new file mode 100644 index 00000000..d1087513 --- /dev/null +++ b/tests/rust/43-sim-a2_order.rs @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + // NOTE - a "hole" was intentionally left between 64 and 128. + // reads of this size should fall through to the default action - + // ScmpAction::KillThread in this test's case. + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 <= 64)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(5), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 128)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(6), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 256)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(7), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 512)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(8), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 1024)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(9), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 2048)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(10), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 4096)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(11), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 8192)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(12), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 16384)], + )?; + + // NOTE - a "hole" was intentionally left between 16384 and 32768. + // writes of this size should fall through to the default action - + // ScmpAction::KillThread in this test's case. + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg2 >= 32768)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(5), + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg2 < 128)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(6), + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg2 < 256)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(7), + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg2 < 512)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(8), + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg2 < 1024)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(9), + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg2 < 2048)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(10), + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg2 < 4096)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(11), + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg2 < 8192)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(12), + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg2 < 16384)], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/44-live-a2_order.rs b/tests/rust/44-live-a2_order.rs new file mode 100644 index 00000000..4971ef48 --- /dev/null +++ b/tests/rust/44-live-a2_order.rs @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::{convert::TryInto, fs::File, io::Read, path::Path, process}; +use utils::*; + +const DEFAULT_ACTION_ERRNO: i32 = 100; +const DEFAULT_ACTION: ScmpAction = ScmpAction::Errno(DEFAULT_ACTION_ERRNO); + +struct SizeAndRc { + size: i32, + expected_rc: i32, +} +impl SizeAndRc { + pub const fn new(size: i32, expected_rc: i32) -> Self { + Self { size, expected_rc } + } +} + +static TEST_CASE: &[SizeAndRc] = &[ + SizeAndRc::new(1, 1), + SizeAndRc::new(10, 10), + SizeAndRc::new(50, 50), + SizeAndRc::new(100, -DEFAULT_ACTION_ERRNO), + SizeAndRc::new(200, -5), + SizeAndRc::new(256, -5), + SizeAndRc::new(257, -6), + SizeAndRc::new(400, -6), + SizeAndRc::new(800, -7), + SizeAndRc::new(1600, -8), + SizeAndRc::new(3200, -9), + SizeAndRc::new(4095, -9), + SizeAndRc::new(4096, -9), + SizeAndRc::new(4097, -10), + SizeAndRc::new(8000, -10), + SizeAndRc::new(8192, -10), + SizeAndRc::new(16383, -11), + SizeAndRc::new(16384, -11), + SizeAndRc::new(16385, -12), + SizeAndRc::new(35000, -12), +]; + +fn do_read(sz: i32, expected_rc: i32) -> Result<()> { + let mut vec = vec![0; sz.try_into().unwrap()]; + let path = Path::new("/dev/zero"); + let mut file = File::open(path)?; + + if file.read_exact(&mut vec).is_err() && expected_rc != -util_errno() { + process::exit(1); + } + + Ok(()) +} + +fn main() -> Result<()> { + let mut ctx = ScmpFilterContext::new(DEFAULT_ACTION)?; + + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 <= 64)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(5), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 128)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(6), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 256)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(7), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 512)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(8), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 1024)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(9), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 2048)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(10), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 4096)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(11), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 8192)], + )?; + ctx.add_rule_conditional( + ScmpAction::Errno(12), + ScmpSyscall::from_name("read")?, + &[scmp_cmp!($arg2 > 16384)], + )?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("exit_group")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("exit")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("open")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("openat")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("stat")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("brk")?)?; + + ctx.load()?; + + for tc in TEST_CASE { + do_read(tc.size, tc.expected_rc)?; + } + + process::exit(160) +} diff --git a/tests/rust/45-sim-chain_code_coverage.rs b/tests/rust/45-sim-chain_code_coverage.rs new file mode 100644 index 00000000..7c028b54 --- /dev/null +++ b/tests/rust/45-sim-chain_code_coverage.rs @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + // the syscall and argument numbers are all fake to make the test simpler + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1008), + &[scmp_cmp!($arg0 >= 1)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1008), + &[scmp_cmp!($arg1 >= 2)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1008), + &[scmp_cmp!($arg0 > 3)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1008), + &[scmp_cmp!($arg2 & 0xf == 4)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1008), + &[scmp_cmp!($arg2 & 0xff == 5)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1008), + &[scmp_cmp!($arg2 & 0xff == 6)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1008), + &[ + scmp_cmp!($arg0 == 7), + scmp_cmp!($arg1 == 8), + scmp_cmp!($arg2 == 9), + scmp_cmp!($arg3 == 10), + scmp_cmp!($arg4 == 11), + scmp_cmp!($arg5 & 0xffff == 12), + ], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1008), + &[ + scmp_cmp!($arg0 == 7), + scmp_cmp!($arg1 == 8), + scmp_cmp!($arg2 == 9), + scmp_cmp!($arg3 == 10), + scmp_cmp!($arg4 == 11), + scmp_cmp!($arg5 & 0xffff == 13), + ], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/46-sim-kill_process.rs b/tests/rust/46-sim-kill_process.rs new file mode 100644 index 00000000..3b9373b5 --- /dev/null +++ b/tests/rust/46-sim-kill_process.rs @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + set_api(3)?; + let mut ctx = ScmpFilterContext::new(ScmpAction::KillProcess)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::X8664)?; + + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("read")?)?; + ctx.add_rule(ScmpAction::Errno(5), ScmpSyscall::from_name("write")?)?; + ctx.add_rule(ScmpAction::KillThread, ScmpSyscall::from_name("open")?)?; + ctx.add_rule_conditional( + ScmpAction::Errno(6), + ScmpSyscall::from_name("close")?, + &[scmp_cmp!($arg0 > 100)], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/47-live-kill_process.rs b/tests/rust/47-live-kill_process.rs new file mode 100644 index 00000000..987fbab4 --- /dev/null +++ b/tests/rust/47-live-kill_process.rs @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use std::fs::File; +use std::thread::spawn; +use std::{thread, time}; + +// Child thread created via thread::spawn() +// +// This thread will call a disallowed syscall. It should +// cause the entire program to die (and not just this thread.) +fn child_start() { + // make a disallowed syscall + let _ = File::open("/dev/null"); + // we should never get here. seccomp should kill the entire process when open() is called. +} + +fn main() -> Result<()> { + let allowlist: [ScmpSyscall; 10] = [ + ScmpSyscall::from_name("clone")?, + ScmpSyscall::from_name("exit")?, + ScmpSyscall::from_name("exit_group")?, + ScmpSyscall::from_name("futex")?, + ScmpSyscall::from_name("madvise")?, + ScmpSyscall::from_name("mmap")?, + ScmpSyscall::from_name("mprotect")?, + ScmpSyscall::from_name("munmap")?, + ScmpSyscall::from_name("nanosleep")?, + ScmpSyscall::from_name("set_robust_list")?, + ]; + let mut ctx = ScmpFilterContext::new(ScmpAction::KillProcess)?; + + for syscall in allowlist { + ctx.add_rule(ScmpAction::Allow, syscall)?; + } + + ctx.load()?; + + spawn(child_start); + // sleep for a bit to ensure that the child thread has time to run + thread::sleep(time::Duration::from_secs(1)); + // we should never get here! + + Ok(()) +} diff --git a/tests/rust/48-sim-32b_args.rs b/tests/rust/48-sim-32b_args.rs new file mode 100644 index 00000000..eb17f234 --- /dev/null +++ b/tests/rust/48-sim-32b_args.rs @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let args: [(ScmpAction, i32, ScmpArgCompare); 3] = [ + (ScmpAction::Allow, 2000, scmp_cmp!($arg0 == u64::MAX)), + ( + ScmpAction::Allow, + 2032, + scmp_cmp!($arg0 == u64::from(u32::MAX)), + ), + (ScmpAction::Allow, 2064, scmp_cmp!($arg0 == u64::MAX)), + ]; + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == u64::MAX)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1064), + &[scmp_cmp!($arg0 == u64::MAX)], + )?; + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1032), + &[scmp_cmp!($arg0 == u64::from(u32::MAX))], + )?; + + for (action, syscall, cmp) in args { + ctx.add_rule_conditional_exact(action, syscall, &[cmp])?; + } + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/49-sim-64b_comparisons.rs b/tests/rust/49-sim-64b_comparisons.rs new file mode 100644 index 00000000..85269b5c --- /dev/null +++ b/tests/rust/49-sim-64b_comparisons.rs @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::KillThread)?; + + ctx.add_rule_conditional_exact( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 < 0x123456789abc)], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/50-sim-hash_collision.rs b/tests/rust/50-sim-hash_collision.rs new file mode 100644 index 00000000..c48d1687 --- /dev/null +++ b/tests/rust/50-sim-hash_collision.rs @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + set_api(1)?; + let mut ctx = ScmpFilterContext::new(ScmpAction::Errno(100))?; + + ctx.remove_arch(ScmpArch::Native)?; + ctx.add_arch(ScmpArch::X8664)?; + + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from(1001), + &[ + scmp_cmp!($arg0 == 1), + scmp_cmp!($arg1 & 0xf == 2), + scmp_cmp!($arg2 == 3), + ], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from(1001), + &[scmp_cmp!($arg0 == 1), scmp_cmp!($arg1 & 0xf == 1)], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 2)], + )?; + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from(1000), + &[scmp_cmp!($arg0 == 1)], + )?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/51-live-user_notification.rs b/tests/rust/51-live-user_notification.rs new file mode 100644 index 00000000..3fbba47a --- /dev/null +++ b/tests/rust/51-live-user_notification.rs @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libc::{fork, getpid, syscall, waitpid, SYS_getpid, WEXITSTATUS, WIFEXITED}; +use libseccomp::*; +use std::process::exit; + +fn main() -> Result<()> { + let mut status: i32 = 0; + let magic = unsafe { getpid() }; + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + ctx.add_rule(ScmpAction::Notify, ScmpSyscall::from_name("getpid")?)?; + ctx.load()?; + + let fd = ctx.get_notify_fd()?; + let pid = unsafe { fork() }; + if pid == 0 { + exit((unsafe { syscall(SYS_getpid) } != magic as i64) as i32); + } + + let req = ScmpNotifReq::receive(fd)?; + assert!(req.data.syscall == ScmpSyscall::from(SYS_getpid as i32)); + notify_id_valid(fd, req.id)?; + + let resp = ScmpNotifResp::new(req.id, magic as i64, 0, 0); + resp.respond(fd)?; + + assert!(unsafe { waitpid(pid, &mut status, 0) } == pid); + assert!(WIFEXITED(status)); + assert!(WEXITSTATUS(status) == 0); + + ctx.reset(ScmpAction::Allow)?; + ctx.add_rule(ScmpAction::Notify, ScmpSyscall::from_name("getppid")?)?; + ctx.load()?; + + let rc = ctx.get_notify_fd()?; + assert!(rc >= 0); + assert!(rc == fd); + + exit(160); +} diff --git a/tests/rust/52-basic-load.rs b/tests/rust/52-basic-load.rs new file mode 100644 index 00000000..df66c8dc --- /dev/null +++ b/tests/rust/52-basic-load.rs @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let api = get_api(); + assert_ne!(api, 0); + + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + if api >= 2 { + ctx.set_ctl_tsync(true)?; + } + if api >= 3 { + ctx.set_ctl_log(true)?; + } + if api >= 4 { + ctx.set_ctl_ssb(true)?; + } + + ctx.load()?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/53-sim-binary_tree.rs b/tests/rust/53-sim-binary_tree.rs new file mode 100644 index 00000000..2ffa5c34 --- /dev/null +++ b/tests/rust/53-sim-binary_tree.rs @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +const ARG_COUNT_MAX: usize = 2; + +struct SyscallErrno { + syscall: ScmpSyscall, + error: i32, + arg_cnt: i32, + // To make the test more interesting, arguments are added to several + // syscalls. To keep the test simple, the arguments always use == operator + args: [i32; ARG_COUNT_MAX], +} + +impl SyscallErrno { + pub const fn new( + syscall: ScmpSyscall, + error: i32, + arg_cnt: i32, + args: [i32; ARG_COUNT_MAX], + ) -> Self { + Self { + syscall, + error, + arg_cnt, + args, + } + } +} +const TABLE: &[SyscallErrno] = &[ + SyscallErrno::new(ScmpSyscall::new("read"), 0, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("write"), 1, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("open"), 2, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("close"), 3, 2, [100, 101]), + SyscallErrno::new(ScmpSyscall::new("stat"), 4, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("fstat"), 5, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("lstat"), 6, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("poll"), 7, 1, [102, 0]), + SyscallErrno::new(ScmpSyscall::new("lseek"), 8, 2, [103, 104]), + SyscallErrno::new(ScmpSyscall::new("mmap"), 9, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("mprotect"), 10, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("munmap"), 11, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("brk"), 12, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("rt_sigaction"), 13, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("rt_sigprocmask"), 14, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("rt_sigreturn"), 15, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("ioctl"), 16, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("pread64"), 17, 1, [105, 0]), + SyscallErrno::new(ScmpSyscall::new("pwrite64"), 18, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("readv"), 19, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("writev"), 20, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("access"), 21, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("pipe"), 22, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("select"), 23, 2, [106, 107]), + SyscallErrno::new(ScmpSyscall::new("sched_yield"), 24, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("mremap"), 25, 2, [108, 109]), + SyscallErrno::new(ScmpSyscall::new("msync"), 26, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("mincore"), 27, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("madvise"), 28, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("dup"), 32, 1, [112, 0]), + SyscallErrno::new(ScmpSyscall::new("dup2"), 33, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("pause"), 34, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("nanosleep"), 35, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("getitimer"), 36, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("alarm"), 37, 0, [0, 0]), +]; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::Aarch64)?; + ctx.add_arch(ScmpArch::Loongarch64)?; + ctx.add_arch(ScmpArch::Ppc64Le)?; + ctx.add_arch(ScmpArch::X8664)?; + + ctx.set_ctl_optimize(2)?; + + for tb in TABLE { + match tb.arg_cnt { + 2 => ctx.add_rule_conditional( + ScmpAction::Errno(tb.error), + tb.syscall, + &[ + scmp_cmp!($arg0 == tb.args[0] as u64), + scmp_cmp!($arg1 == tb.args[1] as u64), + ], + )?, + 1 => ctx.add_rule_conditional( + ScmpAction::Errno(tb.error), + tb.syscall, + &[scmp_cmp!($arg0 == tb.args[0] as u64)], + )?, + _ => ctx.add_rule(ScmpAction::Errno(tb.error), tb.syscall)?, + }; + } + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/54-live-binary_tree.rs b/tests/rust/54-live-binary_tree.rs new file mode 100644 index 00000000..922949f5 --- /dev/null +++ b/tests/rust/54-live-binary_tree.rs @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use nix::fcntl::{open, OFlag}; +use nix::sys::stat::Mode; +use nix::unistd::write; +use std::env; +use std::process; +use utils::*; + +const DENYLIST: [ScmpSyscall; 24] = [ + ScmpSyscall::new("times"), + ScmpSyscall::new("ptrace"), + ScmpSyscall::new("getuid"), + ScmpSyscall::new("syslog"), + ScmpSyscall::new("getgid"), + ScmpSyscall::new("setuid"), + ScmpSyscall::new("setgid"), + ScmpSyscall::new("geteuid"), + ScmpSyscall::new("getegid"), + ScmpSyscall::new("setpgid"), + ScmpSyscall::new("getppid"), + ScmpSyscall::new("getpgrp"), + ScmpSyscall::new("setsid"), + ScmpSyscall::new("setreuid"), + ScmpSyscall::new("setregid"), + ScmpSyscall::new("getgroups"), + ScmpSyscall::new("setgroups"), + ScmpSyscall::new("setresuid"), + ScmpSyscall::new("getresuid"), + ScmpSyscall::new("setresgid"), + ScmpSyscall::new("getresgid"), + ScmpSyscall::new("getpgid"), + ScmpSyscall::new("setfsuid"), + ScmpSyscall::new("setfsgid"), +]; + +fn main() -> Result<()> { + let args: Vec = env::args().collect(); + if args.len() < 2 { + process::exit(1); + } + + let action = util_action_parse(&args[1])?; + assert_eq!(action, ScmpAction::Allow); + util_trap_install()?; + + let fd = open( + "/dev/null", + OFlag::O_WRONLY | OFlag::O_CREAT, + Mode::S_IRUSR | Mode::S_IWUSR, + )?; + let buf = "testing"; + let buf_len = buf.len(); + let mut ctx = ScmpFilterContext::new(ScmpAction::Trap)?; + + ctx.set_ctl_optimize(2)?; + + ctx.add_rule_conditional( + ScmpAction::Allow, + ScmpSyscall::from_name("write")?, + &[scmp_cmp!($arg0 == fd as u64)], + )?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("close")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("rt_sigreturn")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("exit_group")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("sigaltstack")?)?; + ctx.add_rule(ScmpAction::Allow, ScmpSyscall::from_name("munmap")?)?; + + for deny in DENYLIST { + ctx.add_rule(ScmpAction::KillThread, deny)?; + } + + ctx.load()?; + + if write(fd, buf.as_bytes()) == Ok(buf_len) { + process::exit(160); + } else { + process::exit(util_errno()) + } +} diff --git a/tests/rust/55-basic-pfc_binary_tree.rs b/tests/rust/55-basic-pfc_binary_tree.rs new file mode 100644 index 00000000..7974744d --- /dev/null +++ b/tests/rust/55-basic-pfc_binary_tree.rs @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +const ARG_COUNT_MAX: usize = 2; + +struct SyscallErrno { + syscall: ScmpSyscall, + error: i32, + arg_cnt: i32, + // To make the test more interesting, arguments are added to several + // syscalls. To keep the test simple, the arguments always use == operator + args: [i32; ARG_COUNT_MAX], +} + +const TABLE: &[SyscallErrno] = &[ + SyscallErrno::new(ScmpSyscall::new("read"), 0, 2, [100, 101]), + SyscallErrno::new(ScmpSyscall::new("write"), 1, 1, [102, 0]), + SyscallErrno::new(ScmpSyscall::new("open"), 2, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("close"), 3, 2, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("stat"), 4, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("fstat"), 5, 1, [103, 0]), + SyscallErrno::new(ScmpSyscall::new("lstat"), 6, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("poll"), 7, 1, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("lseek"), 8, 1, [104, 0]), + SyscallErrno::new(ScmpSyscall::new("mmap"), 9, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("mprotect"), 10, 1, [105, 0]), + SyscallErrno::new(ScmpSyscall::new("munmap"), 11, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("brk"), 12, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("rt_sigaction"), 13, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("rt_sigprocmask"), 14, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("rt_sigreturn"), 15, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("ioctl"), 16, 0, [0, 0]), + SyscallErrno::new(ScmpSyscall::new("pread64"), 17, 1, [106, 0]), + SyscallErrno::new(ScmpSyscall::new("pwrite64"), 18, 2, [107, 108]), +]; + +impl SyscallErrno { + pub const fn new( + syscall: ScmpSyscall, + error: i32, + arg_cnt: i32, + args: [i32; ARG_COUNT_MAX], + ) -> Self { + Self { + syscall, + error, + arg_cnt, + args, + } + } +} + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + ctx.remove_arch(ScmpArch::Native)?; + + ctx.add_arch(ScmpArch::Aarch64)?; + ctx.add_arch(ScmpArch::Ppc64Le)?; + ctx.add_arch(ScmpArch::X8664)?; + + ctx.set_ctl_optimize(2)?; + + for tb in TABLE { + match tb.arg_cnt { + 2 => ctx.add_rule_conditional( + ScmpAction::Errno(tb.error), + tb.syscall, + &[ + scmp_cmp!($arg0 == tb.args[0] as u64), + scmp_cmp!($arg1 == tb.args[1] as u64), + ], + )?, + 1 => ctx.add_rule_conditional( + ScmpAction::Errno(tb.error), + tb.syscall, + &[scmp_cmp!($arg0 == tb.args[0] as u64)], + )?, + _ => ctx.add_rule(ScmpAction::Errno(tb.error), tb.syscall)?, + }; + } + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/56-basic-iterate_syscalls.rs b/tests/rust/56-basic-iterate_syscalls.rs new file mode 100644 index 00000000..7494e508 --- /dev/null +++ b/tests/rust/56-basic-iterate_syscalls.rs @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::error::SeccompError; +use libseccomp::*; +use std::process::exit; + +const ARCH_LIST: [ScmpArch; 20] = [ + ScmpArch::Native, + ScmpArch::X86, + ScmpArch::X8664, + ScmpArch::X32, + ScmpArch::Arm, + ScmpArch::Aarch64, + ScmpArch::Mips, + ScmpArch::Mips64, + ScmpArch::Mips64N32, + ScmpArch::Mipsel, + ScmpArch::Mipsel64, + ScmpArch::Mipsel64N32, + ScmpArch::Ppc, + ScmpArch::Ppc64, + ScmpArch::Ppc64Le, + ScmpArch::S390, + ScmpArch::S390X, + ScmpArch::Parisc, + ScmpArch::Parisc64, + ScmpArch::Riscv64, +]; + +fn test_arch(arch: ScmpArch, init: i32) -> i32 { + for iter in init..(init + 1000) { + let name: Result = ScmpSyscall::from(iter).get_name_by_arch(arch); + if name.is_err() { + continue; + } + + let n: ScmpSyscall = ScmpSyscall::from_name_by_arch(&name.unwrap(), arch).unwrap(); + if n != iter { + return 1; + } + } + + 0 +} + +fn main() -> Result<()> { + for arch in ARCH_LIST { + let init: i32 = match arch { + ScmpArch::X32 => 0x40000000, + ScmpArch::Mips => 4000, + ScmpArch::Mips64 => 5000, + ScmpArch::Mips64N32 => 6000, + _ => 0, + }; + if test_arch(arch, init) < 0 { + exit(1) + }; + } + + exit(0) +} diff --git a/tests/rust/57-basic-rawsysrc.rs b/tests/rust/57-basic-rawsysrc.rs new file mode 100644 index 00000000..93a33988 --- /dev/null +++ b/tests/rust/57-basic-rawsysrc.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libc::EBADF; +use libseccomp::*; +use nix::unistd::{close, dup}; +use std::os::unix::io::FromRawFd; +use std::os::unix::prelude::OwnedFd; +use utils::*; + +fn main() -> Result<()> { + set_api(3)?; + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + ctx.set_api_sysrawrc(true)?; + + // we must use a closed/invalid fd for this to work + let fd = dup(2)?; + close(fd)?; + assert!(ctx.export_pfc(unsafe { OwnedFd::from_raw_fd(fd) }).is_err()); + assert!(util_errno() == EBADF); + + Ok(()) +} diff --git a/tests/rust/58-live-tsync_notify.rs b/tests/rust/58-live-tsync_notify.rs new file mode 100644 index 00000000..edc55771 --- /dev/null +++ b/tests/rust/58-live-tsync_notify.rs @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libc::{fork, getpid, syscall, waitpid, SYS_getpid, WEXITSTATUS, WIFEXITED}; +use libseccomp::*; +use std::process::exit; + +fn main() -> Result<()> { + let mut status: i32 = 0; + let magic = unsafe { getpid() }; + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + ctx.set_ctl_tsync(true)?; + ctx.add_rule(ScmpAction::Notify, ScmpSyscall::from_name("getpid")?)?; + ctx.load()?; + + let fd = ctx.get_notify_fd()?; + let pid = unsafe { fork() }; + if pid == 0 { + exit((unsafe { syscall(SYS_getpid) } != magic as i64) as i32); + } + + let req = ScmpNotifReq::receive(fd)?; + assert!(req.data.syscall == ScmpSyscall::from(SYS_getpid as i32)); + notify_id_valid(fd, req.id)?; + + let resp = ScmpNotifResp::new(req.id, magic as i64, 0, 0); + resp.respond(fd)?; + + assert!(unsafe { waitpid(pid, &mut status, 0) } == pid); + assert!(WIFEXITED(status)); + assert!(WEXITSTATUS(status) == 0); + + exit(160); +} diff --git a/tests/rust/59-basic-empty_binary_tree.rs b/tests/rust/59-basic-empty_binary_tree.rs new file mode 100644 index 00000000..7d871237 --- /dev/null +++ b/tests/rust/59-basic-empty_binary_tree.rs @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + + ctx.set_ctl_optimize(2)?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/60-sim-precompute.rs b/tests/rust/60-sim-precompute.rs new file mode 100644 index 00000000..9367ed82 --- /dev/null +++ b/tests/rust/60-sim-precompute.rs @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library test program +// + +use anyhow::Result; +use libseccomp::*; +use utils::*; + +fn main() -> Result<()> { + let opts = util_getopt(); + + let mut ctx = ScmpFilterContext::new(ScmpAction::Allow)?; + ctx.precompute()?; + ctx.add_rule_exact(ScmpAction::KillThread, ScmpSyscall::from(1000))?; + ctx.precompute()?; + ctx.add_rule_exact(ScmpAction::KillThread, ScmpSyscall::from(1001))?; + ctx.precompute()?; + + util_filter_output(&opts, &ctx) +} diff --git a/tests/rust/Cargo.lock b/tests/rust/Cargo.lock new file mode 100644 index 00000000..495c008f --- /dev/null +++ b/tests/rust/Cargo.lock @@ -0,0 +1,311 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" +dependencies = [ + "atty", + "bitflags 1.3.2", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libseccomp" +version = "0.3.0" +source = "git+https://github.com/libseccomp-rs/libseccomp-rs.git#41996c63e16b3d282c605a3eab903cd6601d0921" +dependencies = [ + "bitflags 2.4.2", + "cfg-if", + "libc", + "libseccomp-sys", + "pkg-config", +] + +[[package]] +name = "libseccomp-sys" +version = "0.2.1" +source = "git+https://github.com/libseccomp-rs/libseccomp-rs.git#41996c63e16b3d282c605a3eab903cd6601d0921" + +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset", + "pin-utils", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "os_str_bytes" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rust-bindings-tests" +version = "0.0.0" +dependencies = [ + "anyhow", + "clap", + "libc", + "libseccomp", + "nix", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/tests/rust/Cargo.toml b/tests/rust/Cargo.toml new file mode 100644 index 00000000..183b9d47 --- /dev/null +++ b/tests/rust/Cargo.toml @@ -0,0 +1,257 @@ +[package] +name = "rust-bindings-tests" +version = "0.0.0" +authors = ["Manabu Sugimoto "] +license = "LGPL-2.1-only" +edition = "2021" + +[dependencies] +anyhow = "1.0.80" +clap = { version = "~3.2.22", features = ["derive"] } +libc = "0.2.153" +nix = "0.26.3" +libseccomp = { git = "https://github.com/libseccomp-rs/libseccomp-rs.git", features = ["const-syscall"] } + +[lib] +name = "utils" +path = "utils.rs" + +[[bin]] +name = "01-sim-allow" +path = "01-sim-allow.rs" + +[[bin]] +name = "02-sim-basic" +path = "02-sim-basic.rs" + +[[bin]] +name = "03-sim-basic_chains" +path = "03-sim-basic_chains.rs" + +[[bin]] +name = "04-sim-multilevel_chains" +path = "04-sim-multilevel_chains.rs" + +[[bin]] +name = "05-sim-long_jumps" +path = "05-sim-long_jumps.rs" + +[[bin]] +name = "06-sim-actions" +path = "06-sim-actions.rs" + +[[bin]] +name = "07-sim-db_bug_looping" +path = "07-sim-db_bug_looping.rs" + +[[bin]] +name = "08-sim-subtree_checks" +path = "08-sim-subtree_checks.rs" + +[[bin]] +name = "09-sim-syscall_priority_pre" +path = "09-sim-syscall_priority_pre.rs" + +[[bin]] +name = "10-sim-syscall_priority_post" +path = "10-sim-syscall_priority_post.rs" + +[[bin]] +name = "11-basic-basic_errors" +path = "11-basic-basic_errors.rs" + +[[bin]] +name = "12-sim-basic_masked_ops" +path = "12-sim-basic_masked_ops.rs" + +[[bin]] +name = "13-basic-attrs" +path = "13-basic-attrs.rs" + +[[bin]] +name = "14-sim-reset" +path = "14-sim-reset.rs" + +[[bin]] +name = "15-basic-resolver" +path = "15-basic-resolver.rs" + +[[bin]] +name = "16-sim-arch_basic" +path = "16-sim-arch_basic.rs" + +[[bin]] +name = "17-sim-arch_merge" +path = "17-sim-arch_merge.rs" + +[[bin]] +name = "18-sim-basic_allowlist" +path = "18-sim-basic_allowlist.rs" + +[[bin]] +name = "19-sim-missing_syscalls" +path = "19-sim-missing_syscalls.rs" + +[[bin]] +name = "20-live-basic_die" +path = "20-live-basic_die.rs" + +[[bin]] +name = "21-live-basic_allow" +path = "21-live-basic_allow.rs" + +[[bin]] +name = "22-sim-basic_chains_array" +path = "22-sim-basic_chains_array.rs" + +[[bin]] +name = "23-sim-arch_all_le_basic" +path = "23-sim-arch_all_le_basic.rs" + +[[bin]] +name = "24-live-arg_allow" +path = "24-live-arg_allow.rs" + +[[bin]] +name = "25-sim-multilevel_chains_adv" +path = "25-sim-multilevel_chains_adv.rs" + +[[bin]] +name = "26-sim-arch_all_be_basic" +path = "26-sim-arch_all_be_basic.rs" + +[[bin]] +name = "27-sim-bpf_blk_state" +path = "27-sim-bpf_blk_state.rs" + +[[bin]] +name = "28-sim-arch_x86" +path = "28-sim-arch_x86.rs" + +[[bin]] +name = "29-sim-pseudo_syscall" +path = "29-sim-pseudo_syscall.rs" + +[[bin]] +name = "30-sim-socket_syscalls" +path = "30-sim-socket_syscalls.rs" + +[[bin]] +name = "31-basic-version_check" +path = "31-basic-version_check.rs" + +[[bin]] +name = "32-live-tsync_allow" +path = "32-live-tsync_allow.rs" + +[[bin]] +name = "33-sim-socket_syscalls_be" +path = "33-sim-socket_syscalls_be.rs" + +[[bin]] +name = "34-sim-basic_denylist" +path = "34-sim-basic_denylist.rs" + +[[bin]] +name = "35-sim-negative_one" +path = "35-sim-negative_one.rs" + +[[bin]] +name = "36-sim-ipc_syscalls" +path = "36-sim-ipc_syscalls.rs" + +[[bin]] +name = "37-sim-ipc_syscalls_be" +path = "37-sim-ipc_syscalls_be.rs" + +[[bin]] +name = "38-basic-pfc_coverage" +path = "38-basic-pfc_coverage.rs" + +[[bin]] +name = "39-basic-api_level" +path = "39-basic-api_level.rs" + +[[bin]] +name = "40-sim-log" +path = "40-sim-log.rs" + +[[bin]] +name = "41-sim-syscall_priority_arch" +path = "41-sim-syscall_priority_arch.rs" + +[[bin]] +name = "42-sim-adv_chains" +path = "42-sim-adv_chains.rs" + +[[bin]] +name = "43-sim-a2_order" +path = "43-sim-a2_order.rs" + +[[bin]] +name = "44-live-a2_order" +path = "44-live-a2_order.rs" + +[[bin]] +name = "45-sim-chain_code_coverage" +path = "45-sim-chain_code_coverage.rs" + +[[bin]] +name = "46-sim-kill_process" +path = "46-sim-kill_process.rs" + +[[bin]] +name = "47-live-kill_process" +path = "47-live-kill_process.rs" + +[[bin]] +name = "48-sim-32b_args" +path = "48-sim-32b_args.rs" + +[[bin]] +name = "49-sim-64b_comparisons" +path = "49-sim-64b_comparisons.rs" + +[[bin]] +name = "50-sim-hash_collision" +path = "50-sim-hash_collision.rs" + +[[bin]] +name = "51-live-user_notification" +path = "51-live-user_notification.rs" + +[[bin]] +name = "52-basic-load" +path = "52-basic-load.rs" + +[[bin]] +name = "53-sim-binary_tree" +path = "53-sim-binary_tree.rs" + +[[bin]] +name = "54-live-binary_tree" +path = "54-live-binary_tree.rs" + +[[bin]] +name = "55-basic-pfc_binary_tree" +path = "55-basic-pfc_binary_tree.rs" + +[[bin]] +name = "56-basic-iterate_syscalls" +path = "56-basic-iterate_syscalls.rs" + +[[bin]] +name = "57-basic-rawsysrc" +path = "57-basic-rawsysrc.rs" + +[[bin]] +name = "58-live-tsync_notify" +path = "58-live-tsync_notify.rs" + +[[bin]] +name = "59-basic-empty_binary_tree" +path = "59-basic-empty_binary_tree.rs" + +[[bin]] +name = "60-sim-precompute" +path = "60-sim-precompute.rs" diff --git a/tests/rust/utils.rs b/tests/rust/utils.rs new file mode 100644 index 00000000..bbf727c5 --- /dev/null +++ b/tests/rust/utils.rs @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: LGPL-2.1-only +// +// Copyright 2024 Sony Group Corporation +// +// Seccomp Library utility code for tests +// + +use anyhow::{anyhow, Result}; +use clap::Parser; +use libseccomp::*; +use nix::sys::signal::SigmaskHow::SIG_UNBLOCK; +use nix::sys::signal::{sigaction, sigprocmask, SaFlags, SigAction, SigHandler, SigSet, SIGSYS}; +use std::fs::OpenOptions; +use std::io::Write; + +#[derive(Parser)] +#[clap(version, author)] +pub struct Opts { + /// Generate BPF output + #[clap(short, long)] + pub bpf: bool, + /// Generate PFC output [default] + #[clap(short, long)] + pub pfc: bool, +} + +// This function parses the arguments passed to the test from the command line. +// Returns the Opts on success. +pub fn util_getopt() -> Opts { + let mut opts = Opts::parse(); + if !opts.bpf && !opts.pfc { + opts.pfc = true; + } + + opts +} + +// This function outputs the seccomp filter to stdout in either BPF or PFC +// format depending on the test paramaeters supplied by Opts. +pub fn util_filter_output(opts: &Opts, ctx: &ScmpFilterContext) -> Result<()> { + if opts.bpf { + ctx.export_bpf(std::io::stdout())?; + } else { + ctx.export_pfc(std::io::stdout())?; + } + + Ok(()) +} + +// This function outputs the seccomp action corresponding +// to the action name received as parameter +pub fn util_action_parse(action: &str) -> Result { + match action.to_lowercase().as_str() { + "kill" => Ok(ScmpAction::KillThread), + "kill_process" => Ok(ScmpAction::KillProcess), + "trap" => Ok(ScmpAction::Trap), + "errno" => Ok(ScmpAction::Errno(163)), + "trace" => Err(anyhow!("trace is not yet supported")), + "allow" => Ok(ScmpAction::Allow), + "log" => Ok(ScmpAction::Log), + _ => Err(anyhow!("{} is an invalid action", action)), + } +} + +// This function outputs an error representing the last OS error which occurred. +pub fn util_errno() -> i32 { + std::io::Error::last_os_error().raw_os_error().unwrap() +} + +// This function writes a string to a file that is present at the +// path provided as the parameter +pub fn util_file_write(path: &str) -> i32 { + let buff: &str = "testing"; + + let file = OpenOptions::new().write(true).create(true).open(path); + if file.is_err() { + return util_errno(); + } + + if file.unwrap().write_all(buff.as_bytes()).is_err() { + return util_errno(); + } + + 0 +} + +// This function install a TRAP action signal handler +extern "C" fn trap_handler(_: i32, _: *mut libc::siginfo_t, _: *mut libc::c_void) { + unsafe { libc::_exit(161) }; +} + +// Install a TRAP action signal handler +// +// This function installs the TRAP action signal handler and is based on +// examples from Will Drewry and Kees Cook. Returns zero on success, negative +// values on failure. +pub fn util_trap_install() -> Result<(), nix::Error> { + let sig_action = SigAction::new( + SigHandler::SigAction(trap_handler), + SaFlags::SA_SIGINFO, + SigSet::empty(), + ); + + let mut sig_mask = SigSet::empty(); + sig_mask.add(SIGSYS); + + unsafe { + sigaction(SIGSYS, &sig_action)?; + } + sigprocmask(SIG_UNBLOCK, Some(&sig_mask), Some(&mut SigSet::empty()))?; + + Ok(()) +}