Skip to content

Commit 450273e

Browse files
shuahkhgregkh
authored andcommitted
usbip: usbip_host: fix BUG: sleeping function called from invalid context
commit 0c9e8b3 upstream. stub_probe() and stub_disconnect() call functions which could call sleeping function in invalid context whil holding busid_lock. Fix the problem by refining the lock holds to short critical sections to change the busid_priv fields. This fix restructures the code to limit the lock holds in stub_probe() and stub_disconnect(). stub_probe(): [15217.927028] BUG: sleeping function called from invalid context at mm/slab.h:418 [15217.927038] in_atomic(): 1, irqs_disabled(): 0, pid: 29087, name: usbip [15217.927044] 5 locks held by usbip/29087: [15217.927047] #0: 0000000091647f28 (sb_writers#6){....}, at: vfs_write+0x191/0x1c0 [15217.927062] #1: 000000008f9ba75b (&of->mutex){....}, at: kernfs_fop_write+0xf7/0x1b0 [15217.927072] #2: 00000000872e5b4b (&dev->mutex){....}, at: __device_driver_lock+0x3b/0x50 [15217.927082] #3: 00000000e74ececc (&dev->mutex){....}, at: __device_driver_lock+0x46/0x50 [15217.927090] #4: 00000000b20abbe0 (&(&busid_table[i].busid_lock)->rlock){....}, at: get_busid_priv+0x48/0x60 [usbip_host] [15217.927103] CPU: 3 PID: 29087 Comm: usbip Tainted: G W 5.1.0-rc6+ #40 [15217.927106] Hardware name: Dell Inc. OptiPlex 790/0HY9JP, BIOS A18 09/24/2013 [15217.927109] Call Trace: [15217.927118] dump_stack+0x63/0x85 [15217.927127] ___might_sleep+0xff/0x120 [15217.927133] __might_sleep+0x4a/0x80 [15217.927143] kmem_cache_alloc_trace+0x1aa/0x210 [15217.927156] stub_probe+0xe8/0x440 [usbip_host] [15217.927171] usb_probe_device+0x34/0x70 stub_disconnect(): [15279.182478] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:908 [15279.182487] in_atomic(): 1, irqs_disabled(): 0, pid: 29114, name: usbip [15279.182492] 5 locks held by usbip/29114: [15279.182494] #0: 0000000091647f28 (sb_writers#6){....}, at: vfs_write+0x191/0x1c0 [15279.182506] #1: 00000000702cf0f3 (&of->mutex){....}, at: kernfs_fop_write+0xf7/0x1b0 [15279.182514] #2: 00000000872e5b4b (&dev->mutex){....}, at: __device_driver_lock+0x3b/0x50 [15279.182522] #3: 00000000e74ececc (&dev->mutex){....}, at: __device_driver_lock+0x46/0x50 [15279.182529] #4: 00000000b20abbe0 (&(&busid_table[i].busid_lock)->rlock){....}, at: get_busid_priv+0x48/0x60 [usbip_host] [15279.182541] CPU: 0 PID: 29114 Comm: usbip Tainted: G W 5.1.0-rc6+ #40 [15279.182543] Hardware name: Dell Inc. OptiPlex 790/0HY9JP, BIOS A18 09/24/2013 [15279.182546] Call Trace: [15279.182554] dump_stack+0x63/0x85 [15279.182561] ___might_sleep+0xff/0x120 [15279.182566] __might_sleep+0x4a/0x80 [15279.182574] __mutex_lock+0x55/0x950 [15279.182582] ? get_busid_priv+0x48/0x60 [usbip_host] [15279.182587] ? reacquire_held_locks+0xec/0x1a0 [15279.182591] ? get_busid_priv+0x48/0x60 [usbip_host] [15279.182597] ? find_held_lock+0x94/0xa0 [15279.182609] mutex_lock_nested+0x1b/0x20 [15279.182614] ? mutex_lock_nested+0x1b/0x20 [15279.182618] kernfs_remove_by_name_ns+0x2a/0x90 [15279.182625] sysfs_remove_file_ns+0x15/0x20 [15279.182629] device_remove_file+0x19/0x20 [15279.182634] stub_disconnect+0x6d/0x180 [usbip_host] [15279.182643] usb_unbind_device+0x27/0x60 Signed-off-by: Shuah Khan <skhan@linuxfoundation.org> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 3899f1a commit 450273e

File tree

1 file changed

+43
-22
lines changed

1 file changed

+43
-22
lines changed

drivers/usb/usbip/stub_dev.c

+43-22
Original file line numberDiff line numberDiff line change
@@ -315,9 +315,17 @@ static int stub_probe(struct usb_device *udev)
315315
const char *udev_busid = dev_name(&udev->dev);
316316
struct bus_id_priv *busid_priv;
317317
int rc = 0;
318+
char save_status;
318319

319320
dev_dbg(&udev->dev, "Enter probe\n");
320321

322+
/* Not sure if this is our device. Allocate here to avoid
323+
* calling alloc while holding busid_table lock.
324+
*/
325+
sdev = stub_device_alloc(udev);
326+
if (!sdev)
327+
return -ENOMEM;
328+
321329
/* check we should claim or not by busid_table */
322330
busid_priv = get_busid_priv(udev_busid);
323331
if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
@@ -332,14 +340,14 @@ static int stub_probe(struct usb_device *udev)
332340
* See driver_probe_device() in driver/base/dd.c
333341
*/
334342
rc = -ENODEV;
335-
goto call_put_busid_priv;
343+
goto sdev_free;
336344
}
337345

338346
if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
339347
dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n",
340348
udev_busid);
341349
rc = -ENODEV;
342-
goto call_put_busid_priv;
350+
goto sdev_free;
343351
}
344352

345353
if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
@@ -348,15 +356,9 @@ static int stub_probe(struct usb_device *udev)
348356
udev_busid);
349357

350358
rc = -ENODEV;
351-
goto call_put_busid_priv;
359+
goto sdev_free;
352360
}
353361

354-
/* ok, this is my device */
355-
sdev = stub_device_alloc(udev);
356-
if (!sdev) {
357-
rc = -ENOMEM;
358-
goto call_put_busid_priv;
359-
}
360362

361363
dev_info(&udev->dev,
362364
"usbip-host: register new device (bus %u dev %u)\n",
@@ -366,9 +368,13 @@ static int stub_probe(struct usb_device *udev)
366368

367369
/* set private data to usb_device */
368370
dev_set_drvdata(&udev->dev, sdev);
371+
369372
busid_priv->sdev = sdev;
370373
busid_priv->udev = udev;
371374

375+
save_status = busid_priv->status;
376+
busid_priv->status = STUB_BUSID_ALLOC;
377+
372378
/*
373379
* Claim this hub port.
374380
* It doesn't matter what value we pass as owner
@@ -381,15 +387,16 @@ static int stub_probe(struct usb_device *udev)
381387
goto err_port;
382388
}
383389

390+
/* release the busid_lock */
391+
put_busid_priv(busid_priv);
392+
384393
rc = stub_add_files(&udev->dev);
385394
if (rc) {
386395
dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid);
387396
goto err_files;
388397
}
389-
busid_priv->status = STUB_BUSID_ALLOC;
390398

391-
rc = 0;
392-
goto call_put_busid_priv;
399+
return 0;
393400

394401
err_files:
395402
usb_hub_release_port(udev->parent, udev->portnum,
@@ -398,23 +405,24 @@ static int stub_probe(struct usb_device *udev)
398405
dev_set_drvdata(&udev->dev, NULL);
399406
usb_put_dev(udev);
400407

408+
/* we already have busid_priv, just lock busid_lock */
409+
spin_lock(&busid_priv->busid_lock);
401410
busid_priv->sdev = NULL;
411+
busid_priv->status = save_status;
412+
sdev_free:
402413
stub_device_free(sdev);
403-
404-
call_put_busid_priv:
414+
/* release the busid_lock */
405415
put_busid_priv(busid_priv);
416+
406417
return rc;
407418
}
408419

409420
static void shutdown_busid(struct bus_id_priv *busid_priv)
410421
{
411-
if (busid_priv->sdev && !busid_priv->shutdown_busid) {
412-
busid_priv->shutdown_busid = 1;
413-
usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
422+
usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
414423

415-
/* wait for the stop of the event handler */
416-
usbip_stop_eh(&busid_priv->sdev->ud);
417-
}
424+
/* wait for the stop of the event handler */
425+
usbip_stop_eh(&busid_priv->sdev->ud);
418426
}
419427

420428
/*
@@ -446,6 +454,9 @@ static void stub_disconnect(struct usb_device *udev)
446454

447455
dev_set_drvdata(&udev->dev, NULL);
448456

457+
/* release busid_lock before call to remove device files */
458+
put_busid_priv(busid_priv);
459+
449460
/*
450461
* NOTE: rx/tx threads are invoked for each usb_device.
451462
*/
@@ -456,18 +467,27 @@ static void stub_disconnect(struct usb_device *udev)
456467
(struct usb_dev_state *) udev);
457468
if (rc) {
458469
dev_dbg(&udev->dev, "unable to release port\n");
459-
goto call_put_busid_priv;
470+
return;
460471
}
461472

462473
/* If usb reset is called from event handler */
463474
if (usbip_in_eh(current))
464-
goto call_put_busid_priv;
475+
return;
476+
477+
/* we already have busid_priv, just lock busid_lock */
478+
spin_lock(&busid_priv->busid_lock);
479+
if (!busid_priv->shutdown_busid)
480+
busid_priv->shutdown_busid = 1;
481+
/* release busid_lock */
482+
put_busid_priv(busid_priv);
465483

466484
/* shutdown the current connection */
467485
shutdown_busid(busid_priv);
468486

469487
usb_put_dev(sdev->udev);
470488

489+
/* we already have busid_priv, just lock busid_lock */
490+
spin_lock(&busid_priv->busid_lock);
471491
/* free sdev */
472492
busid_priv->sdev = NULL;
473493
stub_device_free(sdev);
@@ -476,6 +496,7 @@ static void stub_disconnect(struct usb_device *udev)
476496
busid_priv->status = STUB_BUSID_ADDED;
477497

478498
call_put_busid_priv:
499+
/* release busid_lock */
479500
put_busid_priv(busid_priv);
480501
}
481502

0 commit comments

Comments
 (0)