FAILED: patch "[PATCH] mmc: vub300: fix use-after-free on probe failure" failed to apply to 6.12-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x a3b5f242997a3be7404112fd48784881560aea57
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026072046-octane-riverside-49ce@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From a3b5f242997a3be7404112fd48784881560aea57 Mon Sep 17 00:00:00 2001
From: Guangshuo Li <[email protected]>
Date: Fri, 12 Jun 2026 11:27:56 +0800
Subject: [PATCH] mmc: vub300: fix use-after-free on probe failure
The vub300 driver lifetime-manages its controller state using vub300->kref, with vub300_delete() freeing the mmc host when the last reference is dropped. The probe error path after the inactivity timer has been armed still bypasses that lifetime rule, however, and falls through to mmc_free_host() directly if mmc_add_host() fails.
The race window is between arming the inactivity timer and reaching the probe error unwind after mmc_add_host() fails:
probe thread timer/workqueue
------------ ---------------
kref_init(&vub300->kref) ref = 1
kref_get(&vub300->kref) ref = 2, timer ref
add_timer(inactivity_timer) fires after one second
|
| race window
|<---------------------------------------------------->
| mmc_add_host(mmc)
inactivity timer fires vub300_queue_dead_work()
kref_get() ref = 3
queue_work(deadwork)
mmc_add_host() fails
timer_delete_sync()
mmc_free_host(mmc)
frees vub300
deadwork runs
use-after-free
The inactivity timeout is one second, so this would require mmc_add_host() to both fail and take more than one second to do so. This is unlikely to happen in practice, but the error path is still wrong.
timer_delete_sync() only waits for the timer callback itself. It does not flush deadwork that the callback may already have queued. As a result, queued deadwork can still hold a kref while the probe error path directly frees the backing mmc host, including the vub300 storage.
Fix this by using the same lifetime mechanism as disconnect. Clear vub300->interface so that the timer callback and any queued deadwork return early and drop their references, then drop the initial probe reference and return without falling through to err_free_host.
drivers/mmc/host/vub300.c +7 -3
@@ -2336,12 +2336,16 @@ static int vub300_probe(struct usb_interface *interface, interface_to_InterfaceNumber(interface)); retval =mmc_add_host (mmc);if (retval) - goto err_delete_timer; + goto err_stop_io;return 0 ; -err_delete_timer: -timer_delete_sync (&vub300->inactivity_timer); +err_stop_io: + vub300->interface =NULL ; +kref_put (&vub300->kref, vub300_delete); + +return retval; + err_free_host:mmc_free_host (mmc);/*
Sasha Levin
maintainerPATCH 1/3 mmc: vub300: fix use-after-free on disconnect
From: Johan Hovold <[email protected]>
The vub300 driver maintains an explicit reference count for the controller and its driver data and the last reference can in theory be dropped after the driver has been unbound.
This specifically means that the controller allocation must not be device managed as that can lead to use-after-free.
Note that the lifetime is currently also incorrectly tied the parent USB device rather than interface, which can lead to memory leaks if the driver is unbound without its device being physically disconnected (e.g. on probe deferral).
Fix both issues by reverting to non-managed allocation of the controller.
--- drivers/mmc/host/vub300.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/mmc/host/vub300.c +6 -6
@@ -2279,7 +2279,7 @@ static int vub300_probe(struct usb_interface *interface,dev_err (&vub300->udev->dev,"Could not find two sets of bulk-in/out endpoint pairs\n" ); retval = -EINVAL ; - goto error5; + goto err_free_host; } retval = usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
@@ -2288,14 +2288,14 @@ static int vub300_probe(struct usb_interface *interface,0x0000 ,0x0000 , &vub300->hc_info, sizeof(vub300->hc_info), 1000);if (retval <0 ) - goto error5; + goto err_free_host; retval =usb_control_msg (vub300->udev,usb_sndctrlpipe (vub300->udev,0 ),SET_ROM_WAIT_STATES ,USB_DIR_OUT |USB_TYPE_VENDOR |USB_RECIP_DEVICE , firmware_rom_wait_states,0x0000 ,NULL ,0 ,1000 );if (retval <0 ) - goto error5; + goto err_free_host; dev_info(&vub300->udev->dev, "operating_mode = %s %s %d MHz %s %d byte USB packets\n", (mmc->caps & MMC_CAP_SDIO_IRQ) ? "IRQs" : "POLL",
@@ -2310,7 +2310,7 @@ static int vub300_probe(struct usb_interface *interface,0x0000 ,0x0000 , &vub300->system_port_status, sizeof(vub300->system_port_status), 1000);if (retval <0 ) { - goto error5; + goto err_free_host; }else if (sizeof (vub300->system_port_status) == retval) { vub300->card_present = (0x0001 & vub300->system_port_status.port_flags) ?1 :0 ;
@@ -2318,7 +2318,7 @@ static int vub300_probe(struct usb_interface *interface, (0x0010 & vub300->system_port_status.port_flags) ?1 :0 ; }else { retval = -EINVAL ; - goto error5; + goto err_free_host; }usb_set_intfdata (interface, vub300);INIT_DELAYED_WORK (&vub300->pollwork, vub300_pollwork_thread);
@@ -2348,7 +2348,7 @@ static int vub300_probe(struct usb_interface *interface,return 0 ; error6:del_timer_sync (&vub300->inactivity_timer); -error5: +err_free_host:mmc_free_host (mmc);/* * and hence also frees vub300
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 mmc: vub300: rename probe error labels
From: Johan Hovold <[email protected]>
Error labels should be named after what they do.
Rename the probe error labels.
--- drivers/mmc/host/vub300.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
drivers/mmc/host/vub300.c +11 -9
@@ -2114,19 +2114,19 @@ static int vub300_probe(struct usb_interface *interface, command_out_urb =usb_alloc_urb (0 ,GFP_KERNEL );if (!command_out_urb) { retval = -ENOMEM ; - goto error0; + goto err_put_udev; } command_res_urb =usb_alloc_urb (0 ,GFP_KERNEL );if (!command_res_urb) { retval = -ENOMEM ; - goto error1; + goto err_free_out_urb; }/* this also allocates memory for our VUB300 mmc host device */ mmc =mmc_alloc_host (sizeof (struct vub300_mmc_host ), &udev->dev);if (!mmc) { retval = -ENOMEM ;dev_err (&udev->dev,"not enough memory for the mmc_host\n" ); - goto error4; + goto err_free_res_urb; }/* MMC core transfer sizes tunable parameters */ mmc->caps =0 ;
@@ -2343,23 +2343,25 @@ static int vub300_probe(struct usb_interface *interface, interface_to_InterfaceNumber(interface)); retval =mmc_add_host (mmc);if (retval) - goto error6; + goto err_delete_timer;return 0 ; -error6: -del_timer_sync (&vub300->inactivity_timer); + +err_delete_timer: +timer_delete_sync (&vub300->inactivity_timer); err_free_host:mmc_free_host (mmc);/* * and hence also frees vub300 * which is contained at the end of struct mmc */ -error4: +err_free_res_urb:usb_free_urb (command_res_urb); -error1: +err_free_out_urb:usb_free_urb (command_out_urb); -error0: +err_put_udev:usb_put_dev (udev); +return retval; }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 mmc: vub300: fix use-after-free on probe failure
In reply to Sasha LevinFrom: Guangshuo Li <[email protected]>
The vub300 driver lifetime-manages its controller state using vub300->kref, with vub300_delete() freeing the mmc host when the last reference is dropped. The probe error path after the inactivity timer has been armed still bypasses that lifetime rule, however, and falls through to mmc_free_host() directly if mmc_add_host() fails.
The race window is between arming the inactivity timer and reaching the probe error unwind after mmc_add_host() fails:
probe thread timer/workqueue
------------ ---------------
kref_init(&vub300->kref) ref = 1
kref_get(&vub300->kref) ref = 2, timer ref
add_timer(inactivity_timer) fires after one second
|
| race window
|<---------------------------------------------------->
| mmc_add_host(mmc)
inactivity timer fires vub300_queue_dead_work()
kref_get() ref = 3
queue_work(deadwork)
mmc_add_host() fails
timer_delete_sync()
mmc_free_host(mmc)
frees vub300
deadwork runs
use-after-free
The inactivity timeout is one second, so this would require mmc_add_host() to both fail and take more than one second to do so. This is unlikely to happen in practice, but the error path is still wrong.
timer_delete_sync() only waits for the timer callback itself. It does not flush deadwork that the callback may already have queued. As a result, queued deadwork can still hold a kref while the probe error path directly frees the backing mmc host, including the vub300 storage.
Fix this by using the same lifetime mechanism as disconnect. Clear vub300->interface so that the timer callback and any queued deadwork return early and drop their references, then drop the initial probe reference and return without falling through to err_free_host.
--- drivers/mmc/host/vub300.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/mmc/host/vub300.c +7 -3
@@ -2343,12 +2343,16 @@ static int vub300_probe(struct usb_interface *interface, interface_to_InterfaceNumber(interface)); retval =mmc_add_host (mmc);if (retval) - goto err_delete_timer; + goto err_stop_io;return 0 ; -err_delete_timer: -timer_delete_sync (&vub300->inactivity_timer); +err_stop_io: + vub300->interface =NULL ; +kref_put (&vub300->kref, vub300_delete); + +return retval; + err_free_host:mmc_free_host (mmc);/*
Signature · 1 line
2.53.0