[PATCH 4.4.y] Bluetooth: Fix decrementing reference count twice in releasing socket

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Myungho Jung <mhjungk@xxxxxxxxx>

commit e20a2e9c42c9e4002d9e338d74e7819e88d77162 upstream

When releasing socket, it is possible to enter hci_sock_release() and
hci_sock_dev_event(HCI_DEV_UNREG) at the same time in different thread.
The reference count of hdev should be decremented only once from one of
them but if storing hdev to local variable in hci_sock_release() before
detached from socket and setting to NULL in hci_sock_dev_event(),
hci_dev_put(hdev) is unexpectedly called twice. This is resolved by
referencing hdev from socket after bt_sock_unlink() in
hci_sock_release().

Reported-by: syzbot+fdc00003f4efff43bc5b@xxxxxxxxxxxxxxxxxxxxxxxxx
Signed-off-by: Myungho Jung <mhjungk@xxxxxxxxx>
Signed-off-by: Marcel Holtmann <marcel@xxxxxxxxxxxx>
Signed-off-by: Zubin Mithra <zsm@xxxxxxxxxxxx>
---
Notes:
* Syzkaller reported a UAF read with the following call trace when fuzzing a
4.4 kernel.
Call Trace:
 [<ffffffff8198c89a>] __dump_stack lib/dump_stack.c:15 [inline]
 [<ffffffff8198c89a>] dump_stack+0xbf/0x113 lib/dump_stack.c:51
 [<ffffffff8146d0d8>] print_trailer+0x14c/0x155 mm/slub.c:658
 [<ffffffff814542cd>] check_bytes_and_report+0xa8/0xe9 mm/slub.c:725
 [<ffffffff814546d2>] check_object+0x108/0x1eb mm/slub.c:846
 [<ffffffff81454f84>] alloc_debug_processing+0x65/0x103 mm/slub.c:1057
 [<ffffffff8145519a>] ___slab_alloc.constprop.68+0x178/0x3c3 mm/slub.c:2421
 [<ffffffff8145542d>] __slab_alloc.isra.63.constprop.67+0x48/0x79 mm/slub.c:2450
 [<ffffffff814558f4>] slab_alloc_node mm/slub.c:2513 [inline]
 [<ffffffff814558f4>] slab_alloc mm/slub.c:2555 [inline]
 [<ffffffff814558f4>] __kmalloc+0xb6/0x170 mm/slub.c:3521
 [<ffffffff82f97bf4>] kmalloc include/linux/slab.h:481 [inline]
 [<ffffffff82f97bf4>] kzalloc.constprop.17+0x1c/0x1e include/linux/slab.h:620
 [<ffffffff82f97c15>] hci_alloc_dev+0x1f/0x156c net/bluetooth/hci_core.c:2945
 [<ffffffff827ce5ab>] __vhci_create_device+0x8c/0x3f9 drivers/bluetooth/hci_vhci.c:114
 [<ffffffff827cebe0>] vhci_create_device drivers/bluetooth/hci_vhci.c:163 [inline]
 [<ffffffff827cebe0>] vhci_get_user drivers/bluetooth/hci_vhci.c:219 [inline]
 [<ffffffff827cebe0>] vhci_write+0x2c8/0x317 drivers/bluetooth/hci_vhci.c:299
 [<ffffffff81473309>] new_sync_write fs/read_write.c:478 [inline]
 [<ffffffff81473309>] __vfs_write+0x22c/0x2dd fs/read_write.c:491
 [<ffffffff81474724>] vfs_write+0x14c/0x182 fs/read_write.c:538
 [<ffffffff814759e1>] SYSC_write fs/read_write.c:585 [inline]
 [<ffffffff814759e1>] SyS_write+0xdf/0x163 fs/read_write.c:577
 [<ffffffff832c56ba>] entry_SYSCALL_64_fastpath+0x31/0xb3
* This commit is present in 4.9.y.
* Applying the original upstream commit causes a conflict as there is a
change in the surrounding code.
* Tests run: Chrome OS tryjobs, Syzkaller reproducer

 net/bluetooth/hci_sock.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index c842f40c1173..ea1cd8b21708 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -558,13 +558,12 @@ static int hci_sock_release(struct socket *sock)
 	if (!sk)
 		return 0;
 
-	hdev = hci_pi(sk)->hdev;
-
 	if (hci_pi(sk)->channel == HCI_CHANNEL_MONITOR)
 		atomic_dec(&monitor_promisc);
 
 	bt_sock_unlink(&hci_sk_list, sk);
 
+	hdev = hci_pi(sk)->hdev;
 	if (hdev) {
 		if (hci_pi(sk)->channel == HCI_CHANNEL_USER) {
 			/* When releasing an user channel exclusive access,
-- 
2.21.0.392.gf8f6787159e-goog




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux