DragonFlyBSD Kernel Audit
← dashboard
DF-0083

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.

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.