lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Wed, 09 Nov 2011 13:33:55 -0800
From:	Greg KH <gregkh@...e.de>
To:	linux-kernel@...r.kernel.org, stable@...r.kernel.org
Cc:	torvalds@...ux-foundation.org, akpm@...ux-foundation.org,
	alan@...rguk.ukuu.org.uk, Clemens Ladisch <clemens@...isch.de>,
	Takashi Iwai <tiwai@...e.de>
Subject: [188/264] ALSA: ua101: fix crash when unplugging

3.1-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Clemens Ladisch <clemens@...isch.de>

commit 862a6244eb9f9f5123fe819454fcfcae0ee1f2f9 upstream.

If the device is unplugged while running, it is possible for a PCM
device to be closed after the disconnect callback has returned.  This
means that kill_stream_urb() and disable_iso_interface() would try to
access already-invalid or freed USB data structures.

The function free_usb_related_resources() was intended to prevent this,
but forgot to clear the affected variables.

Reported-and-tested-by: Olivier Courtay <olivier@...rtay.org>
Signed-off-by: Clemens Ladisch <clemens@...isch.de>
Signed-off-by: Takashi Iwai <tiwai@...e.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@...e.de>

---
 sound/usb/misc/ua101.c |   28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -459,7 +459,8 @@ static void kill_stream_urbs(struct ua10
 	unsigned int i;
 
 	for (i = 0; i < stream->queue_length; ++i)
-		usb_kill_urb(&stream->urbs[i]->urb);
+		if (stream->urbs[i])
+			usb_kill_urb(&stream->urbs[i]->urb);
 }
 
 static int enable_iso_interface(struct ua101 *ua, unsigned int intf_index)
@@ -484,6 +485,9 @@ static void disable_iso_interface(struct
 {
 	struct usb_host_interface *alts;
 
+	if (!ua->intf[intf_index])
+		return;
+
 	alts = ua->intf[intf_index]->cur_altsetting;
 	if (alts->desc.bAlternateSetting != 0) {
 		int err = usb_set_interface(ua->dev,
@@ -1144,27 +1148,37 @@ static void free_stream_urbs(struct ua10
 {
 	unsigned int i;
 
-	for (i = 0; i < stream->queue_length; ++i)
+	for (i = 0; i < stream->queue_length; ++i) {
 		kfree(stream->urbs[i]);
+		stream->urbs[i] = NULL;
+	}
 }
 
 static void free_usb_related_resources(struct ua101 *ua,
 				       struct usb_interface *interface)
 {
 	unsigned int i;
+	struct usb_interface *intf;
 
+	mutex_lock(&ua->mutex);
 	free_stream_urbs(&ua->capture);
 	free_stream_urbs(&ua->playback);
+	mutex_unlock(&ua->mutex);
 	free_stream_buffers(ua, &ua->capture);
 	free_stream_buffers(ua, &ua->playback);
 
-	for (i = 0; i < ARRAY_SIZE(ua->intf); ++i)
-		if (ua->intf[i]) {
-			usb_set_intfdata(ua->intf[i], NULL);
-			if (ua->intf[i] != interface)
+	for (i = 0; i < ARRAY_SIZE(ua->intf); ++i) {
+		mutex_lock(&ua->mutex);
+		intf = ua->intf[i];
+		ua->intf[i] = NULL;
+		mutex_unlock(&ua->mutex);
+		if (intf) {
+			usb_set_intfdata(intf, NULL);
+			if (intf != interface)
 				usb_driver_release_interface(&ua101_driver,
-							     ua->intf[i]);
+							     intf);
 		}
+	}
 }
 
 static void ua101_card_free(struct snd_card *card)


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ