diff mbox series

Bluetooth: do not send mgmt commands to device which is going to close

Message ID 20241007074538.109613-1-dmantipov@yandex.ru
State New
Headers show
Series Bluetooth: do not send mgmt commands to device which is going to close | expand

Commit Message

Dmitry Antipov Oct. 7, 2024, 7:45 a.m. UTC
Syzbot has observed the following race between 'hci_dev_close()' and
'hci_cmd_sync_work()':

T0:                             T1:

...
-> sock_ioctl()
 -> sock_do_ioctl()
  -> hci_dev_close()
   -> hci_dev_close_sync()
    -> __mgmt_power_off()        ...
     -> mgmt_pending_foreach()   -> process_scheduled_works()
      -> settings_rsp()           -> hci_cmd_sync_work()
       -> kfree()                  -> set_powered_sync()

That is, 'hci_cmd_sync_work()' makes an attempt to process a command
from (partially) freed 'cmd_sync_work_list', which causes UAF detected
by KASAN. Fix this by marking the closing device with HCI_CLOSING bit
very early and rejecting new mgmt commands for such a device.

Reported-by: syzbot+03d6270b6425df1605bf@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=03d6270b6425df1605bf
Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
---
 include/net/bluetooth/hci.h | 1 +
 net/bluetooth/hci_core.c    | 4 ++++
 net/bluetooth/hci_sock.c    | 5 +++++
 3 files changed, 10 insertions(+)

Comments

Fedor Pchelkin Oct. 10, 2024, 1:50 p.m. UTC | #1
Hi Dmitry,

On Mon, 07. Oct 10:45, Dmitry Antipov wrote:
> Syzbot has observed the following race between 'hci_dev_close()' and
> 'hci_cmd_sync_work()':
> 
> T0:                             T1:
> 
> ...
> -> sock_ioctl()
>  -> sock_do_ioctl()
>   -> hci_dev_close()
>    -> hci_dev_close_sync()
>     -> __mgmt_power_off()        ...
>      -> mgmt_pending_foreach()   -> process_scheduled_works()
>       -> settings_rsp()           -> hci_cmd_sync_work()
>        -> kfree()                  -> set_powered_sync()

I guess commit f53e1c9c726d ("Bluetooth: MGMT: Fix possible crash on mgmt_index_removed") [1]
is supposed to fix the observed race. Is there something missing?

[1]: https://git.kernel.org/torvalds/c/f53e1c9c726d83092167f2226f32bd3b73f26c21

> Reported-by: syzbot+03d6270b6425df1605bf@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=03d6270b6425df1605bf

Btw, `Fixes` tag is really desirable if you are fixing bugs in kernel, like
KASAN splats and others.

> Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
> ---
diff mbox series

Patch

diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index bab1e3d7452a..492723a22e68 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -345,6 +345,7 @@  enum {
 	HCI_UP,
 	HCI_INIT,
 	HCI_RUNNING,
+	HCI_CLOSING,
 
 	HCI_PSCAN,
 	HCI_ISCAN,
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 629c302f7407..95f55cfb6da6 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -501,12 +501,16 @@  int hci_dev_close(__u16 dev)
 		goto done;
 	}
 
+	set_bit(HCI_CLOSING, &hdev->flags);
+
 	cancel_work_sync(&hdev->power_on);
 	if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF))
 		cancel_delayed_work(&hdev->power_off);
 
 	err = hci_dev_do_close(hdev);
 
+	if (unlikely(err))
+		clear_bit(HCI_CLOSING, &hdev->flags);
 done:
 	hci_dev_put(hdev);
 	return err;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 2272e1849ebd..ff43718822d4 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -1671,6 +1671,11 @@  static int hci_mgmt_cmd(struct hci_mgmt_chan *chan, struct sock *sk,
 			goto done;
 		}
 
+		if (unlikely(test_bit(HCI_CLOSING, &hdev->flags))) {
+			err = -ENODEV;
+			goto done;
+		}
+
 		if (hci_dev_test_flag(hdev, HCI_SETUP) ||
 		    hci_dev_test_flag(hdev, HCI_CONFIG) ||
 		    hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {