Commit a736abc1 authored by Szymon Janc's avatar Szymon Janc Committed by Johan Hedberg

Bluetooth: Fix invalid response for 'Start Discovery' command

According to Management Interface API 'Start Discovery' command should
generate a Command Complete event on failure. Currently kernel is
sending Command Status on early errors. This results in userspace
ignoring such event due to invalid size.

bluetoothd[28499]: src/adapter.c:trigger_start_discovery()
bluetoothd[28499]: src/adapter.c:cancel_passive_scanning()
bluetoothd[28499]: src/adapter.c:start_discovery_timeout()
bluetoothd[28499]: src/adapter.c:start_discovery_complete() status 0x0a
bluetoothd[28499]: Wrong size of start discovery return parameters
Reported-by: default avatarJukka Taimisto <jtt@codenomicon.com>
Signed-off-by: default avatarSzymon Janc <szymon.janc@tieto.com>
Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
parent 845472e8
...@@ -3727,20 +3727,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3727,20 +3727,23 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_NOT_POWERED); MGMT_STATUS_NOT_POWERED,
&cp->type, sizeof(cp->type));
goto failed; goto failed;
} }
if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) { if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type));
goto failed; goto failed;
} }
if (hdev->discovery.state != DISCOVERY_STOPPED) { if (hdev->discovery.state != DISCOVERY_STOPPED) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_BUSY); MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type));
goto failed; goto failed;
} }
...@@ -3758,15 +3761,18 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3758,15 +3761,18 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
case DISCOV_TYPE_BREDR: case DISCOV_TYPE_BREDR:
status = mgmt_bredr_support(hdev); status = mgmt_bredr_support(hdev);
if (status) { if (status) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id,
status); MGMT_OP_START_DISCOVERY, status,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
if (test_bit(HCI_INQUIRY, &hdev->flags)) { if (test_bit(HCI_INQUIRY, &hdev->flags)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id,
MGMT_STATUS_BUSY); MGMT_OP_START_DISCOVERY,
MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
...@@ -3783,16 +3789,19 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3783,16 +3789,19 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
case DISCOV_TYPE_INTERLEAVED: case DISCOV_TYPE_INTERLEAVED:
status = mgmt_le_support(hdev); status = mgmt_le_support(hdev);
if (status) { if (status) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id,
status); MGMT_OP_START_DISCOVERY, status,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED && if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id,
MGMT_STATUS_NOT_SUPPORTED); MGMT_OP_START_DISCOVERY,
MGMT_STATUS_NOT_SUPPORTED,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
...@@ -3804,9 +3813,11 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3804,9 +3813,11 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
*/ */
if (hci_conn_hash_lookup_state(hdev, LE_LINK, if (hci_conn_hash_lookup_state(hdev, LE_LINK,
BT_CONNECT)) { BT_CONNECT)) {
err = cmd_status(sk, hdev->id, err = cmd_complete(sk, hdev->id,
MGMT_OP_START_DISCOVERY, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_REJECTED); MGMT_STATUS_REJECTED,
&cp->type,
sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
...@@ -3829,8 +3840,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3829,8 +3840,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
*/ */
err = hci_update_random_address(&req, true, &own_addr_type); err = hci_update_random_address(&req, true, &own_addr_type);
if (err < 0) { if (err < 0) {
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id,
MGMT_STATUS_FAILED); MGMT_OP_START_DISCOVERY,
MGMT_STATUS_FAILED,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
...@@ -3850,8 +3863,9 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3850,8 +3863,9 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
break; break;
default: default:
err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
goto failed; goto failed;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment