From 4f4502ed23aef5a6c049b4b19aa04084b4532e4e Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Tue, 25 Aug 2026 14:36:48 +0200 Subject: [PATCH] core: block PTRACE_POKE{TEXT,DATA} when RestrictFileSystemAccess= is enabled PTRACE_POKETEXT and PTRACE_POKEDATA use FOLL_FORCE to forcibly write into a tracee's memory. That includes executable read-only pages. If we restrict execution to trusted binaries PID 1 must enforce that it's impossible to abuse this to get untrusted code execution. Note, that usermodehelpers are not subject to PID 1's seccomp filters. Install a ptrace seccomp filter from PID 1 if RestrictFileSystemAccess= is requested. Every process it spawns will inherit it. Signed-off-by: Christian Brauner (Amutable) --- src/core/bpf-restrict-fsaccess.c | 39 +++++++++++++++++++++++++++++++- src/core/manager-serialize.c | 13 ++++++++++- src/core/manager.h | 3 +++ 3 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/core/bpf-restrict-fsaccess.c b/src/core/bpf-restrict-fsaccess.c index 7184bac658..a2a9154d90 100644 --- a/src/core/bpf-restrict-fsaccess.c +++ b/src/core/bpf-restrict-fsaccess.c @@ -13,6 +13,7 @@ #include "lsm-util.h" #include "manager.h" #include "memory-util.h" +#include "seccomp-util.h" #include "serialize.h" #include "string-table.h" @@ -123,6 +124,26 @@ int bpf_restrict_fsaccess_check_prerequisites(void) { return 0; } +/* The seccomp filter survives execve() so ensure that we're not installing another filter. */ +static int restrict_fsaccess_install_ptrace_filter(Manager *m) { + int r; + + assert(m); + + if (m->restrict_fsaccess_ptrace_filter) + return 0; + + r = seccomp_restrict_ptrace(); + if (r == -EOPNOTSUPP) + return log_error_errno(r, "bpf-restrict-fsaccess: seccomp support is not available, cannot block " + "ptrace() code injection."); + if (r < 0) + return log_error_errno(r, "bpf-restrict-fsaccess: Failed to install the ptrace() seccomp filter: %m"); + + m->restrict_fsaccess_ptrace_filter = true; + return 0; +} + static int get_root_s_dev(uint32_t *ret) { struct stat st; @@ -442,6 +463,10 @@ int bpf_restrict_fsaccess_setup(Manager *m) { return r; } + /* v261 serialized the link FDs without installing the filter. Enforcement is active already, + * so only complain. */ + (void) restrict_fsaccess_install_ptrace_filter(m); + return 0; } @@ -449,6 +474,10 @@ int bpf_restrict_fsaccess_setup(Manager *m) { if (r < 0) return r; + r = restrict_fsaccess_install_ptrace_filter(m); + if (r < 0) + return r; + r = bpf_restrict_fsaccess_prepare(&obj); if (r < 0) return r; @@ -548,7 +577,15 @@ int bpf_restrict_fsaccess_serialize(Manager *m, FILE *f, FDSet *fds) { assert(f); assert(fds); - if (!MANAGER_IS_SYSTEM(m) || m->restrict_filesystem_access <= RESTRICT_FILESYSTEM_ACCESS_NO) + if (!MANAGER_IS_SYSTEM(m)) + return 0; + + /* Process state, not policy state: the filter outlives the setting being turned off. */ + r = serialize_bool_elide(f, "restrict-fsaccess-ptrace-filter", m->restrict_fsaccess_ptrace_filter); + if (r < 0) + return r; + + if (m->restrict_filesystem_access <= RESTRICT_FILESYSTEM_ACCESS_NO) return 0; FOREACH_ELEMENT(fd, m->restrict_fsaccess_link_fds) { diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c index 7703d63e7a..7a3d879bc3 100644 --- a/src/core/manager-serialize.c +++ b/src/core/manager-serialize.c @@ -519,7 +519,7 @@ static void manager_deserialize_gid_refs_one(Manager *m, const char *value) { static void deserialize_restrict_fsaccess(Manager *m, const char *l, FDSet *fds) { const char *val; - int fd; + int fd, r; FOREACH_ELEMENT(name, restrict_fsaccess_link_names) { val = startswith(l, *name); @@ -537,6 +537,17 @@ static void deserialize_restrict_fsaccess(Manager *m, const char *l, FDSet *fds) return; } + val = startswith(l, "restrict-fsaccess-ptrace-filter="); + if (val) { + r = parse_boolean(val); + if (r < 0) + log_warning_errno(r, "bpf-restrict-fsaccess: Failed to parse ptrace filter state '%s', " + "ignoring: %m", val); + else + m->restrict_fsaccess_ptrace_filter = r; + return; + } + val = startswith(l, "restrict-fsaccess-bss-map="); if (!val) return; diff --git a/src/core/manager.h b/src/core/manager.h index 453ae74668..f3db614b02 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -514,6 +514,9 @@ typedef struct Manager { int restrict_fsaccess_link_fds[_RESTRICT_FILESYSTEM_ACCESS_LINK_MAX]; int restrict_fsaccess_bss_map_fd; + /* Whether the ptrace seccomp filter is installed in this process; it survives execve() */ + bool restrict_fsaccess_ptrace_filter; + /* Allow users to configure a rate limit for Reload()/Reexecute() operations */ RateLimit reload_reexec_ratelimit; /* Dump*() are slow, so always rate limit them to 10 per 10 minutes */