[PATCH 2/5] Bluetooth: Correctly acquire module reference

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When creating hci_dev objects we may end up with dangling devices that some
other subsystem has a ref-count of. If the bluetooth module is unloaded while
there are still hci_dev objects around, we might end up with calling invalid
callbacks on hci_dev destruction.

This patch correctly takes a module reference for every hci_dev object so when
destroying the object we can be sure that the bluetooth module is still
available.

This is the normal procedure of all bus systems as the device core does not
provide owner-tracking.

Signed-off-by: David Herrmann <dh.herrmann@xxxxxxxxxxxxxx>
---
 include/net/bluetooth/hci_core.h |    2 +-
 net/bluetooth/hci_core.c         |    6 +++++-
 net/bluetooth/hci_sysfs.c        |    8 +++++++-
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ab97ad3..720d81d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -654,7 +654,7 @@ int hci_recv_frame(struct sk_buff *skb);
 int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count);
 int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count);
 
-void hci_init_sysfs(struct hci_dev *hdev);
+int hci_init_sysfs(struct hci_dev *hdev);
 int hci_add_sysfs(struct hci_dev *hdev);
 void hci_del_sysfs(struct hci_dev *hdev);
 void hci_conn_init_sysfs(struct hci_conn *conn);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 6fdd6e5..fb08b01 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -940,7 +940,11 @@ struct hci_dev *hci_alloc_dev(void)
 	if (!hdev)
 		return NULL;
 
-	hci_init_sysfs(hdev);
+	if (hci_init_sysfs(hdev)) {
+		kfree(hdev);
+		return NULL;
+	}
+
 	skb_queue_head_init(&hdev->driver_init);
 
 	return hdev;
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
index 5210956..67f75e9 100644
--- a/net/bluetooth/hci_sysfs.c
+++ b/net/bluetooth/hci_sysfs.c
@@ -372,6 +372,7 @@ static void bt_host_release(struct device *dev)
 {
 	void *data = dev_get_drvdata(dev);
 	kfree(data);
+	module_put(THIS_MODULE);
 }
 
 static struct device_type bt_host = {
@@ -516,15 +517,20 @@ static int auto_accept_delay_get(void *data, u64 *val)
 DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
 					auto_accept_delay_set, "%llu\n");
 
-void hci_init_sysfs(struct hci_dev *hdev)
+int hci_init_sysfs(struct hci_dev *hdev)
 {
 	struct device *dev = &hdev->dev;
 
+	if (!try_module_get(THIS_MODULE))
+		return -EIO;
+
 	dev->type = &bt_host;
 	dev->class = bt_class;
 
 	dev_set_drvdata(dev, hdev);
 	device_initialize(dev);
+
+	return 0;
 }
 
 int hci_add_sysfs(struct hci_dev *hdev)
-- 
1.7.8.1

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux