linux/drivers
Alan Stern a44be3e548 USB: g_mass_storage: Fix deadlock when driver is unbound
commit 1fbbb78f25 upstream.

As a holdover from the old g_file_storage gadget, the g_mass_storage
legacy gadget driver attempts to unregister itself when its main
operating thread terminates (if it hasn't been unregistered already).
This is not strictly necessary; it was never more than an attempt to
have the gadget fail cleanly if something went wrong and the main
thread was killed.

However, now that the UDC core manages gadget drivers independently of
UDC drivers, this scheme doesn't work any more.  A simple test:

	modprobe dummy-hcd
	modprobe g-mass-storage file=...
	rmmod dummy-hcd

ends up in a deadlock with the following backtrace:

 sysrq: SysRq : Show Blocked State
   task                PC stack   pid father
 file-storage    D    0  1130      2 0x00000000
 Call Trace:
  __schedule+0x53e/0x58c
  schedule+0x6e/0x77
  schedule_preempt_disabled+0xd/0xf
  __mutex_lock.isra.1+0x129/0x224
  ? _raw_spin_unlock_irqrestore+0x12/0x14
  __mutex_lock_slowpath+0x12/0x14
  mutex_lock+0x28/0x2b
  usb_gadget_unregister_driver+0x29/0x9b [udc_core]
  usb_composite_unregister+0x10/0x12 [libcomposite]
  msg_cleanup+0x1d/0x20 [g_mass_storage]
  msg_thread_exits+0xd/0xdd7 [g_mass_storage]
  fsg_main_thread+0x1395/0x13d6 [usb_f_mass_storage]
  ? __schedule+0x573/0x58c
  kthread+0xd9/0xdb
  ? do_set_interface+0x25c/0x25c [usb_f_mass_storage]
  ? init_completion+0x1e/0x1e
  ret_from_fork+0x19/0x24
 rmmod           D    0  1155    683 0x00000000
 Call Trace:
  __schedule+0x53e/0x58c
  schedule+0x6e/0x77
  schedule_timeout+0x26/0xbc
  ? __schedule+0x573/0x58c
  do_wait_for_common+0xb3/0x128
  ? usleep_range+0x81/0x81
  ? wake_up_q+0x3f/0x3f
  wait_for_common+0x2e/0x45
  wait_for_completion+0x17/0x19
  fsg_common_put+0x34/0x81 [usb_f_mass_storage]
  fsg_free_inst+0x13/0x1e [usb_f_mass_storage]
  usb_put_function_instance+0x1a/0x25 [libcomposite]
  msg_unbind+0x2a/0x42 [g_mass_storage]
  __composite_unbind+0x4a/0x6f [libcomposite]
  composite_unbind+0x12/0x14 [libcomposite]
  usb_gadget_remove_driver+0x4f/0x77 [udc_core]
  usb_del_gadget_udc+0x52/0xcc [udc_core]
  dummy_udc_remove+0x27/0x2c [dummy_hcd]
  platform_drv_remove+0x1d/0x31
  device_release_driver_internal+0xe9/0x16d
  device_release_driver+0x11/0x13
  bus_remove_device+0xd2/0xe2
  device_del+0x19f/0x221
  ? selinux_capable+0x22/0x27
  platform_device_del+0x21/0x63
  platform_device_unregister+0x10/0x1a
  cleanup+0x20/0x817 [dummy_hcd]
  SyS_delete_module+0x10c/0x197
  ? ____fput+0xd/0xf
  ? task_work_run+0x55/0x62
  ? prepare_exit_to_usermode+0x65/0x75
  do_fast_syscall_32+0x86/0xc3
  entry_SYSENTER_32+0x4e/0x7c

What happens is that removing the dummy-hcd driver causes the UDC core
to unbind the gadget driver, which it does while holding the udc_lock
mutex.  The unbind routine in g_mass_storage tells the main thread to
exit and waits for it to terminate.

But as mentioned above, when the main thread exits it tries to
unregister the mass-storage function driver.  Via the composite
framework this ends up calling usb_gadget_unregister_driver(), which
tries to acquire the udc_lock mutex.  The result is deadlock.

The simplest way to fix the problem is not to be so clever: The main
thread doesn't have to unregister the function driver.  The side
effects won't be so terrible; if the gadget is still attached to a USB
host when the main thread is killed, it will appear to the host as
though the gadget's firmware has crashed -- a reasonably accurate
interpretation, and an all-too-common occurrence for USB mass-storage
devices.

In fact, the code to unregister the driver when the main thread exits
is specific to g-mass-storage; it is not used when f-mass-storage is
included as a function in a larger composite device.  Therefore the
entire mechanism responsible for this (the fsg_operations structure
with its ->thread_exits method, the fsg_common_set_ops() routine, and
the msg_thread_exits() callback routine) can all be eliminated.  Even
the msg_registered bitflag can be removed, because now the driver is
unregistered in only one place rather than in two places.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Acked-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-10-12 11:27:32 +02:00
..
accessibility
acpi ACPI / APEI: Add missing synchronize_rcu() on NOTIFY_SCI removal 2017-08-30 10:19:29 +02:00
amba
android ANDROID: binder: fix proc->tsk check. 2017-08-30 10:19:26 +02:00
ata libata: transport: Remove circular dependency at free time 2017-10-08 10:14:20 +02:00
atm
auxdisplay
base driver core: bus: Fix a potential double free 2017-09-13 14:09:44 -07:00
bcma bcma: use (get|put)_device when probing/removing device driver 2017-03-12 06:37:30 +01:00
block skd: Submit requests to firmware before triggering the doorbell 2017-09-27 11:00:14 +02:00
bluetooth Bluetooth: Add support of 13d3:3494 RTL8723BE device 2017-09-13 14:09:45 -07:00
bus bus: vexpress-config: fix device reference leak 2017-01-19 20:17:22 +01:00
cdrom
char tpm: Replace device number bitmap with IDR 2017-08-06 19:19:43 -07:00
clk clk: Make x86/ conditional on CONFIG_COMMON_CLK 2017-05-14 13:32:55 +02:00
clocksource clocksource/exynos_mct: Clear interrupt when cpu is shut down 2017-01-26 08:23:48 +01:00
connector
cpufreq cpufreq: s3c2416: double free on driver init error path 2017-07-05 14:37:22 +02:00
cpuidle ARM: cpuidle: Fix error return code 2016-10-16 17:36:15 +02:00
crypto crypto: talitos - fix sha224 2017-10-05 09:41:45 +02:00
dca
devfreq
dio
dma dmaengine: ti-dma-crossbar: Add some 'of_node_put()' in error path. 2017-08-06 19:19:45 -07:00
dma-buf
edac EDAC: Increment correct counter in edac_inc_ue_error() 2016-09-07 08:32:41 +02:00
eisa
extcon extcon: axp288: Use vbus-valid instead of -present to determine cable presence 2017-10-08 10:14:16 +02:00
firewire firewire: net: fix fragmented datagram_size off-by-one 2016-11-10 16:36:35 +01:00
firmware drivers: firmware: psci: drop duplicate const from psci_of_match 2017-10-08 10:14:20 +02:00
fmc
fpga
gpio gpio: mpc8xxx: Correct irq handler function 2016-10-28 03:01:25 -04:00
gpu drm/amdkfd: fix improper return value on error 2017-10-08 10:14:17 +02:00
hid HID: ignore Petzl USB headlamp 2017-08-06 19:19:47 -07:00
hsi
hv hv: don't reset hv_context.tsc_page on crash 2017-04-27 09:09:34 +02:00
hwmon hwmon: (gl520sm) Fix overflows and crash seen when writing into limit attributes 2017-10-08 10:14:17 +02:00
hwspinlock
hwtracing intel_th: pci: Add Cannon Lake PCH-LP support 2017-09-13 14:09:44 -07:00
i2c i2c: meson: fix wrong variable usage in meson_i2c_put_data 2017-10-08 10:14:20 +02:00
ide
idle intel_idle: Support for Intel Xeon Phi Processor x200 Product Family 2016-09-15 08:27:46 +02:00
iio iio: adc: axp288: Drop bogus AXP288_ADC_TS_PIN_CTRL register modifications 2017-10-08 10:14:17 +02:00
infiniband IB/qib: fix false-postive maybe-uninitialized warning 2017-10-08 10:14:20 +02:00
input Input: i8042 - add Gigabyte P57 to the keyboard reset table 2017-09-27 11:00:13 +02:00
iommu iommu/io-pgtable-arm: Check for leaf entry before dereferencing it 2017-10-08 10:14:19 +02:00
ipack
irqchip irqchip: mips-gic: SYNC after enabling GIC region 2017-09-07 08:34:08 +02:00
isdn isdn/i4l: fix buffer overflow 2017-08-06 19:19:41 -07:00
leds leds: ktd2692: avoid harmless maybe-uninitialized warning 2017-05-14 13:32:55 +02:00
lguest
lightnvm lightnvm: put bio before return 2016-09-24 10:07:35 +02:00
macintosh
mailbox mailbox: handle empty message in tx_tick 2017-08-06 19:19:41 -07:00
mcb
md md/raid10: submit bio directly to replacement disk 2017-10-08 10:14:20 +02:00
media ttpci: address stringop overflow warning 2017-10-08 10:14:20 +02:00
memory
memstick memstick: rtsx_usb_ms: Manage runtime PM when accessing the device 2016-10-28 03:01:35 -04:00
message
mfd mfd: omap-usb-tll: Fix inverted bit use for USB TLL mode 2017-06-26 07:13:09 +02:00
misc cxl: Fix driver use count 2017-10-05 09:41:47 +02:00
mmc mmc: sdio: fix alignment issue in struct sdio_func 2017-10-08 10:14:19 +02:00
mtd mtd: bcm47xxpart: don't fail because of bit-flips 2017-07-05 14:37:18 +02:00
net usb: plusb: Add support for PL-27A1 2017-10-08 10:14:19 +02:00
nfc nfc: fdp: fix NULL pointer dereference 2017-08-06 19:19:40 -07:00
ntb ntb_transport: fix bug calculating num_qps_mw 2017-08-30 10:19:29 +02:00
nubus
nvdimm libnvdimm, btt: fix btt_rw_page not returning errors 2017-08-06 19:19:42 -07:00
nvme nvme: apply DELAY_BEFORE_CHK_RDY quirk at probe time too 2017-06-29 12:48:53 +02:00
nvmem nvmem: imx-ocotp: Fix wrong register size 2017-08-06 19:19:46 -07:00
of of: device: Export of_device_{get_modalias, uvent_modalias} to modules 2017-07-27 15:06:09 -07:00
oprofile
parisc parisc: pci memory bar assignment fails with 64bit kernels on dino/cujo 2017-08-24 17:02:35 -07:00
parport parisc, parport_gsc: Fixes for printk continuation lines 2017-06-17 06:39:37 +02:00
pci PCI: Fix race condition with driver_override 2017-10-05 09:41:46 +02:00
pcmcia
perf drivers/perf: arm_pmu: Fix leak in error path 2016-10-07 15:23:41 +02:00
phy phy: qcom-usb-hs: Add depends on EXTCON 2017-05-14 13:32:57 +02:00
pinctrl pinctrl: samsung: Remove bogus irq_[un]mask from resource management 2017-08-16 13:40:30 -07:00
platform platform/x86: ideapad-laptop: handle ACPI event 1 2017-07-05 14:37:19 +02:00
pnp
power power: supply: bq24190_charger: Handle fault before status on interrupt 2017-05-14 13:32:54 +02:00
powercap
pps
ps3
ptp
pwm pwm: pca9685: Fix period change with same duty cycle 2017-03-15 09:57:14 +08:00
rapidio
ras
regulator regulator: tps65023: Fix inverted core enable logic. 2017-05-25 14:30:09 +02:00
remoteproc remoteproc: Fix potential race condition in rproc_add 2016-08-20 18:09:20 +02:00
reset
rpmsg
rtc rtc: tegra: Implement clock handling 2017-04-21 09:30:07 +02:00
s390 scsi: zfcp: trace high part of "new" 64 bit SCSI LUN 2017-09-27 11:00:15 +02:00
sbus
scsi scsi: scsi_transport_iscsi: fix the issue that iscsi_if_rx doesn't parse nlmsg properly 2017-10-05 09:41:44 +02:00
sfi
sh
sn
soc soc: qcom/spm: shut up uninitialized variable warning 2016-09-24 10:07:42 +02:00
spi spi: dw: Make debugfs name unique between instances 2017-08-06 19:19:44 -07:00
spmi spmi: Include OF based modalias in device uevent 2017-07-27 15:06:10 -07:00
ssb ssb: Fix error routine when fallback SPROM fails 2017-01-09 08:07:42 +01:00
staging staging/rts5208: fix incorrect shift to extract upper nybble 2017-09-13 14:09:44 -07:00
target iscsi-target: Fix iscsi_np reset hung task during parallel delete 2017-08-16 13:40:28 -07:00
tc
thermal thermal: cpu_cooling: Avoid accessing potentially freed structures 2017-07-27 15:06:02 -07:00
thunderbolt
tty tty: goldfish: Fix a parameter of a call to free_irq 2017-10-08 10:14:17 +02:00
uio uio: fix dmem_region_start computation 2016-10-31 04:13:59 -06:00
usb USB: g_mass_storage: Fix deadlock when driver is unbound 2017-10-12 11:27:32 +02:00
uwb uwb: fix device quirk on big-endian hosts 2017-05-25 14:30:17 +02:00
vfio vfio-pci: Handle error from pci_iomap 2017-08-06 19:19:46 -07:00
vhost vhost/scsi: fix reuse of &vq->iov[out] in response 2016-09-15 08:27:53 +02:00
video video: fbdev: aty: do not leak uninitialized padding in clk to userspace 2017-10-05 09:41:48 +02:00
virt
virtio virtio_balloon: init 1st buffer in stats vq 2017-03-31 09:49:53 +02:00
vlynq
vme vme: Fix wrong pointer utilization in ca91cx42_slave_get 2017-01-19 20:17:21 +01:00
w1 w1: ds2490: USB transfer buffers need to be DMAable 2017-03-12 06:37:29 +01:00
watchdog watchdog: bcm281xx: Fix use of uninitialized spinlock. 2017-07-05 14:37:21 +02:00
xen fix xen_swiotlb_dma_mmap prototype 2017-10-05 09:41:48 +02:00
zorro
Kconfig
Makefile usb: Make sure usb/phy/of gets built-in 2017-05-20 14:26:59 +02:00