DF-4724 / fix.diff
--- a/sys/dev/sound/pci/aureal.c +++ b/sys/dev/sound/pci/aureal.c @@ -629,12 +629,17 @@ au_pci_attach(device_t dev) if (au_init(dev, au) == -1) { device_printf(dev, "unable to initialize the card\n"); goto bad; } + /* + * NB: once mixer_init() succeeds it has published a world-writable + * /dev/mixerN whose mixer holds `codec` (and through it `au`) as + * devinfo. Every later failure must mixer_uninit(dev) BEFORE au + * is freed, otherwise the cdev dangles into freed memory (DF-4724, + * DF-4156 mixer-UAF family). + */ codec = AC97_CREATE(dev, au, au_ac97); if (codec == NULL) goto bad; if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto bad; if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2, /*boundary*/0, @@ -648,9 +653,15 @@ au_pci_attach(device_t dev) snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld %s", (type[0] == SYS_RES_IOPORT)? "io" : "memory", rman_get_start(reg[0]), rman_get_start(irq),PCM_KLDSTRING(snd_aureal)); - if (pcm_register(dev, au, 1, 1)) goto bad; + if (pcm_register(dev, au, 1, 1)) { + mixer_uninit(dev); /* destroys /dev/mixerN + codec */ + codec = NULL; + goto bad; + } + codec = NULL; /* mixer owns it now */ /* pcm_addchan(dev, PCMDIR_REC, &au_chantemplate, au); */ pcm_addchan(dev, PCMDIR_PLAY, &auchan_class, au); pcm_setstatus(dev, status); |