The Spectrum Dispatch News

technology

Researchers Exploit 37‑Year‑Old OpenBSD Kernel Bug to Gain Root

A signed 16‑bit shared‑memory counter introduced in the original BSD code can overflow after repeated forks, leading to a use‑after‑free and out‑of‑bounds write that lets attackers

Researchers Exploit 37‑Year‑Old OpenBSD Kernel Bug to Gain Root

Researchers from Calif disclosed a local privilege‑escalation exploit that abuses a 37‑year‑old integer‑overflow bug in the OpenBSD kernel. The vulnerability originates from a signed 16‑bit short used to track the number of attachments to System V shared memory segments, a definition that dates back to the original BSD sources. Repeatedly forking a process while attaching and detaching shared memory can push the counter past its maximum value of 32,767, causing it to wrap to a negative number. According to the report, this integer overflow can trigger a use‑after‑free condition that, when combined with a separate out‑of‑bounds write in the kernel, enables local attackers to gain root privileges even when KARL, SMAP and SMEP mitigations are enabled.

Researchers Exploit 37‑Year‑Old OpenBSD Kernel Bug to Gain Root

The exploit follows a multi‑step sequence. First, the attacker maps 127 SysV shared memory segments, unmaps them with munmap(), and forks 259 processes to drive the attach counter to –32,643. Heap grooming is performed using metrics from sysctl(KERN_MALLOCSTATS) to monitor kernel allocations and detect when new pages are allocated. The race condition is won by invoking IPC_RMID in one process while a helper process attaches a new, size‑confused shared memory segment. To set up the out‑of‑bounds write, the attacker aligns IP socket allocations and sets IP_MULTICAST_TTL to 2, which creates a persistent 16‑byte struct ip_moptions whose final word contains two 16‑bit counters: imo_num_memberships and imo_max_memberships. Triggering the conditional –1 out‑of‑bounds write overwrites both counters. Closing the socket then traverses the group members, causing atomic decrements that flip a page‑table entry from user‑accessible to supervisor‑accessible, thereby bypassing SMAP/SMEP. By overwriting a predictable kernel pointer with a controlled value, the attacker gains kernel code execution. Finally, shared‑memory accounting is cleaned up and the overwritten pointer is restored, yielding a root shell.

The report notes that the underlying primitive is a “write‑what‑where” operation: the write stems from a TAILQ_REMOVE, the data written is a user‑space memory mapping made supervisor‑mode accessible, and the target location is a predictable kernel pointer. Because OpenBSD’s boot‑time and best‑fit allocators are deterministic, early allocations such as the lo0 and enc0 ioctl handlers reside at fixed addresses across boots, making them reliable targets for overwriting.

To mitigate similar issues, Calif proposes several defensive measures. Implementing safe‑unlinking in the kernel’s doubly linked list operations would abort or panic when list invariants are violated, preventing corrupt unlink writes. Randomizing the self‑referential page‑table entry (PTE) map address at boot time—using a random byte to select a PML4 slot—would move the predictable decrement locations, rendering the atomic‑decrement attack ineffective. Additionally, randomizing the base address of the kernel allocator at boot and/or the allocation order at run time would break deterministic pointer placement. Compiler‑based mitigations such as array bounds sanitizer (a subset of Undefined Behaviour sanitizer) can catch out‑of‑bounds accesses, while the emerging Alloc Tokens feature can isolate pointer‑containing allocations from non‑pointer ones, making use‑after‑free exploits harder to chain. The authors note that OpenBSD already employs many hardening techniques, but layering these additional controls raises the cost for attackers and helps defend against future discoveries.

Key facts

Sources

← All posts