diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index c4b0a4048be2..e7be18a3af33 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -1017,16 +1017,19 @@ static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, hci_dev_lock(hdev); hcon = hci_conn_hash_lookup_le(hdev, addr, le_addr_type); - hci_dev_unlock(hdev); - hci_dev_put(hdev); - - if (!hcon) + if (!hcon) { + hci_dev_unlock(hdev); + hci_dev_put(hdev); return -ENOENT; + } - *conn = (struct l2cap_conn *)hcon->l2cap_data; + *conn = l2cap_conn_hold_unless_zero(hcon->l2cap_data); BT_DBG("conn %p dst %pMR type %u", *conn, &hcon->dst, hcon->dst_type); + hci_dev_unlock(hdev); + hci_dev_put(hdev); + return 0; } @@ -1154,18 +1157,22 @@ static ssize_t lowpan_control_write(struct file *fp, if (conn) { struct lowpan_peer *peer; - if (!is_bt_6lowpan(conn->hcon)) + if (!is_bt_6lowpan(conn->hcon)) { + l2cap_conn_put(conn); return -EINVAL; + } peer = lookup_peer(conn); if (peer) { BT_DBG("6LoWPAN connection already exists"); + l2cap_conn_put(conn); return -EALREADY; } BT_DBG("conn %p dst %pMR type %d user %u", conn, &conn->hcon->dst, conn->hcon->dst_type, addr_type); + l2cap_conn_put(conn); } ret = bt_6lowpan_connect(&addr, addr_type); @@ -1181,6 +1188,8 @@ static ssize_t lowpan_control_write(struct file *fp, return ret; ret = bt_6lowpan_disconnect(conn, addr_type); + if (conn) + l2cap_conn_put(conn); if (ret < 0) return ret; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a1d249f42be7..4ee3b9e30c65 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -7716,6 +7716,7 @@ struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *c) return c; } +EXPORT_SYMBOL(l2cap_conn_hold_unless_zero); int l2cap_recv_acldata(struct hci_dev *hdev, u16 handle, struct sk_buff *skb, u16 flags)