|
|
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 |
|