core: use LSM BPF functions to implement RestrictFileSystems=
It attaches the LSM BPF program when the system manager starts up. It populates the hash of maps BPF map when services that have RestrictFileSystems= set start. It cleans up the hash of maps when the unit cgroup is pruned. To pass the file descriptor of the BPF map we add it to the keep_fds array.
This commit is contained in:
+60
-1
@@ -41,6 +41,7 @@
|
||||
#endif
|
||||
#include "async.h"
|
||||
#include "barrier.h"
|
||||
#include "bpf-lsm.h"
|
||||
#include "cap-list.h"
|
||||
#include "capability-util.h"
|
||||
#include "cgroup-setup.h"
|
||||
@@ -1685,6 +1686,29 @@ static int apply_restrict_namespaces(const Unit *u, const ExecContext *c) {
|
||||
return seccomp_restrict_namespaces(c->restrict_namespaces);
|
||||
}
|
||||
|
||||
#if HAVE_LIBBPF
|
||||
static bool skip_lsm_bpf_unsupported(const Unit* u, const char* msg) {
|
||||
if (lsm_bpf_supported())
|
||||
return false;
|
||||
|
||||
log_unit_debug(u, "LSM BPF not supported, skipping %s", msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int apply_restrict_filesystems(Unit *u, const ExecContext *c) {
|
||||
assert(u);
|
||||
assert(c);
|
||||
|
||||
if (!exec_context_restrict_filesystems_set(c))
|
||||
return 0;
|
||||
|
||||
if (skip_lsm_bpf_unsupported(u, "RestrictFileSystems="))
|
||||
return 0;
|
||||
|
||||
return lsm_bpf_unit_restrict_filesystems(u, c->restrict_filesystems, c->restrict_filesystems_allow_list);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int apply_lock_personality(const Unit* u, const ExecContext *c) {
|
||||
unsigned long personality;
|
||||
int r;
|
||||
@@ -3813,7 +3837,7 @@ static int exec_child(
|
||||
/* In case anything used libc syslog(), close this here, too */
|
||||
closelog();
|
||||
|
||||
int keep_fds[n_fds + 2];
|
||||
int keep_fds[n_fds + 3];
|
||||
memcpy_safe(keep_fds, fds, n_fds * sizeof(int));
|
||||
n_keep_fds = n_fds;
|
||||
|
||||
@@ -3823,6 +3847,24 @@ static int exec_child(
|
||||
return log_unit_error_errno(unit, r, "Failed to shift fd and set FD_CLOEXEC: %m");
|
||||
}
|
||||
|
||||
#if HAVE_LIBBPF
|
||||
if (MANAGER_IS_SYSTEM(unit->manager) && lsm_bpf_supported()) {
|
||||
int bpf_map_fd = -1;
|
||||
|
||||
bpf_map_fd = lsm_bpf_map_restrict_fs_fd(unit);
|
||||
if (bpf_map_fd < 0) {
|
||||
*exit_status = EXIT_FDS;
|
||||
return log_unit_error_errno(unit, r, "Failed to get restrict filesystems BPF map fd: %m");
|
||||
}
|
||||
|
||||
r = add_shifted_fd(keep_fds, ELEMENTSOF(keep_fds), &n_keep_fds, bpf_map_fd, &bpf_map_fd);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_FDS;
|
||||
return log_unit_error_errno(unit, r, "Failed to shift fd and set FD_CLOEXEC: %m");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
r = close_remaining_fds(params, runtime, dcreds, user_lookup_fd, socket_fd, keep_fds, n_keep_fds);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_FDS;
|
||||
@@ -4682,6 +4724,15 @@ static int exec_child(
|
||||
return log_unit_error_errno(unit, r, "Failed to apply system call filters: %m");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBBPF
|
||||
r = apply_restrict_filesystems(unit, context);
|
||||
if (r < 0) {
|
||||
*exit_status = EXIT_BPF;
|
||||
return log_unit_error_errno(unit, r, "Failed to restrict filesystems: %m");
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (!strv_isempty(context->unset_environment)) {
|
||||
@@ -4967,6 +5018,8 @@ void exec_context_done(ExecContext *c) {
|
||||
c->apparmor_profile = mfree(c->apparmor_profile);
|
||||
c->smack_process_label = mfree(c->smack_process_label);
|
||||
|
||||
c->restrict_filesystems = set_free(c->restrict_filesystems);
|
||||
|
||||
c->syscall_filter = hashmap_free(c->syscall_filter);
|
||||
c->syscall_archs = set_free(c->syscall_archs);
|
||||
c->address_families = set_free(c->address_families);
|
||||
@@ -5734,6 +5787,12 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
||||
prefix, strna(s));
|
||||
}
|
||||
|
||||
#if HAVE_LIBBPF
|
||||
if (exec_context_restrict_filesystems_set(c))
|
||||
SET_FOREACH(e, c->restrict_filesystems)
|
||||
fprintf(f, "%sRestrictFileSystems: %s\n", prefix, *e);
|
||||
#endif
|
||||
|
||||
if (c->network_namespace_path)
|
||||
fprintf(f,
|
||||
"%sNetworkNamespacePath: %s\n",
|
||||
|
||||
Reference in New Issue
Block a user