DragonFlyBSD Kernel Audit
← dashboard
DF-0025

Missing privilege check on sys_kldstat()/sys_kldsym() leaks kernel symbol and module addresses

Field Value
ID DF-0025
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
CWE CWE-862 Missing Authorization
File sys/kern/kern_linker.c
Lines 940 (sys_kldstat), 1024 (sys_kldsym)
Area kern
Confidence likely
Discovered 2026-06-29
Reported pending

Summary

Only sys_kldload (:794) and sys_kldunload (:841) are gated by caps_priv_check_self(SYSCAP_NOKLD). The query syscalls sys_kldstat (:940) and sys_kldsym (:1024) have no privilege gate. sys_kldsym resolves an arbitrary kernel symbol name to its absolute runtime address (symval.value = ef->address + es->st_value, per link_elf.c/link_elf_obj.c), and sys_kldstat returns each loaded module's base address (lf->address) and size. Any local user can iterate fileids via kldnext and dump a complete symbol→address map of the running kernel plus every loaded KLD — defeating KASLR and handing an attacker developing another kernel exploit a ready symbol map.

Root cause

sys/kern/kern_linker.c:

/* sys_kldload :794 / sys_kldunload :841 -- gated */
if ((error = caps_priv_check_self(SYSCAP_NOKLD)) != 0)
    return error;

/* sys_kldstat :940 / sys_kldsym :1024 -- NO gate */

The grep confirms caps_priv_check_self(SYSCAP_NOKLD) appears only at :794 and :841. Symbol resolution in sys/kern/link_elf.c / sys/kern/link_elf_obj.c returns the absolute runtime address unmasked.

Threat model & preconditions

  • Attacker position: any local unprivileged user.
  • Privileges gained or impact: information disclosure — a complete kernel symbol→address map and the base address + size of every loaded module. A KASLR-defeat / symbol-map primitive that materially lowers the bar for exploiting any other kernel memory-safety bug (e.g. DF-0013). Standalone impact is info-leak only.
  • Required config or capabilities: none; default kernel.
  • Reachability: kldsym(2) / kldstat(2) / kldnext(2) as any user.

Proof of concept

PoC source: findings/poc/DF-0025/kld_leak.c

Build & run (unprivileged)

cc -o kld_leak findings/poc/DF-0025/kld_leak.c
./kld_leak

Expected output

[+] kldsym("proc0") = 0xffffffff81xxxxxx  (unprivileged KASLR/symbol leak)
[+] kldstat: loaded modules (base + size):
    kernel    id=1 base=0xffffffff80200000 size=1234567 refs=1
    ...

Impact

Unprivileged disclosure of the kernel's symbol map and module layout — a KASLR-defeat / exploit-enabling primitive. Rated Low (info-leak only; matches FreeBSD's historic ungated convention, but Linux restricts the analogous /proc/kallsyms to root readers for exactly this reason).

Gate sys_kldstat and sys_kldsym behind SYSCAP_NOKLD, matching load/unload:

--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -940
+   if ((error = caps_priv_check_self(SYSCAP_NOKLD)) != 0)
+       return error;
@@ -1024
+   error = caps_priv_check_self(SYSCAP_NOKLD);
+   if (error)
+       return error;

(Confirm against any legitimate unprivileged consumer — e.g. the dynamic linker resolving symbols for a loaded module's userland glue — before restricting; if such a consumer exists, gate the address fields rather than the whole call, so name/existence remain queryable but addresses are redacted for unprivileged callers.)

References

Timeline

  • 2026-06-29 Discovered during automated file-by-file audit of sys/kern/kern_linker.c.
  • pending Reported to DragonFlyBSD security contact.