select_tuner() bounds the tuners[] dispatch index on the upper side only β a negative tuner type would install an out-of-bounds TUNER pointer that consumers dereference (hardening)
Summary
'if (tuner_type < Bt848_MAX_TUNER)' accepts any negative value; tuners[-1] would be stored and later dereferenced for pllControl/bandAddrs and a %s name print - a wild kernel read. All current callers pass provably non-negative values (exhaustive enumeration in the pack), so impact is currently unreachable: defense-in-depth for any future caller or enabled override. Add-the-lower-bound fix.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4361 Β· 4 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.7 KB | β raw | |
| VERDICT.md | β | 2.1 KB | β raw | |
| verdict.json | β | 2.1 KB | view raw | |
| manifest.json | β | 542 B | view raw |
DF-4361 β select_tuner() checks only the upper bound of tuner_type β negative index would walk tuners[] OOB (hardening; all current callers proven safe)
File: sys/dev/video/bktr/bktr_tuner.c (pass 2)
Severity: Info (defense-in-depth) Β· Confidence: certain (defect certain, impact currently unreachable)
What
sys/dev/video/bktr/bktr_tuner.c:709 void select_tuner( bktr_ptr_t bktr, int tuner_type ) {
sys/dev/video/bktr/bktr_tuner.c:710 if (tuner_type < Bt848_MAX_TUNER) { /* only UPPER bound */
sys/dev/video/bktr/bktr_tuner.c:711 bktr->card.tuner = &tuners[ tuner_type ];
sys/dev/video/bktr/bktr_tuner.c:712 } else {
sys/dev/video/bktr/bktr_tuner.c:713 bktr->card.tuner = NULL;
sys/dev/video/bktr/bktr_tuner.c:714 }
tuners[] is exactly 16 entries (bktr_tuner.c:119-280; NO_TUNER=0 β¦ LG_TPI8PSB12P_PAL=15,
Bt848_MAX_TUNER == 16, bktr_tuner.h:65). A negative tuner_type passes the check and
stores &tuners[-1] (or further back). Consumers then dereference it:
- tuner->pllControl[band] / tuner->bandAddrs[band] (bktr_tuner.c:825-826, 884-885)
- bktr->card.tuner->name in the attach printout (bktr_card.c:1343-1344) β %s on a
wild char * read from out-of-bounds rodata β potential kernel fault.
Caller enumeration (why Info, not higher)
Every reachable caller passes a provably non-negative value:
1. Boot tunable: masked bt848_tuner & 0xff (bktr_os.c:470, bktr_card.c:906) β 0..255;
β₯16 β NULL. (Root-controlled anyway.)
2. BKTR_OVERRIDE_TUNER path β compile-time constant, not defined in the build.
3. Signature-table dispatch: single entry {5, 9, β¦} β tuner=9 (bktr_card.c:395-398, 862).
4. GPIO/EEPROM derivation: tuner_format <= 9 gating 10-entry constant tables
(bktr_card.c:1128-1152), switch (((INL(...)>>10)-1)&7) (bktr_card.c:920-928) β
all enum constants.
So the OOB is currently unreachable; the defect is the missing lower-bound in a
dispatch function that any future caller (or a future table entry typo'd negative)
would turn into a wild read. Classic CWE-129 hardening.
Fix
--- a/sys/dev/video/bktr/bktr_tuner.c
+++ b/sys/dev/video/bktr/bktr_tuner.c
@@ -709,7 +709,7 @@ void select_tuner( bktr_ptr_t bktr, int tuner_type ) {
- if (tuner_type < Bt848_MAX_TUNER) {
+ if (tuner_type >= 0 && tuner_type < Bt848_MAX_TUNER) {
bktr->card.tuner = &tuners[ tuner_type ];
Verification status
untested β requires Brooktree PCI hardware to reach any of this at runtime; the audit
guest has no Brooktree/0x109e PCI device (pciconf -l clean), so /dev/bktr* never
appears and select_tuner cannot execute there. Static caller enumeration above is
exhaustive for this tree.
VERDICT β DF-4361
status: untested (hardening finding; hardware-gated path) Β· impact: none demonstrated β defect is real but currently unreachable with an out-of-range value Β· confidence: certain.
Reproduced?
No, by design of the finding: select_tuner() lacks the lower-bound half of its range
check (bktr_tuner.c:710), so a negative tuner_type would store &tuners[negative]
into bktr->card.tuner, which consumers dereference (tuner->pllControl[] /
tuner->bandAddrs[] bktr_tuner.c:825-826, 884-885; card.tuner->name %s printout
bktr_card.c:1343-1344). An exhaustive caller enumeration for this tree shows every
reachable call site passes a provably non-negative value:
- boot tunable path β masked
bt848_tuner & 0xff(bktr_os.c:470, bktr_card.c:905-907); - compile-time
BKTR_OVERRIDE_TUNERβ not defined in any build file; - signature-table dispatch β single entry {card=5, tuner=9} (bktr_card.c:395-398, 862);
- EEPROM/GPIO derivation β
tuner_format <= 9into 10-entry constant tables and&7-masked GPIO switch (bktr_card.c:920-928, 1128-1152).
Hence Info (defense-in-depth), not a higher severity: the memory-unsafe half of the
index check is missing in a dispatch function where a future caller, table typo, or
config change (BKTR_OVERRIDE_TUNER) immediately converts it into a wild kernel read.
Runtime exercise would additionally require Brooktree PCI hardware: the audit guest (DragonFly 6.5-DEVELOPMENT x86_64, QEMU/KVM) has no 0x109e PCI device (pciconf), so /dev/bktr* never appears and select_tuner cannot run there.
Fix validation
not_testable β path needs the PCI card; the fix is a one-sided bound addition
(tuner_type >= 0 &&) with no behavior change for any currently-valid value.
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.
(No fix.diff for this item: documented recommendation only - see Fix above.)
Fix verification
not_testablenot_testable β needs Brooktree PCI hardware; fix is a pure lower-bound addition with no behavior change for valid values
fix diff in README.md
Confirmed kernel references
Detail
Evidence (decisive lines)
README.md (code excerpt bktr_tuner.c:709-715 + full caller enumeration with path:line); VERDICT.md; guest pciconf shows no 0x109e device
PoC changes
none β no PoC seed; static verification only (hardware-gated path)
Verified recommended fix
Add the missing lower bound in select_tuner: if (tuner_type >= 0 && tuner_type < Bt848_MAX_TUNER)
Verdict
select_tuner() bounds-checks only the upper end (tuner_type < Bt848_MAX_TUNER) of the tuners[] dispatch index; a negative type would set bktr->card.tuner = &tuners[negative], dereferenced later for pllControl/bandAddrs and a %s name printout β a wild kernel read. Exhaustive caller enumeration (masked boot tunable, compile-time override undefined, constant signature/EEPROM tables) proves every current call site non-negative, so this is a defense-in-depth hardening finding (Info). Path additionally requires Brooktree PCI hardware, absent from the audit guest.
No comments yet.