richardphibel / rpms / systemd

Forked from rpms/systemd 2 years ago
Clone
c2dfb7
From 5a62c0daff82e8343d24f98e1761d27bf8015782 Mon Sep 17 00:00:00 2001
c2dfb7
From: Lennart Poettering <lennart@poettering.net>
c2dfb7
Date: Wed, 20 Mar 2019 19:00:28 +0100
c2dfb7
Subject: [PATCH] seccomp: introduce seccomp_restrict_suid_sgid() for blocking
c2dfb7
 chmod() for suid/sgid files
c2dfb7
c2dfb7
(cherry picked from commit 3c27973b13724ede05a06a5d346a569794cda433)
c2dfb7
Related: #1687512
c2dfb7
---
c2dfb7
 src/shared/seccomp-util.c | 132 ++++++++++++++++++++++++++++++++++++++
c2dfb7
 src/shared/seccomp-util.h |   1 +
c2dfb7
 2 files changed, 133 insertions(+)
c2dfb7
c2dfb7
diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c
c2dfb7
index 92910acf0e..fd46b9f88d 100644
c2dfb7
--- a/src/shared/seccomp-util.c
c2dfb7
+++ b/src/shared/seccomp-util.c
c2dfb7
@@ -1,12 +1,14 @@
c2dfb7
 /* SPDX-License-Identifier: LGPL-2.1+ */
c2dfb7
 
c2dfb7
 #include <errno.h>
c2dfb7
+#include <fcntl.h>
c2dfb7
 #include <linux/seccomp.h>
c2dfb7
 #include <seccomp.h>
c2dfb7
 #include <stddef.h>
c2dfb7
 #include <sys/mman.h>
c2dfb7
 #include <sys/prctl.h>
c2dfb7
 #include <sys/shm.h>
c2dfb7
+#include <sys/stat.h>
c2dfb7
 
c2dfb7
 #include "af-list.h"
c2dfb7
 #include "alloc-util.h"
c2dfb7
@@ -1747,3 +1749,133 @@ int seccomp_lock_personality(unsigned long personality) {
c2dfb7
 
c2dfb7
         return 0;
c2dfb7
 }
c2dfb7
+
c2dfb7
+int seccomp_restrict_suid_sgid(void) {
c2dfb7
+        uint32_t arch;
c2dfb7
+        int r;
c2dfb7
+
c2dfb7
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
c2dfb7
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
c2dfb7
+
c2dfb7
+                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
c2dfb7
+                if (r < 0)
c2dfb7
+                        return r;
c2dfb7
+
c2dfb7
+                /* Checks the mode_t parameter of the following system calls:
c2dfb7
+                 *
c2dfb7
+                 *       → chmod() + fchmod() + fchmodat()
c2dfb7
+                 *       → open() + creat() + openat()
c2dfb7
+                 *       → mkdir() + mkdirat()
c2dfb7
+                 *       → mknod() + mknodat()
c2dfb7
+                 */
c2dfb7
+
c2dfb7
+                for (unsigned bit = 0; bit < 2; bit ++) {
c2dfb7
+                        /* Block S_ISUID in the first iteration, S_ISGID in the second */
c2dfb7
+                        mode_t m = bit == 0 ? S_ISUID : S_ISGID;
c2dfb7
+
c2dfb7
+                        r = seccomp_rule_add_exact(
c2dfb7
+                                        seccomp,
c2dfb7
+                                        SCMP_ACT_ERRNO(EPERM),
c2dfb7
+                                        SCMP_SYS(chmod),
c2dfb7
+                                        1,
c2dfb7
+                                        SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
c2dfb7
+                        if (r < 0)
c2dfb7
+                                break;
c2dfb7
+
c2dfb7
+                        r = seccomp_rule_add_exact(
c2dfb7
+                                        seccomp,
c2dfb7
+                                        SCMP_ACT_ERRNO(EPERM),
c2dfb7
+                                        SCMP_SYS(fchmod),
c2dfb7
+                                        1,
c2dfb7
+                                        SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
c2dfb7
+                        if (r < 0)
c2dfb7
+                                break;
c2dfb7
+
c2dfb7
+                        r = seccomp_rule_add_exact(
c2dfb7
+                                        seccomp,
c2dfb7
+                                        SCMP_ACT_ERRNO(EPERM),
c2dfb7
+                                        SCMP_SYS(fchmodat),
c2dfb7
+                                        1,
c2dfb7
+                                        SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
c2dfb7
+                        if (r < 0)
c2dfb7
+                                break;
c2dfb7
+
c2dfb7
+                        r = seccomp_rule_add_exact(
c2dfb7
+                                        seccomp,
c2dfb7
+                                        SCMP_ACT_ERRNO(EPERM),
c2dfb7
+                                        SCMP_SYS(mkdir),
c2dfb7
+                                        1,
c2dfb7
+                                        SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
c2dfb7
+                        if (r < 0)
c2dfb7
+                                break;
c2dfb7
+
c2dfb7
+                        r = seccomp_rule_add_exact(
c2dfb7
+                                        seccomp,
c2dfb7
+                                        SCMP_ACT_ERRNO(EPERM),
c2dfb7
+                                        SCMP_SYS(mkdirat),
c2dfb7
+                                        1,
c2dfb7
+                                        SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
c2dfb7
+                        if (r < 0)
c2dfb7
+                                break;
c2dfb7
+
c2dfb7
+                        r = seccomp_rule_add_exact(
c2dfb7
+                                        seccomp,
c2dfb7
+                                        SCMP_ACT_ERRNO(EPERM),
c2dfb7
+                                        SCMP_SYS(mknod),
c2dfb7
+                                        1,
c2dfb7
+                                        SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
c2dfb7
+                        if (r < 0)
c2dfb7
+                                break;
c2dfb7
+
c2dfb7
+                        r = seccomp_rule_add_exact(
c2dfb7
+                                        seccomp,
c2dfb7
+                                        SCMP_ACT_ERRNO(EPERM),
c2dfb7
+                                        SCMP_SYS(mknodat),
c2dfb7
+                                        1,
c2dfb7
+                                        SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
c2dfb7
+                        if (r < 0)
c2dfb7
+                                break;
c2dfb7
+
c2dfb7
+                        r = seccomp_rule_add_exact(
c2dfb7
+                                        seccomp,
c2dfb7
+                                        SCMP_ACT_ERRNO(EPERM),
c2dfb7
+                                        SCMP_SYS(open),
c2dfb7
+                                        2,
c2dfb7
+                                        SCMP_A1(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
c2dfb7
+                                        SCMP_A2(SCMP_CMP_MASKED_EQ, m, m));
c2dfb7
+                        if (r < 0)
c2dfb7
+                                break;
c2dfb7
+
c2dfb7
+                        r = seccomp_rule_add_exact(
c2dfb7
+                                        seccomp,
c2dfb7
+                                        SCMP_ACT_ERRNO(EPERM),
c2dfb7
+                                        SCMP_SYS(openat),
c2dfb7
+                                        2,
c2dfb7
+                                        SCMP_A2(SCMP_CMP_MASKED_EQ, O_CREAT, O_CREAT),
c2dfb7
+                                        SCMP_A3(SCMP_CMP_MASKED_EQ, m, m));
c2dfb7
+                        if (r < 0)
c2dfb7
+                                break;
c2dfb7
+
c2dfb7
+                        r = seccomp_rule_add_exact(
c2dfb7
+                                        seccomp,
c2dfb7
+                                        SCMP_ACT_ERRNO(EPERM),
c2dfb7
+                                        SCMP_SYS(creat),
c2dfb7
+                                        1,
c2dfb7
+                                        SCMP_A1(SCMP_CMP_MASKED_EQ, m, m));
c2dfb7
+                        if (r < 0)
c2dfb7
+                                break;
c2dfb7
+                }
c2dfb7
+                if (r < 0) {
c2dfb7
+                        log_debug_errno(r, "Failed to add suid/sgid rule for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
c2dfb7
+                        continue;
c2dfb7
+                }
c2dfb7
+
c2dfb7
+                r = seccomp_load(seccomp);
c2dfb7
+                if (IN_SET(r, -EPERM, -EACCES))
c2dfb7
+                        return r;
c2dfb7
+                if (r < 0)
c2dfb7
+                        log_debug_errno(r, "Failed to apply suid/sgid restrictions for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
c2dfb7
+        }
c2dfb7
+
c2dfb7
+        return 0;
c2dfb7
+}
c2dfb7
diff --git a/src/shared/seccomp-util.h b/src/shared/seccomp-util.h
c2dfb7
index d8a36c4e21..602f092255 100644
c2dfb7
--- a/src/shared/seccomp-util.h
c2dfb7
+++ b/src/shared/seccomp-util.h
c2dfb7
@@ -85,6 +85,7 @@ int seccomp_restrict_address_families(Set *address_families, bool whitelist);
c2dfb7
 int seccomp_restrict_realtime(void);
c2dfb7
 int seccomp_memory_deny_write_execute(void);
c2dfb7
 int seccomp_lock_personality(unsigned long personality);
c2dfb7
+int seccomp_restrict_suid_sgid(void);
c2dfb7
 
c2dfb7
 extern const uint32_t seccomp_local_archs[];
c2dfb7