linux/drivers/usb
Al Viro 2005aabe94 functionfs: use spinlock for FFS_DEACTIVATED/FFS_CLOSING transitions
When all files are closed, functionfs needs ffs_data_reset() to be
done before any further opens are allowed.

During that time we have ffs->state set to FFS_CLOSING; that makes
->open() fail with -EBUSY.  Once ffs_data_reset() is done, it
switches state (to FFS_READ_DESCRIPTORS) indicating that opening
that thing is allowed again.  There's a couple of additional twists:
	* mounting with -o no_disconnect delays ffs_data_reset()
from doing that at the final ->release() to the first subsequent
open().  That's indicated by ffs->state set to FFS_DEACTIVATED;
if open() sees that, it immediately switches to FFS_CLOSING and
proceeds with doing ffs_data_reset() before returning to userland.
	* a couple of usb callbacks need to force the delayed
transition; unfortunately, they are done in locking environment
that does not allow blocking and ffs_data_reset() can block.
As the result, if these callbacks see FFS_DEACTIVATED, they change
state to FFS_CLOSING and use schedule_work() to get ffs_data_reset()
executed asynchronously.

Unfortunately, the locking is rather insufficient.  A fix attempted
in e5bf5ee266 ("functionfs: fix the open/removal races") had closed
a bunch of UAF, but it didn't do anything to the callbacks, lacked
barriers in transition from FFS_CLOSING to FFS_READ_DESCRIPTORS
_and_ it had been too heavy-handed in open()/open() serialization -
I've used ffs->mutex for that, and it's being held over actual IO on
ep0, complete with copy_from_user(), etc.

Even more unfortunately, the userland side is apparently racy enough
to have the resulting timing changes (no failures, just a delayed
return of open(2)) disrupt the things quite badly.  Userland bugs
or not, it's a clear regression that needs to be dealt with.

Solution is to use a spinlock for serializing these state checks and
transitions - unlike ffs->mutex it can be taken in these callbacks
and it doesn't disrupt the timings in open().

We could introduce a new spinlock, but it's easier to use the one
that is already there (ffs->eps_lock) instead - the locking
environment is safe for it in all affected places.

Since now it is held over all places that alter or check the
open count (ffs->opened), there's no need to keep that atomic_t -
int would serve just fine and it's simpler that way.

Fixes: e5bf5ee266 ("functionfs: fix the open/removal races")
Fixes: 18d6b32fca ("usb: gadget: f_fs: add "no_disconnect" mode") # v4.0
Tested-by: Samuel Wu <wusamuel@google.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
2026-02-05 13:53:12 -05:00
..
atm usb: atm: cxacru: Merge cxacru_upload_firmware() into cxacru_heavy_init() 2025-07-24 11:33:31 +02:00
c67x00 usb: Switch back to struct platform_driver::remove() 2024-10-04 15:13:03 +02:00
cdns3 USB/Thunderbolt changes for 6.19-rc1 2025-12-06 18:42:12 -08:00
chipidea USB/Thunderbolt changes for 6.19-rc1 2025-12-06 18:42:12 -08:00
class uapi: cdc.h: cleanly provide for more interfaces and countries 2025-11-21 15:12:12 +01:00
common usb: common: usb-conn-gpio: use a unique name for usb connector device 2025-04-11 16:08:34 +02:00
core usb: core: add USB_QUIRK_NO_BOS for devices that hang on BOS descriptor 2026-01-07 17:07:00 +01:00
dwc2 usb: dwc2: fix hang during suspend if set as peripheral 2025-11-21 15:10:38 +01:00
dwc3 usb: dwc3: apple: Ignore USB role switches to the active role 2026-01-14 16:02:54 +01:00
early usb: early: xhci-dbc: Fix early_ioremap leak 2025-07-07 11:04:46 +02:00
fotg210 usb: fotg210-hcd: Switch to use hrtimer_setup() 2025-02-18 11:19:02 +01:00
gadget functionfs: use spinlock for FFS_DEACTIVATED/FFS_CLOSING transitions 2026-02-05 13:53:12 -05:00
host xhci: sideband: don't dereference freed ring when removing sideband endpoint 2026-01-16 12:19:37 +01:00
image scsi: Rename .slave_alloc() and .slave_destroy() 2024-12-04 15:34:28 -05:00
isp1760 treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
misc usb: Remove redundant pm_runtime_mark_last_busy() calls 2025-11-21 15:11:53 +01:00
mon usb: mon: Increase BUFF_MAX to 64 MiB to support multi-MB URBs 2025-09-17 12:40:05 +02:00
mtu3 usb: Remove redundant pm_runtime_mark_last_busy() calls 2025-11-21 15:11:53 +01:00
musb usb: Remove redundant pm_runtime_mark_last_busy() calls 2025-11-21 15:11:53 +01:00
phy usb: phy: isp1301: fix non-OF device reference imbalance 2025-12-23 15:48:46 +01:00
renesas_usbhs usb: renesas_usbhs: Fix a resource leak in usbhs_pipe_malloc() 2025-12-17 14:51:54 +01:00
roles usb: roles: set switch registered flag early on 2025-02-14 09:26:25 +01:00
serial USB: serial: f81232: fix incomplete serial port generation 2026-01-13 15:59:07 +01:00
storage usb: usb-storage: Maintain minimal modifications to the bcdDevice range. 2025-12-23 15:41:31 +01:00
typec tcpm: allow looking for role_sw device in the main node 2026-01-07 16:28:05 +01:00
usbip usbip: Use min to simplify stub_send_ret_submit 2025-10-22 10:58:31 +02:00
Kconfig
Makefile USB: xen-hcd: Traverse host/ when CONFIG_USB_XEN_HCD is selected 2024-06-04 15:33:38 +02:00
usb-skeleton.c