syscallfilter: port to libseccomp

This commit is contained in:
Ronny Chevalier 2014-02-12 01:29:54 +01:00 committed by Lennart Poettering
parent c6f7b693fe
commit c0467cf387
16 changed files with 157 additions and 346 deletions

View File

@ -654,8 +654,6 @@ noinst_LTLIBRARIES += \
libsystemd_shared_la_SOURCES = \
src/shared/linux/auto_dev-ioctl.h \
src/shared/linux/fanotify.h \
src/shared/linux/seccomp.h \
src/shared/linux/seccomp-bpf.h \
src/shared/ioprio.h \
src/shared/missing.h \
src/shared/initreq.h \
@ -763,8 +761,6 @@ libsystemd_shared_la_SOURCES = \
src/shared/net-util.h \
src/shared/errno-list.c \
src/shared/errno-list.h \
src/shared/syscall-list.c \
src/shared/syscall-list.h \
src/shared/audit.c \
src/shared/audit.h \
src/shared/xml.c \
@ -772,9 +768,7 @@ libsystemd_shared_la_SOURCES = \
nodist_libsystemd_shared_la_SOURCES = \
src/shared/errno-from-name.h \
src/shared/errno-to-name.h \
src/shared/syscall-from-name.h \
src/shared/syscall-to-name.h
src/shared/errno-to-name.h
# ------------------------------------------------------------------------------
noinst_LTLIBRARIES += \
@ -999,6 +993,7 @@ libsystemd_core_la_CFLAGS = \
$(PAM_CFLAGS) \
$(AUDIT_CFLAGS) \
$(KMOD_CFLAGS) \
$(SECCOMP_CFLAGS) \
-pthread
libsystemd_core_la_LIBADD = \
@ -1013,6 +1008,7 @@ libsystemd_core_la_LIBADD = \
$(PAM_LIBS) \
$(AUDIT_LIBS) \
$(CAP_LIBS) \
$(SECCOMP_LIBS) \
$(KMOD_LIBS)
src/core/load-fragment-gperf-nulstr.c: src/core/load-fragment-gperf.gperf
@ -1026,33 +1022,13 @@ CLEANFILES += \
src/core/load-fragment-gperf.gperf \
src/core/load-fragment-gperf.c \
src/core/load-fragment-gperf-nulstr.c \
src/shared/syscall-list.txt \
src/shared/syscall-from-name.gperf \
src/shared/errno-list.txt \
src/shared/errno-from-name.gperf
BUILT_SOURCES += \
src/shared/syscall-from-name.h \
src/shared/syscall-to-name.h \
src/shared/errno-from-name.h \
src/shared/errno-to-name.h
src/shared/syscall-list.txt:
$(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include sys/syscall.h - < /dev/null | $(AWK) '/^#define[ \t]+__NR_[^ ]+[ \t]+[0-9(]/ { sub(/__NR_/, "", $$2); if ($$2 !~ /SYSCALL_BASE/) print $$2; }' > $@
src/shared/syscall-from-name.gperf: src/shared/syscall-list.txt
$(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_GEN)$(AWK) 'BEGIN{ print "struct syscall_name { const char* name; int id; };"; print "%null-strings"; print "%%";} { printf "%s, __NR_%s\n", $$1, $$1 }' < $< > $@
src/shared/syscall-from-name.h: src/shared/syscall-from-name.gperf
$(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_GPERF)$(GPERF) -L ANSI-C -t --ignore-case -N lookup_syscall -H hash_syscall_name -p -C < $< > $@
src/shared/syscall-to-name.h: src/shared/syscall-list.txt
$(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_GEN)$(AWK) 'BEGIN{ print "static const char* const syscall_names[] = { "} { printf "[SYSCALL_TO_INDEX(__NR_%s)] = \"%s\",\n", $$1, $$1 } END{print "};"}' < $< > $@
src/shared/errno-list.txt:
$(AM_V_at)$(MKDIR_P) $(dir $@)
$(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include errno.h - < /dev/null | $(AWK) '/^#define[ \t]+E[^ _]+[ \t]+[0-9]/ { print $$2; }' > $@

1
README
View File

@ -92,6 +92,7 @@ REQUIREMENTS:
glibc >= 2.14
libcap
libseccomp >= 1.0.0 (optional)
libblkid >= 2.20 (from util-linux) (optional)
libkmod >= 15 (optional)
PAM >= 1.1.2 (optional)

1
TODO
View File

@ -490,7 +490,6 @@ Features:
- syscall filter: add knowledge about compat syscalls
- syscall filter: don't enforce no new privs?
- syscall filter: option to return EPERM rather than SIGSYS?
- syscall filter: port to libseccomp
- system-wide seccomp filter
* load-fragment: when loading a unit file via a chain of symlinks

View File

@ -322,6 +322,19 @@ if test "x$enable_blkid" != "xno"; then
fi
AM_CONDITIONAL(HAVE_BLKID, [test "$have_blkid" = "yes"])
# ------------------------------------------------------------------------------
have_seccomp=no
AC_ARG_ENABLE(seccomp, AS_HELP_STRING([--disable-seccomp], [Disable optional SECCOMP support]))
if test "x$enable_seccomp" != "xno"; then
PKG_CHECK_MODULES(SECCOMP, [libseccomp >= 1.0.0],
[AC_DEFINE(HAVE_SECCOMP, 1, [Define if seccomp is available]) have_seccomp=yes],
[have_seccomp=no])
if test "x$have_seccomp" = "xno" -a "x$enable_seccomp" = "xyes"; then
AC_MSG_ERROR([*** seccomp support requested but libraries not found])
fi
fi
AM_CONDITIONAL(HAVE_SECCOMP, [test "$have_seccomp" = "yes"])
# ------------------------------------------------------------------------------
have_ima=yes
AC_ARG_ENABLE([ima], AS_HELP_STRING([--disable-ima],[Disable optional IMA support]),
@ -1090,6 +1103,7 @@ AC_MSG_RESULT([
AUDIT: ${have_audit}
IMA: ${have_ima}
SELinux: ${have_selinux}
SECCOMP: ${have_seccomp}
SMACK: ${have_smack}
XZ: ${have_xz}
ACL: ${have_acl}

View File

@ -1029,7 +1029,23 @@
merged. If the empty string is
assigned, the filter is reset, all
prior assignments will have no
effect.</para></listitem>
effect.</para>
<para>If you specify both types of this option
(i.e. whitelisting and blacklisting) the first
encountered will take precedence and will
dictate the default action (termination
or approval of a system call). Then the
next occurrences of this option will add or
delete the listed system calls from the set
of the filtered system calls, depending of
its type and the default action (e.g. You
have started with a whitelisting of <function>
read</function> and <function>write</function>
and right after it add a blacklisting of
<function>write</function>, then <function>
write</function> will be removed from the set)
</para></listitem>
</varlistentry>
</variablelist>

View File

@ -81,4 +81,10 @@
#define _XZ_FEATURE_ "-XZ"
#endif
#define SYSTEMD_FEATURES _PAM_FEATURE_ " " _LIBWRAP_FEATURE_ " " _AUDIT_FEATURE_ " " _SELINUX_FEATURE_ " " _IMA_FEATURE_ " " _SYSVINIT_FEATURE_ " " _LIBCRYPTSETUP_FEATURE_ " " _GCRYPT_FEATURE_ " " _ACL_FEATURE_ " " _XZ_FEATURE_
#ifdef HAVE_SECCOMP
#define _SECCOMP_FEATURE_ "+SECCOMP"
#else
#define _SECCOMP_FEATURE_ "-SECCOMP"
#endif
#define SYSTEMD_FEATURES _PAM_FEATURE_ " " _LIBWRAP_FEATURE_ " " _AUDIT_FEATURE_ " " _SELINUX_FEATURE_ " " _IMA_FEATURE_ " " _SYSVINIT_FEATURE_ " " _LIBCRYPTSETUP_FEATURE_ " " _GCRYPT_FEATURE_ " " _ACL_FEATURE_ " " _XZ_FEATURE_ _SECCOMP_FEATURE_

View File

@ -25,7 +25,6 @@
#include "missing.h"
#include "ioprio.h"
#include "strv.h"
#include "syscall-list.h"
#include "fileio.h"
#include "execute.h"
#include "dbus-execute.h"
@ -354,10 +353,7 @@ static int property_get_syscall_filter(
assert(reply);
assert(c);
if (c->syscall_filter)
return sd_bus_message_append_array(reply, 'u', c->syscall_filter, (syscall_max() + 31) >> 4);
else
return sd_bus_message_append_array(reply, 'u', NULL, 0);
return sd_bus_message_append(reply, "s", c->syscall_filter_string);
}
const sd_bus_vtable bus_exec_vtable[] = {
@ -422,7 +418,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("SELinuxContext", "s", NULL, offsetof(ExecContext, selinux_context), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallFilter", "au", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SystemCallFilter", "s", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_VTABLE_END
};

View File

@ -38,9 +38,13 @@
#include <linux/fs.h>
#include <linux/oom.h>
#include <sys/poll.h>
#include <linux/seccomp-bpf.h>
#include <glob.h>
#include <libgen.h>
#ifdef HAVE_SECCOMP
#include <seccomp.h>
#include "set.h"
#endif
#undef basename
#ifdef HAVE_PAM
@ -67,7 +71,6 @@
#include "utmp-wtmp.h"
#include "def.h"
#include "path-util.h"
#include "syscall-list.h"
#include "env-util.h"
#include "fileio.h"
#include "unit.h"
@ -933,57 +936,32 @@ static void rename_process_from_path(const char *path) {
rename_process(process_name);
}
static int apply_seccomp(uint32_t *syscall_filter) {
static const struct sock_filter header[] = {
VALIDATE_ARCHITECTURE,
EXAMINE_SYSCALL
};
static const struct sock_filter footer[] = {
_KILL_PROCESS
};
#ifdef HAVE_SECCOMP
static int apply_seccomp(ExecContext *c) {
uint32_t action = SCMP_ACT_ALLOW;
Iterator i;
void *id;
int i;
unsigned n;
struct sock_filter *f;
struct sock_fprog prog = {};
assert(c);
assert(syscall_filter);
c->syscall_filter = seccomp_init(c->syscall_filter_default_action);
if (!c->syscall_filter)
return -1;
/* First: count the syscalls to check for */
for (i = 0, n = 0; i < syscall_max(); i++)
if (syscall_filter[i >> 4] & (1 << (i & 31)))
n++;
if (c->syscall_filter_default_action == SCMP_ACT_ALLOW)
action = SCMP_ACT_KILL;
/* Second: build the filter program from a header the syscall
* matches and the footer */
f = alloca(sizeof(struct sock_filter) * (ELEMENTSOF(header) + 2*n + ELEMENTSOF(footer)));
memcpy(f, header, sizeof(header));
for (i = 0, n = 0; i < syscall_max(); i++)
if (syscall_filter[i >> 4] & (1 << (i & 31))) {
struct sock_filter item[] = {
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, INDEX_TO_SYSCALL(i), 0, 1),
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
};
assert_cc(ELEMENTSOF(item) == 2);
f[ELEMENTSOF(header) + 2*n] = item[0];
f[ELEMENTSOF(header) + 2*n+1] = item[1];
n++;
SET_FOREACH(id, c->filtered_syscalls, i) {
int r = seccomp_rule_add(c->syscall_filter, action, PTR_TO_INT(id) - 1, 0);
if (r < 0) {
log_error("Failed to add syscall filter");
return r;
}
}
memcpy(f + (ELEMENTSOF(header) + 2*n), footer, sizeof(footer));
/* Third: install the filter */
prog.len = ELEMENTSOF(header) + ELEMENTSOF(footer) + 2*n;
prog.filter = f;
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0)
return -errno;
return 0;
return seccomp_load(c->syscall_filter);
}
#endif
static void do_idle_pipe_dance(int idle_pipe[4]) {
assert(idle_pipe);
@ -1562,13 +1540,15 @@ int exec_spawn(ExecCommand *command,
goto fail_child;
}
if (context->syscall_filter) {
err = apply_seccomp(context->syscall_filter);
#ifdef HAVE_SECCOMP
if (context->filtered_syscalls) {
err = apply_seccomp(context);
if (err < 0) {
r = EXIT_SECCOMP;
goto fail_child;
}
}
#endif
#ifdef HAVE_SELINUX
if (context->selinux_context && use_selinux()) {
bool ignore;
@ -1751,6 +1731,18 @@ void exec_context_done(ExecContext *c) {
free(c->syscall_filter);
c->syscall_filter = NULL;
free(c->syscall_filter_string);
c->syscall_filter_string = NULL;
#ifdef HAVE_SECCOMP
if (c->syscall_filter) {
seccomp_release(c->syscall_filter);
c->syscall_filter = NULL;
}
set_free(c->filtered_syscalls);
c->filtered_syscalls = NULL;
#endif
}
void exec_command_done(ExecCommand *c) {

View File

@ -33,6 +33,11 @@ typedef struct ExecRuntime ExecRuntime;
#include <stdbool.h>
#include <stdio.h>
#include <sched.h>
#ifdef HAVE_SECCOMP
#include <seccomp.h>
#include "set.h"
#endif
#include "list.h"
#include "util.h"
@ -162,7 +167,12 @@ struct ExecContext {
* don't enter a trigger loop. */
bool same_pgrp;
uint32_t *syscall_filter;
#ifdef HAVE_SECCOMP
scmp_filter_ctx syscall_filter;
Set *filtered_syscalls;
uint32_t syscall_filter_default_action;
#endif
char *syscall_filter_string;
bool oom_score_adjust_set:1;
bool nice_set:1;

View File

@ -33,6 +33,11 @@
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_SECCOMP
#include <seccomp.h>
#include "set.h"
#endif
#include "sd-messages.h"
#include "unit.h"
@ -47,13 +52,12 @@
#include "unit-printf.h"
#include "utf8.h"
#include "path-util.h"
#include "syscall-list.h"
#include "env-util.h"
#include "cgroup.h"
#include "bus-util.h"
#include "bus-error.h"
#ifndef HAVE_SYSV_COMPAT
#if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP)
int config_parse_warn_compat(const char *unit,
const char *filename,
unsigned line,
@ -1916,16 +1920,7 @@ int config_parse_documentation(const char *unit,
return r;
}
static void syscall_set(uint32_t *p, int nr) {
nr = SYSCALL_TO_INDEX(nr);
p[nr >> 4] |= 1 << (nr & 31);
}
static void syscall_unset(uint32_t *p, int nr) {
nr = SYSCALL_TO_INDEX(nr);
p[nr >> 4] &= ~(1 << (nr & 31));
}
#ifdef HAVE_SECCOMP
int config_parse_syscall_filter(const char *unit,
const char *filename,
unsigned line,
@ -1936,13 +1931,23 @@ int config_parse_syscall_filter(const char *unit,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
Unit *u = userdata;
bool invert = false;
char *w;
size_t l;
char *state;
_cleanup_strv_free_ char **syscalls = strv_new(NULL, NULL);
_cleanup_free_ char *sorted_syscalls = NULL;
uint32_t action = SCMP_ACT_ALLOW;
Iterator i;
void *e;
static char const *default_syscalls[] = {"execve",
"exit",
"exit_group",
"rt_sigreturn",
"sigreturn",
NULL};
assert(filename);
assert(lvalue);
@ -1951,34 +1956,37 @@ int config_parse_syscall_filter(const char *unit,
if (isempty(rvalue)) {
/* Empty assignment resets the list */
free(c->syscall_filter);
c->syscall_filter = NULL;
set_free(c->filtered_syscalls);
c->filtered_syscalls= NULL;
free(c->syscall_filter_string);
c->syscall_filter_string = NULL;
return 0;
}
if (rvalue[0] == '~') {
invert = true;
action = SCMP_ACT_KILL;
rvalue++;
}
if (!c->syscall_filter) {
size_t n;
if (!c->filtered_syscalls) {
c->filtered_syscalls = set_new(trivial_hash_func, trivial_compare_func);
if (invert)
c->syscall_filter_default_action = SCMP_ACT_ALLOW;
else {
char const **syscall;
n = (syscall_max() + 31) >> 4;
c->syscall_filter = new(uint32_t, n);
if (!c->syscall_filter)
return log_oom();
c->syscall_filter_default_action = SCMP_ACT_KILL;
memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
/* accept default syscalls if we are on a whitelist */
STRV_FOREACH(syscall, default_syscalls) {
int id = seccomp_syscall_resolve_name(*syscall);
if (id < 0)
continue;
/* Add these by default */
syscall_set(c->syscall_filter, __NR_execve);
syscall_set(c->syscall_filter, __NR_rt_sigreturn);
#ifdef __NR_sigreturn
syscall_set(c->syscall_filter, __NR_sigreturn);
#endif
syscall_set(c->syscall_filter, __NR_exit_group);
syscall_set(c->syscall_filter, __NR_exit);
set_replace(c->filtered_syscalls, INT_TO_PTR(id + 1));
}
}
}
FOREACH_WORD_QUOTED(w, l, rvalue, state) {
@ -1989,23 +1997,39 @@ int config_parse_syscall_filter(const char *unit,
if (!t)
return log_oom();
id = syscall_from_name(t);
id = seccomp_syscall_resolve_name(t);
if (id < 0) {
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to parse syscall, ignoring: %s", t);
continue;
}
if (invert)
syscall_unset(c->syscall_filter, id);
/* If we previously wanted to forbid a syscall
* and now we want to allow it, then remove it from the list
* libseccomp will also return -EPERM if we try to add
* a rule with the same action as the default
*/
if (action == c->syscall_filter_default_action)
set_remove(c->filtered_syscalls, INT_TO_PTR(id + 1));
else
syscall_set(c->syscall_filter, id);
set_replace(c->filtered_syscalls, INT_TO_PTR(id + 1));
}
SET_FOREACH(e, c->filtered_syscalls, i) {
char *name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(e) - 1);
strv_push(&syscalls, name);
}
sorted_syscalls = strv_join(strv_sort(syscalls), " ");
if (invert)
c->syscall_filter_string = strv_join(STRV_MAKE("~", sorted_syscalls, NULL), "");
else
c->syscall_filter_string = strdup(sorted_syscalls);
c->no_new_privileges = true;
return 0;
}
#endif
int config_parse_unit_slice(
const char *unit,
@ -2778,7 +2802,11 @@ void unit_dump_config_items(FILE *f) {
{ config_parse_set_status, "STATUS" },
{ config_parse_service_sockets, "SOCKETS" },
{ config_parse_environ, "ENVIRON" },
#ifdef HAVE_SECCOMP
{ config_parse_syscall_filter, "SYSCALL" },
#else
{ config_parse_warn_compat, "NOTSUPPORTED" },
#endif
{ config_parse_cpu_shares, "SHARES" },
{ config_parse_memory_limit, "LIMIT" },
{ config_parse_device_allow, "DEVICE" },

View File

@ -1,7 +1,3 @@
/syscall-from-name.gperf
/syscall-from-name.h
/syscall-list.txt
/syscall-to-name.h
/errno-from-name.gperf
/errno-from-name.h
/errno-list.txt

View File

@ -1,76 +0,0 @@
/*
* seccomp example for x86 (32-bit and 64-bit) with BPF macros
*
* Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
* Authors:
* Will Drewry <wad@chromium.org>
* Kees Cook <keescook@chromium.org>
*
* The code may be used by anyone for any purpose, and can serve as a
* starting point for developing applications using mode 2 seccomp.
*/
#ifndef _SECCOMP_BPF_H_
#define _SECCOMP_BPF_H_
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <linux/unistd.h>
#include <linux/audit.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#ifndef SECCOMP_MODE_FILTER
# define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
# define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
# define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
# define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
struct seccomp_data {
int nr;
__u32 arch;
__u64 instruction_pointer;
__u64 args[6];
};
#endif
#ifndef SYS_SECCOMP
# define SYS_SECCOMP 1
#endif
#define syscall_nr (offsetof(struct seccomp_data, nr))
#define arch_nr (offsetof(struct seccomp_data, arch))
#if defined(__i386__)
# define REG_SYSCALL REG_EAX
# define ARCH_NR AUDIT_ARCH_I386
#elif defined(__x86_64__)
# define REG_SYSCALL REG_RAX
# define ARCH_NR AUDIT_ARCH_X86_64
#else
# warning "Platform does not support seccomp filter yet"
# define REG_SYSCALL 0
# define ARCH_NR 0
#endif
#define VALIDATE_ARCHITECTURE \
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, arch_nr), \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
#define EXAMINE_SYSCALL \
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr)
#define ALLOW_SYSCALL(name) \
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
#define _KILL_PROCESS \
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
#endif /* _SECCOMP_BPF_H_ */

View File

@ -1,47 +0,0 @@
#ifndef _LINUX_SECCOMP_H
#define _LINUX_SECCOMP_H
#include <linux/types.h>
/* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */
#define SECCOMP_MODE_DISABLED 0 /* seccomp is not in use. */
#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
/*
* All BPF programs must return a 32-bit value.
* The bottom 16-bits are for optional return data.
* The upper 16-bits are ordered from least permissive values to most.
*
* The ordering ensures that a min_t() over composed return values always
* selects the least permissive choice.
*/
#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
/* Masks for the return value sections. */
#define SECCOMP_RET_ACTION 0x7fff0000U
#define SECCOMP_RET_DATA 0x0000ffffU
/**
* struct seccomp_data - the format the BPF program executes over.
* @nr: the system call number
* @arch: indicates system call convention as an AUDIT_ARCH_* value
* as defined in <linux/audit.h>.
* @instruction_pointer: at the time of the system call.
* @args: up to 6 system call arguments always stored as 64-bit values
* regardless of the architecture.
*/
struct seccomp_data {
int nr;
__u32 arch;
__u64 instruction_pointer;
__u64 args[6];
};
#endif /* _LINUX_SECCOMP_H */

View File

@ -1,56 +0,0 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2012 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd 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 systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/syscall.h>
#include <string.h>
#include "util.h"
#include "syscall-list.h"
static const struct syscall_name* lookup_syscall(register const char *str,
register unsigned int len);
#include "syscall-to-name.h"
#include "syscall-from-name.h"
const char *syscall_to_name(int id) {
id = SYSCALL_TO_INDEX(id);
if (id < 0 || id >= (int) ELEMENTSOF(syscall_names))
return NULL;
return syscall_names[id];
}
int syscall_from_name(const char *name) {
const struct syscall_name *sc;
assert(name);
sc = lookup_syscall(name, strlen(name));
if (!sc)
return -1;
return sc->id;
}
int syscall_max(void) {
return ELEMENTSOF(syscall_names);
}

View File

@ -1,41 +0,0 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
Copyright 2012 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd 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 systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#if defined __x86_64__ && defined __ILP32__
/* The x32 ABI defines all of its syscalls with bit 30 set, which causes
issues when attempting to use syscalls as simple indices into an array.
Instead, use the syscall id & ~SYSCALL_MASK as the index, and | the
internal id with the syscall mask as needed.
*/
#include <asm/unistd.h>
#define SYSCALL_TO_INDEX(x) ((x) & ~__X32_SYSCALL_BIT)
#define INDEX_TO_SYSCALL(x) ((x) | __X32_SYSCALL_BIT)
#else
#define SYSCALL_TO_INDEX(x) (x)
#define INDEX_TO_SYSCALL(x) (x)
#endif
const char *syscall_to_name(int id);
int syscall_from_name(const char *name);
int syscall_max(void);

View File

@ -43,7 +43,6 @@
#include "unit-name.h"
#include "unit.h"
#include "util.h"
#include "syscall-list.h"
#include "test-tables.h"
@ -99,7 +98,5 @@ int main(int argc, char **argv) {
test_table(unit_load_state, UNIT_LOAD_STATE);
test_table(unit_type, UNIT_TYPE);
_test_table("syscall", syscall_to_name, syscall_from_name, syscall_max(), true);
return EXIT_SUCCESS;
}