DF-4334 / verdict.json
{ "finding_id": "DF-4334", "status": "untested", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "via_attach() ignores mixer_init()s return at via8233.c:1335 (which publishes a 0666 /dev/mixerN whose si_drv1->devinfo is the AC97 codec, mixer.c:730-733) and keeps a failure path after it: pcm_register() at via8233.c:1354 returns EINVAL/ENODEV when pcm_veto_load is stuck at its sound.c:50 initial value 1 (cleared only by successful boot-time feeder init, feeder.c:126) or when the pcm unit exceeds PCMMAXUNIT=255 (sound.c:1027). On that failure attach jumps to bad: and ac97_destroy(via->codec) at via8233.c:1372-1373 kobj_delete()s the method table and kfrees the codec (ac97.c:852-858) while /dev/mixerN still dispatches ioctls into it -- use-after-free with indirect-dispatch potential, identical to the DF-4156/DF-4193/DF-4299 family. Untested rather than demonstrated: the trigger needs a real VIA 1106:3059 audio function whose attach reaches mixer_init and then fails at pcm_register; the audit guest has no such function (host QEMU 7.2.22 predates the via-ac97 emulation added in QEMU 8.2 -- see env.txt) and both pcm_register failure preconditions are boot-time anomalies an unprivileged user cannot create.", "exploit_chain": "", "evidence": "findings/poc/DF-4334/VERDICT.md (full source chain); via8233.c:1335 mixer_init ignored vs via8233.c:1354 pcm_register check vs via8233.c:1372 bad: ac97_destroy; mixer.c:730 make_dev 0666 + si_drv1=m(devinfo=codec); ac97.c:852 kobj_delete+kfree; sound.c:1021/1027 failure set; build.log/run.log (guest-side negative-environment probe); env.txt (QEMU 7.2.22 device list, no via-ac97)", "kernel_refs": [ "sys/dev/sound/pci/via8233.c:1335", "sys/dev/sound/pci/via8233.c:1354", "sys/dev/sound/pci/via8233.c:1372", "sys/dev/sound/pcm/mixer.c:730", "sys/dev/sound/pcm/ac97.c:852", "sys/dev/sound/pcm/sound.c:1021", "sys/dev/sound/pcm/sound.c:1027" ], "poc_changes": "authored fresh probe (no seed); probe documents the absent trigger environment rather than the UAF itself", "attempts": 1, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 6, "guest_dirty": 0, "build_cmd": "cc -O -Wall -o /root/via8233_probe /root/via8233_probe.c", "run_cmd": "/root/via8233_probe; pciconf -l | grep 1106:3059; ls /dev/mixer*", "code_hash": "6c97820367be096fcacf8315930d3e71a1a4b692fb05f94e68ceda113617d760", "notes": "Fourth instance of the attach-error-path family (DF-4156 maestro, DF-4193 es137x, DF-4299 emu10kx-pcm); pass-1 missed it. FreeBSD upstream eliminated the class by making pcm_register() void. Also noted: mixer_init()s return is ignored outright (via8233.c:1335), covered by the same fix.", "recommended_fix": "Move pcm_register() before AC97_CREATE/mixer_init() and fail attach on mixer_init() error so no failure path exists after the mixer is published", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff reorders pcm_register() ahead of codec creation/mixer_init and checks mixer_init(), removing every failure path after the mixer is published; git apply --check is clean. Baseline vs patched behaviour is not observable on the audit guest for the same hardware/precondition absence (no 1106:3059 function, pcm_register failure not creatable).", "fix_evidence": "findings/poc/DF-4334/fix.diff; canonical unwind order shown at sound.c:1205 (pcm_unregister does mixer_uninit before codec teardown)" } |