Skip to contentSkip to conversation

Bluetooth: btusb: fix wakeup irq devres lifetime

PATCH RESEND Superseded Johan Hovold 3 participants 9 messages Jun 3 – Jun 4

Subsystems (2)

v3 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v3 cover Bluetooth: btusb: fix wakeup irq devres lifetime

[ This one was posted two months ago and appears to have been archived
in patchwork so resending (with Paul's RB added to patch 1/5). ]

This series fixes a couple of use-after-free issues and a wakeup source leak on probe failure and a (currently benign) OOB wakeup interrupt devres lifetime issue.

Included is also a related cleanup.

Johan

Changes in v3:
- fix use-after-free on registration failure (new patch)
- fix use-after-free on marvell probe failure (new patch)

Changes in v2:
- fix wakeup source leak (new patch)
- fix disconnect-while-suspended issue by making interrupt non-managed
- amend devres lifetime fix commit message with a reference to changed devres behaviour
- clean up error handling (new patch)

Johan Hovold (5):
Bluetooth: btusb: fix use-after-free on registration failure
Bluetooth: btusb: fix use-after-free on marvell probe failure
Bluetooth: btusb: fix wakeup source leak on probe failure
Bluetooth: btusb: fix wakeup irq devres lifetime
Bluetooth: btusb: clean up probe error handling

 drivers/bluetooth/btusb.c | 61 +++++++++++++++++++++++++++------------
 1 file changed, 43 insertions(+), 18 deletions(-)
Signature · 1 line
2.53.0
#1 lore raw

PATCH RESEND v3 1/5 Bluetooth: btusb: fix use-after-free on registration failure

Make sure to release the sibling interfaces in case controller registration fails to avoid use-after-free and double-free when they are eventually disconnected.

This issue was reported by Sashiko while reviewing a fix for a wakeup source leak in the btusb probe errors paths.

Fixes 9bfa35fe422c ("[Bluetooth] Add SCO support to btusb driver")
Fixes 9d08f50401ac ("Bluetooth: btusb: Add support for Broadcom LM_DIAG interface")
Cc [email protected] # 2.6.27
---
 drivers/bluetooth/btusb.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/bluetooth/btusb.c +10 -1
index 830fefb342c6..c8015cee240f 100644
@@ -4407,7 +4407,7 @@ static int btusb_probe(struct usb_interface *intf,
 
 	err = hci_register_dev(hdev);
 	if (err < 0)
-		goto out_free_dev;
+		goto err_release_siblings;
 
 	usb_set_intfdata(intf, data);
 
@@ -4416,6 +4416,15 @@ static int btusb_probe(struct usb_interface *intf,
 
 	return 0;
 
+err_release_siblings:
+	if (data->diag) {
+		usb_set_intfdata(data->diag, NULL);
+		usb_driver_release_interface(&btusb_driver, data->diag);
+	}
+	if (data->isoc) {
+		usb_set_intfdata(data->isoc, NULL);
+		usb_driver_release_interface(&btusb_driver, data->isoc);
+	}
 out_free_dev:
 	if (data->reset_gpio)
 		gpiod_put(data->reset_gpio);
Signature · 1 line
2.53.0
#2 lore raw

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1105369

---Test result---

Test Summary:

CheckPatch                    FAIL      3.64 seconds
VerifyFixes                   PASS      0.14 seconds
VerifySignedoff               PASS      0.14 seconds
GitLint                       FAIL      1.87 seconds
SubjectPrefix                 PASS      0.66 seconds
BuildKernel                   PASS      25.55 seconds
CheckAllWarning               PASS      29.82 seconds
CheckSparse                   PASS      28.84 seconds
BuildKernel32                 PASS      26.46 seconds
TestRunnerSetup               PASS      529.51 seconds
IncrementalBuild              PASS      34.26 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[v3,RESEND,4/5] Bluetooth: btusb: fix wakeup irq devres lifetime
ERROR: Please use git commit description style 'commit <12+ chars of sha1> ("<title line>")' - ie: 'commit 699fb50d9903 ("drivers: base: Free devm resources when unregistering a device")' #82:
[1] 699fb50d9903 ("drivers: base: Free devm resources when unregistering

total: 1 errors, 0 warnings, 51 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/patch/14609619.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.

##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[v3,RESEND,1/5] Bluetooth: btusb: fix use-after-free on registration failure

10: B3 Line contains hard tab characters (\t): "Cc: [email protected] # 2.6.27"
[v3,RESEND,2/5] Bluetooth: btusb: fix use-after-free on marvell probe failure

10: B3 Line contains hard tab characters (\t): "Cc: [email protected] # 4.11"
[v3,RESEND,3/5] Bluetooth: btusb: fix wakeup source leak on probe failure

6: B3 Line contains hard tab characters (\t): "Cc: [email protected] # 4.11"

https://github.com/bluez/bluetooth-next/pull/282

---
Regards,
Linux Bluetooth

#3 lore raw

PATCH RESEND v3 2/5 Bluetooth: btusb: fix use-after-free on marvell probe failure

In reply to Johan Hovold

Make sure to stop any TX URBs submitted during Marvell OOB wakeup configuration on later probe failures to avoid use-after-free in the completion callback.

This issue was reported by Sashiko while reviewing a fix for a wakeup source leak in the btusb probe errors paths.

Fixes a4ccc9e33d2f ("Bluetooth: btusb: Configure Marvell to use one of the pins for oob wakeup")
Cc Rajat Jain <[email protected]>
---
 drivers/bluetooth/btusb.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/bluetooth/btusb.c +5 -3
index c8015cee240f..d0a83a1ffdf2 100644
@@ -4218,7 +4218,7 @@ static int btusb_probe(struct usb_interface *intf,
 	if (id->driver_info & BTUSB_INTEL_COMBINED) {
 		err = btintel_configure_setup(hdev, btusb_driver.name);
 		if (err)
-			goto out_free_dev;
+			goto err_kill_tx_urbs;
 
 		/* Transport specific configuration */
 		hdev->send = btusb_send_frame_intel;
@@ -4381,7 +4381,7 @@ static int btusb_probe(struct usb_interface *intf,
 		err = usb_set_interface(data->udev, 0, 0);
 		if (err < 0) {
 			BT_ERR("failed to set interface 0, alt 0 %d", err);
-			goto out_free_dev;
+			goto err_kill_tx_urbs;
 		}
 	}
 
@@ -4389,7 +4389,7 @@ static int btusb_probe(struct usb_interface *intf,
 		err = usb_driver_claim_interface(&btusb_driver,
 						 data->isoc, data);
 		if (err < 0)
-			goto out_free_dev;
+			goto err_kill_tx_urbs;
 	}
 
 	if (IS_ENABLED(CONFIG_BT_HCIBTUSB_BCM) && data->diag) {
@@ -4425,6 +4425,8 @@ static int btusb_probe(struct usb_interface *intf,
 		usb_set_intfdata(data->isoc, NULL);
 		usb_driver_release_interface(&btusb_driver, data->isoc);
 	}
+err_kill_tx_urbs:
+	usb_kill_anchored_urbs(&data->tx_anchor);
 out_free_dev:
 	if (data->reset_gpio)
 		gpiod_put(data->reset_gpio);
Signature · 1 line
2.53.0
#4 lore raw

PATCH RESEND v3 3/5 Bluetooth: btusb: fix wakeup source leak on probe failure

In reply to Johan Hovold

Make sure to disable wakeup on probe failure to avoid leaking the wakeup source.

Fixes fd913ef7ce61 ("Bluetooth: btusb: Add out-of-band wakeup support")
Cc Rajat Jain <[email protected]>
---
 drivers/bluetooth/btusb.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/bluetooth/btusb.c +4 -1
index d0a83a1ffdf2..622df2fff497 100644
@@ -4181,7 +4181,7 @@ static int btusb_probe(struct usb_interface *intf,
 	if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
 		err = marvell_config_oob_wake(hdev);
 		if (err)
-			goto out_free_dev;
+			goto err_disable_wakeup;
 	}
 #endif
 	if (id->driver_info & BTUSB_CW6622)
@@ -4427,6 +4427,9 @@ static int btusb_probe(struct usb_interface *intf,
 	}
 err_kill_tx_urbs:
 	usb_kill_anchored_urbs(&data->tx_anchor);
+err_disable_wakeup:
+	if (data->oob_wake_irq)
+		device_init_wakeup(&data->udev->dev, false);
 out_free_dev:
 	if (data->reset_gpio)
 		gpiod_put(data->reset_gpio);
Signature · 1 line
2.53.0
#5 lore raw

Re: [PATCH v3 RESEND 3/5] Bluetooth: btusb: fix wakeup source leak on probe failure

Hi Johan,

Quoted 36 lines · Johan Hovold

Make sure to disable wakeup on probe failure to avoid leaking the wakeup source.

Fixes fd913ef7ce61 ("Bluetooth: btusb: Add out-of-band wakeup support")
Cc Rajat Jain <[email protected]>
---
 drivers/bluetooth/btusb.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/bluetooth/btusb.c +4 -2
index d0a83a1ffdf2..622df2fff497 100644
@@ -4181,7 +4181,7 @@ static int btusb_probe(struct usb_interface *intf,
        if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
                err = marvell_config_oob_wake(hdev);
                if (err)
-                       goto out_free_dev;
+                       goto err_disable_wakeup;
        }
 #endif
        if (id->driver_info & BTUSB_CW6622)
@@ -4427,6 +4427,9 @@ static int btusb_probe(struct usb_interface *intf,
        }
 err_kill_tx_urbs:
        usb_kill_anchored_urbs(&data->tx_anchor);
+err_disable_wakeup:
+       if (data->oob_wake_irq)
+               device_init_wakeup(&data->udev->dev, false);
 out_free_dev:
        if (data->reset_gpio)
                gpiod_put(data->reset_gpio);
--
Quoted 1 line

2.53.0

This seem to trigger a compilation problem according to sashiko:

The goto statement targeting err_disable_wakeup is wrapped in an ifdef CONFIG_PM block earlier in the function, but this label is defined unconditionally here. []https://sashiko.dev/#/patchset/20260603143643.2514595-1-johan%40kernel.org

Signature · 1 line
Luiz Augusto von Dentz
#6 lore raw

Re: [PATCH v3 RESEND 3/5] Bluetooth: btusb: fix wakeup source leak on probe failure

Quoted 26 lines · Luiz Augusto von Dentz
Quoted 20 lines · Johan Hovold
drivers/bluetooth/btusb.c +4 -2
@@ -4181,7 +4181,7 @@ static int btusb_probe(struct usb_interface *intf,
        if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
                err = marvell_config_oob_wake(hdev);
                if (err)
-                       goto out_free_dev;
+                       goto err_disable_wakeup;
        }
 #endif
        if (id->driver_info & BTUSB_CW6622)
@@ -4427,6 +4427,9 @@ static int btusb_probe(struct usb_interface *intf,
        }
 err_kill_tx_urbs:
        usb_kill_anchored_urbs(&data->tx_anchor);
+err_disable_wakeup:
+       if (data->oob_wake_irq)
+               device_init_wakeup(&data->udev->dev, false);
 out_free_dev:
        if (data->reset_gpio)
                gpiod_put(data->reset_gpio);
--
Quoted 1 line

2.53.0

This seem to trigger a compilation problem according to sashiko:

Quoted 4 lines

The goto statement targeting err_disable_wakeup is wrapped in an ifdef CONFIG_PM block earlier in the function, but this label is defined unconditionally here. []https://sashiko.dev/#/patchset/20260603143643.2514595-1-johan%40kernel.org

Indeed. Sorry about that. I just sent a v4 addressing this here:

	https://lore.kernel.org/lkml/[email protected]/

Johan

#7 lore raw

PATCH RESEND v3 4/5 Bluetooth: btusb: fix wakeup irq devres lifetime

In reply to Johan Hovold

The OOB wakeup interrupt is device managed but its lifetime is incorrectly tied to the child HCI device rather than the USB interface to which the driver is bound.

This should not cause any trouble currently as the interrupt will be disabled when the HCI device is deregistered on disconnect (but this was not always the case, see [1]), and there should be no further references if probe fails before registering it. But it is still technically wrong as the reference counted HCI device could in theory remain after a probe failure.

Explicitly free the interrupt on disconnect so that it is guaranteed to be disabled before freeing the (non-managed) driver data (including if disconnected while suspended).

[1] 699fb50d9903 ("drivers: base: Free devm resources when unregistering a device")

Fixes fd913ef7ce61 ("Bluetooth: btusb: Add out-of-band wakeup support")
Cc Rajat Jain <[email protected]>
---
 drivers/bluetooth/btusb.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)
drivers/bluetooth/btusb.c +15 -5
index 622df2fff497..450c8746bea6 100644
@@ -3819,8 +3819,7 @@ static int btusb_config_oob_wake(struct hci_dev *hdev)
 	}
 
 	irq_set_status_flags(irq, IRQ_NOAUTOEN);
-	ret = devm_request_irq(&hdev->dev, irq, btusb_oob_wake_handler,
-			       0, "OOB Wake-on-BT", data);
+	ret = request_irq(irq, btusb_oob_wake_handler, 0, "OOB Wake-on-BT", data);
 	if (ret) {
 		bt_dev_err(hdev, "%s: IRQ request failed", __func__);
 		return ret;
@@ -3829,12 +3828,18 @@ static int btusb_config_oob_wake(struct hci_dev *hdev)
 	ret = device_init_wakeup(dev, true);
 	if (ret) {
 		bt_dev_err(hdev, "%s: failed to init_wakeup", __func__);
-		return ret;
+		goto err_free_irq;
 	}
 
 	data->oob_wake_irq = irq;
 	bt_dev_info(hdev, "OOB Wake-on-BT configured at IRQ %u", irq);
+
 	return 0;
+
+err_free_irq:
+	free_irq(irq, data);
+
+	return ret;
 }
 #endif
 
@@ -4428,8 +4433,10 @@ static int btusb_probe(struct usb_interface *intf,
 err_kill_tx_urbs:
 	usb_kill_anchored_urbs(&data->tx_anchor);
 err_disable_wakeup:
-	if (data->oob_wake_irq)
+	if (data->oob_wake_irq) {
 		device_init_wakeup(&data->udev->dev, false);
+		free_irq(data->oob_wake_irq, data);
+	}
 out_free_dev:
 	if (data->reset_gpio)
 		gpiod_put(data->reset_gpio);
@@ -4462,8 +4469,11 @@ static void btusb_disconnect(struct usb_interface *intf)
 
 	hci_unregister_dev(hdev);
 
-	if (data->oob_wake_irq)
+	if (data->oob_wake_irq) {
 		device_init_wakeup(&data->udev->dev, false);
+		free_irq(data->oob_wake_irq, data);
+	}
+
 	if (data->reset_gpio)
 		gpiod_put(data->reset_gpio);
 
Signature · 1 line
2.53.0
#8 lore raw

PATCH RESEND v3 5/5 Bluetooth: btusb: clean up probe error handling

In reply to Johan Hovold

Clean up probe error handling by using dedicated error labels with an "err" prefix.

Note that the endpoint lookup helper returns -ENXIO when endpoints are missing which is functionally equivalent to returning -ENODEV.

---
 drivers/bluetooth/btusb.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)
drivers/bluetooth/btusb.c +10 -9
index 450c8746bea6..83fbb5d2bf4a 100644
@@ -4090,10 +4090,8 @@ static int btusb_probe(struct usb_interface *intf,
 
 	err = usb_find_common_endpoints(intf->cur_altsetting, &data->bulk_rx_ep,
 					&data->bulk_tx_ep, &data->intr_ep, NULL);
-	if (err) {
-		kfree(data);
-		return -ENODEV;
-	}
+	if (err)
+		goto err_free_data;
 
 	if (id->driver_info & BTUSB_AMP) {
 		data->cmdreq_type = USB_TYPE_CLASS | 0x01;
@@ -4149,8 +4147,8 @@ static int btusb_probe(struct usb_interface *intf,
 
 	hdev = hci_alloc_dev_priv(priv_size);
 	if (!hdev) {
-		kfree(data);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto err_free_data;
 	}
 
 	hdev->bus = HCI_USB;
@@ -4164,7 +4162,7 @@ static int btusb_probe(struct usb_interface *intf,
 					GPIOD_OUT_LOW);
 	if (IS_ERR(reset_gpio)) {
 		err = PTR_ERR(reset_gpio);
-		goto out_free_dev;
+		goto err_free_hdev;
 	} else if (reset_gpio) {
 		data->reset_gpio = reset_gpio;
 	}
@@ -4180,7 +4178,7 @@ static int btusb_probe(struct usb_interface *intf,
 #ifdef CONFIG_PM
 	err = btusb_config_oob_wake(hdev);
 	if (err)
-		goto out_free_dev;
+		goto err_put_reset;
 
 	/* Marvell devices may need a specific chip configuration */
 	if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
@@ -4437,11 +4435,14 @@ static int btusb_probe(struct usb_interface *intf,
 		device_init_wakeup(&data->udev->dev, false);
 		free_irq(data->oob_wake_irq, data);
 	}
-out_free_dev:
+err_put_reset:
 	if (data->reset_gpio)
 		gpiod_put(data->reset_gpio);
+err_free_hdev:
 	hci_free_dev(hdev);
+err_free_data:
 	kfree(data);
+
 	return err;
 }
 
Signature · 1 line
2.53.0