1 From 3ea3091f1bd8586125848c62be295910e9802af0 Mon Sep 17 00:00:00 2001
2 From: Shuah Khan <skhan@linuxfoundation.org>
3 Date: Wed, 29 May 2019 13:46:15 -0600
4 Subject: usbip: usbip_host: fix stub_dev lock context imbalance regression
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 From: Shuah Khan <skhan@linuxfoundation.org>
11 commit 3ea3091f1bd8586125848c62be295910e9802af0 upstream.
13 Fix the following sparse context imbalance regression introduced in
14 a patch that fixed sleeping function called from invalid context bug.
16 kbuild test robot reported on:
18 tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-linus
20 Regressions in current branch:
22 drivers/usb/usbip/stub_dev.c:399:9: sparse: sparse: context imbalance in 'stub_probe' - different lock contexts for basic block
23 drivers/usb/usbip/stub_dev.c:418:13: sparse: sparse: context imbalance in 'stub_disconnect' - different lock contexts for basic block
24 drivers/usb/usbip/stub_dev.c:464:1-10: second lock on line 476
26 Error ids grouped by kconfigs:
30 │ └── drivers-usb-usbip-stub_dev.c:second-lock-on-line
31 ├── x86_64-allmodconfig
32 │ ├── drivers-usb-usbip-stub_dev.c:sparse:sparse:context-imbalance-in-stub_disconnect-different-lock-contexts-for-basic-block
33 │ └── drivers-usb-usbip-stub_dev.c:sparse:sparse:context-imbalance-in-stub_probe-different-lock-contexts-for-basic-block
34 └── x86_64-allyesconfig
35 └── drivers-usb-usbip-stub_dev.c:second-lock-on-line
37 This is a real problem in an error leg where spin_lock() is called on an
40 Fix the imbalance in stub_probe() and stub_disconnect().
42 Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
43 Fixes: 0c9e8b3cad65 ("usbip: usbip_host: fix BUG: sleeping function called from invalid context")
44 Cc: stable <stable@vger.kernel.org>
45 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
48 drivers/usb/usbip/stub_dev.c | 36 +++++++++++++++++++++++-------------
49 1 file changed, 23 insertions(+), 13 deletions(-)
51 --- a/drivers/usb/usbip/stub_dev.c
52 +++ b/drivers/usb/usbip/stub_dev.c
53 @@ -326,14 +326,17 @@ static int stub_probe(struct usb_device
54 * See driver_probe_device() in driver/base/dd.c
61 + goto call_put_busid_priv;
64 if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
65 dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n",
69 + goto call_put_busid_priv;
72 if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
73 @@ -342,7 +345,7 @@ static int stub_probe(struct usb_device
78 + goto call_put_busid_priv;
82 @@ -361,6 +364,9 @@ static int stub_probe(struct usb_device
83 save_status = busid_priv->status;
84 busid_priv->status = STUB_BUSID_ALLOC;
86 + /* release the busid_lock */
87 + put_busid_priv(busid_priv);
90 * Claim this hub port.
91 * It doesn't matter what value we pass as owner
92 @@ -373,9 +379,6 @@ static int stub_probe(struct usb_device
96 - /* release the busid_lock */
97 - put_busid_priv(busid_priv);
99 rc = stub_add_files(&udev->dev);
101 dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid);
102 @@ -395,11 +398,17 @@ err_port:
103 spin_lock(&busid_priv->busid_lock);
104 busid_priv->sdev = NULL;
105 busid_priv->status = save_status;
107 - stub_device_free(sdev);
108 + spin_unlock(&busid_priv->busid_lock);
109 + /* lock is released - go to free */
112 +call_put_busid_priv:
113 /* release the busid_lock */
114 put_busid_priv(busid_priv);
117 + stub_device_free(sdev);
122 @@ -435,7 +444,9 @@ static void stub_disconnect(struct usb_d
123 /* get stub_device */
125 dev_err(&udev->dev, "could not get device");
126 - goto call_put_busid_priv;
127 + /* release busid_lock */
128 + put_busid_priv(busid_priv);
132 dev_set_drvdata(&udev->dev, NULL);
133 @@ -465,7 +476,7 @@ static void stub_disconnect(struct usb_d
134 if (!busid_priv->shutdown_busid)
135 busid_priv->shutdown_busid = 1;
136 /* release busid_lock */
137 - put_busid_priv(busid_priv);
138 + spin_unlock(&busid_priv->busid_lock);
140 /* shutdown the current connection */
141 shutdown_busid(busid_priv);
142 @@ -480,10 +491,9 @@ static void stub_disconnect(struct usb_d
144 if (busid_priv->status == STUB_BUSID_ALLOC)
145 busid_priv->status = STUB_BUSID_ADDED;
147 -call_put_busid_priv:
148 /* release busid_lock */
149 - put_busid_priv(busid_priv);
150 + spin_unlock(&busid_priv->busid_lock);