]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.1/usbip-usbip_host-fix-stub_dev-lock-context-imbalance-regression.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / queue-5.1 / usbip-usbip_host-fix-stub_dev-lock-context-imbalance-regression.patch
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
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 From: Shuah Khan <skhan@linuxfoundation.org>
10
11 commit 3ea3091f1bd8586125848c62be295910e9802af0 upstream.
12
13 Fix the following sparse context imbalance regression introduced in
14 a patch that fixed sleeping function called from invalid context bug.
15
16 kbuild test robot reported on:
17
18 tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-linus
19
20 Regressions in current branch:
21
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
25
26 Error ids grouped by kconfigs:
27
28 recent_errors
29 ├── i386-allmodconfig
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
36
37 This is a real problem in an error leg where spin_lock() is called on an
38 already held lock.
39
40 Fix the imbalance in stub_probe() and stub_disconnect().
41
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>
46
47 ---
48 drivers/usb/usbip/stub_dev.c | 36 +++++++++++++++++++++++-------------
49 1 file changed, 23 insertions(+), 13 deletions(-)
50
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
55 */
56 rc = -ENODEV;
57 - goto sdev_free;
58 + if (!busid_priv)
59 + goto sdev_free;
60 +
61 + goto call_put_busid_priv;
62 }
63
64 if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
65 dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n",
66 udev_busid);
67 rc = -ENODEV;
68 - goto sdev_free;
69 + goto call_put_busid_priv;
70 }
71
72 if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
73 @@ -342,7 +345,7 @@ static int stub_probe(struct usb_device
74 udev_busid);
75
76 rc = -ENODEV;
77 - goto sdev_free;
78 + goto call_put_busid_priv;
79 }
80
81
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;
85
86 + /* release the busid_lock */
87 + put_busid_priv(busid_priv);
88 +
89 /*
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
93 goto err_port;
94 }
95
96 - /* release the busid_lock */
97 - put_busid_priv(busid_priv);
98 -
99 rc = stub_add_files(&udev->dev);
100 if (rc) {
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;
106 -sdev_free:
107 - stub_device_free(sdev);
108 + spin_unlock(&busid_priv->busid_lock);
109 + /* lock is released - go to free */
110 + goto sdev_free;
111 +
112 +call_put_busid_priv:
113 /* release the busid_lock */
114 put_busid_priv(busid_priv);
115
116 +sdev_free:
117 + stub_device_free(sdev);
118 +
119 return rc;
120 }
121
122 @@ -435,7 +444,9 @@ static void stub_disconnect(struct usb_d
123 /* get stub_device */
124 if (!sdev) {
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);
129 + return;
130 }
131
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);
139
140 /* shutdown the current connection */
141 shutdown_busid(busid_priv);
142 @@ -480,10 +491,9 @@ static void stub_disconnect(struct usb_d
143
144 if (busid_priv->status == STUB_BUSID_ALLOC)
145 busid_priv->status = STUB_BUSID_ADDED;
146 -
147 -call_put_busid_priv:
148 /* release busid_lock */
149 - put_busid_priv(busid_priv);
150 + spin_unlock(&busid_priv->busid_lock);
151 + return;
152 }
153
154 #ifdef CONFIG_PM