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

Local NULL-deref panic when sbcreatecontrol fails in SO_PASSCRED path

Summary

In SO_PASSCRED SCM_CREDS auto-create path inside uipc_send SOCK_DGRAM return value of sbcreatecontrol never checked. sbcreatecontrol uses M_NOWAIT returns NULL under mbuf-zone pressure. NULL passed straight to unp_internalize which dereferences via mtod(NULL) faulting kernel near address 16 (m_data offset) panicking. Any unprivileged local user with mbuf-zone pressure ability. [VERIFIED pass2: reproduced - mbuf-pin KLD 154526 held plus nobody trigger k 2 Fatal trap 12 VA 0x10 mtod NULL cmsg read exactly as predicted; ENOBUFS fix A/B full sweep survives]

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2559 Β· 5 files
FileTypeDescriptionSize
rig.c β€” 2.1 KB view raw
trigger.c β€” 1.3 KB view raw
build.sh β€” 98 B view raw
run.sh β€” 140 B view raw
panic.txt β€” 14.3 KB view raw

Fix verification

not_testable
↓ fix.diffper-fix-DF-2559

Confirmed kernel references

Detail

Evidence (decisive lines)

panic.txt: Fatal trap 12 VA=0x10, current process = trigger; dmesg pinned 154468 mbufs; now releasing 2 + objcache exhausted warning

PoC changes

mbuf-pinning KLD + unpriv socketpair trigger; k-sweep 64..1

Verified recommended fix

NULL-check sbcreatecontrol return, error=ENOBUFS (in combined fix kernel)

Verdict

uipc_send SOCK_DGRAM SO_PASSCRED auto-creation (uipc_usrreq.c:693-698) never checks sbcreatecontrol() (M_NOWAIT). Rig: KLD pinned 154468 mbufs and released k of them; the unprivileged trigger (uid nobody, SOCK_DGRAM socketpair with receiver SO_PASSCRED, 1-byte send) at k=2 produced Fatal trap 12: page fault, fault virtual address 0x10, supervisor READ, current process = trigger -- exactly the mtod(NULL)->cmsg_len deref at address 16 predicted by the finding. k>=3 runs survived (data mbuf + control mbuf both fit). Mbuf-zone exhaustion is achievable by unprivileged users in principle (the pin here was root-assisted); the panic path itself runs in the nobody process.