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

get_next_valid_apicid() -1 sentinel propagated unvalidated into get_cpuid_from_apicid(-1): OOB read of apic_id_to_cpu_id[-1] whose value is used, plus duplicate leaf member masks on exhaustion

Field Value
ID DF-2847
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L
CWE CWE-125 / CWE-20 (unchecked sentinel)
File sys/kern/subr_cpu_topology.c
Lines 100-103, 131-132
Area kern
Confidence likely
Discovered 2026-09-02
Pass 2 (GLM 5.3 second pass)
Bucket base:kern
Reported pending
Known CVE none
CVE match novel

Summary

When the leaf count of the built tree exceeds the number of registered valid APIC IDs, get_next_valid_apicid() returns βˆ’1. The caller stores the sentinel and immediately calls get_cpuid_from_apicid(βˆ’1) = apic_id_to_cpu_id[βˆ’1] β€” a 4-byte OOB read BEFORE the array (adjacent BSS) whose value, unlike DF-0084's discarded read, is USED as the bit index for CPUMASK_ASSBIT. Memory-safety is contained only by the cpumask element-index masking, so the result is a wrong members bit; the next leaf's call re-walks and builds duplicate member masks (two nodes claim the same CPU). Reachable only with malformed firmware/hypervisor tables (duplicate MADT APIC IDs, x2APIC IDs β‰₯ NAPICID, mptable HT-fixup inflation). Hostile hypervisor/crafted firmware at boot; no user-triggerable path, no uid=0 route.

Validate the sentinel before use in build_topology_tree's leaf path (row diff) + apply DF-0084's condition reorder.

Timeline

  • 2026-09-02 Discovered during pass-2 audit of subr_cpu_topology.c (GLM 5.3); source-proven (firmware-gated).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2847 Β· 1 files
FileTypeDescriptionSize
fix.diff β€” 768 B view raw

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

Sentinel validation compile-validated and boot-tested (patched kernel boots normally); requires hostile firmware tables to exercise.

compile-validated in the fix-all kernel build (make nativekernel, 0 errors)
↓ fix.diffper-fix-DF-2847

Confirmed kernel references

Detail

Evidence (decisive lines)

subr_cpu_topology.c:131-132: sentinel -1 passed to get_cpuid_from_apicid -> apic_id_to_cpu_id[-1] OOB read, value used

PoC changes

n/a

Verified recommended fix

--- sys/kern/subr_cpu_topology.c 2026-06-29 12:51:19.000000000 +0000

Verdict

Code-verified boot-time OOB read; not reproducible on this guest (requires hostile/buggy firmware tables). get_next_valid_apicid returns -1 when the topology tree wants more leaves than registered APIC IDs (sys/kern/subr_cpu_topology.c:100-103); build_topology_tree feeds that -1 straight into get_cpuid_from_apicid(-1) at :131-132, which indexes apic_id_to_cpu_id[-1] - a 4-byte OOB read BEFORE the array whose value, unlike DF-0084s discarded read, is USED as the CPUMASK_ASSBIT index (contained only by cpumask element masking). Triggering requires malformed MADT/mptable data (duplicate APIC IDs counted but not registered, x2APIC IDs >= NAPICID) - QEMU provides clean tables, the guest booted normally, and the topology cannot be rebuilt at runtime. Boot-time hostile-hypervisor class; the sentinel-validation fix is compile-validated and boot-tested (patched kernel boots).