OOB write into cpu_topology_nodes[MAXCPU] during boot topology construction on high-CPU-count systems
| Field | Value |
|---|---|
| ID | DF-0083 |
| Status | new |
| Severity | Medium |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CWE | CWE-787 Out-of-bounds Write |
| File | sys/kern/subr_cpu_topology.c |
| Lines | 115-154 |
| Area | kern (CPU topology / boot) |
| Confidence | likely |
| Discovered | 2026-06-30 |
| Reported | pending |
Summary
build_topology_tree() unconditionally increments a global cpu_node_t
*last_free_node cursor through the fixed-size static array
cpu_topology_nodes[MAXCPU] (MAXCPU = 256 on amd64, param.h:71-72). The
cursor starts at root+1 (:185) and is bumped once per allocated node at
:140-141:
node->child_node[i] = *last_free_node;
(*last_free_node)++; /* sys/kern/subr_cpu_topology.c:140-141 */
There is no upper-bound check against &cpu_topology_nodes[MAXCPU] anywhere.
The tree needs 1 + chips + chips×cores + N nodes (root + package + core +
thread levels). For a single-socket SMT system, total = 2 + 3×cores. For
N = 256 logical CPUs (128 cores × 2 threads) the tree needs 386 nodes,
exceeding the 256-slot array by 130 cpu_node_t entries (~270 KB of BSS). The
overflow threshold is ~170 logical CPUs (85 cores × 2 threads → 257 nodes).
Reachability: boot-time SYSINIT (SI_BOOT2_CPU_TOPOLOGY, :823-824).
The topology parameters come from CPUID on each CPU — firmware/hypervisor
controlled. A malicious hypervisor presenting ≥170 vCPUs in a single package
triggers it deterministically every boot; bare-metal modern many-core silicon
(AMD EPYC-class) with ≥256 threads likewise.
Impact: large kernel BSS corruption at boot — the node-struct writes at
:125-132,143,152 stomp adjacent BSS with topology pointers. Boot crash or
potentially exploitable corruption. Not runtime-exploitable by a local user.
Recommended fix
Bound the cursor:
--- a/sys/kern/subr_cpu_topology.c
+++ b/sys/kern/subr_cpu_topology.c
@@ for (i = 0; i < node->child_no; i++) {
+ if (*last_free_node >= &cpu_topology_nodes[MAXCPU])
+ panic("cpu_topology_nodes overflow");
node->child_node[i] = *last_free_node;
(*last_free_node)++;
Root cause: cpu_topology_nodes[] is sized for MAXCPU leaves but needs
interior nodes too. Either size the array to 2*MAXCPU + LEVEL_NO + 1 (covers
the worst-case single-socket C + CK ≤ 2N), or fall back to a flat topology
when the projected node count would exceed the array.
Timeline
- 2026-06-30 Discovered during automated file-by-file audit of
sys/kern/subr_cpu_topology.c. - pending Reported to DragonFlyBSD security contact.