Skip to main content

max / alloy

1.7 KB · 33 lines History Blame Raw
1 # Never arm USBGuard against an empty policy.
2 #
3 # This is the structural version of the sentence the whole `alloy usb` work has
4 # been repeating since 2026-08-22: an image that boots armed with an empty
5 # policy is worse than one with no usbguard at all, because the second is merely
6 # unprotected and the first has deauthorized every USB device on the machine.
7 #
8 # The four facts behind it, measured off usbguard-1.1.4-1.fc43 rather than read:
9 # rules.conf ships empty, ImplicitPolicyTarget=block, PresentDevicePolicy and
10 # InsertedDevicePolicy are both apply-policy. Together they mean the daemon
11 # denies everything the instant it starts against that file.
12 #
13 # etc/systemd/system/alloy-usb-seed.service is what normally stops that from
14 # happening: it writes a policy from the machine's own devices, ordered before
15 # this unit. This condition is what happens when that fails — a machine whose
16 # seeder could not run, or whose policy was emptied by hand, boots UNARMED
17 # instead of bricked. Failing open is the correct direction for the same reason
18 # the keyboard gate fails open.
19 #
20 # A condition rather than an assertion on purpose. `ConditionFileNotEmpty` makes
21 # systemd skip the unit and record it as such; `AssertFileNotEmpty` would put
22 # the unit into a failed state and pull that into whatever is waiting on it. The
23 # machine is fine here, it is simply not enforcing, and it should not be
24 # reported as broken.
25 #
26 # The consequence for the keyboard gate is real and handled there: `systemctl
27 # start usbguard` on a machine with no policy now returns success while leaving
28 # the unit inactive, so the gate checks whether the daemon is actually running
29 # rather than trusting the exit code.
30
31 [Unit]
32 ConditionFileNotEmpty=/etc/usbguard/rules.conf
33