Note, BPF_PROG_TYPE_CGROUP_DEVICE is supported since kernel v4.15.
As our baseline on the kernel is v5.4, we can assume the bpf type is
always supported.
return 0;
}
-int bpf_devices_supported(void) {
- const struct bpf_insn trivial[] = {
- BPF_MOV64_IMM(BPF_REG_0, 1),
- BPF_EXIT_INSN()
- };
-
- _cleanup_(bpf_program_freep) BPFProgram *program = NULL;
- static int supported = -1;
- int r;
-
- /* Checks whether BPF device controller is supported. For this, we check two things:
- *
- * a) whether we are privileged
- * b) the BPF implementation in the kernel supports BPF_PROG_TYPE_CGROUP_DEVICE programs, which we require
- */
-
- if (supported >= 0)
- return supported;
-
- if (geteuid() != 0) {
- log_debug("Not enough privileges, BPF device control is not supported.");
- return supported = 0;
- }
-
- r = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE, "sd_devices", &program);
- if (r < 0) {
- log_debug_errno(r, "Can't allocate CGROUP DEVICE BPF program, BPF device control is not supported: %m");
- return supported = 0;
- }
-
- r = bpf_program_add_instructions(program, trivial, ELEMENTSOF(trivial));
- if (r < 0) {
- log_debug_errno(r, "Can't add trivial instructions to CGROUP DEVICE BPF program, BPF device control is not supported: %m");
- return supported = 0;
- }
-
- r = bpf_program_load_kernel(program, NULL, 0);
- if (r < 0) {
- log_debug_errno(r, "Can't load kernel CGROUP DEVICE BPF program, BPF device control is not supported: %m");
- return supported = 0;
- }
-
- return supported = 1;
-}
-
static int allow_list_device_pattern(
BPFProgram *prog,
const char *path,
const char *cgroup_path,
BPFProgram **prog_installed);
-int bpf_devices_supported(void);
int bpf_devices_allow_list_device(BPFProgram *prog, const char *path, const char *node, CGroupDevicePermissions p);
int bpf_devices_allow_list_major(BPFProgram *prog, const char *path, const char *name, char type, CGroupDevicePermissions p);
int bpf_devices_allow_list_static(BPFProgram *prog, const char *path);
CGroupMask mask = 0;
int r;
- /* BPF-based firewall and pinned foreign prog */
+ /* BPF-based firewall, device access control, and pinned foreign prog */
if (bpf_program_supported() > 0)
mask |= CGROUP_MASK_BPF_FIREWALL |
+ CGROUP_MASK_BPF_DEVICES |
CGROUP_MASK_BPF_FOREIGN;
- /* BPF-based device access control */
- r = bpf_devices_supported();
- if (r < 0)
- return r;
- if (r > 0)
- mask |= CGROUP_MASK_BPF_DEVICES;
-
/* BPF-based bind{4|6} hooks */
r = bpf_socket_bind_supported();
if (r < 0)
test_setup_logging(LOG_DEBUG);
+ r = bpf_program_supported();
+ if (r < 0)
+ return log_tests_skipped_errno(r, "BPF device filter not supported");
+ ASSERT_TRUE(r);
+
ASSERT_OK(getrlimit(RLIMIT_MEMLOCK, &rl));
rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, CAN_MEMLOCK_SIZE);
(void) setrlimit(RLIMIT_MEMLOCK, &rl);
if (r < 0)
return log_tests_skipped_errno(r, "Failed to prepare cgroup subtree");
- r = bpf_devices_supported();
- if (r == 0)
- return log_tests_skipped("BPF device filter not supported");
- ASSERT_EQ(r, 1);
-
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, cgroup, NULL, &controller_path);
ASSERT_OK(r);