commit: 296415fa509175fd0253091697d1eec1fcf462df Author: Mike Gilbert <floppym <AT> gentoo <DOT> org> AuthorDate: Sat Feb 24 15:48:45 2024 +0000 Commit: Mike Gilbert <floppym <AT> gentoo <DOT> org> CommitDate: Sat Feb 24 15:48:45 2024 +0000 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=296415fa
sys-apps/systemd: backport fchmodat2 support to 254.9 Signed-off-by: Mike Gilbert <floppym <AT> gentoo.org> .../systemd/files/systemd-254.9-fchmodat2.patch | 255 +++++++++++++++++++++ ...ystemd-254.9.ebuild => systemd-254.9-r1.ebuild} | 1 + 2 files changed, 256 insertions(+) diff --git a/sys-apps/systemd/files/systemd-254.9-fchmodat2.patch b/sys-apps/systemd/files/systemd-254.9-fchmodat2.patch new file mode 100644 index 000000000000..27bdd121aa60 --- /dev/null +++ b/sys-apps/systemd/files/systemd-254.9-fchmodat2.patch @@ -0,0 +1,255 @@ +From 3d93b69fa558b33f1f2b52305fa4c2d836789394 Mon Sep 17 00:00:00 2001 +From: Arseny Maslennikov <ars...@altlinux.org> +Date: Sun, 15 Oct 2023 11:00:00 +0300 +Subject: [PATCH 1/3] basic/missing_syscall: generate defs for `fchmodat2(2)` + +We will need this to set seccomp filters on this system call regardless +of libseccomp or kernel support. + +(cherry picked from commit 3677364cc3a2c5429380cfd3a2472e2da87925c4) +--- + src/basic/missing_syscall_def.h | 68 +++++++++++++++++++++++++++++++++ + src/basic/missing_syscalls.py | 1 + + 2 files changed, 69 insertions(+) + +diff --git a/src/basic/missing_syscall_def.h b/src/basic/missing_syscall_def.h +index 402fdd00dc..b5beb434db 100644 +--- a/src/basic/missing_syscall_def.h ++++ b/src/basic/missing_syscall_def.h +@@ -246,6 +246,74 @@ assert_cc(__NR_copy_file_range == systemd_NR_copy_file_range); + # endif + #endif + ++#ifndef __IGNORE_fchmodat2 ++# if defined(__aarch64__) ++# define systemd_NR_fchmodat2 452 ++# elif defined(__alpha__) ++# define systemd_NR_fchmodat2 562 ++# elif defined(__arc__) || defined(__tilegx__) ++# define systemd_NR_fchmodat2 452 ++# elif defined(__arm__) ++# define systemd_NR_fchmodat2 452 ++# elif defined(__i386__) ++# define systemd_NR_fchmodat2 452 ++# elif defined(__ia64__) ++# define systemd_NR_fchmodat2 1476 ++# elif defined(__loongarch_lp64) ++# define systemd_NR_fchmodat2 452 ++# elif defined(__m68k__) ++# define systemd_NR_fchmodat2 452 ++# elif defined(_MIPS_SIM) ++# if _MIPS_SIM == _MIPS_SIM_ABI32 ++# define systemd_NR_fchmodat2 4452 ++# elif _MIPS_SIM == _MIPS_SIM_NABI32 ++# define systemd_NR_fchmodat2 6452 ++# elif _MIPS_SIM == _MIPS_SIM_ABI64 ++# define systemd_NR_fchmodat2 5452 ++# else ++# error "Unknown MIPS ABI" ++# endif ++# elif defined(__hppa__) ++# define systemd_NR_fchmodat2 452 ++# elif defined(__powerpc__) ++# define systemd_NR_fchmodat2 452 ++# elif defined(__riscv) ++# if __riscv_xlen == 32 ++# define systemd_NR_fchmodat2 452 ++# elif __riscv_xlen == 64 ++# define systemd_NR_fchmodat2 452 ++# else ++# error "Unknown RISC-V ABI" ++# endif ++# elif defined(__s390__) ++# define systemd_NR_fchmodat2 452 ++# elif defined(__sparc__) ++# define systemd_NR_fchmodat2 452 ++# elif defined(__x86_64__) ++# if defined(__ILP32__) ++# define systemd_NR_fchmodat2 (452 | /* __X32_SYSCALL_BIT */ 0x40000000) ++# else ++# define systemd_NR_fchmodat2 452 ++# endif ++# elif !defined(missing_arch_template) ++# warning "fchmodat2() syscall number is unknown for your architecture" ++# endif ++ ++/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ ++# if defined __NR_fchmodat2 && __NR_fchmodat2 >= 0 ++# if defined systemd_NR_fchmodat2 ++assert_cc(__NR_fchmodat2 == systemd_NR_fchmodat2); ++# endif ++# else ++# if defined __NR_fchmodat2 ++# undef __NR_fchmodat2 ++# endif ++# if defined systemd_NR_fchmodat2 && systemd_NR_fchmodat2 >= 0 ++# define __NR_fchmodat2 systemd_NR_fchmodat2 ++# endif ++# endif ++#endif ++ + #ifndef __IGNORE_getrandom + # if defined(__aarch64__) + # define systemd_NR_getrandom 278 +diff --git a/src/basic/missing_syscalls.py b/src/basic/missing_syscalls.py +index 5ccf02adec..00f72dc7a8 100644 +--- a/src/basic/missing_syscalls.py ++++ b/src/basic/missing_syscalls.py +@@ -9,6 +9,7 @@ SYSCALLS = [ + 'bpf', + 'close_range', + 'copy_file_range', ++ 'fchmodat2', + 'getrandom', + 'memfd_create', + 'mount_setattr', +-- +2.43.0 + + +From c1ffd32c642dcadb844b149fcc0c6fe0dbe8a292 Mon Sep 17 00:00:00 2001 +From: Arseny Maslennikov <ars...@altlinux.org> +Date: Sun, 15 Oct 2023 11:00:00 +0300 +Subject: [PATCH 2/3] seccomp: include `fchmodat2` in `@file-system` + +(cherry picked from commit 6e10405aa25fe5e76b740d9ec59730e3f4470c7a) +--- + src/shared/seccomp-util.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c +index bd9660cb35..a9c6279b18 100644 +--- a/src/shared/seccomp-util.c ++++ b/src/shared/seccomp-util.c +@@ -468,6 +468,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = { + "fchdir\0" + "fchmod\0" + "fchmodat\0" ++ "fchmodat2\0" + "fcntl\0" + "fcntl64\0" + "fgetxattr\0" +-- +2.43.0 + + +From da6ec29e7f755e14655132b4e0b04f463f40af3e Mon Sep 17 00:00:00 2001 +From: Arseny Maslennikov <ars...@altlinux.org> +Date: Sun, 15 Oct 2023 11:00:00 +0300 +Subject: [PATCH 3/3] seccomp: also check the mode parameter of `fchmodat2(2)` + +If there is no libseccomp support, just ban the entire syscall instead +so wrappers will fall back to older, supported syscalls. +Also reflect all of this in `test-seccomp.c`. + +(cherry picked from commit 8b45281daa3a87b4b7a3248263cd0ba929d15596) +--- + src/shared/seccomp-util.c | 24 +++++++++++++++++++++++- + src/test/test-seccomp.c | 28 ++++++++++++++++++++++++++++ + 2 files changed, 51 insertions(+), 1 deletion(-) + +diff --git a/src/shared/seccomp-util.c b/src/shared/seccomp-util.c +index a9c6279b18..12fd95d95b 100644 +--- a/src/shared/seccomp-util.c ++++ b/src/shared/seccomp-util.c +@@ -2038,7 +2038,7 @@ int seccomp_protect_hostname(void) { + static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) { + /* Checks the mode_t parameter of the following system calls: + * +- * → chmod() + fchmod() + fchmodat() ++ * → chmod() + fchmod() + fchmodat() + fchmodat2() + * → open() + creat() + openat() + * → mkdir() + mkdirat() + * → mknod() + mknodat() +@@ -2081,6 +2081,28 @@ static int seccomp_restrict_sxid(scmp_filter_ctx seccomp, mode_t m) { + else + any = true; + ++#if defined(__SNR_fchmodat2) ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(EPERM), ++ SCMP_SYS(fchmodat2), ++ 1, ++ SCMP_A2(SCMP_CMP_MASKED_EQ, m, m)); ++#else ++ /* It looks like this libseccomp does not know about fchmodat2(). ++ * Pretend the fchmodat2() system call is not supported at all, ++ * regardless of the kernel version. */ ++ r = seccomp_rule_add_exact( ++ seccomp, ++ SCMP_ACT_ERRNO(ENOSYS), ++ __NR_fchmodat2, ++ 0); ++#endif ++ if (r < 0) ++ log_debug_errno(r, "Failed to add filter for fchmodat2: %m"); ++ else ++ any = true; ++ + r = seccomp_rule_add_exact( + seccomp, + SCMP_ACT_ERRNO(EPERM), +diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c +index 2d06098ddd..3a73262a8b 100644 +--- a/src/test/test-seccomp.c ++++ b/src/test/test-seccomp.c +@@ -21,6 +21,7 @@ + #include "macro.h" + #include "memory-util.h" + #include "missing_sched.h" ++#include "missing_syscall_def.h" + #include "nsflags.h" + #include "nulstr-util.h" + #include "process-util.h" +@@ -1003,6 +1004,23 @@ static int real_open(const char *path, int flags, mode_t mode) { + #endif + } + ++static int try_fchmodat2(int dirfd, const char *path, int flags, mode_t mode) { ++ /* glibc does not provide a direct wrapper for fchmodat2(). Let's hence define our own wrapper for ++ * testing purposes that calls the real syscall, on architectures and in environments where ++ * SYS_fchmodat2 is defined. Otherwise, let's just fall back to the glibc fchmodat() call. */ ++ ++#if defined __NR_fchmodat2 && __NR_fchmodat2 >= 0 ++ int r; ++ r = (int) syscall(__NR_fchmodat2, dirfd, path, flags, mode); ++ /* The syscall might still be unsupported by kernel or libseccomp. */ ++ if (r < 0 && errno == ENOSYS) ++ return fchmodat(dirfd, path, flags, mode); ++ return r; ++#else ++ return fchmodat(dirfd, path, flags, mode); ++#endif ++} ++ + TEST(restrict_suid_sgid) { + pid_t pid; + +@@ -1044,6 +1062,11 @@ TEST(restrict_suid_sgid) { + assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0); + assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0); + ++ assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISUID, 0) >= 0); ++ assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID, 0) >= 0); ++ assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) >= 0); ++ assert_se(try_fchmodat2(AT_FDCWD, path, 0755, 0) >= 0); ++ + k = real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID); + k = safe_close(k); + assert_se(unlink(z) >= 0); +@@ -1145,6 +1168,11 @@ TEST(restrict_suid_sgid) { + assert_se(fchmodat(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM); + assert_se(fchmodat(AT_FDCWD, path, 0755, 0) >= 0); + ++ assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISUID, 0) < 0 && errno == EPERM); ++ assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID, 0) < 0 && errno == EPERM); ++ assert_se(try_fchmodat2(AT_FDCWD, path, 0755 | S_ISGID | S_ISUID, 0) < 0 && errno == EPERM); ++ assert_se(try_fchmodat2(AT_FDCWD, path, 0755, 0) >= 0); ++ + assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID) < 0 && errno == EPERM); + assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISGID) < 0 && errno == EPERM); + assert_se(real_open(z, O_CREAT|O_RDWR|O_CLOEXEC|O_EXCL, 0644 | S_ISUID | S_ISGID) < 0 && errno == EPERM); +-- +2.43.0 + diff --git a/sys-apps/systemd/systemd-254.9.ebuild b/sys-apps/systemd/systemd-254.9-r1.ebuild similarity index 99% rename from sys-apps/systemd/systemd-254.9.ebuild rename to sys-apps/systemd/systemd-254.9-r1.ebuild index c12a9240f822..b9a20c537da3 100644 --- a/sys-apps/systemd/systemd-254.9.ebuild +++ b/sys-apps/systemd/systemd-254.9-r1.ebuild @@ -242,6 +242,7 @@ src_prepare() { local PATCHES=( "${FILESDIR}/systemd-253-initrd-generators.patch" "${FILESDIR}/254-PrivateDevices-userdbd.patch" + "${FILESDIR}/systemd-254.9-fchmodat2.patch" ) if ! use vanilla; then