All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.