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

AIOGCAP ioctl dereferences d->mixer_dev without NULL check, causing kernel panic

Summary

AIOGCAP handler at dsp.c:1311-1313: pdev=d->mixer_dev, then p->inputs=pdev->si_drv1?mix_getdevs(pdev->si_drv1):0. Ternary only guards pdev->si_drv1 not pdev itself. pdev->si_drv1 derefs NULL+offsetof(si_drv1) if mixer_dev==NULL. All other ioctls guard (dsp.c:1124/1852/1865/2760). mixer_dev=NULL: mixer_init failed, or mid-detach after mixer_uninit. /dev/dsp is 0666. Fix: check (pdev!=NULL && pdev->si_drv1!=NULL).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1260 Β· 12 files
FileTypeDescriptionSize
trigger.c trigger-source opens /dev/dsp, issues AIOGCAP; reports unreachability on guest 1.7 KB view raw
fix.diff suggested-fix guard pdev != NULL in AIOGCAP 733 B view raw
build.sh repro-script build trigger 337 B view raw
run.sh repro-script run trigger (sound.ko must be loaded) 317 B view raw
build.log build-log trigger build output 14 B view raw
run.log run-log open(/dev/dsp) fails: no pcm device 161 B view raw
VERDICT.md verdict full source-level trace + fix rationale 3.0 KB ↓ raw
env.txt environment guest uname, PCI (no audio), sound.ko load test 1.7 KB view raw
fix_build.log build-log compile-validation: kernel+module build with fix applied, rc=0, no errors 5.6 MB ↓ download
README.md readme human reproduce doc 707 B ↓ raw
../fix_build_combined.log build-log Combined 41-finding kernel build (rc=0, -Werror clean) 5.6 MB ↓ download
../fix_build_summary.txt build-summary Summary of the combined 41-finding kernel build 826 B view raw
README.md readme human reproduce doc
↓ download raw

DF-1260 PoC β€” AIOGCAP NULL-deref on d->mixer_dev (LATENT on guest; source-confirmed)

Status: source-confirmed real; NOT reproducible on audit guest (no audio HW). Impact: NULL-deref panic (DoS) via ioctl(AIOGCAP) on /dev/dsp when a pcm device has mixer_dev==NULL (mixer_init failed / detach race). Driver: sys/dev/sound/pcm/dsp.c (sound subsystem; loads as module but no HW attaches).

Reproduce

# load sound subsystem (creates /dev/dsp but no pcm device registers without HW):
ssh dfbsd 'kldload sound.ko'
./build.sh && ./run.sh    # reports open(/dev/dsp) failure: no audio hardware

The bug needs real audio HW + a mixer-less pcm device. See VERDICT.md + fix.diff.

VERDICT.md verdict full source-level trace + fix rationale
↓ download raw

DF-1260 β€” AIOGCAP NULL-deref on d->mixer_dev (LATENT on audit guest; source-confirmed)

Verdict

NOT REPRODUCED on the audit guest (LATENT / HW-gated). The bug is confirmed real by source-level trace; it cannot fire on this guest because no audio hardware attaches, so /dev/dsp cannot be opened and the AIOGCAP handler is never reached.

Mechanism (confirmed in source)

  • dsp.c:1311 pdev = d->mixer_dev; (no NULL check)
  • dsp.c:1313 p->inputs = pdev->si_drv1 ? mix_getdevs(pdev->si_drv1) : 0; The ternary guards pdev->si_drv1 but not pdev itself. If d->mixer_dev == NULL (mixer_init failed, or mid-detach after mixer_uninit), the read pdev->si_drv1 dereferences NULL + offsetof(struct cdev, si_drv1) β†’ fatal trap.
  • Every sibling ioctl in the same file guards it: dsp.c:1124, dsp.c:1852, dsp.c:1865, dsp.c:2760 all do if (d->mixer_dev != NULL). Only AIOGCAP (1311-1313) forgets to.
  • /dev/dsp is mode 0666 (crw-rw-rw-), so reaching it from an unprivileged user is trivial once a pcm device with a NULL mixer exists.

Why it does not reproduce here

  • kldload sound.ko succeeds and creates /dev/dsp (0666), BUT
  • pciconf -lv shows no multimedia/audio class device; no snd_* PCI bridge driver attaches, so zero pcm devices are registered (/dev/sndstat is empty).
  • With no registered pcm device, open("/dev/dsp", O_RDWR) returns fd=-1 (EBADF on DragonFly), so the AIOGCAP handler β€” which operates on a snddev_info d obtained from an open pcm cdev β€” is never entered.
  • Reaching the bug needs: real audio HW + a snd_* driver that registers a pcm device whose mixer_init failed (or a detach race leaving mixer_dev==NULL).

This is a valid hard blocker for live reproduction: the path is unreachable at runtime on this guest and no userspace action exercises it without audio HW.

Exploit chain

N/A β€” NULL-deref panic (DoS), HW-gated (latent). No write primitive, no escalation chain. Realistic threat: a local unprivileged user on a machine whose audio driver registered a mixer-less pcm device (or racing a detach) triggers a kernel panic via a single ioctl(AIOGCAP) on /dev/dsp.

PoC changes

trigger.c opens /dev/dsp and attempts ioctl(AIOGCAP); on this guest it reports the open failure (no pcm device). The trigger documents the path; the fix is the deliverable.

Fix (fix.diff)

Guard pdev itself, not only pdev->si_drv1 β€” matching the sibling ioctls:

p->inputs = (pdev != NULL && pdev->si_drv1 != NULL)
            ? mix_getdevs(pdev->si_drv1) : 0;

Applies cleanly (patch -p1 rc=0). Matches the finding proposal.

Fix validation

See fix_build.log / fix_run.log. A sound-enabled kernel (DF1260 config = X86_64_GENERIC + device sound) was built with the fix applied to confirm the patched dsp.c compiles cleanly. The bug itself is not triggerable on the guest (no audio HW), so there is no live before/after; fix_status=not_testable per the latent-bug rule, with compile validation.

Fix verification

not_testable

compile validated

kernel/module build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. dsp AIOGCAP mixer_dev no NULL guard (siblings do) -> NULL+offsetof deref. sound module, no audio HW.