| 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 |
|