METEORSSIGNAL stores td->td_proc without a reference and video_close() never clears it β frame-completion interrupt ksignal()s a freed struct proc (UAF from interrupt context)
Summary
METEORSSIGNAL sets bktr->proc = td->td_proc with no PHOLD(); video_close clears flags but never resets/releases bktr->proc (only the next open does). The interrupt handler ksignal()s it on every captured frame. A fork/SCM_RIGHTS fd-sharer installs itself as signal target, exits and is reaped while the parent keeps the device open and capturing -> every frame interrupt dereferences a freed struct proc (lwpsignal takes p->p_token, edits p_siglist). No timing race required. Source-certain (runtime needs real capture interrupts, absent on the guest). Unprivileged UAF write path in interrupt context; slab-reuse of struct proc gives a corruption primitive.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3787 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| poc_stale_proc.c | β | 1.5 KB | view raw | |
| env.txt | β | 412 B | view raw | |
| poc_build_and_device_check.log | β | 1 B | view raw | |
| fix.diff | β | 790 B | view raw | |
| VERDICT.md | β | 3.2 KB | β raw | |
| manifest.json | β | 929 B | view raw | |
| verdict.json | β | 1.9 KB | view raw |
DF-3787 β verdict
INCONCLUSIVE | reproduced=0 | impact=none | confidence=certain
INCONCLUSIVE at runtime (needs real capture interrupts; no Bt848 hardware on this guest). Source-certain: no PHOLD/PRELE pairing, no close-path reset, ksignal() consumer confirmed at bktr_core.c:798-801.
Root cause (citations)
METEORSSIGNAL (bktr_core.c:1485-1496) stores bktr->proc = td->td_proc with no PHOLD() reference, and video_close() (bktr_core.c:1012-1031) never clears or releases it (only the next video_open at :928 resets the field). The frame-completion interrupt path calls ksignal(bktr->proc, bktr->signal) (bktr_core.c:798-801) for as long as capture runs. A process that shares the open fd (fork or SCM_RIGHTS), installs itself as the signal target, then exits and is reaped leaves bktr->proc dangling while the parent keeps the device open and capturing -> every frame interrupt dereferences a freed struct proc (lwpsignal takes p->p_token, edits p_siglist) -> UAF from interrupt context. Reliable, no timing race needed.
Guest reality (why no runtime kernel trigger)
The audit guest is DragonFly 6.5-DEVELOPMENT x86_64 (X86_64_GENERIC). The bktr
driver is NOT compiled into the GENERIC kernel (sys/conf/files: optional
bktr pci), there is no /boot/modules tree, no /dev/bktr, /dev/tuner,
/dev/vbi* nodes, no Brooktree PCI device (QEMU has no Bt848/Bt878 device
model; pciconf -lv shows no vendor 109e). Therefore the kernel code path is
unreachable ON THIS GUEST. Verification is source-level: faithful harnesses of
the exact kernel arithmetic (the same methodology as the accepted DF-1216
evidence pack), run on the DragonFly guest with its native cc, plus fix.diff
compile-validation against the guest's /usr/src. All PoC triggers compile
cleanly against the guest's kernel headers (poc_build_and_device_check.log).
Exploit chain
parent opens /dev/bktr0 + METEORCAPTUR continuous -> forked child (shares fd) issues METEORSSIGNAL(SIGUSR1) -> child exits + reaped (proc freed) -> next frame interrupt ksignal()s freed proc -> UAF token/siglist writes.
Decisive evidence
poc_stale_proc.c (compiles on guest vs /usr/src headers; open() fails ENXIO: no device). Code citations in VERDICT.md.
Fix validation
fix.diff (in this directory) applies cleanly against the pristine sys/ tree
(git apply --check) and compiles as part of the bktr KLD module on the
guest's /usr/src with -Werror together with the seven other pass-2 bktr fixes
(fix_build.log, MAKE_RC=0, bktr.ko + bktr_mem.ko produced). Runtime
patched-behavior validation is not possible on this guest (no device), hence
fix_status=not_testable (compile-validated + logic-reviewed).
Kernel references
- sys/dev/video/bktr/bktr_core.c:1485
- sys/dev/video/bktr/bktr_core.c:1495
- sys/dev/video/bktr/bktr_core.c:798
- sys/dev/video/bktr/bktr_core.c:1012
- sys/kern/kern_sig.c:1118
Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
Fix verification
not_testableRuntime fix validation impossible on this guest (no Bt848/878 hardware, driver not in GENERIC, no module dir). fix.diff applies cleanly to sys/ and the patched bktr KLD module compiles with -Werror on the guest's /usr/src (fix_build.log).
fix.diff; fix_build.log (all-8-fixes module build, MAKE_RC=0)
Confirmed kernel references
Detail
Exploit chain
parent opens /dev/bktr0 + METEORCAPTUR continuous -> forked child (shares fd) issues METEORSSIGNAL(SIGUSR1) -> child exits + reaped (proc freed) -> next frame interrupt ksignal()s freed proc -> UAF token/siglist writes.
Evidence (decisive lines)
poc_stale_proc.c (compiles on guest vs /usr/src headers; open() fails ENXIO: no device). Code citations in VERDICT.md.
PoC changes
none
Verified recommended fix
PHOLD/PRELE around bktr->proc and clear it in video_close (fix.diff)
Verdict
INCONCLUSIVE at runtime (needs real capture interrupts; no Bt848 hardware on this guest). Source-certain: no PHOLD/PRELE pairing, no close-path reset, ksignal() consumer confirmed at bktr_core.c:798-801.
No comments yet.