Commit bdce7baf authored by Szymon Janc's avatar Szymon Janc Committed by Gustavo F. Padovan

Bluetooth: Validate data size before accessing mgmt commands

Crafted (too small) data buffer could result in reading data outside of buffer.
Validate buffer size and return EINVAL if size is wrong.
Signed-off-by: default avatarSzymon Janc <szymon.janc@tieto.com>
Acked-by: default avatarJohan Hedberg <johan.hedberg@nokia.com>
Signed-off-by: default avatarGustavo F. Padovan <padovan@profusion.mobi>
parent 4e51eae9
...@@ -302,6 +302,9 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) ...@@ -302,6 +302,9 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
BT_DBG("request for hci%u", index); BT_DBG("request for hci%u", index);
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_SET_POWERED, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV); return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV);
...@@ -351,6 +354,9 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, ...@@ -351,6 +354,9 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
BT_DBG("request for hci%u", index); BT_DBG("request for hci%u", index);
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV); return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV);
...@@ -409,6 +415,9 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, ...@@ -409,6 +415,9 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
BT_DBG("request for hci%u", index); BT_DBG("request for hci%u", index);
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV); return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV);
...@@ -499,6 +508,9 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, ...@@ -499,6 +508,9 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
BT_DBG("request for hci%u", index); BT_DBG("request for hci%u", index);
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV); return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV);
...@@ -569,6 +581,9 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) ...@@ -569,6 +581,9 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
BT_DBG("request for hci%u", index); BT_DBG("request for hci%u", index);
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_ADD_UUID, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV); return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV);
...@@ -611,6 +626,9 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len) ...@@ -611,6 +626,9 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
BT_DBG("request for hci%u", index); BT_DBG("request for hci%u", index);
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV); return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
...@@ -663,6 +681,9 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data, ...@@ -663,6 +681,9 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
BT_DBG("request for hci%u", index); BT_DBG("request for hci%u", index);
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV); return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
...@@ -692,6 +713,10 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data, ...@@ -692,6 +713,10 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data,
cp = (void *) data; cp = (void *) data;
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE,
EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV); return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
...@@ -726,6 +751,10 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len) ...@@ -726,6 +751,10 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
int i; int i;
cp = (void *) data; cp = (void *) data;
if (len < sizeof(*cp))
return -EINVAL;
key_count = get_unaligned_le16(&cp->key_count); key_count = get_unaligned_le16(&cp->key_count);
expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info); expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
...@@ -775,6 +804,9 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len) ...@@ -775,6 +804,9 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
cp = (void *) data; cp = (void *) data;
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV); return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV);
...@@ -821,6 +853,9 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) ...@@ -821,6 +853,9 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
cp = (void *) data; cp = (void *) data;
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV); return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
...@@ -931,6 +966,9 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data, ...@@ -931,6 +966,9 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
cp = (void *) data; cp = (void *) data;
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV); return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
...@@ -975,6 +1013,10 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data, ...@@ -975,6 +1013,10 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
cp = (void *) data; cp = (void *) data;
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
...@@ -1017,6 +1059,10 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data, ...@@ -1017,6 +1059,10 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
cp = (void *) data; cp = (void *) data;
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV); return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
...@@ -1107,6 +1153,9 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len) ...@@ -1107,6 +1153,9 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
cp = (void *) data; cp = (void *) data;
if (len != sizeof(*cp))
return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV); return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
...@@ -1178,6 +1227,9 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data, ...@@ -1178,6 +1227,9 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY; hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY;
} }
if (len != sizeof(*cp))
return cmd_status(sk, index, mgmt_op, EINVAL);
hdev = hci_dev_get(index); hdev = hci_dev_get(index);
if (!hdev) if (!hdev)
return cmd_status(sk, index, mgmt_op, ENODEV); return cmd_status(sk, index, mgmt_op, ENODEV);
......
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