aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hidp
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2011-08-30 11:53:35 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-10-07 00:43:10 -0400
commit1785dbf9e30be62ab45e34900e574b8307bc98b5 (patch)
tree0f5c033aeb98f1b1ff4c1285798244b9093a4b5a /net/bluetooth/hidp
parentab88f7149e0e3284623adcaa60460a9a69d9f131 (diff)
Bluetooth: hidp: safely acquire hci connection
Claim device lock to safely enumerate hci connection list and bump hci connection proxy device ref count simultaneously. This patch incorporates David Herrmann's fix to prevent adding an HID device when the hci connection no longer exists. Signed-off-by: David Herrmann <dh.herrmann@googlemail.com> Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Diffstat (limited to 'net/bluetooth/hidp')
-rw-r--r--net/bluetooth/hidp/core.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index f2bec4981b76..304a73f96cc2 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -95,8 +95,6 @@ static void __hidp_link_session(struct hidp_session *session)
95{ 95{
96 __module_get(THIS_MODULE); 96 __module_get(THIS_MODULE);
97 list_add(&session->list, &hidp_session_list); 97 list_add(&session->list, &hidp_session_list);
98
99 hci_conn_hold_device(session->conn);
100} 98}
101 99
102static void __hidp_unlink_session(struct hidp_session *session) 100static void __hidp_unlink_session(struct hidp_session *session)
@@ -785,24 +783,26 @@ static int hidp_session(void *arg)
785 return 0; 783 return 0;
786} 784}
787 785
788static struct device *hidp_get_device(struct hidp_session *session) 786static struct hci_conn *hidp_find_connection(struct hidp_session *session)
789{ 787{
790 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src; 788 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
791 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst; 789 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
792 struct device *device = NULL; 790 struct hci_conn *conn;
793 struct hci_dev *hdev; 791 struct hci_dev *hdev;
794 792
795 hdev = hci_get_route(dst, src); 793 hdev = hci_get_route(dst, src);
796 if (!hdev) 794 if (!hdev)
797 return NULL; 795 return NULL;
798 796
799 session->conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); 797 hci_dev_lock_bh(hdev);
800 if (session->conn) 798 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
801 device = &session->conn->dev; 799 if (conn)
800 hci_conn_hold_device(conn);
801 hci_dev_unlock_bh(hdev);
802 802
803 hci_dev_put(hdev); 803 hci_dev_put(hdev);
804 804
805 return device; 805 return conn;
806} 806}
807 807
808static int hidp_setup_input(struct hidp_session *session, 808static int hidp_setup_input(struct hidp_session *session,
@@ -852,7 +852,7 @@ static int hidp_setup_input(struct hidp_session *session,
852 input->relbit[0] |= BIT_MASK(REL_WHEEL); 852 input->relbit[0] |= BIT_MASK(REL_WHEEL);
853 } 853 }
854 854
855 input->dev.parent = hidp_get_device(session); 855 input->dev.parent = &session->conn->dev;
856 856
857 input->event = hidp_input_event; 857 input->event = hidp_input_event;
858 858
@@ -952,7 +952,7 @@ static int hidp_setup_hid(struct hidp_session *session,
952 strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64); 952 strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
953 strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64); 953 strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
954 954
955 hid->dev.parent = hidp_get_device(session); 955 hid->dev.parent = &session->conn->dev;
956 hid->ll_driver = &hidp_hid_driver; 956 hid->ll_driver = &hidp_hid_driver;
957 957
958 hid->hid_get_raw_report = hidp_get_raw_report; 958 hid->hid_get_raw_report = hidp_get_raw_report;
@@ -993,6 +993,12 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
993 goto failed; 993 goto failed;
994 } 994 }
995 995
996 session->conn = hidp_find_connection(session);
997 if (!session->conn) {
998 err = -ENOTCONN;
999 goto failed;
1000 }
1001
996 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst); 1002 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
997 1003
998 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu, 1004 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu,
@@ -1018,6 +1024,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
1018 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID); 1024 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1019 session->idle_to = req->idle_to; 1025 session->idle_to = req->idle_to;
1020 1026
1027 __hidp_link_session(session);
1028
1021 if (req->rd_size > 0) { 1029 if (req->rd_size > 0) {
1022 err = hidp_setup_hid(session, req); 1030 err = hidp_setup_hid(session, req);
1023 if (err) 1031 if (err)
@@ -1030,8 +1038,6 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
1030 goto purge; 1038 goto purge;
1031 } 1039 }
1032 1040
1033 __hidp_link_session(session);
1034
1035 hidp_set_timer(session); 1041 hidp_set_timer(session);
1036 1042
1037 if (session->hid) { 1043 if (session->hid) {
@@ -1084,8 +1090,6 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
1084unlink: 1090unlink:
1085 hidp_del_timer(session); 1091 hidp_del_timer(session);
1086 1092
1087 __hidp_unlink_session(session);
1088
1089 if (session->input) { 1093 if (session->input) {
1090 input_unregister_device(session->input); 1094 input_unregister_device(session->input);
1091 session->input = NULL; 1095 session->input = NULL;
@@ -1100,6 +1104,8 @@ unlink:
1100 session->rd_data = NULL; 1104 session->rd_data = NULL;
1101 1105
1102purge: 1106purge:
1107 __hidp_unlink_session(session);
1108
1103 skb_queue_purge(&session->ctrl_transmit); 1109 skb_queue_purge(&session->ctrl_transmit);
1104 skb_queue_purge(&session->intr_transmit); 1110 skb_queue_purge(&session->intr_transmit);
1105 1111