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) <brauner@kernel.org>
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user