summaryrefslogtreecommitdiffstats
path: root/tests/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/util.c')
-rw-r--r--tests/util.c253
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;
+}