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

mmhub_v1_0_init_cache_regs never programs mmVM_L2_CNTL3: BANK_SELECT/L2_CACHE_BIGK_FRAGMENT_SIZE computed into a stale CNTL2-derived local and silently dropped (the v5.2-era WREG32 line is missing from the DF vendor sync)

Summary

After tmp is written to CNTL2, the CNTL3 field macros are applied to that stale value and the result is never stored - mmVM_L2_CNTL3 is neither read nor written anywhere in the function, so the MMHUB L2 TLB geometry stays at hw reset defaults (notably translate_further on Raven2 where BANK_SELECT must be 12). The DF vendor sync dropped the WREG32 line (upstream v5.2 has it; the in-tree gfxhub twin programs its instance). Functional misconfiguration/dead-code trap; no demonstrated isolation breach. RMW+write fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4815 Β· 6 files
FileTypeDescriptionSize
README.md β€” 932 B ↓ raw
VERDICT.md β€” 4.2 KB ↓ raw
env.txt β€” 1.5 KB view raw
fix.diff β€” 661 B view raw
evidence/comparison.txt β€” 2.9 KB view raw
evidence/upstream_v5.2_mmhub_v1_0.c β€” 19.0 KB view raw

DF-4815 β€” mmhub_v1_0_init_cache_regs computes VM_L2_CNTL3 (BANK_SELECT / L2_CACHE_BIGK_FRAGMENT_SIZE) into a stale CNTL2-derived local and never writes it: the register is left at reset default on every Vega10/12/20/Raven GART init; the DF vendor-sync dropped the WREG32_SOC15(MMHUB, 0, mmVM_L2_CNTL3, tmp); line present in the tree's own v5.2-era source.

Nothing to build/run: the defect is a silently-dropped register write at GPU hardware init; the audit guest has no AMD GPU (see env.txt), and no userspace-observable PoC exists for a register that is never programmed.

REPRODUCE (static, decisive): sysctl-less; simply diff: evidence/comparison.txt # DF vs upstream v4.18 vs upstream v5.2 evidence/upstream_v5.2_mmhub_v1_0.c:185 # the line DF is missing sys/dev/drm/amd/amdgpu/mmhub_v1_0.c:171-184 # dead-code block

FIX: fix.diff (git apply --check clean) restores read+write of CNTL3.

VERDICT.md
↓ download raw

DF-4815 VERDICT β€” mmhub_v1_0_init_cache_regs never programs mmVM_L2_CNTL3

Bottom line. In mmhub_v1_0_init_cache_regs() (called from mmhub_v1_0_gart_enable() at every GMC/GART initialization on Vega10/12/20 and Raven), the MMHUB L2-TLB geometry registers VM_L2_CNTL3.BANK_SELECT / VM_L2_CNTL3.L2_CACHE_BIGK_FRAGMENT_SIZE are computed into a stale local and never written to hardware: after tmp was last assigned from mmVM_L2_CNTL2 (line 166) and written (line 169), lines 171-179 apply VM_L2_CNTL3 field macros to that stale CNTL2 value β€” and the result is dropped on the floor, because line 181 overwrites tmp with mmVM_L2_CNTL4_DEFAULT and the only remaining write is to CNTL4 (line 184). There is no RREG32/WREG32 of mmVM_L2_CNTL3 anywhere in the function.

Consequences: 1. The intended L2 TLB bank-select / bigk-fragment configuration never lands; MMHUB L2 runs on hardware reset defaults. 2. On Raven/Raven2 with gmc.translate_further (the 128TB+512GB VM layout selected in gmc_v9_0.c:943-945), BANK_SELECT must be 12 β€” it stays at the default, i.e. the TLB geometry silently disagrees with the programmed page-table depth/block size (mmhub_v1_0_setup_vmid_config), a functional misconfiguration of the GPU MMU (VM-fault / hang class). 3. The dead computation is a trap for future edits (garbage CNTL2-derived base would be used if a write were ever added naively β€” exactly what upstream v5.2 shipped: it added the write but kept the missing re-read).

Provenance (why this is a real divergence, verified against tags)

  • Upstream v4.18 (AMDGPU import era) has the same missing write (evidence/comparison.txt) β€” the bug was upstream too, then.
  • Upstream v5.2 has WREG32_SOC15(MMHUB, 0, mmVM_L2_CNTL3, tmp); (evidence/upstream_v5.2_mmhub_v1_0.c:185) β€” fixed upstream between 4.18 and 5.2.
  • The DF file is otherwise v5.2-vintage: mmhub_v1_0_setup_vmid_config is byte-identical to v5.2 except one deliberately-backported later line (RETRY_PERMISSION_OR_INVALID_PAGE_FAULT 0, the no-retry XNACK change), and init_gart_aperture/system_aperture (fb_start/fb_end, AGP BAR, Raven2 rev_id>=0x8 workaround, amdgpu_gmc_pd_addr) all match the v5.2-era code. β‡’ the DF vendor-sync dropped the single WREG32_SOC15(... mmVM_L2_CNTL3, tmp); line that its own source vintage carries.

Security assessment (honest)

No attacker-controlled input reaches this path (driver-internal constants at hardware init). The impact ceiling is misconfiguration of the GPU VM's L2 TLB: no demonstrated isolation breach (page tables still enforced), but TLB-geometry mismatch on translate_further parts can produce VM faults / GPU hangs (availability), and on any future part whose reset default differs from the driver's assumption the L2 behaves differently than validated. Filed as Low / hardening-correctness, CWE-561 (dead code) + CWE-754-style improper initialization.

Verification performed

  • Guest kernel runtime: NOT possible. The audit guest has no AMD GPU at all (see env.txt; only QEMU std-VGA). mmhub_v1_0_gart_enable is executed only during amdgpu GMC init on Vega10-class ASICs. Status untested (device absent). Nothing else on the guest exercises this file.
  • Static verification: decisive. evidence/comparison.txt shows side-by-side: DF (no CNTL3 write) / upstream v4.18 (no write) / upstream v5.2 (write present), plus the vintage proof (setup_vmid_config identity). A grep for mmVM_L2_CNTL3 over the whole DF tree shows the only MMHUB programming site is this function (gfxhub_v1_0.c has its own separate GFX-side CNTL3 handling) β€” nothing else compensates for the dropped write.

Fix

Read, set, write β€” restores upstream v5.2 behavior (and adds the re-read upstream still lacks). See fix.diff; git apply --check passes against sys/dev/drm/amd/amdgpu/mmhub_v1_0.c.

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_testable
baseline no→ patch + rebuild →patched clean

fix.diff restores the dropped CNTL3 programming (git apply --check clean); no Vega10 hardware in the audit guest, so patched-kernel behavior cannot be exercised

fix.diff; evidence/comparison.txt; gfxhub_v1_0.c:151-161 in-tree twin shows the intended pattern
↓ fix.diffper-fix-DF-4815

Confirmed kernel references

Detail

Evidence (decisive lines)

evidence/comparison.txt (DF vs upstream v4.18 vs v5.2 side-by-side + gfxhub twin); fix.diff applies cleanly; env.txt documents guest hardware absence

PoC changes

n/a (no orchestrator seed; pack authored during this run)

Verified recommended fix

Restore read-modify-write of mmVM_L2_CNTL3 in mmhub_v1_0_init_cache_regs (see fix.diff); matches upstream v5.2 plus the re-read upstream still lacks

Verdict

mmhub_v1_0_init_cache_regs() applies VM_L2_CNTL3 field macros to a stale mmVM_L2_CNTL2-derived local and never writes the result; mmVM_L2_CNTL3 is neither read nor written anywhere in the function, so the MMHUB L2 TLB geometry stays at reset default. The DF file is otherwise v5.2-vintage (setup_vmid_config byte-identical except one backported line), and both upstream v5.2 (evidence/upstream_v5.2_mmhub_v1_0.c:185) and the in-tree GFX-hub twin (gfxhub_v1_0.c:151-161) contain the write the DF sync dropped. Upstream v4.18 carried the same omission, so this is an inherited-then-fixed-upstream bug that the DF sync missed.