From: Chen Jingpiao Date: Mon, 6 Aug 2018 13:58:43 +0000 (+0800) Subject: tests: check seccomp-assisted syscall filtering X-Git-Tag: v5.3~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3ecaff4fd1e6394ab4aa7e5f02a579c9e746880f;p=strace tests: check seccomp-assisted syscall filtering Test filter_seccomp-perf checks whether seccomp-filter is actually enabled by comparing the number of syscalls performed in a time interval when seccomp-filter is enabled vs. disabled. The number of syscalls should be at least one order of magnitude higher when seccomp-filter is enabled. Test filter_seccomp-flag ensures the audit_arch_vec[].flag constants do not conflict with syscall numbers. If this test fails, then the number of syscalls grew high enough that the code for seccomp-filter needs to be updated. * tests/init.sh (test_prog_set): New function. * tests/status-none-f.c: New file. * tests/filter_seccomp.in: Likewise. * tests/filter_seccomp.sh: Likewise. * tests/filter_seccomp-perf.c: Likewise. * tests/filter_seccomp-flag.c: Likewise. * tests/filter_seccomp-perf.test: New test. * tests/Makefile.am (EXTRA_DIST): Add filter_seccomp.in and filter_seccomp.sh. (MISC_TESTS): Add filter_seccomp-perf.test. (check_PROGRAMS): Add filter_seccomp-perf and filter_seccomp-flag. * tests/pure_executables.list: Add status-none-f. * tests/.gitignore: Add status-none-f, filter_seccomp-perf, and filter_seccomp-flag. * tests/gen_tests.in (filter_seccomp, filter_seccomp-flag): New entries. Co-authored-by: Paul Chaignon Co-Authored-by: Dmitry V. Levin --- diff --git a/tests/.gitignore b/tests/.gitignore index f8374754..7ac73640 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -93,6 +93,7 @@ fdatasync fflush file_handle file_ioctl +filter_seccomp-perf filter-unavailable finit_module flock @@ -523,6 +524,7 @@ sched_yield scm_rights scno.h seccomp-filter +filter_seccomp-flag seccomp-filter-v seccomp-strict seccomp_get_action_avail @@ -602,6 +604,7 @@ statfs64 status-all status-failed status-none +status-none-f status-none-threads status-successful status-unfinished diff --git a/tests/Makefile.am b/tests/Makefile.am index 622f761c..bd9f5465 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -96,6 +96,8 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \ delay \ execve-v \ execveat-v \ + filter_seccomp-flag \ + filter_seccomp-perf \ filter-unavailable \ fork-f \ fsync-y \ @@ -324,6 +326,7 @@ MISC_TESTS = \ detach-sleeping.test \ detach-stopped.test \ fflush.test \ + filter_seccomp-perf.test \ filter-unavailable.test \ filtering_fd-syntax.test \ filtering_syscall-syntax.test \ @@ -406,6 +409,8 @@ EXTRA_DIST = \ eventfd.expected \ fadvise.h \ fcntl-common.c \ + filter_seccomp.in \ + filter_seccomp.sh \ filter-unavailable.expected \ fstatat.c \ fstatx.c \ diff --git a/tests/filter_seccomp-flag.c b/tests/filter_seccomp-flag.c new file mode 100644 index 00000000..25d78800 --- /dev/null +++ b/tests/filter_seccomp-flag.c @@ -0,0 +1,83 @@ +/* + * Check that syscall numbers do not conflict with seccomp filter flags. + * + * Copyright (c) 2019 Paul Chaignon + * Copyright (c) 2019 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include "arch_defs.h" +#include "sysent.h" +#include "scno.h" +#include + +#ifdef __x86_64__ +# ifndef __X32_SYSCALL_BIT +# define __X32_SYSCALL_BIT 0x40000000 +# endif +#endif + +/* Define these shorthand notations to simplify the syscallent files. */ +#include "sysent_shorthand_defs.h" + +const struct_sysent sysent0[] = { +#include "syscallent.h" +}; + +#if SUPPORTED_PERSONALITIES > 1 +static const struct_sysent sysent1[] = { +# include "syscallent1.h" +}; +#endif + +#if SUPPORTED_PERSONALITIES > 2 +static const struct_sysent sysent2[] = { +# include "syscallent2.h" +}; +#endif + +const unsigned int nsyscall_vec[SUPPORTED_PERSONALITIES] = { + ARRAY_SIZE(sysent0), +#if SUPPORTED_PERSONALITIES > 1 + ARRAY_SIZE(sysent1), +#endif +#if SUPPORTED_PERSONALITIES > 2 + ARRAY_SIZE(sysent2), +#endif +}; + +struct audit_arch_t { + unsigned int arch; + unsigned int flag; +}; + +static const struct audit_arch_t audit_arch_vec[SUPPORTED_PERSONALITIES] = { +#if SUPPORTED_PERSONALITIES > 1 + PERSONALITY0_AUDIT_ARCH, + PERSONALITY1_AUDIT_ARCH, +# if SUPPORTED_PERSONALITIES > 2 + PERSONALITY2_AUDIT_ARCH, +# endif +#endif +}; + +int +main(void) +{ + for (unsigned int p = 0; p < SUPPORTED_PERSONALITIES; ++p) { + if (!audit_arch_vec[p].flag) + continue; + for (unsigned int nr = 1; nr < nsyscall_vec[p]; ++nr) { + if (!(audit_arch_vec[p].flag & nr)) + continue; + error_msg_and_fail("system call number %u of" + " personality %u conflicts with" + " seccomp filter flag %#x", + nr, p, audit_arch_vec[p].flag); + } + } + return 0; +} diff --git a/tests/filter_seccomp-perf.c b/tests/filter_seccomp-perf.c new file mode 100644 index 00000000..9d5f90a1 --- /dev/null +++ b/tests/filter_seccomp-perf.c @@ -0,0 +1,39 @@ +/* + * Check seccomp filter performance. + * + * Copyright (c) 2019 Paul Chaignon + * Copyright (c) 2019 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include +#include +#include +#include + +static volatile bool stop = false; + +static void +handler(int signo) +{ + stop = true; +} + +int +main(void) +{ + unsigned int i; + int rc = 0; + + signal(SIGALRM, handler); + alarm(1); + + for (i = 0; !stop; i++) { + rc |= chdir("."); + } + printf("%d\n", i); + return rc; +} diff --git a/tests/filter_seccomp-perf.test b/tests/filter_seccomp-perf.test new file mode 100755 index 00000000..9e6f45f7 --- /dev/null +++ b/tests/filter_seccomp-perf.test @@ -0,0 +1,27 @@ +#!/bin/sh +# +# Check seccomp filter performance. +# +# Copyright (c) 2019 Paul Chaignon +# Copyright (c) 2019 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +. "${srcdir=.}/init.sh" +. "${srcdir=.}/filter_seccomp.sh" + +args="-f -qq -e signal=none -e trace=fchdir ../$NAME" +num_regular="$(run_strace $args)" +mv "$LOG" "$LOG.regular" +num_seccomp="$(run_strace --seccomp-bpf $args)" +mv "$LOG" "$LOG.seccomp" +match_diff "$LOG.regular" "$LOG.seccomp" + +min_ratio=8 +# With seccomp filter enabled, we should be able to complete +# at least $min_ratio times more chdir system calls. +ratio="$((num_seccomp / num_regular))" +if [ "$ratio" -lt "$min_ratio" ]; then + fail_ "Only $ratio times more syscalls performed with seccomp filter enabled, expected at least $min_ratio times speedup" +fi diff --git a/tests/filter_seccomp.in b/tests/filter_seccomp.in new file mode 100644 index 00000000..76e4d7e6 --- /dev/null +++ b/tests/filter_seccomp.in @@ -0,0 +1,4 @@ +fork-f -a26 -qq -e signal=none -e trace=chdir +vfork-f -a26 -qq -e signal=none -e trace=chdir +fork-f -a26 -qq -e signal=none -e trace=chdir,%memory,%ipc,%pure,%signal,%network -e status=failed +status-none-f -e trace=!ptrace -e status=none diff --git a/tests/filter_seccomp.sh b/tests/filter_seccomp.sh new file mode 100755 index 00000000..783e9519 --- /dev/null +++ b/tests/filter_seccomp.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# +# Skip the test if seccomp filter is not available. +# +# Copyright (c) 2019 The strace developers. +# All rights reserved. +# +# SPDX-License-Identifier: GPL-2.0-or-later + +$STRACE --seccomp-bpf -f -e trace=fchdir / > /dev/null 2> "$LOG" ||: +if grep -x "[^:]*strace: seccomp filter is requested but unavailable" \ + "$LOG" > /dev/null; then + skip_ 'seccomp filter is unavailable' +fi diff --git a/tests/gen_tests.in b/tests/gen_tests.in index 9d913749..fe56addd 100644 --- a/tests/gen_tests.in +++ b/tests/gen_tests.in @@ -72,6 +72,8 @@ fcntl64 -a8 fdatasync -a14 file_handle -e trace=name_to_handle_at,open_by_handle_at file_ioctl +ioctl.test +filter_seccomp . "${srcdir=.}/filter_seccomp.sh"; test_prog_set --seccomp-bpf -f +filter_seccomp-flag ../$NAME finit_module -a25 flock -a19 fork-f -a26 -qq -f -e signal=none -e trace=chdir diff --git a/tests/init.sh b/tests/init.sh index 40e62188..4cd2d153 100644 --- a/tests/init.sh +++ b/tests/init.sh @@ -324,6 +324,11 @@ test_trace_expr() < negative.list } +test_prog_set() +{ + test_pure_prog_set "$@" < "$srcdir/$NAME.in" +} + check_prog cat check_prog rm diff --git a/tests/pure_executables.list b/tests/pure_executables.list index 0a61a8eb..6f3650c6 100755 --- a/tests/pure_executables.list +++ b/tests/pure_executables.list @@ -511,6 +511,7 @@ statfs64 status-all status-failed status-none +status-none-f status-successful status-unfinished statx diff --git a/tests/status-none-f.c b/tests/status-none-f.c new file mode 100644 index 00000000..33887a1b --- /dev/null +++ b/tests/status-none-f.c @@ -0,0 +1,19 @@ +/* + * Check basic seccomp filtering with large number of traced syscalls. + * + * Copyright (c) 2019 The strace developers. + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "tests.h" +#include +#include + +int +main(void) +{ + printf("%-5d +++ exited with 0 +++\n", getpid()); + return 0; +}