* [bug report] Bluetooth: ISO: Add broadcast support
@ 2022-07-29 8:00 Dan Carpenter
0 siblings, 0 replies; only message in thread
From: Dan Carpenter @ 2022-07-29 8:00 UTC (permalink / raw)
To: luiz.von.dentz, Harshit Mogalapalli; +Cc: linux-bluetooth
Hi Luiz,
Harshit Mogalapalli brought this memory corruption issue to me. Can you
take a look? I don't know how to fix it.
The patch f764a6c2c1e4: "Bluetooth: ISO: Add broadcast support" from
Mar 9, 2022, leads to the following Smatch static checker warning:
net/bluetooth/iso.c:1282 iso_sock_getsockopt()
error: copy_to_user() 'base' too small (252 vs 254)
That warning is because Smatch gets confused but in reviewing the code,
it turns out that Smatch is correct (like a stopped clock which is
correct by accident). The actual bug happens earlier in
eir_append_service_data().
Step 1: iso_sock_setsockopt() sets ->base_len to 0-252
net/bluetooth/iso.c
1208 if (optlen > sizeof(iso_pi(sk)->base)) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1209 err = -EOVERFLOW;
1210 break;
1211 }
1212
1213 len = min_t(unsigned int, sizeof(iso_pi(sk)->base), optlen);
1214
1215 if (copy_from_sockptr(iso_pi(sk)->base, optval, len)) {
1216 err = -EFAULT;
1217 break;
1218 }
1219
1220 iso_pi(sk)->base_len = len;
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Step 2: iso_connect_bis() passes ->base_len to hci_connect_bis()
net/bluetooth/iso.c
235 static int iso_connect_bis(struct sock *sk)
236 {
237 struct iso_conn *conn;
238 struct hci_conn *hcon;
239 struct hci_dev *hdev;
240 int err;
241
242 BT_DBG("%pMR", &iso_pi(sk)->src);
243
244 hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
245 iso_pi(sk)->src_type);
246 if (!hdev)
247 return -EHOSTUNREACH;
248
249 hci_dev_lock(hdev);
250
251 if (!bis_capable(hdev)) {
252 err = -EOPNOTSUPP;
253 goto done;
254 }
255
256 /* Fail if out PHYs are marked as disabled */
257 if (!iso_pi(sk)->qos.out.phy) {
258 err = -EINVAL;
259 goto done;
260 }
261
262 hcon = hci_connect_bis(hdev, &iso_pi(sk)->dst, iso_pi(sk)->dst_type,
263 &iso_pi(sk)->qos, iso_pi(sk)->base_len,
^^^^^^^^^^^^^^^^^^^^^
264 iso_pi(sk)->base);
265 if (IS_ERR(hcon)) {
266 err = PTR_ERR(hcon);
Step 3: hci_connect_bis() passes base_len to eir_append_service_data().
The buffer here is ->le_per_adv_data which is also size 252 bytes.
net/bluetooth/hci_conn.c
2058 /* Add Basic Announcement into Peridic Adv Data if BASE is set */
2059 if (base_len && base) {
2060 base_len = eir_append_service_data(conn->le_per_adv_data, 0,
^^^^^^^^^^^^^^^^^^^^^
2061 0x1851, base, base_len);
^^^^^^^^
2062 conn->le_per_adv_data_len = base_len;
2063 }
Step 4: memory corruption in eir_append_service_data()
net/bluetooth/eir.c
69 u8 eir_append_service_data(u8 *eir, u16 eir_len, u16 uuid, u8 *data,
70 u8 data_len)
71 {
72 eir[eir_len++] = sizeof(u8) + sizeof(uuid) + data_len;
73 eir[eir_len++] = EIR_SERVICE_DATA;
74 put_unaligned_le16(uuid, &eir[eir_len]);
75 eir_len += sizeof(uuid);
76 memcpy(&eir[eir_len], data, data_len);
^^^^^^^ ^^^^^^^^
77 eir_len += data_len;
78
79 return eir_len;
80 }
The "eir" buffer has 252 bytes and data_len is 252 but we do a memcpy()
to &eir[4] so this can corrupt 4 bytes beyond the end of the buffer.
If you look back at the caller it sets conn->le_per_adv_data_len to a
max of 4 + 252 = 256 but truncated to 255. This eventually gets passed
to iso_sock_getsockopt() leading to a read overflow. But the first part
of the bug is in eir_append_service_data().
regards,
dan carpenter
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-07-29 8:01 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-29 8:00 [bug report] Bluetooth: ISO: Add broadcast support Dan Carpenter
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.