|
Packit |
56e23f |
/**
|
|
Packit |
56e23f |
* Seccomp Library utility code for tests
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
* Copyright (c) 2012 Red Hat <eparis@redhat.com>
|
|
Packit |
56e23f |
* Author: Eric Paris <eparis@redhat.com>
|
|
Packit |
56e23f |
*/
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
/*
|
|
Packit |
56e23f |
* This library is free software; you can redistribute it and/or modify it
|
|
Packit |
56e23f |
* under the terms of version 2.1 of the GNU Lesser General Public License as
|
|
Packit |
56e23f |
* published by the Free Software Foundation.
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
* This library is distributed in the hope that it will be useful, but WITHOUT
|
|
Packit |
56e23f |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
Packit |
56e23f |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
Packit |
56e23f |
* for more details.
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
56e23f |
* along with this library; if not, see <http://www.gnu.org/licenses>.
|
|
Packit |
56e23f |
*/
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
#include <errno.h>
|
|
Packit |
56e23f |
#include <fcntl.h>
|
|
Packit |
56e23f |
#include <getopt.h>
|
|
Packit |
56e23f |
#include <signal.h>
|
|
Packit |
56e23f |
#include <stdio.h>
|
|
Packit |
56e23f |
#include <string.h>
|
|
Packit |
56e23f |
#include <unistd.h>
|
|
Packit |
56e23f |
#include <sys/types.h>
|
|
Packit |
56e23f |
#include <sys/stat.h>
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
#include <seccomp.h>
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
#include "util.h"
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
/**
|
|
Packit |
56e23f |
* SIGSYS signal handler
|
|
Packit |
56e23f |
* @param nr the signal number
|
|
Packit |
56e23f |
* @param info siginfo_t pointer
|
|
Packit |
56e23f |
* @param void_context handler context
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
* Simple signal handler for SIGSYS which exits with error code 161.
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
*/
|
|
Packit |
56e23f |
static void _trap_handler(int signal, siginfo_t *info, void *ctx)
|
|
Packit |
56e23f |
{
|
|
Packit |
56e23f |
_exit(161);
|
|
Packit |
56e23f |
}
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
/**
|
|
Packit |
56e23f |
* Parse the arguments passed to main
|
|
Packit |
56e23f |
* @param argc the argument count
|
|
Packit |
56e23f |
* @param argv the argument pointer
|
|
Packit |
56e23f |
* @param opts the options structure
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
* This function parses the arguments passed to the test from the command line.
|
|
Packit |
56e23f |
* Returns zero on success and negative values on failure.
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
*/
|
|
Packit |
56e23f |
int util_getopt(int argc, char *argv[], struct util_options *opts)
|
|
Packit |
56e23f |
{
|
|
Packit |
56e23f |
int rc = 0;
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
if (opts == NULL)
|
|
Packit |
56e23f |
return -EFAULT;
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
memset(opts, 0, sizeof(*opts));
|
|
Packit |
56e23f |
while (1) {
|
|
Packit |
56e23f |
int c, option_index = 0;
|
|
Packit |
56e23f |
const struct option long_options[] = {
|
|
Packit |
56e23f |
{"bpf", no_argument, &(opts->bpf_flg), 1},
|
|
Packit |
56e23f |
{"pfc", no_argument, &(opts->bpf_flg), 0},
|
|
Packit |
56e23f |
{0, 0, 0, 0},
|
|
Packit |
56e23f |
};
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
c = getopt_long(argc, argv, "bp",
|
|
Packit |
56e23f |
long_options, &option_index);
|
|
Packit |
56e23f |
if (c == -1)
|
|
Packit |
56e23f |
break;
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
switch (c) {
|
|
Packit |
56e23f |
case 0:
|
|
Packit |
56e23f |
break;
|
|
Packit |
56e23f |
case 'b':
|
|
Packit |
56e23f |
opts->bpf_flg = 1;
|
|
Packit |
56e23f |
break;
|
|
Packit |
56e23f |
case 'p':
|
|
Packit |
56e23f |
opts->bpf_flg = 0;
|
|
Packit |
56e23f |
break;
|
|
Packit |
56e23f |
default:
|
|
Packit |
56e23f |
rc = -EINVAL;
|
|
Packit |
56e23f |
break;
|
|
Packit |
56e23f |
}
|
|
Packit |
56e23f |
}
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
if (rc == -EINVAL || optind < argc) {
|
|
Packit |
56e23f |
fprintf(stderr, "usage %s: [--bpf,-b] [--pfc,-p]\n", argv[0]);
|
|
Packit |
56e23f |
rc = -EINVAL;
|
|
Packit |
56e23f |
}
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
return rc;
|
|
Packit |
56e23f |
}
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
/**
|
|
Packit |
56e23f |
* Output the filter in either BPF or PFC
|
|
Packit |
56e23f |
* @param opts the options structure
|
|
Packit |
56e23f |
* @param ctx the filter context
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
* This function outputs the seccomp filter to stdout in either BPF or PFC
|
|
Packit |
56e23f |
* format depending on the test paramaeters supplied by @opts.
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
*/
|
|
Packit |
56e23f |
int util_filter_output(const struct util_options *opts,
|
|
Packit |
56e23f |
const scmp_filter_ctx ctx)
|
|
Packit |
56e23f |
{
|
|
Packit |
56e23f |
int rc;
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
if (opts == NULL)
|
|
Packit |
56e23f |
return -EFAULT;
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
if (opts->bpf_flg)
|
|
Packit |
56e23f |
rc = seccomp_export_bpf(ctx, STDOUT_FILENO);
|
|
Packit |
56e23f |
else
|
|
Packit |
56e23f |
rc = seccomp_export_pfc(ctx, STDOUT_FILENO);
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
return rc;
|
|
Packit |
56e23f |
}
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
/**
|
|
Packit |
56e23f |
* Install a TRAP action signal handler
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
* This function installs the TRAP action signal handler and is based on
|
|
Packit |
56e23f |
* examples from Will Drewry and Kees Cook. Returns zero on success, negative
|
|
Packit |
56e23f |
* values on failure.
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
*/
|
|
Packit |
56e23f |
int util_trap_install(void)
|
|
Packit |
56e23f |
{
|
|
Packit |
56e23f |
struct sigaction signal_handler;
|
|
Packit |
56e23f |
sigset_t signal_mask;
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
memset(&signal_handler, 0, sizeof(signal_handler));
|
|
Packit |
56e23f |
sigemptyset(&signal_mask);
|
|
Packit |
56e23f |
sigaddset(&signal_mask, SIGSYS);
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
signal_handler.sa_sigaction = &_trap_handler;
|
|
Packit |
56e23f |
signal_handler.sa_flags = SA_SIGINFO;
|
|
Packit |
56e23f |
if (sigaction(SIGSYS, &signal_handler, NULL) < 0)
|
|
Packit |
56e23f |
return -errno;
|
|
Packit |
56e23f |
if (sigprocmask(SIG_UNBLOCK, &signal_mask, NULL))
|
|
Packit |
56e23f |
return -errno;
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
return 0;
|
|
Packit |
56e23f |
}
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
/**
|
|
Packit |
56e23f |
* Parse a filter action string into an action value
|
|
Packit |
56e23f |
* @param action the action string
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
* Parse a seccomp action string into the associated integer value. Returns
|
|
Packit |
56e23f |
* the correct value on success, -1 on failure.
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
*/
|
|
Packit |
56e23f |
int util_action_parse(const char *action)
|
|
Packit |
56e23f |
{
|
|
Packit |
56e23f |
if (action == NULL)
|
|
Packit |
56e23f |
return -1;
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
if (strcasecmp(action, "KILL") == 0)
|
|
Packit |
56e23f |
return SCMP_ACT_KILL;
|
|
Packit |
56e23f |
if (strcasecmp(action, "KILL_PROCESS") == 0)
|
|
Packit |
56e23f |
return SCMP_ACT_KILL_PROCESS;
|
|
Packit |
56e23f |
else if (strcasecmp(action, "TRAP") == 0)
|
|
Packit |
56e23f |
return SCMP_ACT_TRAP;
|
|
Packit |
56e23f |
else if (strcasecmp(action, "ERRNO") == 0)
|
|
Packit |
56e23f |
return SCMP_ACT_ERRNO(163);
|
|
Packit |
56e23f |
else if (strcasecmp(action, "TRACE") == 0)
|
|
Packit |
56e23f |
return -1; /* not yet supported */
|
|
Packit |
56e23f |
else if (strcasecmp(action, "ALLOW") == 0)
|
|
Packit |
56e23f |
return SCMP_ACT_ALLOW;
|
|
Packit |
56e23f |
else if (strcasecmp(action, "LOG") == 0)
|
|
Packit |
56e23f |
return SCMP_ACT_LOG;
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
return -1;
|
|
Packit |
56e23f |
}
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
/**
|
|
Packit |
56e23f |
* Write a string to a file
|
|
Packit |
56e23f |
* @param path the file path
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
* Open the specified file, write a string to the file, and close the file.
|
|
Packit |
56e23f |
* Return zero on success, negative values on error.
|
|
Packit |
56e23f |
*
|
|
Packit |
56e23f |
*/
|
|
Packit |
56e23f |
int util_file_write(const char *path)
|
|
Packit |
56e23f |
{
|
|
Packit |
56e23f |
int fd;
|
|
Packit |
56e23f |
const char buf[] = "testing";
|
|
Packit |
56e23f |
ssize_t buf_len = strlen(buf);
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
|
|
Packit |
56e23f |
if (fd < 0)
|
|
Packit Service |
10c312 |
return -errno;
|
|
Packit |
56e23f |
if (write(fd, buf, buf_len) < buf_len) {
|
|
Packit Service |
10c312 |
int rc = -errno;
|
|
Packit |
56e23f |
close(fd);
|
|
Packit |
56e23f |
return rc;
|
|
Packit |
56e23f |
}
|
|
Packit |
56e23f |
if (close(fd) < 0)
|
|
Packit Service |
10c312 |
return -errno;
|
|
Packit |
56e23f |
|
|
Packit |
56e23f |
return 0;
|
|
Packit |
56e23f |
}
|