This test type enables the creation of "live", not simulated, tests which can be used to verify proper operation of the library on systems that support seccomp mode 2.
Signed-off-by: Paul Moore <[email protected]> --- tests/regression | 64 +++++++++++++++++++++++++++++++++++ tests/util.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/util.h | 6 +++ tests/util.py | 53 +++++++++++++++++++++++++++++ 4 files changed, 223 insertions(+) diff --git a/tests/regression b/tests/regression index a572966..e4df007 100755 --- a/tests/regression +++ b/tests/regression @@ -533,6 +533,63 @@ function run_test_basic() { } # +# Run the specified "live" test +# +# Tests that belong to the "live" test type will attempt to run a live test +# of the libseccomp library on the host system; for obvious reasons the host +# system must support seccomp mode 2 for this to work correctly. +# +# Arguments: +# 1 value of test number from batch file +# 2 string containing line of test data from batch file +# +function run_test_live() { + local rc + local line=($2) + + # parse the test line + line_cmd=${line[0]} + line_act=${line[1]} + line_test="$line_cmd $line_act" + + # print out the input test data to the log file + print_data "$1" "$2" + + # run the command + exec 4>/dev/null + run_test_command "$1" "$line_cmd" "$line_act" "" 4 + rc=$? + exec 4>&- + + # return value codes for this test type: + # 159: KILL + # 160: ALLOW + # 161: TRAP + # 162: TRACE (currently unsupported) + # 163: ERRNO + if [[ $line_act == "KILL" && $rc -eq 159 ]]; then + print_result $1 "SUCCESS" "" + stats_success=$(($stats_success+1)) + elif [[ $line_act == "ALLOW" && $rc -eq 160 ]]; then + print_result $1 "SUCCESS" "" + stats_success=$(($stats_success+1)) + elif [[ $line_act == "TRAP" && $rc -eq 161 ]]; then + print_result $1 "SUCCESS" "" + stats_success=$(($stats_success+1)) + elif [[ $line_act == "TRACE" ]]; then + print_result $1 "ERROR" "unsupported action \"$line_act\"" + stats_error=$(($stats_error+1)) + elif [[ $line_act == "ERRNO" && $rc -eq 163 ]]; then + print_result $1 "SUCCESS" "" + stats_success=$(($stats_success+1)) + else + print_result $1 "FAILURE" "$line_test rc=$rc" + stats_failure=$(($stats_failure+1)) + fi + stats_all=$(($stats_all+1)) +} + +# # Run a single test from the specified batch # # Arguments: @@ -555,6 +612,13 @@ function run_test() { run_test_bpf_sim "$1" $2 "$3" elif [[ "$4" == "bpf-sim-fuzz" ]]; then run_test_bpf_sim_fuzz "$1" $2 "$3" + elif [[ "$4" == "live" ]]; then + # only run this test if explicitly requested + if [[ -n $type ]]; then + run_test_live "$testnumstr" "$3" + else + stats_skipped=$(($stats_skipped+1)) + fi else print_result $testnumstr "ERROR" "test type $4 not supported" stats_error=$(($stats_error+1)) diff --git a/tests/util.c b/tests/util.c index ce507fa..02b0043 100644 --- a/tests/util.c +++ b/tests/util.c @@ -20,16 +20,34 @@ */ #include <errno.h> +#include <fcntl.h> #include <getopt.h> +#include <signal.h> #include <stdio.h> #include <string.h> #include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> #include <seccomp.h> #include "util.h" /** + * SIGSYS signal handler + * @param nr the signal number + * @param info siginfo_t pointer + * @param void_context handler context + * + * Simple signal handler for SIGSYS which exits with error code 161. + * + */ +static void _trap_handler(int signal, siginfo_t *info, void *ctx) +{ + _exit(161); +} + +/** * Parse the arguments passed to main * @param argc the argument count * @param argv the argument pointer @@ -107,3 +125,85 @@ int util_filter_output(const struct util_options *opts, return rc; } + +/** + * 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. + * + */ +int util_trap_install(void) +{ + struct sigaction signal_handler; + sigset_t signal_mask; + + memset(&signal_handler, 0, sizeof(signal_handler)); + sigemptyset(&signal_mask); + sigaddset(&signal_mask, SIGSYS); + + signal_handler.sa_sigaction = &_trap_handler; + signal_handler.sa_flags = SA_SIGINFO; + if (sigaction(SIGSYS, &signal_handler, NULL) < 0) + return -errno; + if (sigprocmask(SIG_UNBLOCK, &signal_mask, NULL)) + return -errno; + + return 0; +} + +/** + * Parse a filter action string into an action value + * @param action the action string + * + * Parse a seccomp action string into the associated integer value. Returns + * the correct value on success, -1 on failure. + * + */ +int util_action_parse(const char *action) +{ + if (action == NULL) + return -1; + + if (strcasecmp(action, "KILL") == 0) + return SCMP_ACT_KILL; + else if (strcasecmp(action, "TRAP") == 0) + return SCMP_ACT_TRAP; + else if (strcasecmp(action, "ERRNO") == 0) + return SCMP_ACT_ERRNO(163); + else if (strcasecmp(action, "TRACE") == 0) + return -1; /* not yet supported */ + else if (strcasecmp(action, "ALLOW") == 0) + return SCMP_ACT_ALLOW; + + return -1; +} + +/** + * Write a string to a file + * @param path the file path + * + * Open the specified file, write a string to the file, and close the file. + * Return zero on success, negative values on error. + * + */ +int util_file_write(const char *path) +{ + int fd; + const char buf[] = "testing"; + ssize_t buf_len = strlen(buf); + + fd = open(path, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); + if (fd < 0) + return errno; + if (write(fd, buf, buf_len) < buf_len) { + int rc = errno; + close(fd); + return rc; + } + if (close(fd) < 0) + return errno; + + return 0; +} diff --git a/tests/util.h b/tests/util.h index 68af8a0..b3c5a29 100644 --- a/tests/util.h +++ b/tests/util.h @@ -31,4 +31,10 @@ int util_getopt(int argc, char *argv[], struct util_options *opts); int util_filter_output(const struct util_options *opts, const scmp_filter_ctx ctx); +int util_trap_install(void); + +int util_action_parse(const char *action); + +int util_file_write(const char *path); + #endif diff --git a/tests/util.py b/tests/util.py index 8e4c689..20704f6 100644 --- a/tests/util.py +++ b/tests/util.py @@ -22,7 +22,16 @@ """ Python utility code for the libseccomp test suite """ import argparse +import os import sys +import signal + +from seccomp import * + +def trap_handler(signum, frame): + """ SIGSYS signal handler, internal use only + """ + os._exit(161) def get_opt(): """ Parse the arguments passed to main @@ -52,5 +61,49 @@ def filter_output(args, ctx): else: ctx.export_pfc(sys.stdout) +def install_trap(): + """ Install a TRAP action signal handler + + Description: + Install the TRAP action signal handler. + """ + signal.signal(signal.SIGSYS, trap_handler) + +def parse_action(action): + """ Parse a filter action string into an action value + + Arguments: + action - the action string + + Description: + Parse a seccomp action string into the associated integer value. + """ + if action == "KILL": + return KILL + elif action == "TRAP": + return TRAP + elif action == "ERRNO": + return ERRNO(163) + elif action == "TRACE": + raise RuntimeError("the TRACE action is not currently supported") + elif action == "ALLOW": + return ALLOW + raise RuntimeError("invalid action string") + + +def write_file(path): + """ Write a string to a file + + Arguments: + path - the file path + + Description: + Open the specified file, write a string to the file, and close the file. + """ + fd = os.open(path, os.O_WRONLY|os.O_CREAT, 0600) + if not os.write(fd, "testing") == len("testing"): + raise IOError("failed to write the full test string in write_file()") + os.close(fd) + # kate: syntax python; # kate: indent-mode python; space-indent on; indent-width 4; mixedindent off; ------------------------------------------------------------------------------ Free Next-Gen Firewall Hardware Offer Buy your Sophos next-gen firewall before the end March 2013 and get the hardware for free! Learn more. http://p.sf.net/sfu/sophos-d2d-feb _______________________________________________ libseccomp-discuss mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/libseccomp-discuss
