@@ -1894,6 +1894,10 @@ struct hci_cp_le_reject_cis {
} __packed;
/* ---- HCI Events ---- */
+struct hci_ev_status {
+ __u8 status;
+} __packed;
+
#define HCI_EV_INQUIRY_COMPLETE 0x01
#define HCI_EV_INQUIRY_RESULT 0x02
@@ -1906,6 +1910,11 @@ struct inquiry_info {
__le16 clock_offset;
} __packed;
+struct hci_ev_inquiry_result {
+ __u8 num;
+ struct inquiry_info info[];
+};
+
#define HCI_EV_CONN_COMPLETE 0x03
struct hci_ev_conn_complete {
__u8 status;
@@ -2017,7 +2026,7 @@ struct hci_comp_pkts_info {
} __packed;
struct hci_ev_num_comp_pkts {
- __u8 num_hndl;
+ __u8 num;
struct hci_comp_pkts_info handles[];
} __packed;
@@ -2067,7 +2076,7 @@ struct hci_ev_pscan_rep_mode {
} __packed;
#define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22
-struct inquiry_info_with_rssi {
+struct inquiry_info_rssi {
bdaddr_t bdaddr;
__u8 pscan_rep_mode;
__u8 pscan_period_mode;
@@ -2075,7 +2084,7 @@ struct inquiry_info_with_rssi {
__le16 clock_offset;
__s8 rssi;
} __packed;
-struct inquiry_info_with_rssi_and_pscan_mode {
+struct inquiry_info_rssi_pscan {
bdaddr_t bdaddr;
__u8 pscan_rep_mode;
__u8 pscan_period_mode;
@@ -2084,6 +2093,14 @@ struct inquiry_info_with_rssi_and_pscan_mode {
__le16 clock_offset;
__s8 rssi;
} __packed;
+struct hci_ev_inquiry_result_rssi {
+ __u8 num;
+ struct inquiry_info_rssi info[];
+} __packed;
+struct hci_ev_inquiry_result_rssi_pscan {
+ __u8 num;
+ struct inquiry_info_rssi_pscan info[];
+} __packed;
#define HCI_EV_REMOTE_EXT_FEATURES 0x23
struct hci_ev_remote_ext_features {
@@ -2138,6 +2155,11 @@ struct extended_inquiry_info {
__u8 data[240];
} __packed;
+struct hci_ev_ext_inquiry_result {
+ __u8 num;
+ struct extended_inquiry_info info[];
+} __packed;
+
#define HCI_EV_KEY_REFRESH_COMPLETE 0x30
struct hci_ev_key_refresh_complete {
__u8 status;
@@ -2305,13 +2327,18 @@ struct hci_ev_le_conn_complete {
#define HCI_EV_LE_ADVERTISING_REPORT 0x02
struct hci_ev_le_advertising_info {
- __u8 evt_type;
+ __u8 type;
__u8 bdaddr_type;
bdaddr_t bdaddr;
__u8 length;
__u8 data[];
} __packed;
+struct hci_ev_le_advertising_report {
+ __u8 num;
+ struct hci_ev_le_advertising_info info[];
+} __packed;
+
#define HCI_EV_LE_CONN_UPDATE_COMPLETE 0x03
struct hci_ev_le_conn_update_complete {
__u8 status;
@@ -2355,7 +2382,7 @@ struct hci_ev_le_data_len_change {
#define HCI_EV_LE_DIRECT_ADV_REPORT 0x0B
struct hci_ev_le_direct_adv_info {
- __u8 evt_type;
+ __u8 type;
__u8 bdaddr_type;
bdaddr_t bdaddr;
__u8 direct_addr_type;
@@ -2363,6 +2390,11 @@ struct hci_ev_le_direct_adv_info {
__s8 rssi;
} __packed;
+struct hci_ev_le_direct_adv_report {
+ __u8 num;
+ struct hci_ev_le_direct_adv_info info[];
+} __packed;
+
#define HCI_EV_LE_PHY_UPDATE_COMPLETE 0x0c
struct hci_ev_le_phy_update_complete {
__u8 status;
@@ -2372,8 +2404,8 @@ struct hci_ev_le_phy_update_complete {
} __packed;
#define HCI_EV_LE_EXT_ADV_REPORT 0x0d
-struct hci_ev_le_ext_adv_report {
- __le16 evt_type;
+struct hci_ev_le_ext_adv_info {
+ __le16 type;
__u8 bdaddr_type;
bdaddr_t bdaddr;
__u8 primary_phy;
@@ -2381,11 +2413,16 @@ struct hci_ev_le_ext_adv_report {
__u8 sid;
__u8 tx_power;
__s8 rssi;
- __le16 interval;
- __u8 direct_addr_type;
+ __le16 interval;
+ __u8 direct_addr_type;
bdaddr_t direct_addr;
- __u8 length;
- __u8 data[];
+ __u8 length;
+ __u8 data[];
+} __packed;
+
+struct hci_ev_le_ext_adv_report {
+ __u8 num;
+ struct hci_ev_le_ext_adv_info info[];
} __packed;
#define HCI_EV_LE_ENHANCED_CONN_COMPLETE 0x0a
@@ -45,9 +45,16 @@
static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
u8 *new_status)
{
- __u8 status = *((__u8 *) skb->data);
+ struct hci_ev_status *rp;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_INQUIRY_CANCEL);
+ return;
+ }
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
/* It is possible that we receive Inquiry Complete event right
* before we receive Inquiry Cancel Command Complete event, in
@@ -56,14 +63,14 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
* we actually achieve what Inquiry Cancel wants to achieve,
* which is to end the last Inquiry session.
*/
- if (status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) {
+ if (rp->status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) {
bt_dev_warn(hdev, "Ignoring error of Inquiry Cancel command");
- status = 0x00;
+ rp->status = 0x00;
}
- *new_status = status;
+ *new_status = rp->status;
- if (status)
+ if (rp->status)
return;
clear_bit(HCI_INQUIRY, &hdev->flags);
@@ -84,11 +91,18 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb,
static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status = *((__u8 *) skb->data);
+ struct hci_ev_status *rp;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp->status) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_PERIODIC_INQ);
+ return;
+ }
- if (status)
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+ if (rp->status)
return;
hci_dev_set_flag(hdev, HCI_PERIODIC_INQ);
@@ -96,11 +110,18 @@ static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status = *((__u8 *) skb->data);
+ struct hci_ev_status *rp;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_EXIT_PERIODIC_INQ);
+ return;
+ }
- if (status)
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+ if (rp->status)
return;
hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ);
@@ -116,9 +137,16 @@ static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev,
static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_rp_role_discovery *rp = (void *) skb->data;
+ struct hci_rp_role_discovery *rp;
struct hci_conn *conn;
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_ROLE_DISCOVERY);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
if (rp->status)
@@ -135,9 +163,16 @@ static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_rp_read_link_policy *rp = (void *) skb->data;
+ struct hci_rp_read_link_policy *rp;
struct hci_conn *conn;
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_READ_LINK_POLICY);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
if (rp->status)
@@ -154,10 +189,17 @@ static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_rp_write_link_policy *rp = (void *) skb->data;
+ struct hci_rp_write_link_policy *rp;
struct hci_conn *conn;
void *sent;
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_WRITE_LINK_POLICY);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
if (rp->status)
@@ -179,7 +221,14 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_rp_read_def_link_policy *rp = (void *) skb->data;
+ struct hci_rp_read_def_link_policy *rp;
+
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_READ_DEF_LINK_POLICY);
+ return;
+ }
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
@@ -192,12 +241,19 @@ static void hci_cc_read_def_link_policy(struct hci_dev *hdev,
static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
struct sk_buff *skb)
{
- __u8 status = *((__u8 *) skb->data);
+ struct hci_ev_status *rp;
void *sent;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_WRITE_DEF_LINK_POLICY);
+ return;
+ }
- if (status)
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+ if (rp->status)
return;
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
@@ -209,13 +265,20 @@ static void hci_cc_write_def_link_policy(struct hci_dev *hdev,
static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status = *((__u8 *) skb->data);
+ struct hci_ev_status *rp;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_RESET);
+ return;
+ }
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
clear_bit(HCI_RESET, &hdev->flags);
- if (status)
+ if (rp->status)
return;
/* Reset all non-persistent flags */
@@ -243,9 +306,16 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_read_stored_link_key(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_rp_read_stored_link_key *rp = (void *)skb->data;
+ struct hci_rp_read_stored_link_key *rp;
struct hci_cp_read_stored_link_key *sent;
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_READ_STORED_LINK_KEY);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY);
@@ -261,7 +331,14 @@ static void hci_cc_read_stored_link_key(struct hci_dev *hdev,
static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_rp_delete_stored_link_key *rp = (void *)skb->data;
+ struct hci_rp_delete_stored_link_key *rp;
+
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_DELETE_STORED_LINK_KEY);
+ return;
+ }
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
@@ -276,10 +353,17 @@ static void hci_cc_delete_stored_link_key(struct hci_dev *hdev,
static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status = *((__u8 *) skb->data);
+ struct hci_ev_status *rp;
void *sent;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_WRITE_LOCAL_NAME);
+ return;
+ }
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
if (!sent)
@@ -288,8 +372,8 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev);
if (hci_dev_test_flag(hdev, HCI_MGMT))
- mgmt_set_local_name_complete(hdev, sent, status);
- else if (!status)
+ mgmt_set_local_name_complete(hdev, sent, rp->status);
+ else if (!rp->status)
memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
hci_dev_unlock(hdev);
@@ -297,7 +381,14 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_rp_read_local_name *rp = (void *) skb->data;
+ struct hci_rp_read_local_name *rp;
+
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_READ_LOCAL_NAME);
+ return;
+ }
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
@@ -311,10 +402,17 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status = *((__u8 *) skb->data);
+ struct hci_ev_status *rp;
void *sent;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_WRITE_AUTH_ENABLE);
+ return;
+ }
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
if (!sent)
@@ -322,7 +420,7 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev);
- if (!status) {
+ if (!rp->status) {
__u8 param = *((__u8 *) sent);
if (param == AUTH_ENABLED)
@@ -332,20 +430,27 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
}
if (hci_dev_test_flag(hdev, HCI_MGMT))
- mgmt_auth_enable_complete(hdev, status);
+ mgmt_auth_enable_complete(hdev, rp->status);
hci_dev_unlock(hdev);
}
static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status = *((__u8 *) skb->data);
+ struct hci_ev_status *rp;
__u8 param;
void *sent;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_WRITE_ENCRYPT_MODE);
+ return;
+ }
- if (status)
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+ if (rp->status)
return;
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
@@ -362,11 +467,18 @@ static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status = *((__u8 *) skb->data);
+ struct hci_ev_status *rp;
__u8 param;
void *sent;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_WRITE_SCAN_ENABLE);
+ return;
+ }
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
if (!sent)
@@ -376,7 +488,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev);
- if (status) {
+ if (rp->status) {
hdev->discov_timeout = 0;
goto done;
}
@@ -397,13 +509,20 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status = *((__u8 *)skb->data);
+ struct hci_ev_status *rp;
struct hci_cp_set_event_filter *cp;
void *sent;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ rp = bt_skb_pull(skb, sizeof(*rp));
+ if (!rp) {
+ bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x",
+ HCI_OP_WRITE_SCAN_ENABLE);
+ return;
+ }
- if (status)
+ BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
+
+ if (rp->status)
return;
sent = hci_sent_cmd_data(hdev, HCI_OP_SET_EVENT_FLT);
@@ -2507,11 +2626,18 @@ static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- __u8 status = *((__u8 *) skb->data);
+ struct hci_ev_status *ev;
struct discovery_state *discov = &hdev->discovery;
struct inquiry_entry *e;
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_INQUIRY_COMPLETE);
+ return;
+ }
+
+ BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_conn_check_pending(hdev);
@@ -2566,13 +2692,20 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
+ struct hci_ev_inquiry_result *ev;
struct inquiry_data data;
- struct inquiry_info *info = (void *) (skb->data + 1);
- int num_rsp = *((__u8 *) skb->data);
+ int i;
+
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev || skb->len < flex_array_size(ev, info, ev->num)) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_INQUIRY_RESULT);
+ return;
+ }
- BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+ BT_DBG("%s num %d", hdev->name, ev->num);
- if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1)
+ if (!ev->num)
return;
if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
@@ -2580,7 +2713,8 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_lock(hdev);
- for (; num_rsp; num_rsp--, info++) {
+ for (i = 0; i < ev->num; i++) {
+ struct inquiry_info *info = &ev->info[i];
u32 flags;
bacpy(&data.bdaddr, &info->bdaddr);
@@ -2604,9 +2738,16 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_conn_complete *ev = (void *) skb->data;
+ struct hci_ev_conn_complete *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_CONN_COMPLETE);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -2728,12 +2869,19 @@ static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr)
static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_conn_request *ev = (void *) skb->data;
+ struct hci_ev_conn_request *ev;
int mask = hdev->link_mode;
struct inquiry_entry *ie;
struct hci_conn *conn;
__u8 flags = 0;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_CONN_REQUEST);
+ return;
+ }
+
BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr,
ev->link_type);
@@ -2839,13 +2987,20 @@ static u8 hci_to_mgmt_reason(u8 err)
static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_disconn_complete *ev = (void *) skb->data;
+ struct hci_ev_disconn_complete *ev;
u8 reason;
struct hci_conn_params *params;
struct hci_conn *conn;
bool mgmt_connected;
u8 type;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_DISCONN_COMPLETE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -2931,9 +3086,16 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_auth_complete *ev = (void *) skb->data;
+ struct hci_ev_auth_complete *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_AUTH_COMPLETE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -3001,9 +3163,16 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_remote_name *ev = (void *) skb->data;
+ struct hci_ev_remote_name *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_REMOTE_NAME);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_conn_check_pending(hdev);
@@ -3084,9 +3253,16 @@ static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status,
static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_encrypt_change *ev = (void *) skb->data;
+ struct hci_ev_encrypt_change *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_ENCRYPT_CHANGE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -3199,9 +3375,16 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_change_link_key_complete *ev = (void *) skb->data;
+ struct hci_ev_change_link_key_complete *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_CHANGE_LINK_KEY_COMPLETE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -3222,9 +3405,16 @@ static void hci_change_link_key_complete_evt(struct hci_dev *hdev,
static void hci_remote_features_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_remote_features *ev = (void *) skb->data;
+ struct hci_ev_remote_features *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_REMOTE_FEATURES);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -3273,12 +3463,17 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
hci_req_complete_t *req_complete,
hci_req_complete_skb_t *req_complete_skb)
{
- struct hci_ev_cmd_complete *ev = (void *) skb->data;
+ struct hci_ev_cmd_complete *ev;
- *opcode = __le16_to_cpu(ev->opcode);
- *status = skb->data[sizeof(*ev)];
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_CMD_COMPLETE);
+ return;
+ }
- skb_pull(skb, sizeof(*ev));
+ *opcode = __le16_to_cpu(ev->opcode);
+ *status = skb->data[0];
switch (*opcode) {
case HCI_OP_INQUIRY_CANCEL:
@@ -3654,9 +3849,14 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
hci_req_complete_t *req_complete,
hci_req_complete_skb_t *req_complete_skb)
{
- struct hci_ev_cmd_status *ev = (void *) skb->data;
+ struct hci_ev_cmd_status *ev;
- skb_pull(skb, sizeof(*ev));
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_CMD_STATUS);
+ return;
+ }
*opcode = __le16_to_cpu(ev->opcode);
*status = ev->status;
@@ -3764,7 +3964,14 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_hardware_error *ev = (void *) skb->data;
+ struct hci_ev_hardware_error *ev;
+
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_HARDWARE_ERROR);
+ return;
+ }
hdev->hw_error_code = ev->code;
@@ -3773,9 +3980,16 @@ static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_role_change *ev = (void *) skb->data;
+ struct hci_ev_role_change *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_ROLE_CHANGE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -3795,23 +4009,24 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_num_comp_pkts *ev = (void *) skb->data;
+ struct hci_ev_num_comp_pkts *ev;
int i;
- if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
- bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev || skb->len < flex_array_size(ev, handles, ev->num)) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_NUM_COMP_PKTS);
return;
}
- if (skb->len < sizeof(*ev) ||
- skb->len < struct_size(ev, handles, ev->num_hndl)) {
- BT_DBG("%s bad parameters", hdev->name);
+ if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
+ bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
return;
}
- BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl);
+ BT_DBG("%s num %d", hdev->name, ev->num);
- for (i = 0; i < ev->num_hndl; i++) {
+ for (i = 0; i < ev->num; i++) {
struct hci_comp_pkts_info *info = &ev->handles[i];
struct hci_conn *conn;
__u16 handle, count;
@@ -3883,17 +4098,18 @@ static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_num_comp_blocks *ev = (void *) skb->data;
+ struct hci_ev_num_comp_blocks *ev;
int i;
- if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
- bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev || skb->len < flex_array_size(ev, handles, ev->num_hndl)) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_NUM_COMP_BLOCKS);
return;
}
- if (skb->len < sizeof(*ev) ||
- skb->len < struct_size(ev, handles, ev->num_hndl)) {
- BT_DBG("%s bad parameters", hdev->name);
+ if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
+ bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
return;
}
@@ -3934,9 +4150,16 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_mode_change *ev = (void *) skb->data;
+ struct hci_ev_mode_change *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_MODE_CHANGE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -3962,9 +4185,16 @@ static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_pin_code_req *ev = (void *) skb->data;
+ struct hci_ev_pin_code_req *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_PIN_CODE_REQ);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -4032,11 +4262,18 @@ static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_link_key_req *ev = (void *) skb->data;
+ struct hci_ev_link_key_req *ev;
struct hci_cp_link_key_reply cp;
struct hci_conn *conn;
struct link_key *key;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_LINK_KEY_REQ);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
if (!hci_dev_test_flag(hdev, HCI_MGMT))
@@ -4092,12 +4329,19 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_link_key_notify *ev = (void *) skb->data;
+ struct hci_ev_link_key_notify *ev;
struct hci_conn *conn;
struct link_key *key;
bool persistent;
u8 pin_len = 0;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_LINK_KEY_NOTIFY);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -4152,9 +4396,16 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_clock_offset *ev = (void *) skb->data;
+ struct hci_ev_clock_offset *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_CLOCK_OFFSET);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -4175,9 +4426,16 @@ static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_pkt_type_change *ev = (void *) skb->data;
+ struct hci_ev_pkt_type_change *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_PKT_TYPE_CHANGE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -4191,9 +4449,16 @@ static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_pscan_rep_mode *ev = (void *) skb->data;
+ struct hci_ev_pscan_rep_mode *ev;
struct inquiry_entry *ie;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_PSCAN_REP_MODE);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -4210,12 +4475,22 @@ static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
+ union {
+ struct hci_ev_inquiry_result_rssi *res1;
+ struct hci_ev_inquiry_result_rssi_pscan *res2;
+ } *ev = bt_skb_pull(skb, sizeof(*ev));
struct inquiry_data data;
- int num_rsp = *((__u8 *) skb->data);
+ int i;
- BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_INQUIRY_RESULT_WITH_RSSI);
+ return;
+ }
- if (!num_rsp)
+ BT_DBG("%s num_rsp %d", hdev->name, ev->res1->num);
+
+ if (!ev->res1->num)
return;
if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
@@ -4223,16 +4498,13 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
hci_dev_lock(hdev);
- if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) {
- struct inquiry_info_with_rssi_and_pscan_mode *info;
- info = (void *) (skb->data + 1);
-
- if (skb->len < num_rsp * sizeof(*info) + 1)
- goto unlock;
+ if (skb->len == flex_array_size(ev, res2->info, ev->res2->num)) {
+ struct inquiry_info_rssi_pscan *info;
- for (; num_rsp; num_rsp--, info++) {
+ for (i = 0; i < ev->res2->num; i++) {
u32 flags;
+ info = &ev->res2->info[i];
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
@@ -4248,15 +4520,13 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
info->dev_class, info->rssi,
flags, NULL, 0, NULL, 0);
}
- } else {
- struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
+ } else if (skb->len == flex_array_size(ev, res1->info, ev->res1->num)) {
+ struct inquiry_info_rssi *info;
- if (skb->len < num_rsp * sizeof(*info) + 1)
- goto unlock;
-
- for (; num_rsp; num_rsp--, info++) {
+ for (i = 0; i < ev->res1->num; i++) {
u32 flags;
+ info = &ev->res1->info[i];
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
@@ -4272,18 +4542,27 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev,
info->dev_class, info->rssi,
flags, NULL, 0, NULL, 0);
}
+ } else {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_INQUIRY_RESULT_WITH_RSSI);
}
-unlock:
hci_dev_unlock(hdev);
}
static void hci_remote_ext_features_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_remote_ext_features *ev = (void *) skb->data;
+ struct hci_ev_remote_ext_features *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_REMOTE_EXT_FEATURES);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -4345,9 +4624,16 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev,
static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_sync_conn_complete *ev = (void *) skb->data;
+ struct hci_ev_sync_conn_complete *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_SYNC_CONN_COMPLETE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -4443,14 +4729,21 @@ static inline size_t eir_get_length(u8 *eir, size_t eir_len)
static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
+ struct hci_ev_ext_inquiry_result *ev;
struct inquiry_data data;
- struct extended_inquiry_info *info = (void *) (skb->data + 1);
- int num_rsp = *((__u8 *) skb->data);
size_t eir_len;
+ int i;
- BT_DBG("%s num_rsp %d", hdev->name, num_rsp);
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev || skb->len < flex_array_size(ev, info, ev->num)) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_EXTENDED_INQUIRY_RESULT);
+ return;
+ }
- if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1)
+ BT_DBG("%s num %d", hdev->name, ev->num);
+
+ if (!ev->num)
return;
if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
@@ -4458,7 +4751,8 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
hci_dev_lock(hdev);
- for (; num_rsp; num_rsp--, info++) {
+ for (i = 0; i < ev->num; i++) {
+ struct extended_inquiry_info *info = &ev->info[i];
u32 flags;
bool name_known;
@@ -4493,9 +4787,16 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
static void hci_key_refresh_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_key_refresh_complete *ev = (void *) skb->data;
+ struct hci_ev_key_refresh_complete *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_KEY_REFRESH_COMPLETE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status,
__le16_to_cpu(ev->handle));
@@ -4602,9 +4903,16 @@ static u8 bredr_oob_data_present(struct hci_conn *conn)
static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_io_capa_request *ev = (void *) skb->data;
+ struct hci_ev_io_capa_request *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_IO_CAPA_REQUEST);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -4671,9 +4979,16 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_io_capa_reply *ev = (void *) skb->data;
+ struct hci_ev_io_capa_reply *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_IO_CAPA_REPLY);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -4692,10 +5007,17 @@ static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_user_confirm_request_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_user_confirm_req *ev = (void *) skb->data;
+ struct hci_ev_user_confirm_req *ev;
int loc_mitm, rem_mitm, confirm_hint = 0;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_USER_CONFIRM_REQUEST);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -4777,7 +5099,14 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
static void hci_user_passkey_request_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_user_passkey_req *ev = (void *) skb->data;
+ struct hci_ev_user_passkey_req *ev;
+
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_USER_PASSKEY_REQUEST);
+ return;
+ }
BT_DBG("%s", hdev->name);
@@ -4788,9 +5117,16 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev,
static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_user_passkey_notify *ev = (void *) skb->data;
+ struct hci_ev_user_passkey_notify *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_USER_PASSKEY_NOTIFY);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
@@ -4808,9 +5144,16 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev,
static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_keypress_notify *ev = (void *) skb->data;
+ struct hci_ev_keypress_notify *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_KEYPRESS_NOTIFY);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
@@ -4847,9 +5190,16 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_simple_pair_complete *ev = (void *) skb->data;
+ struct hci_ev_simple_pair_complete *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_SIMPLE_PAIR_COMPLETE);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -4878,10 +5228,17 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev,
static void hci_remote_host_features_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_remote_host_features *ev = (void *) skb->data;
+ struct hci_ev_remote_host_features *ev;
struct inquiry_entry *ie;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_REMOTE_HOST_FEATURES);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -4900,9 +5257,16 @@ static void hci_remote_host_features_evt(struct hci_dev *hdev,
static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
+ struct hci_ev_remote_oob_data_request *ev;
struct oob_data *data;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_REMOTE_OOB_DATA_REQUEST);
+ return;
+ }
+
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
@@ -4954,12 +5318,17 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
#if IS_ENABLED(CONFIG_BT_HS)
static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_channel_selected *ev = (void *)skb->data;
+ struct hci_ev_channel_selected *ev;
struct hci_conn *hcon;
- BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_CHANNEL_SELECTED);
+ return;
+ }
- skb_pull(skb, sizeof(*ev));
+ BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle);
hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
if (!hcon)
@@ -4971,9 +5340,16 @@ static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_phy_link_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_phy_link_complete *ev = (void *) skb->data;
+ struct hci_ev_phy_link_complete *ev;
struct hci_conn *hcon, *bredr_hcon;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_PHY_LINK_COMPLETE);
+ return;
+ }
+
BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle,
ev->status);
@@ -5011,11 +5387,18 @@ static void hci_phy_link_complete_evt(struct hci_dev *hdev,
static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_logical_link_complete *ev = (void *) skb->data;
+ struct hci_ev_logical_link_complete *ev;
struct hci_conn *hcon;
struct hci_chan *hchan;
struct amp_mgr *mgr;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_LOGICAL_LINK_COMPLETE);
+ return;
+ }
+
BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
hdev->name, le16_to_cpu(ev->handle), ev->phy_handle,
ev->status);
@@ -5051,9 +5434,16 @@ static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data;
+ struct hci_ev_disconn_logical_link_complete *ev;
struct hci_chan *hchan;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE);
+ return;
+ }
+
BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name,
le16_to_cpu(ev->handle), ev->status);
@@ -5075,9 +5465,15 @@ static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev,
static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data;
+ struct hci_ev_disconn_phy_link_complete *ev = bt_skb_pull(skb, sizeof(*ev));
struct hci_conn *hcon;
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_DISCONN_PHY_LINK_COMPLETE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
if (ev->status)
@@ -5259,7 +5655,14 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_le_conn_complete *ev = (void *) skb->data;
+ struct hci_ev_le_conn_complete *ev;
+
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_CONN_COMPLETE);
+ return;
+ }
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
@@ -5273,7 +5676,14 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_le_enh_conn_complete *ev = (void *) skb->data;
+ struct hci_ev_le_enh_conn_complete *ev;
+
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_ENHANCED_CONN_COMPLETE);
+ return;
+ }
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
@@ -5291,9 +5701,16 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev,
static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_evt_le_ext_adv_set_term *ev = (void *) skb->data;
+ struct hci_evt_le_ext_adv_set_term *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_EXT_ADV_SET_TERM);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
if (ev->status)
@@ -5320,9 +5737,16 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_le_conn_update_complete *ev = (void *) skb->data;
+ struct hci_ev_le_conn_update_complete *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_CONN_UPDATE_COMPLETE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
if (ev->status)
@@ -5639,25 +6063,41 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- u8 num_reports = skb->data[0];
- void *ptr = &skb->data[1];
+ struct hci_ev_le_advertising_report *ev;
+
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_ADVERTISING_REPORT);
+ return;
+ }
+
+ if (!ev->num)
+ return;
hci_dev_lock(hdev);
- while (num_reports--) {
- struct hci_ev_le_advertising_info *ev = ptr;
+ while (ev->num--) {
+ struct hci_ev_le_advertising_info *info;
s8 rssi;
- if (ev->length <= HCI_MAX_AD_LENGTH) {
- rssi = ev->data[ev->length];
- process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
- ev->bdaddr_type, NULL, 0, rssi,
- ev->data, ev->length, false);
+ info = bt_skb_pull(skb, sizeof(*info));
+ if (!info || skb->len < info->length + 1) {
+ bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
+ HCI_EV_LE_ADVERTISING_REPORT);
+ break;
+ }
+
+ if (info->length <= HCI_MAX_AD_LENGTH) {
+ rssi = info->data[info->length];
+ process_adv_report(hdev, info->type, &info->bdaddr,
+ info->bdaddr_type, NULL, 0, rssi,
+ info->data, info->length, false);
} else {
bt_dev_err(hdev, "Dropping invalid advertising data");
}
- ptr += sizeof(*ev) + ev->length + 1;
+ skb_pull(skb, info->length + 1);
}
hci_dev_unlock(hdev);
@@ -5709,26 +6149,42 @@ static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type)
static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- u8 num_reports = skb->data[0];
- void *ptr = &skb->data[1];
+ struct hci_ev_le_ext_adv_report *ev;
+
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_EXT_ADV_REPORT);
+ return;
+ }
+
+ if (!ev->num)
+ return;
hci_dev_lock(hdev);
- while (num_reports--) {
- struct hci_ev_le_ext_adv_report *ev = ptr;
+ while (ev->num--) {
+ struct hci_ev_le_ext_adv_info *info;
u8 legacy_evt_type;
u16 evt_type;
- evt_type = __le16_to_cpu(ev->evt_type);
+ info = bt_skb_pull(skb, sizeof(*info));
+ if (!info || skb->len < info->length) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_EXT_ADV_REPORT);
+ break;
+ }
+
+ evt_type = __le16_to_cpu(info->type);
legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type);
if (legacy_evt_type != LE_ADV_INVALID) {
- process_adv_report(hdev, legacy_evt_type, &ev->bdaddr,
- ev->bdaddr_type, NULL, 0, ev->rssi,
- ev->data, ev->length,
+ process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
+ info->bdaddr_type, NULL, 0,
+ info->rssi, info->data, info->length,
!(evt_type & LE_EXT_ADV_LEGACY_PDU));
}
- ptr += sizeof(*ev) + ev->length;
+ skb_pull(skb, info->length);
}
hci_dev_unlock(hdev);
@@ -5737,9 +6193,16 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_le_remote_feat_complete *ev = (void *)skb->data;
+ struct hci_ev_le_remote_feat_complete *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_EXT_ADV_REPORT);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
hci_dev_lock(hdev);
@@ -5778,12 +6241,19 @@ static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev,
static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_le_ltk_req *ev = (void *) skb->data;
+ struct hci_ev_le_ltk_req *ev;
struct hci_cp_le_ltk_reply cp;
struct hci_cp_le_ltk_neg_reply neg;
struct hci_conn *conn;
struct smp_ltk *ltk;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_LTK_REQ);
+ return;
+ }
+
BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle));
hci_dev_lock(hdev);
@@ -5855,11 +6325,18 @@ static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data;
+ struct hci_ev_le_remote_conn_param_req *ev;
struct hci_cp_le_conn_param_req_reply cp;
struct hci_conn *hcon;
u16 handle, min, max, latency, timeout;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_REMOTE_CONN_PARAM_REQ);
+ return;
+ }
+
handle = le16_to_cpu(ev->handle);
min = le16_to_cpu(ev->interval_min);
max = le16_to_cpu(ev->interval_max);
@@ -5913,28 +6390,45 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev,
static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
struct sk_buff *skb)
{
- u8 num_reports = skb->data[0];
- struct hci_ev_le_direct_adv_info *ev = (void *)&skb->data[1];
+ struct hci_ev_le_direct_adv_report *ev;
+ int i;
- if (!num_reports || skb->len < num_reports * sizeof(*ev) + 1)
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev || skb->len < flex_array_size(ev, info, ev->num)) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_REMOTE_CONN_PARAM_REQ);
+ return;
+ }
+
+ if (!ev->num)
return;
hci_dev_lock(hdev);
- for (; num_reports; num_reports--, ev++)
- process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
- ev->bdaddr_type, &ev->direct_addr,
- ev->direct_addr_type, ev->rssi, NULL, 0,
+ for (i = 0; i < ev->num; i++) {
+ struct hci_ev_le_direct_adv_info *info = &ev->info[i];
+
+ process_adv_report(hdev, info->type, &info->bdaddr,
+ info->bdaddr_type, &info->direct_addr,
+ info->direct_addr_type, info->rssi, NULL, 0,
false);
+ }
hci_dev_unlock(hdev);
}
static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_le_phy_update_complete *ev = (void *) skb->data;
+ struct hci_ev_le_phy_update_complete *ev;
struct hci_conn *conn;
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent: 0x%2.2x",
+ HCI_EV_LE_PHY_UPDATE_COMPLETE);
+ return;
+ }
+
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
if (ev->status)
@@ -5955,11 +6449,15 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- struct hci_ev_le_meta *le_ev = (void *) skb->data;
+ struct hci_ev_le_meta *ev;
- skb_pull(skb, sizeof(*le_ev));
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
+ bt_dev_err(hdev, "Malformed HCI LE metaevent");
+ return;
+ }
- switch (le_ev->subevent) {
+ switch (ev->subevent) {
case HCI_EV_LE_CONN_COMPLETE:
hci_le_conn_complete_evt(hdev, skb);
break;
@@ -6018,14 +6516,12 @@ static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
if (!skb)
return false;
- if (skb->len < sizeof(*hdr)) {
+ hdr = bt_skb_pull(skb, sizeof(*hdr));
+ if (!hdr) {
bt_dev_err(hdev, "too short HCI event");
return false;
}
- hdr = (void *) skb->data;
- skb_pull(skb, HCI_EVENT_HDR_SIZE);
-
if (event) {
if (hdr->evt != event)
return false;
@@ -6044,14 +6540,12 @@ static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
return false;
}
- if (skb->len < sizeof(*ev)) {
+ ev = bt_skb_pull(skb, sizeof(*ev));
+ if (!ev) {
bt_dev_err(hdev, "too short cmd_complete event");
return false;
}
- ev = (void *) skb->data;
- skb_pull(skb, sizeof(*ev));
-
if (opcode != __le16_to_cpu(ev->opcode)) {
BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode,
__le16_to_cpu(ev->opcode));
@@ -6066,7 +6560,7 @@ static void hci_store_wake_reason(struct hci_dev *hdev, u8 event,
{
struct hci_ev_le_advertising_info *adv;
struct hci_ev_le_direct_adv_info *direct_adv;
- struct hci_ev_le_ext_adv_report *ext_adv;
+ struct hci_ev_le_ext_adv_info *ext_adv;
const struct hci_ev_conn_complete *conn_complete = (void *)skb->data;
const struct hci_ev_conn_request *conn_request = (void *)skb->data;
@@ -6136,9 +6630,15 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_req_complete_t req_complete = NULL;
hci_req_complete_skb_t req_complete_skb = NULL;
struct sk_buff *orig_skb = NULL;
- u8 status = 0, event = hdr->evt, req_evt = 0;
+ u8 status = 0, event, req_evt = 0;
u16 opcode = HCI_OP_NOP;
+ if (skb->len < sizeof(*hdr)) {
+ bt_dev_err(hdev, "Malformed HCI Event");
+ goto done;
+ }
+
+ event = hdr->evt;
if (!event) {
bt_dev_warn(hdev, "Received unexpected HCI Event 00000000");
goto done;