Zbigniew Jędrzejewski-Szmek 03e93e
From 8296437564980199342f4fd9f2c85312570ba060 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 03e93e
From: Lennart Poettering <lennart@poettering.net>
Zbigniew Jędrzejewski-Szmek 03e93e
Date: Tue, 27 Dec 2016 15:28:25 +0100
Zbigniew Jędrzejewski-Szmek 03e93e
Subject: [PATCH] seccomp: rework seccomp code, to improve compat with some
Zbigniew Jędrzejewski-Szmek 03e93e
 archs
Zbigniew Jędrzejewski-Szmek 03e93e
Zbigniew Jędrzejewski-Szmek 03e93e
This substantially reworks the seccomp code, to ensure better
Zbigniew Jędrzejewski-Szmek 03e93e
compatibility with some architectures, including i386.
Zbigniew Jędrzejewski-Szmek 03e93e
Zbigniew Jędrzejewski-Szmek 03e93e
So far we relied on libseccomp's internal handling of the multiple
Zbigniew Jędrzejewski-Szmek 03e93e
syscall ABIs supported on Linux. This is problematic however, as it does
Zbigniew Jędrzejewski-Szmek 03e93e
not define clear semantics if an ABI is not able to support specific
Zbigniew Jędrzejewski-Szmek 03e93e
seccomp rules we install.
Zbigniew Jędrzejewski-Szmek 03e93e
Zbigniew Jędrzejewski-Szmek 03e93e
This rework hence changes a couple of things:
Zbigniew Jędrzejewski-Szmek 03e93e
Zbigniew Jędrzejewski-Szmek 03e93e
- We no longer use seccomp_rule_add(), but only
Zbigniew Jędrzejewski-Szmek 03e93e
  seccomp_rule_add_exact(), and fail the installation of a filter if the
Zbigniew Jędrzejewski-Szmek 03e93e
  architecture doesn't support it.
Zbigniew Jędrzejewski-Szmek 03e93e
Zbigniew Jędrzejewski-Szmek 03e93e
- We no longer rely on adding multiple syscall architectures to a single filter,
Zbigniew Jędrzejewski-Szmek 03e93e
  but instead install a separate filter for each syscall architecture
Zbigniew Jędrzejewski-Szmek 03e93e
  supported. This way, we can install a strict filter for x86-64, while
Zbigniew Jędrzejewski-Szmek 03e93e
  permitting a less strict filter for i386.
Zbigniew Jędrzejewski-Szmek 03e93e
Zbigniew Jędrzejewski-Szmek 03e93e
- All high-level filter additions are now moved from execute.c to
Zbigniew Jędrzejewski-Szmek 03e93e
  seccomp-util.c, so that we can test them independently of the service
Zbigniew Jędrzejewski-Szmek 03e93e
  execution logic.
Zbigniew Jędrzejewski-Szmek 03e93e
Zbigniew Jędrzejewski-Szmek 03e93e
- Tests have been added for all types of our seccomp filters.
Zbigniew Jędrzejewski-Szmek 03e93e
Zbigniew Jędrzejewski-Szmek 03e93e
- SystemCallFilters= and SystemCallArchitectures= are now implemented in
Zbigniew Jędrzejewski-Szmek 03e93e
  independent filters and installation logic, as they semantically are
Zbigniew Jędrzejewski-Szmek 03e93e
  very much independent of each other.
Zbigniew Jędrzejewski-Szmek 03e93e
Zbigniew Jędrzejewski-Szmek 03e93e
Fixes: #4575
Zbigniew Jędrzejewski-Szmek 03e93e
(cherry picked from commit 469830d1426a91e0897c321fdc8ee428f0a750c1)
Zbigniew Jędrzejewski-Szmek 03e93e
---
Zbigniew Jędrzejewski-Szmek 03e93e
 src/core/execute.c          | 466 ++++++++----------------------
Zbigniew Jędrzejewski-Szmek 03e93e
 src/core/main.c             |  34 +--
Zbigniew Jędrzejewski-Szmek 03e93e
 src/nspawn/nspawn-seccomp.c | 117 ++++----
Zbigniew Jędrzejewski-Szmek 03e93e
 src/shared/seccomp-util.c   | 670 +++++++++++++++++++++++++++++++++++---------
Zbigniew Jędrzejewski-Szmek 03e93e
 src/shared/seccomp-util.h   |  25 +-
Zbigniew Jędrzejewski-Szmek 03e93e
 src/test/test-execute.c     |   1 +
Zbigniew Jędrzejewski-Szmek 03e93e
 src/test/test-seccomp.c     | 272 +++++++++++++++++-
Zbigniew Jędrzejewski-Szmek 03e93e
 7 files changed, 1016 insertions(+), 569 deletions(-)
Zbigniew Jędrzejewski-Szmek 03e93e
Zbigniew Jędrzejewski-Szmek 03e93e
diff --git a/src/core/execute.c b/src/core/execute.c
Zbigniew Jędrzejewski-Szmek 03e93e
index 59ce0774c4..2dfd43a8f2 100644
Zbigniew Jędrzejewski-Szmek 03e93e
--- a/src/core/execute.c
Zbigniew Jędrzejewski-Szmek 03e93e
+++ b/src/core/execute.c
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -1184,6 +1184,41 @@ static void rename_process_from_path(const char *path) {
Zbigniew Jędrzejewski-Szmek 03e93e
         rename_process(process_name);
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+static bool context_has_address_families(const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        return c->address_families_whitelist ||
Zbigniew Jędrzejewski-Szmek 03e93e
+                !set_isempty(c->address_families);
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+static bool context_has_syscall_filters(const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        return c->syscall_whitelist ||
Zbigniew Jędrzejewski-Szmek 03e93e
+                !set_isempty(c->syscall_filter);
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+static bool context_has_no_new_privileges(const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (c->no_new_privileges)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return true;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (have_effective_cap(CAP_SYS_ADMIN)) /* if we are privileged, we don't need NNP */
Zbigniew Jędrzejewski-Szmek 03e93e
+                return false;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        /* We need NNP if we have any form of seccomp and are unprivileged */
Zbigniew Jędrzejewski-Szmek 03e93e
+        return context_has_address_families(c) ||
Zbigniew Jędrzejewski-Szmek 03e93e
+                c->memory_deny_write_execute ||
Zbigniew Jędrzejewski-Szmek 03e93e
+                c->restrict_realtime ||
Zbigniew Jędrzejewski-Szmek 03e93e
+                exec_context_restrict_namespaces_set(c) ||
Zbigniew Jędrzejewski-Szmek 03e93e
+                c->protect_kernel_tunables ||
Zbigniew Jędrzejewski-Szmek 03e93e
+                c->protect_kernel_modules ||
Zbigniew Jędrzejewski-Szmek 03e93e
+                c->private_devices ||
Zbigniew Jędrzejewski-Szmek 03e93e
+                context_has_syscall_filters(c) ||
Zbigniew Jędrzejewski-Szmek 03e93e
+                !set_isempty(c->syscall_archs);
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
 #ifdef HAVE_SECCOMP
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static bool skip_seccomp_unavailable(const Unit* u, const char* msg) {
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -1197,344 +1232,131 @@ static bool skip_seccomp_unavailable(const Unit* u, const char* msg) {
Zbigniew Jędrzejewski-Szmek 03e93e
         return true;
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-static int apply_seccomp(const Unit* u, const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        uint32_t negative_action, action;
Zbigniew Jędrzejewski-Szmek 03e93e
-        scmp_filter_ctx seccomp;
Zbigniew Jędrzejewski-Szmek 03e93e
-        Iterator i;
Zbigniew Jędrzejewski-Szmek 03e93e
-        void *id;
Zbigniew Jędrzejewski-Szmek 03e93e
-        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
+static int apply_syscall_filter(const Unit* u, const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        uint32_t negative_action, default_action, action;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(u);
Zbigniew Jędrzejewski-Szmek 03e93e
         assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (skip_seccomp_unavailable(u, "syscall filtering"))
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!context_has_syscall_filters(c))
Zbigniew Jędrzejewski-Szmek 03e93e
+                return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (skip_seccomp_unavailable(u, "SystemCallFilter="))
Zbigniew Jędrzejewski-Szmek 03e93e
                 return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         negative_action = c->syscall_errno == 0 ? SCMP_ACT_KILL : SCMP_ACT_ERRNO(c->syscall_errno);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp = seccomp_init(c->syscall_whitelist ? negative_action : SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (!seccomp)
Zbigniew Jędrzejewski-Szmek 03e93e
-                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (c->syscall_archs) {
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                SET_FOREACH(id, c->syscall_archs, i) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1);
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r == -EEXIST)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                continue;
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-                }
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (c->syscall_whitelist) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                default_action = negative_action;
Zbigniew Jędrzejewski-Szmek 03e93e
+                action = SCMP_ACT_ALLOW;
Zbigniew Jędrzejewski-Szmek 03e93e
         } else {
Zbigniew Jędrzejewski-Szmek 03e93e
-                r = seccomp_add_secondary_archs(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
+                default_action = SCMP_ACT_ALLOW;
Zbigniew Jędrzejewski-Szmek 03e93e
+                action = negative_action;
Zbigniew Jędrzejewski-Szmek 03e93e
         }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        action = c->syscall_whitelist ? SCMP_ACT_ALLOW : negative_action;
Zbigniew Jędrzejewski-Szmek 03e93e
-        SET_FOREACH(id, c->syscall_filter, i) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                r = seccomp_rule_add(seccomp, action, PTR_TO_INT(id) - 1, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-        }
Zbigniew Jędrzejewski-Szmek 03e93e
+        return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action);
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+static int apply_syscall_archs(const Unit *u, const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(u);
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (set_isempty(c->syscall_archs))
Zbigniew Jędrzejewski-Szmek 03e93e
+                return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (skip_seccomp_unavailable(u, "SystemCallArchitectures="))
Zbigniew Jędrzejewski-Szmek 03e93e
+                return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-finish:
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp_release(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+        return seccomp_restrict_archs(c->syscall_archs);
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static int apply_address_families(const Unit* u, const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        scmp_filter_ctx seccomp;
Zbigniew Jędrzejewski-Szmek 03e93e
-        Iterator i;
Zbigniew Jędrzejewski-Szmek 03e93e
-        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(u);
Zbigniew Jędrzejewski-Szmek 03e93e
         assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!context_has_address_families(c))
Zbigniew Jędrzejewski-Szmek 03e93e
+                return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
         if (skip_seccomp_unavailable(u, "RestrictAddressFamilies="))
Zbigniew Jędrzejewski-Szmek 03e93e
                 return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (c->address_families_whitelist) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                int af, first = 0, last = 0;
Zbigniew Jędrzejewski-Szmek 03e93e
-                void *afp;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                /* If this is a whitelist, we first block the address
Zbigniew Jędrzejewski-Szmek 03e93e
-                 * families that are out of range and then everything
Zbigniew Jędrzejewski-Szmek 03e93e
-                 * that is not in the set. First, we find the lowest
Zbigniew Jędrzejewski-Szmek 03e93e
-                 * and highest address family in the set. */
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                SET_FOREACH(afp, c->address_families, i) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        af = PTR_TO_INT(afp);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (af <= 0 || af >= af_max())
Zbigniew Jędrzejewski-Szmek 03e93e
-                                continue;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (first == 0 || af < first)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                first = af;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (last == 0 || af > last)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                last = af;
Zbigniew Jędrzejewski-Szmek 03e93e
-                }
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                assert((first == 0) == (last == 0));
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (first == 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                        /* No entries in the valid range, block everything */
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_ACT_ERRNO(EPROTONOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        0);
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                } else {
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                        /* Block everything below the first entry */
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_ACT_ERRNO(EPROTONOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_A0(SCMP_CMP_LT, first));
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                        /* Block everything above the last entry */
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_ACT_ERRNO(EPROTONOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_A0(SCMP_CMP_GT, last));
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                        /* Block everything between the first and last
Zbigniew Jędrzejewski-Szmek 03e93e
-                         * entry */
Zbigniew Jędrzejewski-Szmek 03e93e
-                        for (af = 1; af < af_max(); af++) {
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                                if (set_contains(c->address_families, INT_TO_PTR(af)))
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                                r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                                SCMP_ACT_ERRNO(EPROTONOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                                SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                                SCMP_A0(SCMP_CMP_EQ, af));
Zbigniew Jędrzejewski-Szmek 03e93e
-                                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-                        }
Zbigniew Jędrzejewski-Szmek 03e93e
-                }
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        } else {
Zbigniew Jędrzejewski-Szmek 03e93e
-                void *af;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                /* If this is a blacklist, then generate one rule for
Zbigniew Jędrzejewski-Szmek 03e93e
-                 * each address family that are then combined in OR
Zbigniew Jędrzejewski-Szmek 03e93e
-                 * checks. */
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                SET_FOREACH(af, c->address_families, i) {
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_ACT_ERRNO(EPROTONOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_A0(SCMP_CMP_EQ, PTR_TO_INT(af)));
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-                }
Zbigniew Jędrzejewski-Szmek 03e93e
-        }
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-finish:
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp_release(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+        return seccomp_restrict_address_families(c->address_families, c->address_families_whitelist);
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static int apply_memory_deny_write_execute(const Unit* u, const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        scmp_filter_ctx seccomp;
Zbigniew Jędrzejewski-Szmek 03e93e
-        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(u);
Zbigniew Jędrzejewski-Szmek 03e93e
         assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!c->memory_deny_write_execute)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
         if (skip_seccomp_unavailable(u, "MemoryDenyWriteExecute="))
Zbigniew Jędrzejewski-Szmek 03e93e
                 return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_SYS(mmap),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC|PROT_WRITE, PROT_EXEC|PROT_WRITE));
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_SYS(mprotect),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC));
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_SYS(shmat),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_A2(SCMP_CMP_MASKED_EQ, SHM_EXEC, SHM_EXEC));
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-finish:
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp_release(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+        return seccomp_memory_deny_write_execute();
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static int apply_restrict_realtime(const Unit* u, const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        static const int permitted_policies[] = {
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCHED_OTHER,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCHED_BATCH,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCHED_IDLE,
Zbigniew Jędrzejewski-Szmek 03e93e
-        };
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        scmp_filter_ctx seccomp;
Zbigniew Jędrzejewski-Szmek 03e93e
-        unsigned i;
Zbigniew Jędrzejewski-Szmek 03e93e
-        int r, p, max_policy = 0;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(u);
Zbigniew Jędrzejewski-Szmek 03e93e
         assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!c->restrict_realtime)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
         if (skip_seccomp_unavailable(u, "RestrictRealtime="))
Zbigniew Jędrzejewski-Szmek 03e93e
                 return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        /* Determine the highest policy constant we want to allow */
Zbigniew Jędrzejewski-Szmek 03e93e
-        for (i = 0; i < ELEMENTSOF(permitted_policies); i++)
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (permitted_policies[i] > max_policy)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        max_policy = permitted_policies[i];
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        /* Go through all policies with lower values than that, and block them -- unless they appear in the
Zbigniew Jędrzejewski-Szmek 03e93e
-         * whitelist. */
Zbigniew Jędrzejewski-Szmek 03e93e
-        for (p = 0; p < max_policy; p++) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                bool good = false;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                /* Check if this is in the whitelist. */
Zbigniew Jędrzejewski-Szmek 03e93e
-                for (i = 0; i < ELEMENTSOF(permitted_policies); i++)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (permitted_policies[i] == p) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                                good = true;
Zbigniew Jędrzejewski-Szmek 03e93e
-                                break;
Zbigniew Jędrzejewski-Szmek 03e93e
-                        }
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (good)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                /* Deny this policy */
Zbigniew Jędrzejewski-Szmek 03e93e
-                r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_SYS(sched_setscheduler),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_A1(SCMP_CMP_EQ, p));
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-        }
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        /* Blacklist all other policies, i.e. the ones with higher values. Note that all comparisons are unsigned here,
Zbigniew Jędrzejewski-Szmek 03e93e
-         * hence no need no check for < 0 values. */
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_SYS(sched_setscheduler),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_A1(SCMP_CMP_GT, max_policy));
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-finish:
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp_release(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+        return seccomp_restrict_realtime();
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static int apply_protect_sysctl(const Unit *u, const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        scmp_filter_ctx seccomp;
Zbigniew Jędrzejewski-Szmek 03e93e
-        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(u);
Zbigniew Jędrzejewski-Szmek 03e93e
         assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         /* Turn off the legacy sysctl() system call. Many distributions turn this off while building the kernel, but
Zbigniew Jędrzejewski-Szmek 03e93e
          * let's protect even those systems where this is left on in the kernel. */
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!c->protect_kernel_tunables)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
         if (skip_seccomp_unavailable(u, "ProtectKernelTunables="))
Zbigniew Jędrzejewski-Szmek 03e93e
                 return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_SYS(_sysctl),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        0);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-finish:
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp_release(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+        return seccomp_protect_sysctl();
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static int apply_protect_kernel_modules(const Unit *u, const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(u);
Zbigniew Jędrzejewski-Szmek 03e93e
         assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         /* Turn off module syscalls on ProtectKernelModules=yes */
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!c->protect_kernel_modules)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
         if (skip_seccomp_unavailable(u, "ProtectKernelModules="))
Zbigniew Jędrzejewski-Szmek 03e93e
                 return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        return seccomp_load_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM));
Zbigniew Jędrzejewski-Szmek 03e93e
+        return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_MODULE, SCMP_ACT_ERRNO(EPERM));
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static int apply_private_devices(const Unit *u, const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(u);
Zbigniew Jędrzejewski-Szmek 03e93e
         assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         /* If PrivateDevices= is set, also turn off iopl and all @raw-io syscalls. */
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!c->private_devices)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
         if (skip_seccomp_unavailable(u, "PrivateDevices="))
Zbigniew Jędrzejewski-Szmek 03e93e
                 return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        return seccomp_load_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO, SCMP_ACT_ERRNO(EPERM));
Zbigniew Jędrzejewski-Szmek 03e93e
+        return seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + SYSCALL_FILTER_SET_RAW_IO, SCMP_ACT_ERRNO(EPERM));
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static int apply_restrict_namespaces(Unit *u, const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert(u);
Zbigniew Jędrzejewski-Szmek 03e93e
         assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         if (!exec_context_restrict_namespaces_set(c))
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -2168,40 +1990,6 @@ static int close_remaining_fds(
Zbigniew Jędrzejewski-Szmek 03e93e
         return close_all_fds(dont_close, n_dont_close);
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-static bool context_has_address_families(const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        return c->address_families_whitelist ||
Zbigniew Jędrzejewski-Szmek 03e93e
-                !set_isempty(c->address_families);
Zbigniew Jędrzejewski-Szmek 03e93e
-}
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-static bool context_has_syscall_filters(const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        return c->syscall_whitelist ||
Zbigniew Jędrzejewski-Szmek 03e93e
-                !set_isempty(c->syscall_filter) ||
Zbigniew Jędrzejewski-Szmek 03e93e
-                !set_isempty(c->syscall_archs);
Zbigniew Jędrzejewski-Szmek 03e93e
-}
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-static bool context_has_no_new_privileges(const ExecContext *c) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        assert(c);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (c->no_new_privileges)
Zbigniew Jędrzejewski-Szmek 03e93e
-                return true;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (have_effective_cap(CAP_SYS_ADMIN)) /* if we are privileged, we don't need NNP */
Zbigniew Jędrzejewski-Szmek 03e93e
-                return false;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        return context_has_address_families(c) || /* we need NNP if we have any form of seccomp and are unprivileged */
Zbigniew Jędrzejewski-Szmek 03e93e
-                c->memory_deny_write_execute ||
Zbigniew Jędrzejewski-Szmek 03e93e
-                c->restrict_realtime ||
Zbigniew Jędrzejewski-Szmek 03e93e
-                exec_context_restrict_namespaces_set(c) ||
Zbigniew Jędrzejewski-Szmek 03e93e
-                c->protect_kernel_tunables ||
Zbigniew Jędrzejewski-Szmek 03e93e
-                c->protect_kernel_modules ||
Zbigniew Jędrzejewski-Szmek 03e93e
-                c->private_devices ||
Zbigniew Jędrzejewski-Szmek 03e93e
-                context_has_syscall_filters(c);
Zbigniew Jędrzejewski-Szmek 03e93e
-}
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
 static int send_user_lookup(
Zbigniew Jędrzejewski-Szmek 03e93e
                 Unit *unit,
Zbigniew Jędrzejewski-Szmek 03e93e
                 int user_lookup_fd,
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -2753,28 +2541,22 @@ static int exec_child(
Zbigniew Jędrzejewski-Szmek 03e93e
                         }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 #ifdef HAVE_SECCOMP
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (context_has_address_families(context)) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = apply_address_families(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                                *exit_status = EXIT_ADDRESS_FAMILIES;
Zbigniew Jędrzejewski-Szmek 03e93e
-                                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = apply_address_families(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        *exit_status = EXIT_ADDRESS_FAMILIES;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (context->memory_deny_write_execute) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = apply_memory_deny_write_execute(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                                *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
-                                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = apply_memory_deny_write_execute(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (context->restrict_realtime) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = apply_restrict_realtime(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                                *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
-                                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = apply_restrict_realtime(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
                 r = apply_restrict_namespaces(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -2783,38 +2565,36 @@ static int exec_child(
Zbigniew Jędrzejewski-Szmek 03e93e
                         return r;
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (context->protect_kernel_tunables) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = apply_protect_sysctl(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                                *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
-                                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = apply_protect_sysctl(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (context->protect_kernel_modules) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = apply_protect_kernel_modules(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                                *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
-                                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = apply_protect_kernel_modules(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (context->private_devices) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = apply_private_devices(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                                *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
-                                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = apply_private_devices(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = apply_syscall_archs(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
                 /* This really should remain the last step before the execve(), to make sure our own code is unaffected
Zbigniew Jędrzejewski-Szmek 03e93e
                  * by the filter as little as possible. */
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (context_has_syscall_filters(context)) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = apply_seccomp(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                                *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
-                                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = apply_syscall_filter(unit, context);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        *exit_status = EXIT_SECCOMP;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
 #endif
Zbigniew Jędrzejewski-Szmek 03e93e
         }
Zbigniew Jędrzejewski-Szmek 03e93e
diff --git a/src/core/main.c b/src/core/main.c
Zbigniew Jędrzejewski-Szmek 03e93e
index 94602611a7..fc1ae123a8 100644
Zbigniew Jędrzejewski-Szmek 03e93e
--- a/src/core/main.c
Zbigniew Jędrzejewski-Szmek 03e93e
+++ b/src/core/main.c
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -1185,44 +1185,16 @@ oom:
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static int enforce_syscall_archs(Set *archs) {
Zbigniew Jędrzejewski-Szmek 03e93e
 #ifdef HAVE_SECCOMP
Zbigniew Jędrzejewski-Szmek 03e93e
-        scmp_filter_ctx *seccomp;
Zbigniew Jędrzejewski-Szmek 03e93e
-        Iterator i;
Zbigniew Jędrzejewski-Szmek 03e93e
-        void *id;
Zbigniew Jędrzejewski-Szmek 03e93e
         int r;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         if (!is_seccomp_available())
Zbigniew Jędrzejewski-Szmek 03e93e
                 return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp = seccomp_init(SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (!seccomp)
Zbigniew Jędrzejewski-Szmek 03e93e
-                return log_oom();
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        SET_FOREACH(id, arg_syscall_archs, i) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1);
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (r == -EEXIST)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        log_error_errno(r, "Failed to add architecture to seccomp: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
-                        goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-                }
Zbigniew Jędrzejewski-Szmek 03e93e
-        }
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                log_error_errno(r, "Failed to unset NO_NEW_PRIVS: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-        }
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+        r = seccomp_restrict_archs(arg_syscall_archs);
Zbigniew Jędrzejewski-Szmek 03e93e
         if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                log_error_errno(r, "Failed to add install architecture seccomp: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-finish:
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp_release(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-#else
Zbigniew Jędrzejewski-Szmek 03e93e
-        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+                return log_error_errno(r, "Failed to enforce system call architecture restrication: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
 #endif
Zbigniew Jędrzejewski-Szmek 03e93e
+        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static int status_welcome(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
diff --git a/src/nspawn/nspawn-seccomp.c b/src/nspawn/nspawn-seccomp.c
Zbigniew Jędrzejewski-Szmek 03e93e
index 03a397d30c..72ecc51b16 100644
Zbigniew Jędrzejewski-Szmek 03e93e
--- a/src/nspawn/nspawn-seccomp.c
Zbigniew Jędrzejewski-Szmek 03e93e
+++ b/src/nspawn/nspawn-seccomp.c
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -26,20 +26,21 @@
Zbigniew Jędrzejewski-Szmek 03e93e
 #include <seccomp.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 #endif
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+#include "alloc-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "log.h"
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-#ifdef HAVE_SECCOMP
Zbigniew Jędrzejewski-Szmek 03e93e
-#include "seccomp-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
-#endif
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "nspawn-seccomp.h"
Zbigniew Jędrzejewski-Szmek 03e93e
+#ifdef HAVE_SECCOMP
Zbigniew Jędrzejewski-Szmek 03e93e
+#include "seccomp-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
+#endif
Zbigniew Jędrzejewski-Szmek 03e93e
+#include "string-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 #ifdef HAVE_SECCOMP
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-static int seccomp_add_default_syscall_filter(scmp_filter_ctx ctx,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                              uint64_t cap_list_retain) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        unsigned i;
Zbigniew Jędrzejewski-Szmek 03e93e
-        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
+static int seccomp_add_default_syscall_filter(
Zbigniew Jędrzejewski-Szmek 03e93e
+                scmp_filter_ctx ctx,
Zbigniew Jędrzejewski-Szmek 03e93e
+                uint32_t arch,
Zbigniew Jędrzejewski-Szmek 03e93e
+                uint64_t cap_list_retain) {
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
         static const struct {
Zbigniew Jędrzejewski-Szmek 03e93e
                 uint64_t capability;
Zbigniew Jędrzejewski-Szmek 03e93e
                 int syscall_num;
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -111,23 +112,29 @@ static int seccomp_add_default_syscall_filter(scmp_filter_ctx ctx,
Zbigniew Jędrzejewski-Szmek 03e93e
                 { CAP_SYS_TIME,   SCMP_SYS(settimeofday)        },
Zbigniew Jędrzejewski-Szmek 03e93e
                 { CAP_SYS_TIME,   SCMP_SYS(stime)               },
Zbigniew Jędrzejewski-Szmek 03e93e
         };
Zbigniew Jędrzejewski-Szmek 03e93e
+        unsigned i;
Zbigniew Jędrzejewski-Szmek 03e93e
+        int r, c = 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         for (i = 0; i < ELEMENTSOF(blacklist); i++) {
Zbigniew Jędrzejewski-Szmek 03e93e
                 if (blacklist[i].capability != 0 && (cap_list_retain & (1ULL << blacklist[i].capability)))
Zbigniew Jędrzejewski-Szmek 03e93e
                         continue;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-                r = seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), blacklist[i].syscall_num, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (r == -EFAULT)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        continue; /* unknown syscall */
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        return log_error_errno(r, "Failed to block syscall: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EPERM), blacklist[i].syscall_num, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        /* If the system call is not known on this architecture, then that's fine, let's ignore it */
Zbigniew Jędrzejewski-Szmek 03e93e
+                        _cleanup_free_ char *n = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        n = seccomp_syscall_resolve_num_arch(arch, blacklist[i].syscall_num);
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to add rule for system call %s, ignoring: %m", strna(n));
Zbigniew Jędrzejewski-Szmek 03e93e
+                } else
Zbigniew Jędrzejewski-Szmek 03e93e
+                        c++;
Zbigniew Jędrzejewski-Szmek 03e93e
         }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+        return c;
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 int setup_seccomp(uint64_t cap_list_retain) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        scmp_filter_ctx seccomp;
Zbigniew Jędrzejewski-Szmek 03e93e
+        uint32_t arch;
Zbigniew Jędrzejewski-Szmek 03e93e
         int r;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         if (!is_seccomp_available()) {
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -135,45 +142,51 @@ int setup_seccomp(uint64_t cap_list_retain) {
Zbigniew Jędrzejewski-Szmek 03e93e
                 return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
         }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                return log_error_errno(r, "Failed to allocate seccomp object: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_add_default_syscall_filter(seccomp, cap_list_retain);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        /*
Zbigniew Jędrzejewski-Szmek 03e93e
-           Audit is broken in containers, much of the userspace audit
Zbigniew Jędrzejewski-Szmek 03e93e
-           hookup will fail if running inside a container. We don't
Zbigniew Jędrzejewski-Szmek 03e93e
-           care and just turn off creation of audit sockets.
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-           This will make socket(AF_NETLINK, *, NETLINK_AUDIT) fail
Zbigniew Jędrzejewski-Szmek 03e93e
-           with EAFNOSUPPORT which audit userspace uses as indication
Zbigniew Jędrzejewski-Szmek 03e93e
-           that audit is disabled in the kernel.
Zbigniew Jędrzejewski-Szmek 03e93e
-         */
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_ACT_ERRNO(EAFNOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        2,
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_A0(SCMP_CMP_EQ, AF_NETLINK),
Zbigniew Jędrzejewski-Szmek 03e93e
-                        SCMP_A2(SCMP_CMP_EQ, NETLINK_AUDIT));
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                log_error_errno(r, "Failed to add audit seccomp rule: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-        }
Zbigniew Jędrzejewski-Szmek 03e93e
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+                int n;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return log_error_errno(r, "Failed to allocate seccomp object: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                n = seccomp_add_default_syscall_filter(seccomp, arch, cap_list_retain);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (n < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return n;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                /*
Zbigniew Jędrzejewski-Szmek 03e93e
+                  Audit is broken in containers, much of the userspace audit hookup will fail if running inside a
Zbigniew Jędrzejewski-Szmek 03e93e
+                  container. We don't care and just turn off creation of audit sockets.
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                  This will make socket(AF_NETLINK, *, NETLINK_AUDIT) fail with EAFNOSUPPORT which audit userspace uses
Zbigniew Jędrzejewski-Szmek 03e93e
+                  as indication that audit is disabled in the kernel.
Zbigniew Jędrzejewski-Szmek 03e93e
+                */
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_ACT_ERRNO(EAFNOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                2,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_A0(SCMP_CMP_EQ, AF_NETLINK),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_A2(SCMP_CMP_EQ, NETLINK_AUDIT));
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to add audit seccomp rule, ignoring: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
+                else
Zbigniew Jędrzejewski-Szmek 03e93e
+                        n++;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (n <= 0) /* no rule added? then skip this architecture */
Zbigniew Jędrzejewski-Szmek 03e93e
+                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                log_error_errno(r, "Failed to install seccomp audit filter: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (IN_SET(r, -EPERM, -EACCES))
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return log_error_errno(r, "Failed to install seccomp audit filter: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to install filter set for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
         }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-finish:
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp_release(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 #else
Zbigniew Jędrzejewski-Szmek 03e93e
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
Zbigniew Jędrzejewski-Szmek 03e93e
index 55b97e1efb..aa37e12db7 100644
Zbigniew Jędrzejewski-Szmek 03e93e
--- a/src/shared/seccomp-util.c
Zbigniew Jędrzejewski-Szmek 03e93e
+++ b/src/shared/seccomp-util.c
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -18,17 +18,52 @@
Zbigniew Jędrzejewski-Szmek 03e93e
 ***/
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 #include <errno.h>
Zbigniew Jędrzejewski-Szmek 03e93e
+#include <linux/seccomp.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 #include <seccomp.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 #include <stddef.h>
Zbigniew Jędrzejewski-Szmek 03e93e
+#include <sys/mman.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 #include <sys/prctl.h>
Zbigniew Jędrzejewski-Szmek 03e93e
-#include <linux/seccomp.h>
Zbigniew Jędrzejewski-Szmek 03e93e
+#include <sys/shm.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+#include "af-list.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "alloc-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "macro.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "nsflags.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "seccomp-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "string-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
+#include "errno-list.h"
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+const uint32_t seccomp_local_archs[] = {
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+#if defined(__i386__) || defined(__x86_64__)
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_X86,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_X86_64,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_X32,
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+#elif defined(__arm__) || defined(__aarch64__)
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_ARM,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_AARCH64,
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+#elif defined(__mips__) || defined(__mips64__)
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_MIPS,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_MIPS64,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_MIPS64N32,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_MIPSEL,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_MIPSEL64,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_MIPSEL64N32,
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+#elif defined(__powerpc__) || defined(__powerpc64__)
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_PPC,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_PPC64,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_PPC64LE,
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+#elif defined(__s390__) || defined(__s390x__)
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_S390,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCMP_ARCH_S390X,
Zbigniew Jędrzejewski-Szmek 03e93e
+#endif
Zbigniew Jędrzejewski-Szmek 03e93e
+                (uint32_t) -1
Zbigniew Jędrzejewski-Szmek 03e93e
+        };
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 const char* seccomp_arch_to_string(uint32_t c) {
Zbigniew Jędrzejewski-Szmek 03e93e
         /* Maintain order used in <seccomp.h>.
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -122,18 +157,37 @@ int seccomp_arch_from_string(const char *n, uint32_t *ret) {
Zbigniew Jędrzejewski-Szmek 03e93e
         return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-int seccomp_init_conservative(scmp_filter_ctx *ret, uint32_t default_action) {
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_action) {
Zbigniew Jędrzejewski-Szmek 03e93e
         scmp_filter_ctx seccomp;
Zbigniew Jędrzejewski-Szmek 03e93e
         int r;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        /* Much like seccomp_init(), but tries to be a bit more conservative in its defaults: all secondary archs are
Zbigniew Jędrzejewski-Szmek 03e93e
-         * added by default, and NNP is turned off. */
Zbigniew Jędrzejewski-Szmek 03e93e
+        /* Much like seccomp_init(), but initializes the filter for one specific architecture only, without affecting
Zbigniew Jędrzejewski-Szmek 03e93e
+         * any others. Also, turns off the NNP fiddling. */
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         seccomp = seccomp_init(default_action);
Zbigniew Jędrzejewski-Szmek 03e93e
         if (!seccomp)
Zbigniew Jędrzejewski-Szmek 03e93e
                 return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_add_secondary_archs(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (arch != SCMP_ARCH_NATIVE &&
Zbigniew Jędrzejewski-Szmek 03e93e
+            arch != seccomp_arch_native()) {
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_arch_add(seccomp, arch);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_arch_remove(seccomp, seccomp_arch_native());
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert(seccomp_arch_exist(seccomp, arch) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert(seccomp_arch_exist(seccomp, SCMP_ARCH_NATIVE) == -EEXIST);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert(seccomp_arch_exist(seccomp, seccomp_arch_native()) == -EEXIST);
Zbigniew Jędrzejewski-Szmek 03e93e
+        } else {
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert(seccomp_arch_exist(seccomp, SCMP_ARCH_NATIVE) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert(seccomp_arch_exist(seccomp, seccomp_arch_native()) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        r = seccomp_attr_set(seccomp, SCMP_FLTATR_ACT_BADARCH, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
         if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
                 goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -149,56 +203,6 @@ finish:
Zbigniew Jędrzejewski-Szmek 03e93e
         return r;
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-int seccomp_add_secondary_archs(scmp_filter_ctx ctx) {
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        /* Add in all possible secondary archs we are aware of that
Zbigniew Jędrzejewski-Szmek 03e93e
-         * this kernel might support. */
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        static const int seccomp_arches[] = {
Zbigniew Jędrzejewski-Szmek 03e93e
-#if defined(__i386__) || defined(__x86_64__)
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_X86,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_X86_64,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_X32,
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-#elif defined(__arm__) || defined(__aarch64__)
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_ARM,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_AARCH64,
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-#elif defined(__arm__) || defined(__aarch64__)
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_ARM,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_AARCH64,
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-#elif defined(__mips__) || defined(__mips64__)
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_MIPS,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_MIPS64,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_MIPS64N32,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_MIPSEL,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_MIPSEL64,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_MIPSEL64N32,
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-#elif defined(__powerpc__) || defined(__powerpc64__)
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_PPC,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_PPC64,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_PPC64LE,
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-#elif defined(__s390__) || defined(__s390x__)
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_S390,
Zbigniew Jędrzejewski-Szmek 03e93e
-                SCMP_ARCH_S390X,
Zbigniew Jędrzejewski-Szmek 03e93e
-#endif
Zbigniew Jędrzejewski-Szmek 03e93e
-        };
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        unsigned i;
Zbigniew Jędrzejewski-Szmek 03e93e
-        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        for (i = 0; i < ELEMENTSOF(seccomp_arches); i++) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                r = seccomp_arch_add(ctx, seccomp_arches[i]);
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (r < 0 && r != -EEXIST)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-        }
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
-}
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
 static bool is_basic_seccomp_available(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
         int r;
Zbigniew Jędrzejewski-Szmek 03e93e
         r = prctl(PR_GET_SECCOMP, 0, 0, 0, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -523,7 +527,12 @@ const SyscallFilterSet *syscall_filter_set_find(const char *name) {
Zbigniew Jędrzejewski-Szmek 03e93e
         return NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action) {
Zbigniew Jędrzejewski-Szmek 03e93e
+static int seccomp_add_syscall_filter_set(
Zbigniew Jędrzejewski-Szmek 03e93e
+                scmp_filter_ctx seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                uint32_t default_action,
Zbigniew Jędrzejewski-Szmek 03e93e
+                const SyscallFilterSet *set,
Zbigniew Jędrzejewski-Szmek 03e93e
+                uint32_t action) {
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
         const char *sys;
Zbigniew Jędrzejewski-Szmek 03e93e
         int r;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -540,47 +549,102 @@ int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterS
Zbigniew Jędrzejewski-Szmek 03e93e
                         if (!other)
Zbigniew Jędrzejewski-Szmek 03e93e
                                 return -EINVAL;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = seccomp_add_syscall_filter_set(seccomp, other, action);
Zbigniew Jędrzejewski-Szmek 03e93e
+                        r = seccomp_add_syscall_filter_set(seccomp, default_action, other, action);
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
                 } else {
Zbigniew Jędrzejewski-Szmek 03e93e
                         id = seccomp_syscall_resolve_name(sys);
Zbigniew Jędrzejewski-Szmek 03e93e
                         if (id == __NR_SCMP_ERROR)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                return -EINVAL;
Zbigniew Jędrzejewski-Szmek 03e93e
+                                return -EINVAL; /* Not known at all? Then that's a real error */
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = seccomp_rule_add(seccomp, action, id, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                        r = seccomp_rule_add_exact(seccomp, action, id, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                                /* If the system call is not known on this architecture, then that's fine, let's ignore it */
Zbigniew Jędrzejewski-Szmek 03e93e
+                                log_debug_errno(r, "Failed to add rule for system call %s, ignoring: %m", sys);
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
-                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
         }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-int seccomp_load_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        scmp_filter_ctx seccomp;
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        uint32_t arch;
Zbigniew Jędrzejewski-Szmek 03e93e
         int r;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         assert(set);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        /* The one-stop solution: allocate a seccomp object, add a filter to it, and apply it */
Zbigniew Jędrzejewski-Szmek 03e93e
+        /* The one-stop solution: allocate a seccomp object, add the specified filter to it, and apply it. Once for
Zbigniew Jędrzejewski-Szmek 03e93e
+         * earch local arch. */
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_init_conservative(&seccomp, default_action);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_add_syscall_filter_set(seccomp, set, action);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
+                log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_init_for_arch(&seccomp, arch, default_action);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-finish:
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp_release(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_add_syscall_filter_set(seccomp, default_action, set, action);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to add filter set, ignoring: %m");
Zbigniew Jędrzejewski-Szmek 03e93e
+                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (IN_SET(r, -EPERM, -EACCES))
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to install filter set for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Set* set, uint32_t action) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        uint32_t arch;
Zbigniew Jędrzejewski-Szmek 03e93e
+        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        /* Similar to seccomp_load_syscall_filter_set(), but takes a raw Set* of syscalls, instead of a
Zbigniew Jędrzejewski-Szmek 03e93e
+         * SyscallFilterSet* table. */
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (set_isempty(set) && default_action == SCMP_ACT_ALLOW)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+                Iterator i;
Zbigniew Jędrzejewski-Szmek 03e93e
+                void *id;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_init_for_arch(&seccomp, arch, default_action);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                SET_FOREACH(id, set, i) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        r = seccomp_rule_add_exact(seccomp, action, PTR_TO_INT(id) - 1, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                /* If the system call is not known on this architecture, then that's fine, let's ignore it */
Zbigniew Jędrzejewski-Szmek 03e93e
+                                _cleanup_free_ char *n = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                n = seccomp_syscall_resolve_num_arch(arch, PTR_TO_INT(id) - 1);
Zbigniew Jędrzejewski-Szmek 03e93e
+                                log_debug_errno(r, "Failed to add rule for system call %s, ignoring: %m", strna(n));
Zbigniew Jędrzejewski-Szmek 03e93e
+                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (IN_SET(r, -EPERM, -EACCES))
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to install filter set for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 int seccomp_restrict_namespaces(unsigned long retain) {
Zbigniew Jędrzejewski-Szmek 03e93e
-        scmp_filter_ctx seccomp;
Zbigniew Jędrzejewski-Szmek 03e93e
-        unsigned i;
Zbigniew Jędrzejewski-Szmek 03e93e
+        uint32_t arch;
Zbigniew Jędrzejewski-Szmek 03e93e
         int r;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         if (log_get_max_level() >= LOG_DEBUG) {
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -594,74 +658,420 @@ int seccomp_restrict_namespaces(unsigned long retain) {
Zbigniew Jędrzejewski-Szmek 03e93e
         if ((retain & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL)
Zbigniew Jędrzejewski-Szmek 03e93e
                 return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_init_conservative(&seccomp, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        if ((retain & NAMESPACE_FLAGS_ALL) == 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                /* If every single kind of namespace shall be prohibited, then let's block the whole setns() syscall
Zbigniew Jędrzejewski-Szmek 03e93e
-                 * altogether. */
Zbigniew Jędrzejewski-Szmek 03e93e
-                r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+                unsigned i;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                if ((retain & NAMESPACE_FLAGS_ALL) == 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        /* If every single kind of namespace shall be prohibited, then let's block the whole setns() syscall
Zbigniew Jędrzejewski-Szmek 03e93e
+                         * altogether. */
Zbigniew Jędrzejewski-Szmek 03e93e
+                        r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_SYS(setns),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                else
Zbigniew Jędrzejewski-Szmek 03e93e
+                        /* Otherwise, block only the invocations with the appropriate flags in the loop below, but also the
Zbigniew Jędrzejewski-Szmek 03e93e
+                         * special invocation with a zero flags argument, right here. */
Zbigniew Jędrzejewski-Szmek 03e93e
+                        r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_SYS(setns),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_A1(SCMP_CMP_EQ, 0));
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to add setns() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                for (i = 0; namespace_flag_map[i].name; i++) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        unsigned long f;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        f = namespace_flag_map[i].flag;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if ((retain & f) == f) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                log_debug("Permitting %s.", namespace_flag_map[i].name);
Zbigniew Jędrzejewski-Szmek 03e93e
+                                continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug("Blocking %s.", namespace_flag_map[i].name);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_SYS(unshare),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_A0(SCMP_CMP_MASKED_EQ, f, f));
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                log_debug_errno(r, "Failed to add unshare() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                break;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_SYS(clone),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_A0(SCMP_CMP_MASKED_EQ, f, f));
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                log_debug_errno(r, "Failed to add clone() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                break;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if ((retain & NAMESPACE_FLAGS_ALL) != 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_SYS(setns),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_A1(SCMP_CMP_MASKED_EQ, f, f));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        log_debug_errno(r, "Failed to add setns() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        break;
Zbigniew Jędrzejewski-Szmek 03e93e
+                                }
Zbigniew Jędrzejewski-Szmek 03e93e
+                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+                }
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (IN_SET(r, -EPERM, -EACCES))
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to install namespace restriction rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_protect_sysctl(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        uint32_t arch;
Zbigniew Jędrzejewski-Szmek 03e93e
+        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
                                 seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
                                 SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_SYS(setns),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_SYS(_sysctl),
Zbigniew Jędrzejewski-Szmek 03e93e
                                 0);
Zbigniew Jędrzejewski-Szmek 03e93e
-        else
Zbigniew Jędrzejewski-Szmek 03e93e
-                /* Otherwise, block only the invocations with the appropriate flags in the loop below, but also the
Zbigniew Jędrzejewski-Szmek 03e93e
-                 * special invocation with a zero flags argument, right here. */
Zbigniew Jędrzejewski-Szmek 03e93e
-                r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_SYS(setns),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_A1(SCMP_CMP_EQ, 0));
Zbigniew Jędrzejewski-Szmek 03e93e
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-        for (i = 0; namespace_flag_map[i].name; i++) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                unsigned long f;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                f = namespace_flag_map[i].flag;
Zbigniew Jędrzejewski-Szmek 03e93e
-                if ((retain & f) == f) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        log_debug("Permitting %s.", namespace_flag_map[i].name);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to add _sysctl() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
                         continue;
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-                log_debug("Blocking %s.", namespace_flag_map[i].name);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_SYS(unshare),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_A0(SCMP_CMP_MASKED_EQ, f, f));
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (IN_SET(r, -EPERM, -EACCES))
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
                 if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-                r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
-                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_SYS(clone),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                SCMP_A0(SCMP_CMP_MASKED_EQ, f, f));
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to install sysctl protection rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_restrict_address_families(Set *address_families, bool whitelist) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        uint32_t arch;
Zbigniew Jędrzejewski-Szmek 03e93e
+        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+                Iterator i;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
                 if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                        goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (whitelist) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        int af, first = 0, last = 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        void *afp;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        /* If this is a whitelist, we first block the address families that are out of range and then
Zbigniew Jędrzejewski-Szmek 03e93e
+                         * everything that is not in the set. First, we find the lowest and highest address family in
Zbigniew Jędrzejewski-Szmek 03e93e
+                         * the set. */
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        SET_FOREACH(afp, address_families, i) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                af = PTR_TO_INT(afp);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                if (af <= 0 || af >= af_max())
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                if (first == 0 || af < first)
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        first = af;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                if (last == 0 || af > last)
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        last = af;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        assert((first == 0) == (last == 0));
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if (first == 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                /* No entries in the valid range, block everything */
Zbigniew Jędrzejewski-Szmek 03e93e
+                                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_ACT_ERRNO(EAFNOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        } else {
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                /* Block everything below the first entry */
Zbigniew Jędrzejewski-Szmek 03e93e
+                                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_ACT_ERRNO(EAFNOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_A0(SCMP_CMP_LT, first));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                /* Block everything above the last entry */
Zbigniew Jędrzejewski-Szmek 03e93e
+                                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_ACT_ERRNO(EAFNOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_A0(SCMP_CMP_GT, last));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                /* Block everything between the first and last entry */
Zbigniew Jędrzejewski-Szmek 03e93e
+                                for (af = 1; af < af_max(); af++) {
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        if (set_contains(address_families, INT_TO_PTR(af)))
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                        seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                        SCMP_ACT_ERRNO(EAFNOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                        SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                        1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                        SCMP_A0(SCMP_CMP_EQ, af));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                break;
Zbigniew Jędrzejewski-Szmek 03e93e
+                                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                                }
Zbigniew Jędrzejewski-Szmek 03e93e
+                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                } else {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        void *af;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        /* If this is a blacklist, then generate one rule for
Zbigniew Jędrzejewski-Szmek 03e93e
+                         * each address family that are then combined in OR
Zbigniew Jędrzejewski-Szmek 03e93e
+                         * checks. */
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        SET_FOREACH(af, address_families, i) {
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_ACT_ERRNO(EAFNOSUPPORT),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_SYS(socket),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                                SCMP_A0(SCMP_CMP_EQ, PTR_TO_INT(af)));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        break;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                log_debug_errno(r, "Failed to add socket() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        }
Zbigniew Jędrzejewski-Szmek 03e93e
+                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (IN_SET(r, -EPERM, -EACCES))
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to install socket family rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_restrict_realtime(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        static const int permitted_policies[] = {
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCHED_OTHER,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCHED_BATCH,
Zbigniew Jędrzejewski-Szmek 03e93e
+                SCHED_IDLE,
Zbigniew Jędrzejewski-Szmek 03e93e
+        };
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        int r, max_policy = 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+        uint32_t arch;
Zbigniew Jędrzejewski-Szmek 03e93e
+        unsigned i;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        /* Determine the highest policy constant we want to allow */
Zbigniew Jędrzejewski-Szmek 03e93e
+        for (i = 0; i < ELEMENTSOF(permitted_policies); i++)
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (permitted_policies[i] > max_policy)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        max_policy = permitted_policies[i];
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+                int p;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                /* Go through all policies with lower values than that, and block them -- unless they appear in the
Zbigniew Jędrzejewski-Szmek 03e93e
+                 * whitelist. */
Zbigniew Jędrzejewski-Szmek 03e93e
+                for (p = 0; p < max_policy; p++) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        bool good = false;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        /* Check if this is in the whitelist. */
Zbigniew Jędrzejewski-Szmek 03e93e
+                        for (i = 0; i < ELEMENTSOF(permitted_policies); i++)
Zbigniew Jędrzejewski-Szmek 03e93e
+                                if (permitted_policies[i] == p) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        good = true;
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        break;
Zbigniew Jędrzejewski-Szmek 03e93e
+                                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if (good)
Zbigniew Jędrzejewski-Szmek 03e93e
+                                continue;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-                if ((retain & NAMESPACE_FLAGS_ALL) != 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
-                        r = seccomp_rule_add(
Zbigniew Jędrzejewski-Szmek 03e93e
+                        /* Deny this policy */
Zbigniew Jędrzejewski-Szmek 03e93e
+                        r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
                                         seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
                                         SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_SYS(setns),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_SYS(sched_setscheduler),
Zbigniew Jędrzejewski-Szmek 03e93e
                                         1,
Zbigniew Jędrzejewski-Szmek 03e93e
-                                        SCMP_A1(SCMP_CMP_MASKED_EQ, f, f));
Zbigniew Jędrzejewski-Szmek 03e93e
-                        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
-                                goto finish;
Zbigniew Jędrzejewski-Szmek 03e93e
+                                        SCMP_A1(SCMP_CMP_EQ, p));
Zbigniew Jędrzejewski-Szmek 03e93e
+                        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                                log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                        }
Zbigniew Jędrzejewski-Szmek 03e93e
                 }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                /* Blacklist all other policies, i.e. the ones with higher values. Note that all comparisons are
Zbigniew Jędrzejewski-Szmek 03e93e
+                 * unsigned here, hence no need no check for < 0 values. */
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_SYS(sched_setscheduler),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_A1(SCMP_CMP_GT, max_policy));
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to add scheduler rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (IN_SET(r, -EPERM, -EACCES))
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to install realtime protection rules for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_memory_deny_write_execute(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        uint32_t arch;
Zbigniew Jędrzejewski-Szmek 03e93e
+        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_SYS(mmap),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC|PROT_WRITE, PROT_EXEC|PROT_WRITE));
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to add mmap() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_SYS(mprotect),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC));
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to add mprotect() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_rule_add_exact(
Zbigniew Jędrzejewski-Szmek 03e93e
+                                seccomp,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_ACT_ERRNO(EPERM),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_SYS(shmat),
Zbigniew Jędrzejewski-Szmek 03e93e
+                                1,
Zbigniew Jędrzejewski-Szmek 03e93e
+                                SCMP_A2(SCMP_CMP_MASKED_EQ, SHM_EXEC, SHM_EXEC));
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to add shmat() rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (IN_SET(r, -EPERM, -EACCES))
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        log_debug_errno(r, "Failed to install MemoryDenyWriteExecute= rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_restrict_archs(Set *archs) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+        Iterator i;
Zbigniew Jędrzejewski-Szmek 03e93e
+        void *id;
Zbigniew Jędrzejewski-Szmek 03e93e
+        int r;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        /* This installs a filter with no rules, but that restricts the system call architectures to the specified
Zbigniew Jędrzejewski-Szmek 03e93e
+         * list. */
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        seccomp = seccomp_init(SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!seccomp)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        SET_FOREACH(id, archs, i) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1);
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r == -EEXIST)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        continue;
Zbigniew Jędrzejewski-Szmek 03e93e
+                if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
         }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-        r = seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
+        r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return r;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-finish:
Zbigniew Jędrzejewski-Szmek 03e93e
-        seccomp_release(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
-        return r;
Zbigniew Jędrzejewski-Szmek 03e93e
+        return seccomp_load(seccomp);
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
Zbigniew Jędrzejewski-Szmek 03e93e
index e325dab628..50e4f43c43 100644
Zbigniew Jędrzejewski-Szmek 03e93e
--- a/src/shared/seccomp-util.h
Zbigniew Jędrzejewski-Szmek 03e93e
+++ b/src/shared/seccomp-util.h
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -23,12 +23,12 @@
Zbigniew Jędrzejewski-Szmek 03e93e
 #include <stdbool.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 #include <stdint.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+#include "set.h"
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
 const char* seccomp_arch_to_string(uint32_t c);
Zbigniew Jędrzejewski-Szmek 03e93e
 int seccomp_arch_from_string(const char *n, uint32_t *ret);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-int seccomp_init_conservative(scmp_filter_ctx *ret, uint32_t default_action);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-int seccomp_add_secondary_archs(scmp_filter_ctx c);
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_init_for_arch(scmp_filter_ctx *ret, uint32_t arch, uint32_t default_action);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 bool is_seccomp_available(void);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -61,8 +61,21 @@ extern const SyscallFilterSet syscall_filter_sets[];
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 const SyscallFilterSet *syscall_filter_set_find(const char *name);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
-int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action);
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
-int seccomp_load_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action);
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action);
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Set* set, uint32_t action);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_restrict_archs(Set *archs);
Zbigniew Jędrzejewski-Szmek 03e93e
 int seccomp_restrict_namespaces(unsigned long retain);
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_protect_sysctl(void);
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_restrict_address_families(Set *address_families, bool whitelist);
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_restrict_realtime(void);
Zbigniew Jędrzejewski-Szmek 03e93e
+int seccomp_memory_deny_write_execute(void);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+extern const uint32_t seccomp_local_archs[];
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+#define SECCOMP_FOREACH_LOCAL_ARCH(arch) \
Zbigniew Jędrzejewski-Szmek 03e93e
+        for (unsigned _i = ({ (arch) = seccomp_local_archs[0]; 0; });   \
Zbigniew Jędrzejewski-Szmek 03e93e
+             seccomp_local_archs[_i] != (uint32_t) -1;                  \
Zbigniew Jędrzejewski-Szmek 03e93e
+             (arch) = seccomp_local_archs[++_i])
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+DEFINE_TRIVIAL_CLEANUP_FUNC(scmp_filter_ctx, seccomp_release);
Zbigniew Jędrzejewski-Szmek 03e93e
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
Zbigniew Jędrzejewski-Szmek 03e93e
index 6029853e3e..7d7790cf1e 100644
Zbigniew Jędrzejewski-Szmek 03e93e
--- a/src/test/test-execute.c
Zbigniew Jędrzejewski-Szmek 03e93e
+++ b/src/test/test-execute.c
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -457,6 +457,7 @@ int main(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 03e93e
         };
Zbigniew Jędrzejewski-Szmek 03e93e
         int r;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+        log_set_max_level(LOG_DEBUG);
Zbigniew Jędrzejewski-Szmek 03e93e
         log_parse_environment();
Zbigniew Jędrzejewski-Szmek 03e93e
         log_open();
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c
Zbigniew Jędrzejewski-Szmek 03e93e
index beb6a7f422..6f15879c45 100644
Zbigniew Jędrzejewski-Szmek 03e93e
--- a/src/test/test-seccomp.c
Zbigniew Jędrzejewski-Szmek 03e93e
+++ b/src/test/test-seccomp.c
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -17,10 +17,12 @@
Zbigniew Jędrzejewski-Szmek 03e93e
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
Zbigniew Jędrzejewski-Szmek 03e93e
 ***/
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+#include <sched.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 #include <stdlib.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 #include <sys/eventfd.h>
Zbigniew Jędrzejewski-Szmek 03e93e
+#include <sys/mman.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 #include <unistd.h>
Zbigniew Jędrzejewski-Szmek 03e93e
-#include <sched.h>
Zbigniew Jędrzejewski-Szmek 03e93e
+#include <sys/poll.h>
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "alloc-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "fd-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -30,8 +32,10 @@
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "process-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "raw-clone.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "seccomp-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
+#include "set.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "string-util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 #include "util.h"
Zbigniew Jędrzejewski-Szmek 03e93e
+#include "virt.h"
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static void test_seccomp_arch_to_string(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
         uint32_t a, b;
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -92,7 +96,6 @@ static void test_filter_sets(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         if (!is_seccomp_available())
Zbigniew Jędrzejewski-Szmek 03e93e
                 return;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
         if (geteuid() != 0)
Zbigniew Jędrzejewski-Szmek 03e93e
                 return;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -108,16 +111,16 @@ static void test_filter_sets(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
                         int fd;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
                         if (i == SYSCALL_FILTER_SET_DEFAULT) /* if we look at the default set, whitelist instead of blacklist */
Zbigniew Jędrzejewski-Szmek 03e93e
-                                r = seccomp_load_filter_set(SCMP_ACT_ERRNO(EPERM), syscall_filter_sets + i, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
+                                r = seccomp_load_syscall_filter_set(SCMP_ACT_ERRNO(EUCLEAN), syscall_filter_sets + i, SCMP_ACT_ALLOW);
Zbigniew Jędrzejewski-Szmek 03e93e
                         else
Zbigniew Jędrzejewski-Szmek 03e93e
-                                r = seccomp_load_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EPERM));
Zbigniew Jędrzejewski-Szmek 03e93e
+                                r = seccomp_load_syscall_filter_set(SCMP_ACT_ALLOW, syscall_filter_sets + i, SCMP_ACT_ERRNO(EUCLEAN));
Zbigniew Jędrzejewski-Szmek 03e93e
                         if (r < 0)
Zbigniew Jędrzejewski-Szmek 03e93e
                                 _exit(EXIT_FAILURE);
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
                         /* Test the sycall filter with one random system call */
Zbigniew Jędrzejewski-Szmek 03e93e
                         fd = eventfd(0, EFD_NONBLOCK|EFD_CLOEXEC);
Zbigniew Jędrzejewski-Szmek 03e93e
                         if (IN_SET(i, SYSCALL_FILTER_SET_IO_EVENT, SYSCALL_FILTER_SET_DEFAULT))
Zbigniew Jędrzejewski-Szmek 03e93e
-                                assert_se(fd < 0 && errno == EPERM);
Zbigniew Jędrzejewski-Szmek 03e93e
+                                assert_se(fd < 0 && errno == EUCLEAN);
Zbigniew Jędrzejewski-Szmek 03e93e
                         else {
Zbigniew Jędrzejewski-Szmek 03e93e
                                 assert_se(fd >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
                                 safe_close(fd);
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -132,8 +135,8 @@ static void test_filter_sets(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
 static void test_restrict_namespace(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
         _cleanup_free_ char *s = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
-        pid_t pid;
Zbigniew Jędrzejewski-Szmek 03e93e
         unsigned long ul;
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid_t pid;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         assert_se(namespace_flag_to_string(0) == NULL);
Zbigniew Jędrzejewski-Szmek 03e93e
         assert_se(streq(namespace_flag_to_string(CLONE_NEWNS), "mnt"));
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -157,7 +160,6 @@ static void test_restrict_namespace(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         if (!is_seccomp_available())
Zbigniew Jędrzejewski-Szmek 03e93e
                 return;
Zbigniew Jędrzejewski-Szmek 03e93e
-
Zbigniew Jędrzejewski-Szmek 03e93e
         if (geteuid() != 0)
Zbigniew Jędrzejewski-Szmek 03e93e
                 return;
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -216,6 +218,256 @@ static void test_restrict_namespace(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
         assert_se(wait_for_terminate_and_warn("nsseccomp", pid, true) == EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
+static void test_protect_sysctl(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid_t pid;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!is_seccomp_available())
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (geteuid() != 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (detect_container() > 0) /* in containers _sysctl() is likely missing anyway */
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid = fork();
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(pid >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (pid == 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(syscall(__NR__sysctl, NULL) < 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EFAULT);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(seccomp_protect_sysctl() >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(syscall(__NR__sysctl, 0, 0, 0) < 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EPERM);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                _exit(EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(wait_for_terminate_and_warn("sysctlseccomp", pid, true) == EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+static void test_restrict_address_families(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid_t pid;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!is_seccomp_available())
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (geteuid() != 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid = fork();
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(pid >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (pid == 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                int fd;
Zbigniew Jędrzejewski-Szmek 03e93e
+                Set *s;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                fd = socket(AF_INET, SOCK_DGRAM, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(fd >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                safe_close(fd);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                fd = socket(AF_UNIX, SOCK_DGRAM, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(fd >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                safe_close(fd);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(fd >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                safe_close(fd);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(s = set_new(NULL));
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(set_put(s, INT_TO_PTR(AF_UNIX)) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(seccomp_restrict_address_families(s, false) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                fd = socket(AF_INET, SOCK_DGRAM, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(fd >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                safe_close(fd);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(socket(AF_UNIX, SOCK_DGRAM, 0) < 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EAFNOSUPPORT);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                fd = socket(AF_NETLINK, SOCK_DGRAM, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(fd >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                safe_close(fd);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                set_clear(s);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(set_put(s, INT_TO_PTR(AF_INET)) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(seccomp_restrict_address_families(s, true) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                fd = socket(AF_INET, SOCK_DGRAM, 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(fd >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                safe_close(fd);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(socket(AF_UNIX, SOCK_DGRAM, 0) < 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EAFNOSUPPORT);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(socket(AF_NETLINK, SOCK_DGRAM, 0) < 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EAFNOSUPPORT);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                _exit(EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(wait_for_terminate_and_warn("socketseccomp", pid, true) == EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+static void test_restrict_realtime(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid_t pid;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!is_seccomp_available())
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (geteuid() != 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (detect_container() > 0) /* in containers RT privs are likely missing anyway */
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid = fork();
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(pid >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (pid == 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(seccomp_restrict_realtime() >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(sched_setscheduler(0, SCHED_IDLE, &(struct sched_param) { .sched_priority = 0 }) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(sched_setscheduler(0, SCHED_BATCH, &(struct sched_param) { .sched_priority = 0 }) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(sched_setscheduler(0, SCHED_OTHER, &(struct sched_param) {}) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(sched_setscheduler(0, SCHED_FIFO, &(struct sched_param) { .sched_priority = 1 }) < 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EPERM);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(sched_setscheduler(0, SCHED_RR, &(struct sched_param) { .sched_priority = 1 }) < 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EPERM);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                _exit(EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(wait_for_terminate_and_warn("realtimeseccomp", pid, true) == EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+static void test_memory_deny_write_execute(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid_t pid;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!is_seccomp_available())
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (geteuid() != 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid = fork();
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(pid >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (pid == 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                void *p;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(p != MAP_FAILED);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(munmap(p, page_size()) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                seccomp_memory_deny_write_execute();
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                p = mmap(NULL, page_size(), PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(p == MAP_FAILED);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EPERM);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                p = mmap(NULL, page_size(), PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1,0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(p != MAP_FAILED);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(munmap(p, page_size()) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                _exit(EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(wait_for_terminate_and_warn("memoryseccomp", pid, true) == EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+static void test_restrict_archs(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid_t pid;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!is_seccomp_available())
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (geteuid() != 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid = fork();
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(pid >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (pid == 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                _cleanup_set_free_ Set *s = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(access("/", F_OK) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(s = set_new(NULL));
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+#ifdef __x86_64__
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(set_put(s, UINT32_TO_PTR(SCMP_ARCH_X86+1)) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+#endif
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(seccomp_restrict_archs(s) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(access("/", F_OK) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(seccomp_restrict_archs(NULL) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(access("/", F_OK) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                _exit(EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(wait_for_terminate_and_warn("archseccomp", pid, true) == EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+static void test_load_syscall_filter_set_raw(void) {
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid_t pid;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (!is_seccomp_available())
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (geteuid() != 0)
Zbigniew Jędrzejewski-Szmek 03e93e
+                return;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        pid = fork();
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(pid >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        if (pid == 0) {
Zbigniew Jędrzejewski-Szmek 03e93e
+                _cleanup_set_free_ Set *s = NULL;
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(access("/", F_OK) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(poll(NULL, 0, 0) == 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, NULL, SCMP_ACT_KILL) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(access("/", F_OK) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(poll(NULL, 0, 0) == 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(s = set_new(NULL));
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(set_put(s, UINT32_TO_PTR(__NR_access + 1)) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUCLEAN)) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(access("/", F_OK) < 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EUCLEAN);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(poll(NULL, 0, 0) == 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                s = set_free(s);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(s = set_new(NULL));
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(set_put(s, UINT32_TO_PTR(__NR_poll + 1)) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EUNATCH)) >= 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(access("/", F_OK) < 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EUCLEAN);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(poll(NULL, 0, 0) < 0);
Zbigniew Jędrzejewski-Szmek 03e93e
+                assert_se(errno == EUNATCH);
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+                _exit(EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+        }
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
+        assert_se(wait_for_terminate_and_warn("syscallrawseccomp", pid, true) == EXIT_SUCCESS);
Zbigniew Jędrzejewski-Szmek 03e93e
+}
Zbigniew Jędrzejewski-Szmek 03e93e
+
Zbigniew Jędrzejewski-Szmek 03e93e
 int main(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         log_set_max_level(LOG_DEBUG);
Zbigniew Jędrzejewski-Szmek 03e93e
@@ -225,6 +477,12 @@ int main(int argc, char *argv[]) {
Zbigniew Jędrzejewski-Szmek 03e93e
         test_syscall_filter_set_find();
Zbigniew Jędrzejewski-Szmek 03e93e
         test_filter_sets();
Zbigniew Jędrzejewski-Szmek 03e93e
         test_restrict_namespace();
Zbigniew Jędrzejewski-Szmek 03e93e
+        test_protect_sysctl();
Zbigniew Jędrzejewski-Szmek 03e93e
+        test_restrict_address_families();
Zbigniew Jędrzejewski-Szmek 03e93e
+        test_restrict_realtime();
Zbigniew Jędrzejewski-Szmek 03e93e
+        test_memory_deny_write_execute();
Zbigniew Jędrzejewski-Szmek 03e93e
+        test_restrict_archs();
Zbigniew Jędrzejewski-Szmek 03e93e
+        test_load_syscall_filter_set_raw();
Zbigniew Jędrzejewski-Szmek 03e93e
 
Zbigniew Jędrzejewski-Szmek 03e93e
         return 0;
Zbigniew Jędrzejewski-Szmek 03e93e
 }
Zbigniew Jędrzejewski-Szmek 03e93e
-- 
Zbigniew Jędrzejewski-Szmek 03e93e
2.9.3
Zbigniew Jędrzejewski-Szmek 03e93e