Skip to content

Commit 5c19daa

Browse files
pvgregkh
authored andcommitted
Bluetooth: MGMT: fix crash in set_mesh_sync and set_mesh_complete
commit e878540 upstream. 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 <[email protected]> Reviewed-by: Paul Menzel <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 01c7a6e commit 5c19daa

File tree

2 files changed

+16
-12
lines changed

2 files changed

+16
-12
lines changed

include/net/bluetooth/mgmt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,7 @@ struct mgmt_cp_set_mesh {
847847
__le16 window;
848848
__le16 period;
849849
__u8 num_ad_types;
850-
__u8 ad_types[];
850+
__u8 ad_types[] __counted_by(num_ad_types);
851851
} __packed;
852852
#define MGMT_SET_MESH_RECEIVER_SIZE 6
853853

net/bluetooth/mgmt.c

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

21722172
if (status) {
2173+
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER,
2174+
status);
21732175
mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true,
21742176
cmd_status_rsp, &status);
2175-
return;
2177+
goto done;
21762178
}
21772179

2178-
mgmt_pending_remove(cmd);
21792180
mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, 0, NULL, 0);
2181+
2182+
done:
2183+
mgmt_pending_free(cmd);
21802184
}
21812185

21822186
static int set_mesh_sync(struct hci_dev *hdev, void *data)
21832187
{
21842188
struct mgmt_pending_cmd *cmd = data;
2185-
struct mgmt_cp_set_mesh cp;
2189+
DEFINE_FLEX(struct mgmt_cp_set_mesh, cp, ad_types, num_ad_types,
2190+
sizeof(hdev->mesh_ad_types));
21862191
size_t len;
21872192

21882193
mutex_lock(&hdev->mgmt_pending_lock);
@@ -2192,27 +2197,26 @@ static int set_mesh_sync(struct hci_dev *hdev, void *data)
21922197
return -ECANCELED;
21932198
}
21942199

2195-
memcpy(&cp, cmd->param, sizeof(cp));
2200+
len = cmd->param_len;
2201+
memcpy(cp, cmd->param, min(__struct_size(cp), len));
21962202

21972203
mutex_unlock(&hdev->mgmt_pending_lock);
21982204

2199-
len = cmd->param_len;
2200-
22012205
memset(hdev->mesh_ad_types, 0, sizeof(hdev->mesh_ad_types));
22022206

2203-
if (cp.enable)
2207+
if (cp->enable)
22042208
hci_dev_set_flag(hdev, HCI_MESH);
22052209
else
22062210
hci_dev_clear_flag(hdev, HCI_MESH);
22072211

2208-
hdev->le_scan_interval = __le16_to_cpu(cp.period);
2209-
hdev->le_scan_window = __le16_to_cpu(cp.window);
2212+
hdev->le_scan_interval = __le16_to_cpu(cp->period);
2213+
hdev->le_scan_window = __le16_to_cpu(cp->window);
22102214

2211-
len -= sizeof(cp);
2215+
len -= sizeof(struct mgmt_cp_set_mesh);
22122216

22132217
/* If filters don't fit, forward all adv pkts */
22142218
if (len <= sizeof(hdev->mesh_ad_types))
2215-
memcpy(hdev->mesh_ad_types, cp.ad_types, len);
2219+
memcpy(hdev->mesh_ad_types, cp->ad_types, len);
22162220

22172221
hci_update_passive_scan_sync(hdev);
22182222
return 0;

0 commit comments

Comments
 (0)