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

kobj_class_free() reclaims the compiled ops table with no grace period while the lock-free dispatch hot path reads it (force multiplier turning any consumer refcount slip into a freed function-pointer table call)

Field Value
ID DF-2961
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
CWE CWE-362 / CWE-416
File sys/kern/subr_kobj.c
Lines 179-208 (dispatch :184-188; kfree :206; publish :260)
Area kern/kobj
Confidence certain
Discovered 2026-09-02
Pass 2 (GLM 5.3 second pass)
Bucket memcorrupt
Reported pending
Known CVE none
CVE match novel

Summary

Every KOBJOPLOOKUP dispatch executes kobj_lookup_method_cache() completely unsynchronized: it reads OPS->cls, cep[desc->id & 255], ce->desc and finally indirect-calls ce->func, and the slow path even WRITES the cache slot. Meanwhile kobj_class_uninstantiate() drops the last reference and kobj_class_free() immediately kfree()s the 2056-byte ops table holding only kobj_token β€” a lock the dispatch path never takes. kobj_init() likewise publishes obj->ops = cls->ops with no release/acquire discipline relative to a concurrent free. kobj therefore provides zero read-side lifetime protection: any consumer that drops the class reference even transiently while another CPU is mid-dispatch (exactly the unprivileged sysctl-reader-vs-device-teardown race already proven as DF-2679 against subr_bus) turns a would-be benign stale read into a UAF walk of freed slab memory culminating in an indirect call through reclaimed data β€” RIP control if the attacker grooms the freed 2056-byte block (/dev/dsp open/close cycles legitimately compile/free channel-class ops at attacker-influenced timing). No in-tree caller misbalances refs by itself β€” newbus, libiconv, and PCM sound are balanced β€” which is why this is filed Low/defense-in-depth: the kobj layer is the multiplier, the trigger is a consumer lifetime bug. No standalone PoC exists or should exist at the kobj layer (manufacturing the primitive requires a buggy demonstration driver; verification deferred to the consumer-side DF-2679 which owns the reachable trigger). Fix: grace period or never-free static classes (row sketch).

Timeline

  • 2026-09-02 Discovered during pass-2 audit of subr_kobj.c (GLM 5.3).

Discussion (0)

No comments yet.