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

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.msgbuf to 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 because db_numargs returns 0 (line 166) and db_sym_numargs always returns FALSE (db_kld.c:110), so the argument-printing loop in db_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").

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

Timeline

  • 2026-07-14 Discovered during automated audit.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1077 Β· 1 files
FileTypeDescriptionSize
fix.diff suggested-fix Panic backtrace writes raw kernel addresses to world-readable msgbuf 281 B view raw

Fix verification

not_testable
baseline reproduced→ patch + rebuild →patched clean

fix.diff authored but did not apply cleanly; needs context rework

fix.diff authored but did not apply cleanly; needs context rework
↓ fix.diffcombined build rc=0

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