freenode
Kernel & Low-Level

Kernel objpool race can double-hand or drop objects under NMI

A nested push from kretprobe NMI context could publish past an unfinished entry, letting another CPU pop a NULL or stale pointer.

A race in the Linux kernel's per-CPU object pool can hand the same object out twice or lose one entirely when a push is interrupted by NMI context, Shashank Mohan Jain reports.

The pool is used by rethook-based kretprobes (and, before 6.14, by fprobe). Those paths recycle instances with objpool_push after a probed function returns. Because kretprobes may run in NMI, a second push can land on the same CPU slot while the first is still writing its entry. The nested push advances the published index past the unfinished slot. A concurrent pop on another CPU can then take a NULL or stale pointer; the slot index can also move backwards, leaving the owning CPU spinning with interrupts off.

The bug became reachable once kretprobes moved onto objpool. It needs a probe on a function that runs both in ordinary context and inside NMI (for example a perf PMU path on x86). Jain found it with a TLA+ model of the single-slot push and pop sequences under one level of nesting; the model checker confirmed the failure on current code and its absence after the fix.

The repair publishes entries in order with a compare-and-swap on the slot's last index so a nested push cannot leapfrog an unfinished write. A KUnit test uses a pinned hard hrtimer to stand in for NMI nesting and verifies that objects are neither duplicated nor lost. Andrew Morton has taken the series.