diff options
author | Hui Peng <benquike@gmail.com> | 2018-12-03 16:09:34 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-12-13 09:20:27 +0100 |
commit | 73000a4cec933fd331224df79df731ea929bb85c (patch) | |
tree | 722b7b87ef4281f3bead154a8f998b786ec2a058 /sound/usb/card.c | |
parent | fe26b8d06e965239795bee0a71c9073bed931716 (diff) |
ALSA: usb-audio: Fix UAF decrement if card has no live interfaces in card.c
commit 5f8cf712582617d523120df67d392059eaf2fc4b upstream.
If a USB sound card reports 0 interfaces, an error condition is triggered
and the function usb_audio_probe errors out. In the error path, there was a
use-after-free vulnerability where the memory object of the card was first
freed, followed by a decrement of the number of active chips. Moving the
decrement above the atomic_dec fixes the UAF.
[ The original problem was introduced in 3.1 kernel, while it was
developed in a different form. The Fixes tag below indicates the
original commit but it doesn't mean that the patch is applicable
cleanly. -- tiwai ]
Fixes: 362e4e49abe5 ("ALSA: usb-audio - clear chip->probing on error exit")
Reported-by: Hui Peng <benquike@gmail.com>
Reported-by: Mathias Payer <mathias.payer@nebelwelt.net>
Signed-off-by: Hui Peng <benquike@gmail.com>
Signed-off-by: Mathias Payer <mathias.payer@nebelwelt.net>
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound/usb/card.c')
-rw-r--r-- | sound/usb/card.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/sound/usb/card.c b/sound/usb/card.c index 8906199a83e6..549b9b061694 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -644,9 +644,12 @@ static int usb_audio_probe(struct usb_interface *intf, __error: if (chip) { + /* chip->active is inside the chip->card object, + * decrement before memory is possibly returned. + */ + atomic_dec(&chip->active); if (!chip->num_interfaces) snd_card_free(chip->card); - atomic_dec(&chip->active); } mutex_unlock(®ister_mutex); return err; |