Re: [Bugme-new] [Bug 19192] New: Oops after removing unauthorized USB device

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



2010/9/28 Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx>:
>
> (switched to email.  Please respond via emailed reply-to-all, not via the
> bugzilla web interface).
>
> On Mon, 27 Sep 2010 22:45:06 GMT
> bugzilla-daemon@xxxxxxxxxxxxxxxxxxx wrote:
>
>> https://bugzilla.kernel.org/show_bug.cgi?id=19192
>>
>>            Summary: Oops after removing unauthorized USB device
>>            Product: Drivers
>>            Version: 2.5
>>     Kernel Version: 2.6.35.6
>>           Platform: All
>>         OS/Version: Linux
>>               Tree: Mainline
>>             Status: NEW
>>           Severity: normal
>>           Priority: P1
>>          Component: USB
>>         AssignedTo: greg@xxxxxxxxx
>>         ReportedBy: carsten_sommer@xxxxxxxxx
>>         Regression: No
>>
>>
>> If a plugged-in USB device (in this case an USB stick) is set to unauthorized
>> (echo 0 > /sys/bus/usb/devices/DEVICE/authorized) and is removed from the USB
>> port afterwards, the kernel throws an Oops. The system often freezes after a
>> short time, or after another USB device is connected.
>>
>> System is Ubuntu 10.04 with mainline kernel 2.6.35.6
>>
>>
>> The trace:
>>
>> [  261.987545] usb 1-1.5.3: USB disconnect, address 7
>> [  261.987578] BUG: unable to handle kernel NULL pointer dereference at
>> 00000055
>> [  261.987796] IP: [<c0465dce>] unlink1+0x1e/0xe0
>> [  261.987939] *pdpt = 000000002ae9a001 *pde = 0000000000000000
>> [  261.988130] Oops: 0000 [#1] SMP
>> [  261.988318] last sysfs file: /sys/devices/pci0000:00/0000:00:1a.0/class
>> [  261.988400] Modules linked in: parport_pc binfmt_misc ppdev usblp nfsd
>> exportfs nfs lockd nfs_acl auth_rpcgss arc4 iwl3945 iwlagn iwlcore
>> snd_hda_codec_nvhdmi mac80211 snd_hda_codec_conexant sn
>> d_hda_intel snd_pcm_oss snd_hda_codec thinkpad_acpi snd_hwdep snd_mixer_oss
>> snd_pcm snd_seq_dummy snd_seq_oss snd_seq_midi snd_rawmidi snd_seq_midi_event
>> xt_tcpudp snd_seq nf_conntrack_ipv4 nf_defrag_ipv4 xt_state nf_conntrack s
>> nd_timer uvcvideo cfg80211 sunrpc snd_seq_device uinput videodev sdhci_pci
>> tpm_tis iptable_filter qcserial sdhci psmouse sbp2 v4l1_compat snd usb_wwan
>> usbserial soundcore tpm snd_page_alloc ip_tables serio_raw led_class tpm_bios
>>  nvram intel_agp agpgart x_tables video output lp parport usb_storage raid10
>> raid456 async_raid6_recov async_pq raid6_pq async_xor xor async_memcpy async_tx
>> ohci1394 raid1 ieee1394 ahci libahci raid0 e1000e multipath linear
>> [  261.993673]
>> [  261.993749] Pid: 42, comm: khubd Not tainted 2.6.35.6 #1 43494JG/43494JG
>> [  261.993837] EIP: 0060:[<c0465dce>] EFLAGS: 00010082 CPU: 3
>> [  261.993919] EIP is at unlink1+0x1e/0xe0
>> [  261.993995] EAX: 00000025 EBX: eaf10e2c ECX: ffffff94 EDX: eaf10e2c
>> [  261.994079] ESI: eaf10e2c EDI: f75fb000 EBP: f764fe94 ESP: f764fe80
>> [  261.994162]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
>> [  261.994244] Process khubd (pid: 42, ti=f764e000 task=f7651960
>> task.ti=f764e000)
>> [  261.994341] Stack:
>> [  261.994414]  00000000 ffffff94 eaf10e2c eaf10bb0 eaf10ba0 f764feb0 c0465f81
>> 00000001
>> [  261.994897] <0> f75fb000 f35a1800 eaf10ba0 00000001 f764fec4 c04681de
>> f35a1800 00000002
>> [  261.995499] <0> f35a1898 f764fed8 c046824b f35a1800 c4841264 f35a1898
>> f764ff04 c046269e
>> [  261.996170] Call Trace:
>> [  261.996249]  [<c0465f81>] ? usb_hcd_flush_endpoint+0xf1/0x110
>> [  261.996336]  [<c04681de>] ? usb_disable_endpoint+0x4e/0x80
>> [  261.996422]  [<c046824b>] ? usb_disable_device+0x3b/0x100
>> [  261.996507]  [<c046269e>] ? usb_disconnect+0xae/0x140
>> [  261.996592]  [<c046349f>] ? hub_thread+0x3cf/0x1050
>> [  261.996680]  [<c014b7c9>] ? dequeue_task_fair+0x79/0x80
>> [  261.996769]  [<c016cdf0>] ? autoremove_wake_function+0x0/0x50
>> [  261.996855]  [<c04630d0>] ? hub_thread+0x0/0x1050
>> [  261.996936]  [<c016c9c4>] ? kthread+0x74/0x80
>> [  261.997019]  [<c016c950>] ? kthread+0x0/0x80
>> [  261.997099]  [<c0109886>] ? kernel_thread_helper+0x6/0x10
>> [  261.997181] Code: e8 f8 98 cd ff eb 9e 8d b6 00 00 00 00 55 89 e5 83 ec 14
>> 89 5d f4 89 75 f8 89 7d fc 0f 1f 44 00 00 89 4d f0 89 c7 8b 42 28 89 d6 <8b> 58
>> 30 85 db 74 23 8b 9f b4 00 00 00 89 f8 8b 4d f0 ff 53 34
>> [  262.001055] EIP: [<c0465dce>] unlink1+0x1e/0xe0 SS:ESP 0068:f764fe80
>> [  262.001251] CR2: 0000000000000055
>> [  262.001331] ---[ end trace e9feb35d2da8ce3d ]---

The following patch can fix the oops, if no objections from other
guys, I will submit a formal version.

The oops is caused by usb_enable_interface called from
usb_unbind_interface, usb_enable_interface can make
udev->ep_out[epnum] point to usb_host_endpoint instance
which will be freed from usb_destroy_configuration later, so when
the device is removed from usb bus, oops will happen since
usb_disable_device is called again from usb_disconnect to touch
this freed usb_host_endpoint instance.

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index d7a4401..332eafc 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -359,7 +359,7 @@ static int usb_unbind_interface(struct device *dev)
 	/* Terminate all URBs for this interface unless the driver
 	 * supports "soft" unbinding.
 	 */
-	if (!driver->soft_unbind)
+	if (!driver->soft_unbind && udev->authorized)
 		usb_disable_interface(udev, intf, false);

 	driver->disconnect(intf);
@@ -371,18 +371,20 @@ static int usb_unbind_interface(struct device *dev)
 	 * altsetting means creating new endpoint device entries).
 	 * When either of these happens, defer the Set-Interface.
 	 */
-	if (intf->cur_altsetting->desc.bAlternateSetting == 0) {
-		/* Already in altsetting 0 so skip Set-Interface.
-		 * Just re-enable it without affecting the endpoint toggles.
-		 */
-		usb_enable_interface(udev, intf, false);
-	} else if (!error && intf->dev.power.status == DPM_ON) {
-		r = usb_set_interface(udev, intf->altsetting[0].
-				desc.bInterfaceNumber, 0);
-		if (r < 0)
+	if (udev->authorized) {
+		if (intf->cur_altsetting->desc.bAlternateSetting == 0) {
+			/* Already in altsetting 0 so skip Set-Interface.
+			 * Just re-enable it without affecting the endpoint toggles.
+			 */
+			usb_enable_interface(udev, intf, false);
+		} else if (!error && intf->dev.power.status == DPM_ON) {
+			r = usb_set_interface(udev, intf->altsetting[0].
+					desc.bInterfaceNumber, 0);
+			if (r < 0)
+				intf->needs_altsetting0 = 1;
+		} else {
 			intf->needs_altsetting0 = 1;
-	} else {
-		intf->needs_altsetting0 = 1;
+		}
 	}
 	usb_set_intfdata(intf, NULL);



thanks,
-- 
Lei Ming
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux