Skip to content

Commit 4e1538b

Browse files
committed
Merge tag 'mmc-v7.0-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC fixes from Ulf Hansson: - vub300: Fix use-after-free and NULL-deref on disconnect * tag 'mmc-v7.0-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: mmc: vub300: fix use-after-free on disconnect mmc: vub300: fix NULL-deref on disconnect
2 parents d58305b + 8f4d20a commit 4e1538b

1 file changed

Lines changed: 12 additions & 7 deletions

File tree

drivers/mmc/host/vub300.c

Lines changed: 12 additions & 7 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
@@ -2365,8 +2370,8 @@ static void vub300_disconnect(struct usb_interface *interface)
23652370
usb_set_intfdata(interface, NULL);
23662371
/* prevent more I/O from starting */
23672372
vub300->interface = NULL;
2368-
kref_put(&vub300->kref, vub300_delete);
23692373
mmc_remove_host(mmc);
2374+
kref_put(&vub300->kref, vub300_delete);
23702375
pr_info("USB vub300 remote SDIO host controller[%d]"
23712376
" now disconnected", ifnum);
23722377
return;

0 commit comments

Comments
 (0)