DF-4551 / als_intr_window.c
/* DF-4551 โ als_intr() NULL/dangling channel-state window proof-of-concept. * * sys/dev/sound/pci/als4000.c orders its lifetime badly: * * als_resource_grab() :783 snd_setup_intr(als_intr) <- handler live * als_init() :704 GCR_MISC |= 0x28000 <- IRQs enabled * ... mixer_init/pcm_register run ... * pcm_addchan :852 sc->pch.channel still NULL until alschan_init * * Any interrupt in that window (shared line โ the IRQ is allocated * RF_SHAREABLE at :777 โ or the card itself asserting during mixer_init's * register writes) takes the (intr & 0x80)/(intr & 0x40) branches at * :648-658 into chn_intr(sc->pch.channel == NULL) -> CHN_LOCKOWNED(c) on a * NULL pcm_channel (channel.c:683-694) -> kernel NULL-deref panic. * * Symmetrically on teardown, pcm_unregister() (:872) destroys the channel * objects while the handler stays registered until als_resource_free() * (:745-748), and the I/O region is released (:742) BEFORE the interrupt is * torn down โ a racing IRQ runs the handler over freed channels and a * released bus_space mapping. * * This program documents the exerciser: it cannot run on the QEMU guest * because there is no ALS4000 PCI device there (guest_hw_evidence.txt), so * snd_setup_intr/als_intr are never invoked. The trigger on real hardware * is simply "have the card share its IRQ line with a busy device and * load/unload snd_als4000" โ no privileges needed beyond a device that * raises interrupts on the shared line while the module attaches/detaches. * * Compile-check only on the guest: * cc -Wall -c als_intr_window.c */ int als_intr_window_poc_placeholder; /* documentation artifact */ |