Panic backtrace writes raw kernel addresses to world-readable msgbuf
| Field | Value |
|---|---|
| ID | DF-1077 |
| Status | new |
| Severity | Info |
| CVSS 3.1 | CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N |
| CWE | CWE-200 Exposure of Sensitive Information to an Unauthorized Actor |
| File | sys/platform/pc64/x86_64/db_trace.c |
| Lines | 211 (%p), 280-301 (trap/syscall/intr frame addresses), 451 (print_backtrace caller) |
| Area | platform/pc64/x86_64 (DDB backtrace) |
| Confidence | certain |
| Discovered | 2026-07-14 |
| Reported | pending |
| Known CVE | none |
| CVE match | dfly_specific |
Summary
db_print_stack_entry and db_nextframe print raw kernel addresses via %p (line 211) and
%016lx (lines 280-301). When invoked from the panic path (print_backtrace at line 451,
called from kern_shutdown.c:881 before Debugger() entry), db_active is 0, so
db_putchar routes every character through kprintf to the kernel message buffer
(db_output.c:108-116). security.unprivileged_read_msgbuf defaults to 1
(subr_prf.c:126), so any unprivileged local user can read these kernel text and stack
addresses via sysctl kern.msgbuf or dmesg(8) after any kernel panic.
Root cause
db_print_stack_entry unconditionally prints the return address:
db_printf(" %p ", (void *) callpc) at db_trace.c:211.
db_nextframe unconditionally prints rip / rsp / rbp for trap, syscall, and interrupt
frames via db_printf("--- trap %016lx, rip = %016lx, rsp = %016lx, rbp = %016lx ---\n", ...)
at db_trace.c:280-282, and similarly for syscall (lines 289-291) and interrupt (lines
299-301).
During panic, print_backtrace (db_trace.c:450-457) calls db_stack_trace_cmd with
db_active still 0 (Debugger('panic') is called afterward at kern_shutdown.c:882-883).
With db_active == 0, db_putchar (db_output.c:108) calls kprintf("%c", c) which writes
to the message buffer. The msgbuf is readable by unprivileged users by default because
security.unprivileged_read_msgbuf = 1 (subr_prf.c:126) and sysctl_kern_msgbuf only
restricts access when that tunable is 0 (subr_prf.c:1134).
Note: when DDB is interactively active (db_active == 1), db_putchar uses cnputc only
(db_output.c:131) and does NOT write to msgbuf, so interactive trace does not leak β
only the panic-backtrace path does.
Threat model & preconditions
- Attacker position: Any unprivileged local user who can observe the system after a kernel panic (or trigger one via a separate kernel bug).
- Privileges gained or impact: Reads
sysctl kern.msgbufto obtain kernel instruction-pointer values (callpc,rip) and stack-pointer values (rsp,rbp). Practical impact is LOW on current DragonFlyBSD x86-64: there is no KASLR (grep finds no randomization of kernel mapping), so kernel text / data addresses are at fixed known locations and the leaked values do not defeat ASLR. Additionally, no function-argument values are leaked becausedb_numargsreturns 0 (line 166) anddb_sym_numargsalways returnsFALSE(db_kld.c:110), so the argument-printing loop indb_print_stack_entry(lines 201-208) never executes.
The leak is a hardening / defense-in-depth concern: it would become a real KASLR-bypass
if KASLR is ever adopted, and stack-pointer values could aid stack-targeting exploitation
in conjunction with a separate write primitive. Other BSDs have addressed this class via
kernel %p hashing (FreeBSD) or default-restricted dmesg.
- Required config or capabilities: Default kernel. A kernel panic must occur (via any
separate kernel bug, or via root sysctl debug.enter=1 then exit DDB).
- Reachability: After any kernel panic, an unprivileged user runs
sysctl kern.msgbuf and greps for hex addresses.
Proof of concept
#!/bin/sh
# Run as unprivileged user; works whenever a panic backtrace is in msgbuf
sysctl -n kern.msgbuf | grep -E '0x[0-9a-f]{8,16}|ffffffff[0-9a-f]{8}|fffffe[0-9a-f]{6}'
Build & run
No build needed.
# Trigger a panic (requires a separate kernel bug, or root-driven debug.enter), # then after reboot / on a still-running system: sysctl -n kern.msgbuf | grep -E '^(at |--- )'
Expected output
Example observable output:
mi_switch() at cpu_idle 0xffffffff80623456 --- trap 0000000000000003, rip = ffffffff8058abcd, rsp = fffffe00abcdef00, rbp = fffffe00abcdef80 ---
The unprivileged user obtains raw kernel .text addresses and kernel-stack addresses from
msgbuf without any privilege.
Impact
Info leak of raw kernel text and stack addresses via kern.msgbuf after a panic. No KASLR
to bypass on current DFly, so the leak is mostly defense-in-depth; would become a real
concern if KASLR is ever adopted. Info severity per the AGENT.md rubric ("hardening
opportunity, no demonstrated impact").
Recommended fix
The principled fix is system-wide, not in this file: change the default of
security.unprivileged_read_msgbuf from 1 to 0 in sys/kern/subr_prf.c:126 so only
root/wheel can read the message buffer. One-line change:
--- a/sys/kern/subr_prf.c
+++ b/sys/kern/subr_prf.c
@@ -123,7 +123,7 @@ static int msgbufmapped;
int msgbuftrigger;
-static int unprivileged_read_msgbuf = 1;
+static int unprivileged_read_msgbuf = 0;
TUNABLE_INT("security.unprivileged_read_msgbuf", &unprivileged_read_msgbuf);
A complementary defense-in-depth measure (matching FreeBSD) is to add kernel-side %p
pointer obfuscation in kvcprintf so that raw %p output is hashed unless explicitly
requested, which would protect all kernel printf callers, not just this one.
Modifying db_trace.c itself to suppress addresses is impractical because raw addresses
are the entire purpose of a debugger backtrace; the routing / policy layer is the correct
fix point.
References
sys/platform/pc64/x86_64/db_trace.c:211βdb_printf(" %p ", callpc)sys/platform/pc64/x86_64/db_trace.c:280-301β trap/syscall/intr frame address printssys/platform/pc64/x86_64/db_trace.c:451βprint_backtracecaller (panic path)sys/ddb/db_output.c:108-116βdb_putcharroutes to kprintf whendb_active == 0sys/kern/subr_prf.c:126βunprivileged_read_msgbuf = 1(default)sys/kern/subr_prf.c:1134βsysctl_kern_msgbufgatesys/kern/kern_shutdown.c:881-883β panic callsprint_backtracebeforeDebugger- CWE-200 Exposure of Sensitive Information to an Unauthorized Actor
Timeline
- 2026-07-14 Discovered during automated audit.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1077 Β· 1 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | Panic backtrace writes raw kernel addresses to world-readable msgbuf | 281 B | view raw |
Fix verification
not_testablefix.diff authored but did not apply cleanly; needs context rework
fix.diff authored but did not apply cleanly; needs context rework
Confirmed kernel references
β
Detail
Exploit chain
none (Info severity)
Evidence (decisive lines)
Source-confirmed at sys/platform/pc64/x86_64/db_trace.c:211: panic backtrace writes raw kernel addresses to world-readable msgbuf
Verified recommended fix
Source-confirmed at sys/platform/pc64/x86_64/db_trace.c:211: panic backtrace writes raw kernel addresses to world-readable msgbuf
Verdict
Source-confirmed at sys/platform/pc64/x86_64/db_trace.c:211: panic backtrace writes raw kernel addresses to world-readable msgbuf
No comments yet.