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