diff options
Diffstat (limited to 'tests/util.c')
-rw-r--r-- | tests/util.c | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/tests/util.c b/tests/util.c new file mode 100644 index 0000000..f978e8a --- /dev/null +++ b/tests/util.c @@ -0,0 +1,253 @@ +/** + * Seccomp Library utility code for tests + * + * Copyright (c) 2012 Red Hat <eparis@redhat.com> + * Author: Eric Paris <eparis@redhat.com> + */ + +/* + * This library is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see <http://www.gnu.org/licenses>. + */ + +#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); +} + +/** + * Add rules for gcov/lcov + * @param ctx the filter context + * @param action the action for the rules + * + * This function is to make it easier for developers to temporarily add support + * for gcov/lcov to a test program; it likely should not be used in the normal + * regression tests. Further, this should only be necessary for the "live" + * tests. + * + */ +int util_gcov_rules(const scmp_filter_ctx ctx, int action) +{ + int rc; + + rc = seccomp_rule_add(ctx, action, SCMP_SYS(open), 0); + if (rc != 0) + return rc; + rc = seccomp_rule_add(ctx, action, SCMP_SYS(openat), 0); + if (rc != 0) + return rc; + rc = seccomp_rule_add(ctx, action, SCMP_SYS(fcntl), 0); + if (rc != 0) + return rc; + rc = seccomp_rule_add(ctx, action, SCMP_SYS(lseek), 0); + if (rc != 0) + return rc; + rc = seccomp_rule_add(ctx, action, SCMP_SYS(read), 0); + if (rc != 0) + return rc; + rc = seccomp_rule_add(ctx, action, SCMP_SYS(write), 0); + if (rc != 0) + return rc; + rc = seccomp_rule_add(ctx, action, SCMP_SYS(getpid), 0); + if (rc != 0) + return rc; + + return 0; +} + +/** + * Parse the arguments passed to main + * @param argc the argument count + * @param argv the argument pointer + * @param opts the options structure + * + * This function parses the arguments passed to the test from the command line. + * Returns zero on success and negative values on failure. + * + */ +int util_getopt(int argc, char *argv[], struct util_options *opts) +{ + int rc = 0; + + if (opts == NULL) + return -EFAULT; + + memset(opts, 0, sizeof(*opts)); + while (1) { + int c, option_index = 0; + const struct option long_options[] = { + {"bpf", no_argument, &(opts->bpf_flg), 1}, + {"pfc", no_argument, &(opts->bpf_flg), 0}, + {0, 0, 0, 0}, + }; + + c = getopt_long(argc, argv, "bp", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + break; + case 'b': + opts->bpf_flg = 1; + break; + case 'p': + opts->bpf_flg = 0; + break; + default: + rc = -EINVAL; + break; + } + } + + if (rc == -EINVAL || optind < argc) { + fprintf(stderr, "usage %s: [--bpf,-b] [--pfc,-p]\n", argv[0]); + rc = -EINVAL; + } + + return rc; +} + +/** + * Output the filter in either BPF or PFC + * @param opts the options structure + * @param ctx the filter context + * + * This function outputs the seccomp filter to stdout in either BPF or PFC + * format depending on the test paramaeters supplied by @opts. + * + */ +int util_filter_output(const struct util_options *opts, + const scmp_filter_ctx ctx) +{ + int rc; + + if (opts == NULL) + return -EFAULT; + + if (opts->bpf_flg) + rc = seccomp_export_bpf(ctx, STDOUT_FILENO); + else + rc = seccomp_export_pfc(ctx, STDOUT_FILENO); + + 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; + if (strcasecmp(action, "KILL_PROCESS") == 0) + return SCMP_ACT_KILL_PROCESS; + 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; + else if (strcasecmp(action, "LOG") == 0) + return SCMP_ACT_LOG; + + 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; +} |