diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml index a9600917ea..bf7aff6b20 100644 --- a/man/systemd.resource-control.xml +++ b/man/systemd.resource-control.xml @@ -720,10 +720,15 @@ Note that whitelists defined this way should only reference device groups which are resolvable at the time the unit is started. Any device groups not resolvable then are not added to the device whitelist. In order to work around this limitation, consider extending service units - with an ExecStartPre=/sbin/modprobe… line that loads the necessary - kernel module implementing the device group if missing. Example: … + with a pair of After=modprobe@xyz.service and + Wants=modprobe@xyz.service lines that load the necessary kernel module + implementing the device group if missing. + Example: … +[Unit] +Wants=modprobe@loop.service +After=modprobe@loop.service + [Service] -ExecStartPre=-/sbin/modprobe -abq loop DeviceAllow=block-loop DeviceAllow=/dev/loop-control … diff --git a/src/core/bpf-devices.c b/src/core/bpf-devices.c index 984603003e..07ef9f6777 100644 --- a/src/core/bpf-devices.c +++ b/src/core/bpf-devices.c @@ -38,7 +38,13 @@ static int bpf_access_type(const char *acc) { return r; } -static int bpf_prog_whitelist_device(BPFProgram *prog, char type, int major, int minor, const char *acc) { +static int bpf_prog_whitelist_device( + BPFProgram *prog, + char type, + int major, + int minor, + const char *acc) { + int r, access; assert(prog); @@ -74,7 +80,12 @@ static int bpf_prog_whitelist_device(BPFProgram *prog, char type, int major, int return r; } -static int bpf_prog_whitelist_major(BPFProgram *prog, char type, int major, const char *acc) { +static int bpf_prog_whitelist_major( + BPFProgram *prog, + char type, + int major, + const char *acc) { + int r, access; assert(prog); @@ -109,7 +120,11 @@ static int bpf_prog_whitelist_major(BPFProgram *prog, char type, int major, cons return r; } -static int bpf_prog_whitelist_class(BPFProgram *prog, char type, const char *acc) { +static int bpf_prog_whitelist_class( + BPFProgram *prog, + char type, + const char *acc) { + int r, access; assert(prog); @@ -143,7 +158,11 @@ static int bpf_prog_whitelist_class(BPFProgram *prog, char type, const char *acc return r; } -int bpf_devices_cgroup_init(BPFProgram **ret, CGroupDevicePolicy policy, bool whitelist) { +int bpf_devices_cgroup_init( + BPFProgram **ret, + CGroupDevicePolicy policy, + bool whitelist) { + const struct bpf_insn pre_insn[] = { /* load device type to r2 */ BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, @@ -306,7 +325,14 @@ int bpf_devices_supported(void) { return supported = 1; } -static int whitelist_device_pattern(BPFProgram *prog, const char *path, char type, const unsigned *maj, const unsigned *min, const char *acc) { +static int whitelist_device_pattern( + BPFProgram *prog, + const char *path, + char type, + const unsigned *maj, + const unsigned *min, + const char *acc) { + assert(IN_SET(type, 'b', 'c')); if (cg_all_unified() > 0) { @@ -343,7 +369,12 @@ static int whitelist_device_pattern(BPFProgram *prog, const char *path, char typ } } -int bpf_devices_whitelist_device(BPFProgram *prog, const char *path, const char *node, const char *acc) { +int bpf_devices_whitelist_device( + BPFProgram *prog, + const char *path, + const char *node, + const char *acc) { + mode_t mode; dev_t rdev; int r; @@ -377,7 +408,13 @@ int bpf_devices_whitelist_device(BPFProgram *prog, const char *path, const char return whitelist_device_pattern(prog, path, S_ISCHR(mode) ? 'c' : 'b', &maj, &min, acc); } -int bpf_devices_whitelist_major(BPFProgram *prog, const char *path, const char *name, char type, const char *acc) { +int bpf_devices_whitelist_major( + BPFProgram *prog, + const char *path, + const char *name, + char type, + const char *acc) { + unsigned maj; int r; @@ -459,7 +496,10 @@ int bpf_devices_whitelist_major(BPFProgram *prog, const char *path, const char * return 0; } -int bpf_devices_whitelist_static(BPFProgram *prog, const char *path) { +int bpf_devices_whitelist_static( + BPFProgram *prog, + const char *path) { + static const char auto_devices[] = "/dev/null\0" "rwm\0" "/dev/zero\0" "rwm\0" diff --git a/src/core/unit.c b/src/core/unit.c index 03b4b57273..399a8cf655 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -4324,6 +4324,11 @@ int unit_patch_contexts(Unit *u) { r = cgroup_add_device_allow(cc, "block-blkext", "rwm"); if (r < 0) return r; + + /* Make sure "block-loop" can be resolved, i.e. make sure "loop" shows up in /proc/devices */ + r = unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, "modprobe@loop.service", true, UNIT_DEPENDENCY_FILE); + if (r < 0) + return r; } } diff --git a/units/modprobe@.service b/units/modprobe@.service index 4c5bd637e3..5dca2cb771 100644 --- a/units/modprobe@.service +++ b/units/modprobe@.service @@ -8,8 +8,11 @@ # (at your option) any later version. [Unit] -Description=Load kernel module %i +Description=Load Kernel Module %i +DefaultDependencies=no +Before=sysinit.target Documentation=man:modprobe(8) +ConditionCapability=CAP_SYS_MODULE [Service] Type=oneshot