hammer2_volconf_update() uses iocom->conn_state unlocked across a peer-driven drop (TOCTOU): kdmsg_lnk_conn_reply mutates conn_state without msglk
| Field | Value |
|---|---|
| ID | DF-2709 |
| Status | new |
| Severity | Low |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:N/I:H/A:H |
| CWE | CWE-367 TOCTOU |
| File | sys/kern/kern_dmsg.c |
| Lines | 231-233 (unlocked drop), consumer hammer2_iocom.c:377-385 |
| Area | kern |
| Confidence | likely |
| Discovered | 2026-08-30 |
| Pass | 2 (GLM 5.3 second pass β expands the DF-0906 TOCTOU with the reply-side mutation) |
| Bucket | memcorrupt |
| Reported | pending |
| Known CVE | none |
| CVE match | variant |
Summary
kdmsg_lnk_conn_reply() runs from the receive path without msglk and
does if (iocom->conn_state) kdmsg_state_drop(...); iocom->conn_state
= NULL; β an unlocked read/drop/store of a shared pointer.
hammer2_volconf_update() reads the same pointer from the
REMOTE_ADD/REMOTE_DEL ioctl thread and passes it to kdmsg_msg_alloc()
(first deref at :1770). Racing a peer-terminated CONN can
hold-after-free or hit the :1973 KKASSERT on INVARIANTS; the
in-source XXX acknowledges the race. Root ioctl caller racing a
malicious peer's CONN termination; narrow window.
Recommended fix
Protect conn_state with msglk on both sides: take msglk around the check+msg_alloc in hammer2_volconf_update (or add a kdmsg helper returning a referenced conn_state under msglk), and perform the drop+NULL in kdmsg_lnk_conn_reply under msglk.
References
- DF-0906 (the original TOCTOU note), DF-2666 (adjacent caller fp leak)
Timeline
- 2026-08-30 Discovered during pass-2 audit of kern_dmsg.c (GLM 5.3).
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2709 Β· 1 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | β | 3.4 KB | view raw |
Fix verification
not_testablemsglk interlock + state-hold fix (with _kdmsg_state_hold/drop exported) compile-validated and boot-tested; race window not drivable on this guest.
compile-validated in the fix-all kernel build (make nativekernel, 0 errors)
Confirmed kernel references
Detail
Evidence (decisive lines)
kern_dmsg.c:231-233 unlocked drop vs hammer2_iocom.c:375-379 unguarded read + XXX comment
PoC changes
n/a
Verified recommended fix
--- sys/kern/kern_dmsg.c 2026-06-29 12:51:19.000000000 +0000
Verdict
Code-verified TOCTOU with an in-source acknowledgment; race window not drivable on the stock guest. kdmsg_lnk_conn_reply (sys/kern/kern_dmsg.c:226-234) drops and NULLs iocom->conn_state in the receive path with no msglk, while hammer2_volconf_update (sys/vfs/hammer2/hammer2_iocom.c:375-386) reads the same pointer unguarded (the literal comment at :375 is XXX interlock against connection state termination) and passes it to kdmsg_msg_alloc whose first dereference is state->iocom (kern_dmsg.c:1770). Driving it requires a clustered hammer2 volume: a REMOTE_ADD/DEL ioctl loop on the root mounts iocom racing a peer-terminated CONN - the DIOCRECLUSTER wire rig used for DF-2711 attaches to the DISK iocom, not the mount iocom, and the stock guest has no cluster config. Line-accurate confirmation only; the fix (msglk + state ref in volconf_update, msglk around the reply-side drop) is compile-validated. Note :376 also kprintfs the conn_state pointer to the world-readable msgbuf (same family as DF-2736).
No comments yet.