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