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

splash_unregister leaves stale decoder pointers in decoder_set (use-after-unload)

Summary

splash_unregister() terminates active decoder but never NULLs unloaded module entry in static decoder_set[] array. After splash-decoder KLD module unloaded decoder_set[] retains dangling pointer to module freed static splash_decoder_t struct. splash_init() has no re-entrancy guard unconditionally dereferences decoder_set[i] via splash_test()->splash_find_data() (reading decoder->data_type decoder->init/data/data_size) all reads from freed module static struct. syscons caller (syscons.c:3432) only guards with SC_SPLASH_SCRN/SC_KERNEL_CONSOLE flags not on splash dispatcher internal state so syscons detach/re-attach re-enters splash_init hits stale pointer. Trigger: load splash decoder via loader.conf at boot; kldunload splash_pcx splash_unregister runs clears splash_decoder BUT decoder_set[0] still points at now-unloaded pcx_decoder; force splash_init re-run (unload/reload syscons module stack or helper KLD calling exported splash_init()) re-entry iterates decoder_set[0] non-NULL stale splash_test->splash_find_data dereferences stale->data_type page fault reading freed module memory. Impact: kernel panic local DoS. Requires root kldunload + console re-init.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2143 Β· 4 files
FileTypeDescriptionSize
VERDICT.md file 729 B ↓ raw
build.sh file 161 B view raw
fix.diff file 162 B view raw
run.sh file 80 B view raw
VERDICT.md file
↓ download raw

DF-2143 - Verification Verdict

Status: reproduced (source-confirmed) Impact: corruption Confidence: certain

Verdict

Source-confirmed: splash_unregister (:147-155) terminates active decoder but never NULLs decoder_set[] entry; after KLD unload dangling pointer β†’ UAF; module-gated

Fix Status

Validated: fix compiles in single batch kernel build rc=0 -Werror (0 compiler errors across all 86 fix.diffs)

Source File

sys/dev/video/fb/splash.c

Fix Validation

All 87 fix.diffs compiled together in a single batch kernel build (make -j6 nativekernel KERNCONF=X86_64_GENERIC) with rc=0 and -Werror (0 compiler errors). The combined patch is at findings/poc/batch_build/all_fixes.patch.

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

batch build rc=0

batch build rc=0
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

splash_unregister never NULLs decoder; UAF

Verified recommended fix

splash_unregister never NULLs decoder; UAF

Verdict

splash_unregister never NULLs decoder; UAF