Skip to content

Commit 8f4d20a

Browse files
jhovoldstorulf
authored andcommitted
mmc: vub300: fix use-after-free on disconnect
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. Fixes: dcfdd69 ("mmc: vub300: Use devm_mmc_alloc_host() helper") Cc: stable@vger.kernel.org # 6.17+ Cc: Binbin Zhou <zhoubinbin@loongson.cn> Signed-off-by: Johan Hovold <johan@kernel.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
1 parent dff34ef commit 8f4d20a

1 file changed

Lines changed: 11 additions & 6 deletions

File tree

drivers/mmc/host/vub300.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -369,11 +369,14 @@ struct vub300_mmc_host {
369369
static void vub300_delete(struct kref *kref)
370370
{ /* kref callback - softirq */
371371
struct vub300_mmc_host *vub300 = kref_to_vub300_mmc_host(kref);
372+
struct mmc_host *mmc = vub300->mmc;
373+
372374
usb_free_urb(vub300->command_out_urb);
373375
vub300->command_out_urb = NULL;
374376
usb_free_urb(vub300->command_res_urb);
375377
vub300->command_res_urb = NULL;
376378
usb_put_dev(vub300->udev);
379+
mmc_free_host(mmc);
377380
/*
378381
* and hence also frees vub300
379382
* which is contained at the end of struct mmc
@@ -2112,7 +2115,7 @@ static int vub300_probe(struct usb_interface *interface,
21122115
goto error1;
21132116
}
21142117
/* this also allocates memory for our VUB300 mmc host device */
2115-
mmc = devm_mmc_alloc_host(&udev->dev, sizeof(*vub300));
2118+
mmc = mmc_alloc_host(sizeof(*vub300), &udev->dev);
21162119
if (!mmc) {
21172120
retval = -ENOMEM;
21182121
dev_err(&udev->dev, "not enough memory for the mmc_host\n");
@@ -2269,7 +2272,7 @@ static int vub300_probe(struct usb_interface *interface,
22692272
dev_err(&vub300->udev->dev,
22702273
"Could not find two sets of bulk-in/out endpoint pairs\n");
22712274
retval = -EINVAL;
2272-
goto error4;
2275+
goto err_free_host;
22732276
}
22742277
retval =
22752278
usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
@@ -2278,14 +2281,14 @@ static int vub300_probe(struct usb_interface *interface,
22782281
0x0000, 0x0000, &vub300->hc_info,
22792282
sizeof(vub300->hc_info), 1000);
22802283
if (retval < 0)
2281-
goto error4;
2284+
goto err_free_host;
22822285
retval =
22832286
usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
22842287
SET_ROM_WAIT_STATES,
22852288
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
22862289
firmware_rom_wait_states, 0x0000, NULL, 0, 1000);
22872290
if (retval < 0)
2288-
goto error4;
2291+
goto err_free_host;
22892292
dev_info(&vub300->udev->dev,
22902293
"operating_mode = %s %s %d MHz %s %d byte USB packets\n",
22912294
(mmc->caps & MMC_CAP_SDIO_IRQ) ? "IRQs" : "POLL",
@@ -2300,15 +2303,15 @@ static int vub300_probe(struct usb_interface *interface,
23002303
0x0000, 0x0000, &vub300->system_port_status,
23012304
sizeof(vub300->system_port_status), 1000);
23022305
if (retval < 0) {
2303-
goto error4;
2306+
goto err_free_host;
23042307
} else if (sizeof(vub300->system_port_status) == retval) {
23052308
vub300->card_present =
23062309
(0x0001 & vub300->system_port_status.port_flags) ? 1 : 0;
23072310
vub300->read_only =
23082311
(0x0010 & vub300->system_port_status.port_flags) ? 1 : 0;
23092312
} else {
23102313
retval = -EINVAL;
2311-
goto error4;
2314+
goto err_free_host;
23122315
}
23132316
usb_set_intfdata(interface, vub300);
23142317
INIT_DELAYED_WORK(&vub300->pollwork, vub300_pollwork_thread);
@@ -2338,6 +2341,8 @@ static int vub300_probe(struct usb_interface *interface,
23382341
return 0;
23392342
error6:
23402343
timer_delete_sync(&vub300->inactivity_timer);
2344+
err_free_host:
2345+
mmc_free_host(mmc);
23412346
/*
23422347
* and hence also frees vub300
23432348
* which is contained at the end of struct mmc

0 commit comments

Comments
 (0)