diff --git a/src/core/bpf-restrict-fsaccess.c b/src/core/bpf-restrict-fsaccess.c index ab746bda05..7184bac658 100644 --- a/src/core/bpf-restrict-fsaccess.c +++ b/src/core/bpf-restrict-fsaccess.c @@ -81,7 +81,7 @@ assert_cc(sizeof_field(typeof_field(struct restrict_fsaccess_bpf, bss[0]), initr [RESTRICT_FILESYSTEM_ACCESS_LINK_BPF_GUARD] = (obj)->links.restrict_fsaccess_bpf_guard, \ } -bool dm_verity_require_signatures(void) { +static bool dm_verity_require_signatures(void) { int r; r = read_boolean_file("/sys/module/dm_verity/parameters/require_signatures"); @@ -94,6 +94,35 @@ bool dm_verity_require_signatures(void) { return r > 0; } +/* The kernel-side prerequisites of the policy, shared with test-bpf-restrict-fsaccess. */ +int bpf_restrict_fsaccess_check_prerequisites(void) { + int r; + + r = dlopen_bpf(LOG_ERR); + if (r < 0) + return r; + + r = lsm_supported("bpf"); + if (r == -ENOPKG) + return log_error_errno(r, "bpf-restrict-fsaccess: securityfs not mounted, BPF LSM not available."); + if (r < 0) + return log_error_errno(r, "bpf-restrict-fsaccess: Can't determine whether the BPF LSM module is " + "used: %m"); + if (r == 0) + return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), + "bpf-restrict-fsaccess: BPF LSM hook not enabled in the kernel, not supported."); + log_debug("bpf-restrict-fsaccess: BPF LSM: supported."); + + if (!dm_verity_require_signatures()) + return log_error_errno(SYNTHETIC_ERRNO(ENOKEY), + "bpf-restrict-fsaccess: dm-verity require_signatures is not enabled. " + "RestrictFileSystemAccess= requires the kernel to enforce dm-verity signatures. " + "Set dm_verity.require_signatures=1 on the kernel command line."); + log_debug("bpf-restrict-fsaccess: dm-verity require_signatures: enabled."); + + return 0; +} + static int get_root_s_dev(uint32_t *ret) { struct stat st; @@ -416,27 +445,10 @@ int bpf_restrict_fsaccess_setup(Manager *m) { return 0; } - /* Fresh setup: verify BPF LSM is available */ - r = dlopen_bpf(LOG_WARNING); + r = bpf_restrict_fsaccess_check_prerequisites(); if (r < 0) return r; - r = lsm_supported("bpf"); - if (r == -ENOPKG) - return log_warning_errno(r, "bpf-restrict-fsaccess: securityfs not mounted, BPF LSM not available."); - if (r < 0) - return log_warning_errno(r, "bpf-restrict-fsaccess: Can't determine whether the BPF LSM module is used: %m"); - if (r == 0) - return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "bpf-restrict-fsaccess: BPF LSM hook not enabled in the kernel, not supported."); - - /* Require dm-verity signature enforcement */ - if (!dm_verity_require_signatures()) - return log_error_errno(SYNTHETIC_ERRNO(ENOKEY), - "bpf-restrict-fsaccess: dm-verity require_signatures is not enabled. " - "RestrictFileSystemAccess= requires the kernel to enforce dm-verity signatures. " - "Set dm_verity.require_signatures=1 on the kernel command line."); - r = bpf_restrict_fsaccess_prepare(&obj); if (r < 0) return r; @@ -554,8 +566,8 @@ int bpf_restrict_fsaccess_serialize(Manager *m, FILE *f, FDSet *fds) { #else /* ! BPF_FRAMEWORK || ! HAVE_LSM_INTEGRITY_TYPE */ -bool dm_verity_require_signatures(void) { - return false; +int bpf_restrict_fsaccess_check_prerequisites(void) { + return -EOPNOTSUPP; } int bpf_restrict_fsaccess_setup(Manager *m) { diff --git a/src/core/bpf-restrict-fsaccess.h b/src/core/bpf-restrict-fsaccess.h index 0a8cb45c8f..0549e18165 100644 --- a/src/core/bpf-restrict-fsaccess.h +++ b/src/core/bpf-restrict-fsaccess.h @@ -33,7 +33,7 @@ enum { extern const char* const restrict_fsaccess_link_names[_RESTRICT_FILESYSTEM_ACCESS_LINK_MAX]; -bool dm_verity_require_signatures(void); +int bpf_restrict_fsaccess_check_prerequisites(void); int bpf_restrict_fsaccess_setup(Manager *m); int bpf_restrict_fsaccess_prepare(struct restrict_fsaccess_bpf **ret); int bpf_restrict_fsaccess_populate_guard(struct restrict_fsaccess_bpf *obj); diff --git a/src/test/test-bpf-restrict-fsaccess.c b/src/test/test-bpf-restrict-fsaccess.c index 0e2358c2ea..7e99a37cc6 100644 --- a/src/test/test-bpf-restrict-fsaccess.c +++ b/src/test/test-bpf-restrict-fsaccess.c @@ -7,7 +7,8 @@ * test-bpf-restrict-fsaccess attach — Load, attach, print IDs, then block. * Kill the process to detach (synchronous * via bpf_link_put_direct on last FD close). - * test-bpf-restrict-fsaccess check — Check BPF LSM + require_signatures preconditions + * test-bpf-restrict-fsaccess check — Run PID 1's prerequisite checks (BPF LSM, + * require_signatures) * test-bpf-restrict-fsaccess mmap-exec PATH — Attempt PROT_READ|PROT_EXEC mmap of PATH * test-bpf-restrict-fsaccess anon-mmap-exec — Attempt anonymous PROT_READ|PROT_EXEC mmap * test-bpf-restrict-fsaccess mprotect-exec PATH — mmap PATH PROT_READ, then mprotect to PROT_EXEC @@ -34,7 +35,6 @@ #include "errno-util.h" #include "fd-util.h" #include "log.h" -#include "lsm-util.h" #include "string-util.h" #include "tests.h" @@ -241,15 +241,12 @@ static int do_attach(void) { static int do_check(void) { int r; - r = dlopen_bpf(LOG_WARNING); + r = bpf_restrict_fsaccess_check_prerequisites(); if (r < 0) return r; - r = lsm_supported("bpf"); - if (r <= 0) - return log_error_errno(r < 0 ? r : EOPNOTSUPP, "BPF LSM is not available: %m"); - log_info("BPF LSM: supported"); - + /* Last: linking attaches bprm_check for an instant with an empty trust map, during which every + * execve() on the system is denied. Keep that window out of the cheap failure paths above. */ _cleanup_(restrict_fsaccess_bpf_freep) struct restrict_fsaccess_bpf *obj = NULL; r = bpf_restrict_fsaccess_prepare(&obj); if (r < 0) @@ -259,10 +256,6 @@ static int do_check(void) { return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "bpf-restrict-fsaccess: Failed to link program."); - if (!dm_verity_require_signatures()) - return log_error_errno(SYNTHETIC_ERRNO(ENOKEY), "dm-verity require_signatures is not enabled."); - log_info("dm-verity require_signatures: enabled"); - return 0; } diff --git a/test/units/TEST-90-RESTRICT-FSACCESS.config.sh b/test/units/TEST-90-RESTRICT-FSACCESS.config.sh index 40f3782f18..d83e310060 100755 --- a/test/units/TEST-90-RESTRICT-FSACCESS.config.sh +++ b/test/units/TEST-90-RESTRICT-FSACCESS.config.sh @@ -90,9 +90,8 @@ testcase_no_require_signatures_helper() { fi fi - # The helper's "check" command runs the same bpf_restrict_fsaccess_supported() - # and dm_verity_require_signatures() checks that PID1 uses. It must fail - # because require_signatures is not enabled. + # The helper's "check" command runs the same bpf_restrict_fsaccess_check_prerequisites() + # checks that PID1 uses. It must fail because require_signatures is not enabled. if "$HELPER" check; then echo "ERROR: helper check succeeded but require_signatures is not enabled" return 1