John Keeping reported and posted a patch for a potential UAF in rawmidi sequencer destruction: the snd_rawmidi_dev_seq_free() may be called after the associated rawmidi object got already freed. After a deeper look, it turned out that the bug is rather the incorrect private_free call order for a snd_seq_device. The snd_seq_device private_free gets called at the release callback of the sequencer device object, while this was rather expected to be executed at the snd_device call chains that runs at the beginning of the whole card-free procedure. It's been broken since the rewrite of sequencer-device binding (although it hasn't surfaced because the sequencer device release happens usually right along with the card device release).
This patch corrects the private_free call to be done in the right place, at snd_seq_device_dev_free().
Fixes: 7c37ae5c625a ("ALSA: seq: Rewrite sequencer device binding with standard bus") Reported-and-tested-by: John Keeping john@metanate.com Cc: stable@vger.kernel.org Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/core/seq_device.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/sound/core/seq_device.c b/sound/core/seq_device.c index 382275c5b193..7f3fd8eb016f 100644 --- a/sound/core/seq_device.c +++ b/sound/core/seq_device.c @@ -156,6 +156,8 @@ static int snd_seq_device_dev_free(struct snd_device *device) struct snd_seq_device *dev = device->device_data;
cancel_autoload_drivers(); + if (dev->private_free) + dev->private_free(dev); put_device(&dev->dev); return 0; } @@ -183,11 +185,7 @@ static int snd_seq_device_dev_disconnect(struct snd_device *device)
static void snd_seq_dev_release(struct device *dev) { - struct snd_seq_device *sdev = to_seq_dev(dev); - - if (sdev->private_free) - sdev->private_free(sdev); - kfree(sdev); + kfree(to_seq_dev(dev)); }
/*