BT848_SIGNATURE: signCard() has no bound on count β single-bit OOB read-modify-write up to ~3.8 KiB past the 260-byte ioctl argument (bit-OR heap corruption primitive)
Summary
BT848_SIGNATURE passes user count (short, <=32767) to signCard(), whose loop does sig[x/8] |= (1 << (x%8)) for every probed i2c read address that ACKs, x/8 reaching 4095 while sig is eeProm.bytes[256] -> OOB bit-OR over ~3.8 KiB after the 260-byte kmalloc'd ioctl buffer. Any tuner card ACKs at 0xC1/0xC3 (x = 96+128k), so for x >= 2048 the bits land out of bounds at attacker-chosen density. VERIFIED: harness reproduces the OOB RMW reach (sig[3836] vs bytes[256]). Unprivileged single-bit-OR corruption of adjacent kernel heap objects (refcounts, flags, pointer LSBs) - groomable kernel memory corruption.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3786 Β· 10 files| File | Type | Description | Size | |
|---|---|---|---|---|
| harness_signcard.c | β | 1.8 KB | view raw | |
| poc_signcard.c | β | 1.0 KB | view raw | |
| build.log | β | 1.5 KB | view raw | |
| run.log | β | 263 B | view raw | |
| env.txt | β | 412 B | view raw | |
| poc_build_and_device_check.log | β | 1 B | view raw | |
| fix.diff | β | 1.9 KB | view raw | |
| VERDICT.md | β | 3.0 KB | β raw | |
| manifest.json | β | 837 B | view raw | |
| verdict.json | β | 1.8 KB | view raw |
DF-3786 β verdict
REPRODUCED | reproduced=1 | impact=dos | confidence=certain
REPRODUCED at source level (loop-bound harness): count=32767 touches sig[3836] vs the 256-byte array; OOB RMW reaches ioctl-buffer offset 3840 (allocation 260 bytes). The ACK-dependent bit-set requires real i2c devices (absent on this guest).
Root cause (citations)
BT848_SIGNATURE (bktr_core.c:2094-2100) passes user count (short, up to
32767) to signCard() (bktr_card.c:461-476), whose loop executes
sig[x/8] |= (1 << (x % 8)) for every probed i2c address (2*x+1) that ACKs,
with x running to count-1. sig is eeProm.bytes[256]; x/8 reaches 4095 ->
~3.8 KiB past the 260-byte kmalloc(M_IOCTLOPS) ioctl argument. Any card with
an i2c device (every tuner card ACKs at 0xC1/0xC3, hit for x = 96+128k) gets
single bits OR'd into adjacent kernel heap for x >= 2048. Kernel memory
corruption primitive: bit-set OR at attacker-chosen byte offsets (via count)
in the ~4 KiB after the allocation. Unprivileged: /dev/tuner0 0444.
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
open /dev/tuner0 (0444) -> BT848_SIGNATURE{count=32767} -> signCard ORs bits into ~3.8 KiB past the 260-byte heap allocation (groomable bit-flip corruption of adjacent kernel objects).
Decisive evidence
run.log: sig[3836] touched, allocation 260 bytes.
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:2094
- sys/dev/video/bktr/bktr_card.c:461
- sys/dev/video/bktr/bktr_card.c:468
- sys/dev/video/bktr/ioctl_bt848.h:96
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
open /dev/tuner0 (0444) -> BT848_SIGNATURE{count=32767} -> signCard ORs bits into ~3.8 KiB past the 260-byte heap allocation (groomable bit-flip corruption of adjacent kernel objects).
Evidence (decisive lines)
run.log: sig[3836] touched, allocation 260 bytes.
PoC changes
none
Verified recommended fix
Bound count by sizeof(bytes)*8 in BT848_SIGNATURE (fix.diff)
Verdict
REPRODUCED at source level (loop-bound harness): count=32767 touches sig[3836] vs the 256-byte array; OOB RMW reaches ioctl-buffer offset 3840 (allocation 260 bytes). The ACK-dependent bit-set requires real i2c devices (absent on this guest).
No comments yet.