mirror of
https://github.com/troglobit/finit.git
synced 2026-09-30 13:02:37 +07:00
Merge pull request #499 from aanderse/docs
docs: cleanup some development work
This commit is contained in:
+1
-1
@@ -7,6 +7,6 @@ dist_docs_DATA = build.md cmdline.md commands.md conditions.md \
|
||||
distro.md example.md features.md index.md initctl.md \
|
||||
keventd.md plugins.md requirements.md runlevels.md \
|
||||
runparts.md service.md signals.md state-machine.md \
|
||||
udev-matching.md watchdog.md
|
||||
watchdog.md
|
||||
dist_docs_DATA += img/logo.png img/svc-machine.png img/svc-machine.svg \
|
||||
img/alpine-screenshot2.png
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
# How udev rules work
|
||||
|
||||
## Summary of the complete fix
|
||||
|
||||
- hardware.c: Write authorized_default=1 on the bus path before nftw
|
||||
runs (just 2 lines added). This exploits the fact that apath already
|
||||
contains path/authorized_default at that point (set by the snprintf on
|
||||
line 71). With authorized_default=1 set on the root hub, any device
|
||||
that appears behind an intermediate hub during hub enumeration gets
|
||||
auto-authorized by the kernel.
|
||||
- 70-usb-authorize.rules: Belt-and-suspenders for the async case. If hub
|
||||
port probing is slow enough that children appear after nftw has
|
||||
already returned, udev sees the add event with authorized=0, walks up
|
||||
the parent chain with ATTRS{authorized_default}=="1", and authorizes
|
||||
the device. Locked buses (authorized_default=0) are correctly skipped.
|
||||
|
||||
```
|
||||
ACTION=="add", SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", \
|
||||
ATTR{authorized}=="0", \
|
||||
ATTRS{authorized_default}=="1", \
|
||||
RUN+="/bin/sh -c 'echo 1 > /sys%p/authorized'"
|
||||
```
|
||||
|
||||
This keeps authorized_default=2 (deny by default) fully intact — the
|
||||
security window stays closed. The udev rule only fires when confd has
|
||||
explicitly marked a bus as unlocked.
|
||||
|
||||
## Comment from Undersigned
|
||||
|
||||
Very interesting, I did not know you could do such complex operations
|
||||
with udev rules. Could you explain a bit more in detail how the matching
|
||||
works and how we can guarantee locked buses/ports are not accidentally unlocked?
|
||||
|
||||
> Sure. Let's walk through it step by step.
|
||||
|
||||
## How udev ATTRS{} matching works
|
||||
|
||||
A udev rule matches against a device and its entire parent chain in the
|
||||
sysfs device tree. When a device like 2-1.4 (the keyboard) is added, its
|
||||
sysfs hierarchy looks like:
|
||||
|
||||
```
|
||||
/sys/devices/.../0000:01:00.0/usb2/ ← root hub (usbN)
|
||||
usb2/2-1/ ← VIA Labs hub
|
||||
usb2/2-1/2-1.4/ ← keyboard ← event fires here
|
||||
```
|
||||
|
||||
- ATTR{} (no trailing S) — matches attributes on the device itself only
|
||||
- ATTRS{} (with S) — matches attributes on the device or any of its
|
||||
parents, walking up the tree until it finds a match or runs out of
|
||||
parents
|
||||
|
||||
So ATTRS{authorized_default}=="1" on a keyboard event at 2-1.4 walks:
|
||||
|
||||
1. 2-1.4/authorized_default — doesn't exist (not a hub/controller)
|
||||
2. 2-1/authorized_default — doesn't exist (downstream hubs don't have
|
||||
this attribute, only root hubs do)
|
||||
3. usb2/authorized_default — exists, check its value
|
||||
|
||||
This is exactly the right level: authorized_default only lives on root
|
||||
hubs (usbN), which is precisely where confd writes.
|
||||
|
||||
## Why locked buses can't be accidentally unlocked
|
||||
|
||||
The invariant is: confd owns `authorized_default`. It sets it to 0
|
||||
(locked) or 1 (unlocked). The udev rule only reads it, never writes it.
|
||||
|
||||
Walk through the locked case:
|
||||
|
||||
```
|
||||
confd sets usb2/authorized_default = 0 ← locked
|
||||
```
|
||||
|
||||
A device plugs into usb2. udev fires:
|
||||
|
||||
1. ATTR{authorized}=="0" — matches (device is unauthorized)
|
||||
2. ATTRS{authorized_default}=="1" — walks up to usb2, finds 0 → no match
|
||||
3. Rule doesn't fire. Device stays denied. ✓
|
||||
|
||||
For a device behind an intermediate hub on a locked bus:
|
||||
|
||||
```
|
||||
usb2/authorized_default = 0 ← bus locked
|
||||
usb2/2-1/ ← hub (somehow authorized)
|
||||
usb2/2-1/2-1.4/ ← keyboard
|
||||
```
|
||||
|
||||
Even if the hub itself were authorized somehow, the keyboard's parent
|
||||
chain still reaches `usb2/authorized_default = 0` before finding any
|
||||
`authorized_default = 1`. The rule doesn't fire. ✓
|
||||
|
||||
The only remaining question: what if two buses exist and one is locked?
|
||||
|
||||
Say usb1 is unlocked and usb2 is locked. A device on usb2 fires a udev
|
||||
event. ATTRS walks up: `usb2/authorized_default = 0` — stops there (once
|
||||
it finds the attribute it stops). It does not continue up to PCIe or
|
||||
platform buses looking for usb1's attribute. Each USB device's parent
|
||||
chain only goes through its own root hub.
|
||||
|
||||
This is because authorized_default is found at usb2 — udev stops as soon
|
||||
as it matches the attribute name, regardless of value. If the value
|
||||
doesn't match the condition, the whole rule fails. It doesn't continue
|
||||
looking at other buses.
|
||||
|
||||
## Summary of the guarantee
|
||||
|
||||
```
|
||||
┌───────────────────────┬─────────────────────────┬─────────────────────────┐
|
||||
│ Scenario │ usb2/authorized_default │ Rule fires? │
|
||||
├───────────────────────┼─────────────────────────┼─────────────────────────┤
|
||||
│ Bus unlocked by confd │ 1 │ Yes → device authorized │
|
||||
├───────────────────────┼─────────────────────────┼─────────────────────────┤
|
||||
│ Bus locked by confd │ 0 │ No → device denied │
|
||||
├───────────────────────┼─────────────────────────┼─────────────────────────┤
|
||||
│ Bus at kernel default │ 2 │ No → device denied │
|
||||
├───────────────────────┼─────────────────────────┼─────────────────────────┤
|
||||
│ Bus doesn't exist yet │ — │ No → no match │
|
||||
└───────────────────────┴─────────────────────────┴─────────────────────────┘
|
||||
```
|
||||
|
||||
The rule is purely reactive: it can only authorize devices on buses that
|
||||
confd has already explicitly declared unlocked. It has no ability to
|
||||
override a lock.
|
||||
@@ -56,7 +56,6 @@ nav:
|
||||
- Plugins: plugins.md
|
||||
- Watchdog: watchdog.md
|
||||
- keventd: keventd.md
|
||||
- udev Rule Matching: udev-matching.md
|
||||
- D-Bus Integration: dbus.md
|
||||
- Service State Machine: state-machine.md
|
||||
- Distributions: distro.md
|
||||
|
||||
Reference in New Issue
Block a user