diff options
Diffstat (limited to 'net/bluetooth/hci_event.c')
| -rw-r--r-- | net/bluetooth/hci_event.c | 80 | 
1 files changed, 47 insertions, 33 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index abaabfae19cc..66451661283c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2834,7 +2834,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)  	bt_dev_dbg(hdev, "status 0x%2.2x", status);  	/* All connection failure handling is taken care of by the -	 * hci_le_conn_failed function which is triggered by the HCI +	 * hci_conn_failed function which is triggered by the HCI  	 * request completion callbacks used for connecting.  	 */  	if (status) @@ -2859,7 +2859,7 @@ static void hci_cs_le_ext_create_conn(struct hci_dev *hdev, u8 status)  	bt_dev_dbg(hdev, "status 0x%2.2x", status);  	/* All connection failure handling is taken care of by the -	 * hci_le_conn_failed function which is triggered by the HCI +	 * hci_conn_failed function which is triggered by the HCI  	 * request completion callbacks used for connecting.  	 */  	if (status) @@ -3067,18 +3067,20 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,  {  	struct hci_ev_conn_complete *ev = data;  	struct hci_conn *conn; +	u8 status = ev->status; -	if (__le16_to_cpu(ev->handle) > HCI_CONN_HANDLE_MAX) { -		bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for invalid handle"); -		return; -	} - -	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); +	bt_dev_dbg(hdev, "status 0x%2.2x", status);  	hci_dev_lock(hdev);  	conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);  	if (!conn) { +		/* In case of error status and there is no connection pending +		 * just unlock as there is nothing to cleanup. +		 */ +		if (ev->status) +			goto unlock; +  		/* Connection may not exist if auto-connected. Check the bredr  		 * allowlist to see if this device is allowed to auto connect.  		 * If link is an ACL type, create a connection class @@ -3122,8 +3124,14 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,  		goto unlock;  	} -	if (!ev->status) { +	if (!status) {  		conn->handle = __le16_to_cpu(ev->handle); +		if (conn->handle > HCI_CONN_HANDLE_MAX) { +			bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x", +				   conn->handle, HCI_CONN_HANDLE_MAX); +			status = HCI_ERROR_INVALID_PARAMETERS; +			goto done; +		}  		if (conn->type == ACL_LINK) {  			conn->state = BT_CONFIG; @@ -3164,19 +3172,14 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,  			hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),  				     &cp);  		} -	} else { -		conn->state = BT_CLOSED; -		if (conn->type == ACL_LINK) -			mgmt_connect_failed(hdev, &conn->dst, conn->type, -					    conn->dst_type, ev->status);  	}  	if (conn->type == ACL_LINK)  		hci_sco_setup(conn, ev->status); -	if (ev->status) { -		hci_connect_cfm(conn, ev->status); -		hci_conn_del(conn); +done: +	if (status) { +		hci_conn_failed(conn, status);  	} else if (ev->link_type == SCO_LINK) {  		switch (conn->setting & SCO_AIRMODE_MASK) {  		case SCO_AIRMODE_CVSD: @@ -3185,7 +3188,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,  			break;  		} -		hci_connect_cfm(conn, ev->status); +		hci_connect_cfm(conn, status);  	}  unlock: @@ -4676,6 +4679,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,  {  	struct hci_ev_sync_conn_complete *ev = data;  	struct hci_conn *conn; +	u8 status = ev->status;  	switch (ev->link_type) {  	case SCO_LINK: @@ -4690,12 +4694,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,  		return;  	} -	if (__le16_to_cpu(ev->handle) > HCI_CONN_HANDLE_MAX) { -		bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete for invalid handle"); -		return; -	} - -	bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); +	bt_dev_dbg(hdev, "status 0x%2.2x", status);  	hci_dev_lock(hdev); @@ -4729,9 +4728,17 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,  		goto unlock;  	} -	switch (ev->status) { +	switch (status) {  	case 0x00:  		conn->handle = __le16_to_cpu(ev->handle); +		if (conn->handle > HCI_CONN_HANDLE_MAX) { +			bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x", +				   conn->handle, HCI_CONN_HANDLE_MAX); +			status = HCI_ERROR_INVALID_PARAMETERS; +			conn->state = BT_CLOSED; +			break; +		} +  		conn->state  = BT_CONNECTED;  		conn->type   = ev->link_type; @@ -4775,8 +4782,8 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,  		}  	} -	hci_connect_cfm(conn, ev->status); -	if (ev->status) +	hci_connect_cfm(conn, status); +	if (status)  		hci_conn_del(conn);  unlock: @@ -5527,11 +5534,6 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,  	struct smp_irk *irk;  	u8 addr_type; -	if (handle > HCI_CONN_HANDLE_MAX) { -		bt_dev_err(hdev, "Ignoring HCI_LE_Connection_Complete for invalid handle"); -		return; -	} -  	hci_dev_lock(hdev);  	/* All controllers implicitly stop advertising in the event of a @@ -5541,6 +5543,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,  	conn = hci_lookup_le_connect(hdev);  	if (!conn) { +		/* In case of error status and there is no connection pending +		 * just unlock as there is nothing to cleanup. +		 */ +		if (status) +			goto unlock; +  		conn = hci_conn_add(hdev, LE_LINK, bdaddr, role);  		if (!conn) {  			bt_dev_err(hdev, "no memory for new connection"); @@ -5603,8 +5611,14 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,  	conn->dst_type = ev_bdaddr_type(hdev, conn->dst_type, NULL); +	if (handle > HCI_CONN_HANDLE_MAX) { +		bt_dev_err(hdev, "Invalid handle: 0x%4.4x > 0x%4.4x", handle, +			   HCI_CONN_HANDLE_MAX); +		status = HCI_ERROR_INVALID_PARAMETERS; +	} +  	if (status) { -		hci_le_conn_failed(conn, status); +		hci_conn_failed(conn, status);  		goto unlock;  	}  | 
