]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-4.19/usbip-usbip_host-fix-stub_dev-lock-context-imbalance-regression.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / queue-4.19 / usbip-usbip_host-fix-stub_dev-lock-context-imbalance-regression.patch
CommitLineData
14e9555d
GKH
1From 3ea3091f1bd8586125848c62be295910e9802af0 Mon Sep 17 00:00:00 2001
2From: Shuah Khan <skhan@linuxfoundation.org>
3Date: Wed, 29 May 2019 13:46:15 -0600
4Subject: usbip: usbip_host: fix stub_dev lock context imbalance regression
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9From: Shuah Khan <skhan@linuxfoundation.org>
10
11commit 3ea3091f1bd8586125848c62be295910e9802af0 upstream.
12
13Fix the following sparse context imbalance regression introduced in
14a patch that fixed sleeping function called from invalid context bug.
15
16kbuild test robot reported on:
17
18tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-linus
19
20Regressions in current branch:
21
22drivers/usb/usbip/stub_dev.c:399:9: sparse: sparse: context imbalance in 'stub_probe' - different lock contexts for basic block
23drivers/usb/usbip/stub_dev.c:418:13: sparse: sparse: context imbalance in 'stub_disconnect' - different lock contexts for basic block
24drivers/usb/usbip/stub_dev.c:464:1-10: second lock on line 476
25
26Error ids grouped by kconfigs:
27
28recent_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
37This is a real problem in an error leg where spin_lock() is called on an
38already held lock.
39
40Fix the imbalance in stub_probe() and stub_disconnect().
41
42Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
43Fixes: 0c9e8b3cad65 ("usbip: usbip_host: fix BUG: sleeping function called from invalid context")
44Cc: stable <stable@vger.kernel.org>
45Signed-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