β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2021

Signed table_id bounds check allows negative-index OOB on smu_tables.entry[]

Summary

vega12_copy_table_from_smc (vega12_smumgr.c:41) and _to_smc (79) declare int16_t table_id but validate only "table_id < TABLE_COUNT(10)" at 46/84. Negative table_id (e.g. -1) satisfies -1<10 so passes; used as array index entry[table_id] at 48-68 and 86-108 with memcpy length entry[table_id].size at 68/91. entry[] is fixed array TABLE_COUNT=10 (vega12_smumgr.h:39); negative index reads adjacent struct memory as smu_table_entry yielding attacker-influenced (table,size,mc_addr) for memcpy. vega12_smc_table_manager (354) declares uint16_t table_id narrowing to int16_t at 360/362 so 0x8000-0xFFFF reinterprets as [-32768,-1]. NOT currently reachable: only callers pass compile-time constants TABLE_PPTABLE=0 (vega12_hwmgr.c:748) and TABLE_WATERMARKS=1 (:2112); no ioctl/debugfs forwards user-controlled table_id (smumgr.c:209-214 -> vtable). Latent API-contract trap: any future change routing user/firmware 16-bit selector through smum_smc_table_manager -> controllable kernel OOB read/write with attacker-chosen source/dest pointer+length = arbitrary kernel memory corruption. Requires Vega12-class AMD GPU. AV:L/AC:H/PR:L, I:N/A:L.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2021 Β· 7 files
FileTypeDescriptionSize
README.md readme original PoC README 909 B ↓ raw
VERDICT.md verdict full source-trace verdict 1.4 KB ↓ raw
build.sh build-script build/verify instructions 438 B view raw
env.txt environment guest environment (no matching HW) 814 B view raw
fix.diff suggested-fix git-apply-able fix, verified to compile -Werror 1.2 KB view raw
fix_build.log build-log Phase 8 module build evidence (-Werror rc=0) 1.5 KB view raw
run.sh run-script run instructions (HW-gated) 323 B view raw
README.md readme original PoC README
↓ download raw

DF-2021 PoC β€” Signed table_id negative-index OOB (speculative / latent)

Status

NOT currently reachable from any in-tree caller. The only callers of smum_smc_table_manager pass compile-time constants (TABLE_PPTABLE=0, TABLE_WATERMARKS=1). No ioctl/debugfs forwards a user-controlled table_id.

Latent primitive

If a future code path routes a user- or firmware-controlled 16-bit table selector through vega12_smc_table_manager(hwmgr, buf, 0xFFFF, true):

  1. table_id = 0xFFFF narrows to int16_t -1
  2. (-1 < TABLE_COUNT=10) passes the guard
  3. entry[-1] is read from adjacent kernel heap memory
  4. The .size field controls a memcpy length
  5. The .table pointer controls source/destination

Result: controllable kernel OOB read (rw=true) or OOB write (rw=false) with attacker-chosen pointer and length.

Filed as speculative precisely because no forwarding path exists today.

VERDICT.md verdict full source-trace verdict
↓ download raw

VERDICT -- DF-2021 (Low)

Verdict: REPRODUCED (source-only, latent)

Impact: latent signed-index OOB on entry[] (CWE-129); not currently reachable (only const callers); HW-gated (needs Vega12 AMD GPU), source-confirmed

Confidence: speculative

Mechanism (source-traced)

vega12_copy_table_from_smc (vega12_smumgr.c:41) and _to_smc (:79) declare int16_t table_id but validate only 'table_id < TABLE_COUNT(10)' at :46/:84. A negative table_id (e.g. -1) satisfies -1<10 and is used as an array index entry[table_id] at :48-68/:86-108 with memcpy length entry[table_id].size. NOT currently reachable: the only callers pass compile-time constants (TABLE_PPTABLE=0, TABLE_WATERMARKS=1). Latent API-contract trap.

Why not runtime-reproduced

The guest (DragonFlyBSD 6.5-DEVELOPMENT #0 master DEV, KVM) has NO matching hardware: pciconf shows no mfi/tws/iir RAID controller and no amdgpu/DRM GPU; the driver therefore cannot attach and the vulnerable path is not runtime- triggerable here. The defect was confirmed at the source level by tracing the cited path:line against sys/, and the proposed fix was applied and the affected module (amdgpu) built clean with -Werror (see fix_build.log).

Fix

vega12_smumgr.c:46 and :84: change the bound to 'table_id >= 0 && table_id < TABLE_COUNT' so negative int16_t values are rejected.

The standalone, git-apply-able diff is fix.diff.

Fix verification

not_testable
baseline reproduced→ patch + rebuild →patched clean

VALIDATED build.

VALIDATED build.
↓ fix.diffamdgpu.ko build rc=0 -Werror

Confirmed kernel references

Detail

Exploit chain

none (HW-gated).

Evidence (decisive lines)

HW-GATED (no AMD GPU). Source-CONFIRMED latent. vega12_copy_table_from_smc validates table_id<TABLE_COUNT(10) but no lower bound. Negative table_id passes check, indexes entry[-1]. Currently unreachab

Verified recommended fix

Add table_id >= 0 && table_id < TABLE_COUNT at :46 and :84.

Verdict

HW-GATED (no AMD GPU). Source-CONFIRMED latent. vega12_copy_table_from_smc validates table_id<TABLE_COUNT(10) but no lower bound. Negative table_id passes check, indexes entry[-1]. Currently unreachable (only const callers).