diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c index 5736c16..7d010a3 100644 --- a/sys/dev/sound/pci/ich.c +++ b/sys/dev/sound/pci/ich.c @@ -1028,8 +1028,6 @@ ich_pci_attach(device_t dev) break; } - mixer_init(dev, ac97_getmixerclass(), sc->codec); - /* check and set VRA function */ extcaps = ac97_getextcaps(sc->codec); sc->hasvra = extcaps & AC97_EXTCAP_VRA; @@ -1069,6 +1067,19 @@ ich_pci_attach(device_t dev) if (pcm_register(dev, sc, 1, (sc->hasmic) ? 2 : 1)) goto bad; + /* + * pcm_register() must precede mixer_init(): mixer_init() publishes a + * 0666 /dev/mixerN whose devinfo is the AC97 codec. Were any of the + * earlier failure paths (or pcm_register itself) to unwind after a + * successful mixer_init(), the bad: path below would ac97_destroy() + * the codec and kfree() the softc while /dev/mixerN still dispatches + * ioctls into them (UAF) -- DF-4421, same family as DF-4156/DF-4193/ + * DF-4299/DF-4334/DF-4344. With pcm_register() first, no failure + * path remains after the mixer cdev is created. + */ + if (mixer_init(dev, ac97_getmixerclass(), sc->codec)) + goto bad; + pcm_addchan(dev, PCMDIR_PLAY, &ichchan_class, sc); /* play */ pcm_addchan(dev, PCMDIR_REC, &ichchan_class, sc); /* record */ if (sc->hasmic)