summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/condition.c9
-rw-r--r--src/shared/seccomp-util.c185
-rw-r--r--src/shared/seccomp-util.h37
3 files changed, 184 insertions, 47 deletions
diff --git a/src/shared/condition.c b/src/shared/condition.c
index f13fa6a9fd..69b4837e1f 100644
--- a/src/shared/condition.c
+++ b/src/shared/condition.c
@@ -329,9 +329,9 @@ static int condition_test_needs_update(Condition *c) {
uint64_t timestamp;
int r;
- r = parse_env_file(p, NULL, "TimestampNSec", &timestamp_str, NULL);
+ r = parse_env_file(p, NULL, "TIMESTAMP_NSEC", &timestamp_str, NULL);
if (r < 0) {
- log_error_errno(-r, "Failed to parse timestamp file '%s', using mtime: %m", p);
+ log_error_errno(r, "Failed to parse timestamp file '%s', using mtime: %m", p);
return true;
} else if (r == 0) {
log_debug("No data in timestamp file '%s', using mtime", p);
@@ -340,12 +340,11 @@ static int condition_test_needs_update(Condition *c) {
r = safe_atou64(timestamp_str, &timestamp);
if (r < 0) {
- log_error_errno(-r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m",
- timestamp_str, p);
+ log_error_errno(r, "Failed to parse timestamp value '%s' in file '%s', using mtime: %m", timestamp_str, p);
return true;
}
- other.st_mtim.tv_nsec = timestamp % NSEC_PER_SEC;
+ timespec_store(&other.st_mtim, timestamp);
}
return usr.st_mtim.tv_nsec > other.st_mtim.tv_nsec;
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
index 8116c7671f..6252cd16a6 100644
--- a/src/shared/seccomp-util.c
+++ b/src/shared/seccomp-util.c
@@ -26,6 +26,7 @@
#include "macro.h"
#include "seccomp-util.h"
#include "string-util.h"
+#include "util.h"
const char* seccomp_arch_to_string(uint32_t c) {
@@ -73,7 +74,34 @@ int seccomp_arch_from_string(const char *n, uint32_t *ret) {
return 0;
}
-int seccomp_add_secondary_archs(scmp_filter_ctx *c) {
+int seccomp_init_conservative(scmp_filter_ctx *ret, uint32_t default_action) {
+ scmp_filter_ctx seccomp;
+ int r;
+
+ /* Much like seccomp_init(), but tries to be a bit more conservative in its defaults: all secondary archs are
+ * added by default, and NNP is turned off. */
+
+ seccomp = seccomp_init(default_action);
+ if (!seccomp)
+ return -ENOMEM;
+
+ r = seccomp_add_secondary_archs(seccomp);
+ if (r < 0)
+ goto finish;
+
+ r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
+ if (r < 0)
+ goto finish;
+
+ *ret = seccomp;
+ return 0;
+
+finish:
+ seccomp_release(seccomp);
+ return r;
+}
+
+int seccomp_add_secondary_archs(scmp_filter_ctx c) {
#if defined(__i386__) || defined(__x86_64__)
int r;
@@ -110,7 +138,6 @@ int seccomp_add_secondary_archs(scmp_filter_ctx *c) {
#endif
return 0;
-
}
static bool is_basic_seccomp_available(void) {
@@ -132,28 +159,30 @@ bool is_seccomp_available(void) {
return cached_enabled;
}
-const SystemCallFilterSet syscall_filter_sets[] = {
- {
+const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
+ [SYSCALL_FILTER_SET_CLOCK] = {
/* Clock */
- .set_name = "@clock",
+ .name = "@clock",
.value =
"adjtimex\0"
"clock_adjtime\0"
"clock_settime\0"
"settimeofday\0"
"stime\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_CPU_EMULATION] = {
/* CPU emulation calls */
- .set_name = "@cpu-emulation",
+ .name = "@cpu-emulation",
.value =
"modify_ldt\0"
"subpage_prot\0"
"switch_endian\0"
"vm86\0"
"vm86old\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_DEBUG] = {
/* Debugging/Performance Monitoring/Tracing */
- .set_name = "@debug",
+ .name = "@debug",
.value =
"lookup_dcookie\0"
"perf_event_open\0"
@@ -161,11 +190,14 @@ const SystemCallFilterSet syscall_filter_sets[] = {
"process_vm_writev\0"
"ptrace\0"
"rtas\0"
+#ifdef __NR_s390_runtime_instr
"s390_runtime_instr\0"
+#endif
"sys_debug_setcontext\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_DEFAULT] = {
/* Default list */
- .set_name = "@default",
+ .name = "@default",
.value =
"execve\0"
"exit\0"
@@ -173,9 +205,10 @@ const SystemCallFilterSet syscall_filter_sets[] = {
"getrlimit\0" /* make sure processes can query stack size and such */
"rt_sigreturn\0"
"sigreturn\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_IO_EVENT] = {
/* Event loop use */
- .set_name = "@io-event",
+ .name = "@io-event",
.value =
"_newselect\0"
"epoll_create1\0"
@@ -191,9 +224,10 @@ const SystemCallFilterSet syscall_filter_sets[] = {
"ppoll\0"
"pselect6\0"
"select\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_IPC] = {
/* Message queues, SYSV IPC or other IPC: unusual */
- .set_name = "@ipc",
+ .name = "@ipc",
.value = "ipc\0"
"mq_getsetattr\0"
"mq_notify\0"
@@ -215,33 +249,36 @@ const SystemCallFilterSet syscall_filter_sets[] = {
"shmctl\0"
"shmdt\0"
"shmget\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_KEYRING] = {
/* Keyring */
- .set_name = "@keyring",
+ .name = "@keyring",
.value =
"add_key\0"
"keyctl\0"
"request_key\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_MODULE] = {
/* Kernel module control */
- .set_name = "@module",
+ .name = "@module",
.value =
"delete_module\0"
"finit_module\0"
"init_module\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_MOUNT] = {
/* Mounting */
- .set_name = "@mount",
+ .name = "@mount",
.value =
"chroot\0"
"mount\0"
- "oldumount\0"
"pivot_root\0"
"umount2\0"
"umount\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_NETWORK_IO] = {
/* Network or Unix socket IO, should not be needed if not network facing */
- .set_name = "@network-io",
+ .name = "@network-io",
.value =
"accept4\0"
"accept\0"
@@ -264,9 +301,10 @@ const SystemCallFilterSet syscall_filter_sets[] = {
"socket\0"
"socketcall\0"
"socketpair\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_OBSOLETE] = {
/* Unusual, obsolete or unimplemented, some unknown even to libseccomp */
- .set_name = "@obsolete",
+ .name = "@obsolete",
.value =
"_sysctl\0"
"afs_syscall\0"
@@ -292,9 +330,10 @@ const SystemCallFilterSet syscall_filter_sets[] = {
"uselib\0"
"ustat\0"
"vserver\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_PRIVILEGED] = {
/* Nice grab-bag of all system calls which need superuser capabilities */
- .set_name = "@privileged",
+ .name = "@privileged",
.value =
"@clock\0"
"@module\0"
@@ -331,11 +370,12 @@ const SystemCallFilterSet syscall_filter_sets[] = {
"setuid\0"
"swapoff\0"
"swapon\0"
- "sysctl\0"
+ "_sysctl\0"
"vhangup\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_PROCESS] = {
/* Process control, execution, namespaces */
- .set_name = "@process",
+ .name = "@process",
.value =
"arch_prctl\0"
"clone\0"
@@ -349,19 +389,90 @@ const SystemCallFilterSet syscall_filter_sets[] = {
"tkill\0"
"unshare\0"
"vfork\0"
- }, {
+ },
+ [SYSCALL_FILTER_SET_RAW_IO] = {
/* Raw I/O ports */
- .set_name = "@raw-io",
+ .name = "@raw-io",
.value =
"ioperm\0"
"iopl\0"
"pciconfig_iobase\0"
"pciconfig_read\0"
"pciconfig_write\0"
+#ifdef __NR_s390_pci_mmio_read
"s390_pci_mmio_read\0"
+#endif
+#ifdef __NR_s390_pci_mmio_write
"s390_pci_mmio_write\0"
- }, {
- .set_name = NULL,
- .value = NULL
- }
+#endif
+ },
};
+
+const SyscallFilterSet *syscall_filter_set_find(const char *name) {
+ unsigned i;
+
+ if (isempty(name) || name[0] != '@')
+ return NULL;
+
+ for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++)
+ if (streq(syscall_filter_sets[i].name, name))
+ return syscall_filter_sets + i;
+
+ return NULL;
+}
+
+int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action) {
+ const char *sys;
+ int r;
+
+ assert(seccomp);
+ assert(set);
+
+ NULSTR_FOREACH(sys, set->value) {
+ int id;
+
+ if (sys[0] == '@') {
+ const SyscallFilterSet *other;
+
+ other = syscall_filter_set_find(sys);
+ if (!other)
+ return -EINVAL;
+
+ r = seccomp_add_syscall_filter_set(seccomp, other, action);
+ } else {
+ id = seccomp_syscall_resolve_name(sys);
+ if (id == __NR_SCMP_ERROR)
+ return -EINVAL;
+
+ r = seccomp_rule_add(seccomp, action, id, 0);
+ }
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
+int seccomp_load_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action) {
+ scmp_filter_ctx seccomp;
+ int r;
+
+ assert(set);
+
+ /* The one-stop solution: allocate a seccomp object, add a filter to it, and apply it */
+
+ r = seccomp_init_conservative(&seccomp, default_action);
+ if (r < 0)
+ return r;
+
+ r = seccomp_add_syscall_filter_set(seccomp, set, action);
+ if (r < 0)
+ goto finish;
+
+ r = seccomp_load(seccomp);
+
+finish:
+ seccomp_release(seccomp);
+ return r;
+
+}
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
index cca7c17912..8050fc6fbf 100644
--- a/src/shared/seccomp-util.h
+++ b/src/shared/seccomp-util.h
@@ -20,18 +20,45 @@
***/
#include <seccomp.h>
+#include <stdbool.h>
#include <stdint.h>
const char* seccomp_arch_to_string(uint32_t c);
int seccomp_arch_from_string(const char *n, uint32_t *ret);
-int seccomp_add_secondary_archs(scmp_filter_ctx *c);
+int seccomp_init_conservative(scmp_filter_ctx *ret, uint32_t default_action);
+
+int seccomp_add_secondary_archs(scmp_filter_ctx c);
bool is_seccomp_available(void);
-typedef struct SystemCallFilterSet {
- const char *set_name;
+typedef struct SyscallFilterSet {
+ const char *name;
const char *value;
-} SystemCallFilterSet;
+} SyscallFilterSet;
+
+enum {
+ SYSCALL_FILTER_SET_CLOCK,
+ SYSCALL_FILTER_SET_CPU_EMULATION,
+ SYSCALL_FILTER_SET_DEBUG,
+ SYSCALL_FILTER_SET_DEFAULT,
+ SYSCALL_FILTER_SET_IO_EVENT,
+ SYSCALL_FILTER_SET_IPC,
+ SYSCALL_FILTER_SET_KEYRING,
+ SYSCALL_FILTER_SET_MODULE,
+ SYSCALL_FILTER_SET_MOUNT,
+ SYSCALL_FILTER_SET_NETWORK_IO,
+ SYSCALL_FILTER_SET_OBSOLETE,
+ SYSCALL_FILTER_SET_PRIVILEGED,
+ SYSCALL_FILTER_SET_PROCESS,
+ SYSCALL_FILTER_SET_RAW_IO,
+ _SYSCALL_FILTER_SET_MAX
+};
+
+extern const SyscallFilterSet syscall_filter_sets[];
+
+const SyscallFilterSet *syscall_filter_set_find(const char *name);
+
+int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action);
-extern const SystemCallFilterSet syscall_filter_sets[];
+int seccomp_load_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action);