DMSG wire msgid discloses the kernel heap address of every kernel-initiated transaction state to the cluster peer (msgid = (uint64_t)(uintptr_t)state)
| Field | Value |
|---|---|
| ID | DF-2708 |
| Status | new |
| Severity | Medium |
| CVSS 3.1 | CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N |
| CWE | CWE-200 Exposure of Sensitive Information |
| File | sys/kern/kern_dmsg.c |
| Lines | 1804 (assignment), 1833 (transmission) |
| Area | kern |
| Confidence | certain |
| Discovered | 2026-08-30 |
| Pass | 2 (GLM 5.3 second pass) |
| Bucket | kernleak |
| Reported | pending |
| Known CVE | none |
| CVE match | novel |
Summary
kdmsg_msg_alloc() derives kernel-initiated msgids from the state object pointer and transmits them in every message header. The auto-initiated LNK_CONN of every cluster reconnect β plus each kernel-initiated LNK_SPAN and VOLCONF β hands the peer the kmalloc'd kdmsg_state_t address from the HAMMER2-msg zone. Verified: peer received msgid=0xfffff8011741eae0 on the wire; dmesg simultaneously printed "volconf update 0xfffff8011741eae0" for the same conn_state object.
Threat model & preconditions
Any cluster peer (or MITM, given no rx CRC/auth) learns live kernel heap addresses with no log access; defeats heap-layout randomization and primes pointer forgery for same-subsystem corruption (e.g. DF-2707's stale-rbnode writes). Different sink than DF-2614 (console msgbuf); not reachable by unprivileged local users.
Proof of concept
VERIFIED on the stock INVARIANTS guest (findings/poc/DF-2708/): mount hammer2 with cluster_fd = socketpair end, read the auto-LNK_CONN frame, print head.msgid; cross-check against the REMOTE_ADD-driven "volconf update %p" console line β identical values.
Recommended fix
Allocate kernel-initiated msgids from a per-iocom 64-bit counter under
msglk (plus a uint64_t msgid_seq in struct kdmsg_iocom):
state->msgid = ++iocom->msgid_seq;
Timeline
- 2026-08-30 Discovered during pass-2 audit of kern_dmsg.c (GLM 5.3); wire leak verified same run.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-2708 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.6 KB | β raw | |
| run.log | β | 151 B | view raw | |
| dmesg.txt | β | 7.8 KB | view raw | |
| manifest.json | β | 687 B | view raw | |
| verdict.json | β | 2.4 KB | view raw |
DF-2708 β DMSG wire msgid discloses the kernel heap address of every
kernel-initiated transaction state to the cluster peer
What was verified (stock INVARIANTS kernel #0, guest dfbsd)
kdmsg_msg_alloc() assigns each kernel-initiated transaction state
state->msgid = (uint64_t)(uintptr_t)state (sys/kern/kern_dmsg.c:1804)
and transmits it as msg->any.head.msgid (:1833) β so every
kernel-initiated transaction hands the peer the kmalloc address of its
kdmsg_state_t (allocated :1796 from the HAMMER2-msg zone, ~160-byte
class). The kernel's auto-initiated LNK_CONN on every cluster reconnect
(kdmsg_iocom_autoinitiate(), kern_dmsg.c:184-191) is the always-present
instance; kernel-initiated LNK_SPANs (hammer2_update_spans) leak one
pointer each.
PoC: df2707_trigger leak (source shared with the DF-2707 pack) mounts
a hammer2 volume with cluster_fd = our socketpair end, reads the
auto-LNK_CONN, and cross-checks against the console print
volconf update %p of the very same object (hmp->iocom.conn_state,
hammer2_iocom.c:376, populated via the REMOTE_ADD ioctl).
Result (exact values, one run):
trigger stdout: AUTO_CONN cmd=80001106 msgid=0xfffff8011741eae0 dmesg: volconf update 0xfffff8011741eae0 <-- identical
Repeat runs (3 mounts across this session) always produced a fresh
0xfffff80xxxxxxxxx direct-map kernel heap pointer.
Impact
Any cluster peer β the userland hammer2 service daemon's remote connection, a malicious/compromised cluster node, or a network MITM (receive-side CRCs are not verified, LNK_AUTH unimplemented) β learns kernel heap addresses without any log access. Defeats heap-layout randomization and primes pointer forgery for exploitation of memory corruption in the same subsystem (e.g. DF-2707's stale-rbnode writes). Not directly reachable by an unprivileged local user (mount/REMOTE_ADD require root; the leak goes to the peer, not to dmesg).
Build & run
scp -F dfbsd-qemu/config findings/poc/DF-2707/df2707_trigger.c \
findings/poc/DF-2707/run_df2707.sh dfbsd:/root/poc/df2707/
dfbsd-qemu/vm.sh run_root 'sh /root/poc/df2707/run_df2707.sh leak'
# compare: AUTO_CONN msgid == dmesg 'volconf update' value
Fix direction
Use an opaque per-iocom 64-bit counter (protected by msglk) for
kernel-initiated msgids instead of the state pointer, matching the
msg_seq allocator already present for salt (kern_dmsg.c:2002-2003).
Peer-initiated states already use peer-chosen msgids, so no protocol
change is needed. (msgid uniqueness within statewr_tree is all the
protocol requires, kern_dmsg.c:1808-1809.)
Fix verification
not_testableConfirmed kernel references
Detail
Exploit chain
cluster peer reads head.msgid of the kernel's auto-LNK_CONN (one per reconnect) or any kernel-initiated LNK_SPAN -> direct kernel heap pointer -> heap-layout disclosure defeating KASLR-style randomization, priming pointer forgery for same-subsystem corruption bugs (e.g. DF-2707 stale-rbnode writes).
Evidence (decisive lines)
['run.log (trigger stdout: AUTO_CONN cmd=80001106 msgid=0xfffff8011741eae0)', 'dmesg.txt (volconf update 0xfffff8011741eae0 - identical value, same object)']
PoC changes
Used the DF-2614 cluster_fd mount harness in a leak mode that prints the wire msgid and cross-checks it against the console %p print of conn_state.
Verified recommended fix
Allocate kernel-initiated msgids from a per-iocom 64-bit counter under msglk instead of the state pointer (peer-initiated states already use peer-chosen msgids; uniqueness in statewr_tree is the only requirement).
Verdict
kdmsg_msg_alloc() sets state->msgid = (uint64_t)(uintptr_t)state (kern_dmsg.c:1804) and transmits it as head.msgid (:1833), disclosing the kmalloc'd kdmsg_state_t heap address of every kernel-initiated transaction to the cluster peer. Verified on the stock INVARIANTS guest: the auto-LNK_CONN observed on the peer socket carried msgid=0xfffff8011741eae0 and dmesg simultaneously printed 'volconf update 0xfffff8011741eae0' for the same object (hmp->iocom.conn_state via the REMOTE_ADD ioctl). Fresh 0xfffff80xxxxxxxxx pointers observed on every mount across 4+ runs.
No comments yet.