Skip to content

Commit e878540

Browse files
pvVudentz
authored andcommitted
Bluetooth: MGMT: fix crash in set_mesh_sync and set_mesh_complete
There is a BUG: KASAN: stack-out-of-bounds in set_mesh_sync due to memcpy from badly declared on-stack flexible array. Another crash is in set_mesh_complete() due to double list_del via mgmt_pending_valid + mgmt_pending_remove. Use DEFINE_FLEX to declare the flexible array right, and don't memcpy outside bounds. As mgmt_pending_valid removes the cmd from list, use mgmt_pending_free, and also report status on error. Fixes: 302a1f6 ("Bluetooth: MGMT: Fix possible UAFs") Signed-off-by: Pauli Virtanen <pav@iki.fi> Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
1 parent 0d92808 commit e878540

2 files changed

Lines changed: 16 additions & 12 deletions

File tree

include/net/bluetooth/mgmt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ struct mgmt_cp_set_mesh {
853853
__le16 window;
854854
__le16 period;
855855
__u8 num_ad_types;
856-
__u8 ad_types[];
856+
__u8 ad_types[] __counted_by(num_ad_types);
857857
} __packed;
858858
#define MGMT_SET_MESH_RECEIVER_SIZE 6
859859

net/bluetooth/mgmt.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,19 +2175,24 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err)
21752175
sk = cmd->sk;
21762176

21772177
if (status) {
2178+
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER,
2179+
status);
21782180
mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true,
21792181
cmd_status_rsp, &status);
2180-
return;
2182+
goto done;
21812183
}
21822184

2183-
mgmt_pending_remove(cmd);
21842185
mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, 0, NULL, 0);
2186+
2187+
done:
2188+
mgmt_pending_free(cmd);
21852189
}
21862190

21872191
static int set_mesh_sync(struct hci_dev *hdev, void *data)
21882192
{
21892193
struct mgmt_pending_cmd *cmd = data;
2190-
struct mgmt_cp_set_mesh cp;
2194+
DEFINE_FLEX(struct mgmt_cp_set_mesh, cp, ad_types, num_ad_types,
2195+
sizeof(hdev->mesh_ad_types));
21912196
size_t len;
21922197

21932198
mutex_lock(&hdev->mgmt_pending_lock);
@@ -2197,27 +2202,26 @@ static int set_mesh_sync(struct hci_dev *hdev, void *data)
21972202
return -ECANCELED;
21982203
}
21992204

2200-
memcpy(&cp, cmd->param, sizeof(cp));
2205+
len = cmd->param_len;
2206+
memcpy(cp, cmd->param, min(__struct_size(cp), len));
22012207

22022208
mutex_unlock(&hdev->mgmt_pending_lock);
22032209

2204-
len = cmd->param_len;
2205-
22062210
memset(hdev->mesh_ad_types, 0, sizeof(hdev->mesh_ad_types));
22072211

2208-
if (cp.enable)
2212+
if (cp->enable)
22092213
hci_dev_set_flag(hdev, HCI_MESH);
22102214
else
22112215
hci_dev_clear_flag(hdev, HCI_MESH);
22122216

2213-
hdev->le_scan_interval = __le16_to_cpu(cp.period);
2214-
hdev->le_scan_window = __le16_to_cpu(cp.window);
2217+
hdev->le_scan_interval = __le16_to_cpu(cp->period);
2218+
hdev->le_scan_window = __le16_to_cpu(cp->window);
22152219

2216-
len -= sizeof(cp);
2220+
len -= sizeof(struct mgmt_cp_set_mesh);
22172221

22182222
/* If filters don't fit, forward all adv pkts */
22192223
if (len <= sizeof(hdev->mesh_ad_types))
2220-
memcpy(hdev->mesh_ad_types, cp.ad_types, len);
2224+
memcpy(hdev->mesh_ad_types, cp->ad_types, len);
22212225

22222226
hci_update_passive_scan_sync(hdev);
22232227
return 0;

0 commit comments

Comments
 (0)