Skip to content

Commit b75ef21

Browse files
Arseniy Krasnovopsiff
authored andcommitted
Bluetooth: hci_sync: fix double free in 'hci_discovery_filter_clear()'
[ Upstream commit 2935e556850e9c94d7a00adf14d3cd7fe406ac03 ] Function 'hci_discovery_filter_clear()' frees 'uuids' array and then sets it to NULL. There is a tiny chance of the following race: 'hci_cmd_sync_work()' 'update_passive_scan_sync()' 'hci_update_passive_scan_sync()' 'hci_discovery_filter_clear()' kfree(uuids); <-------------------------preempted--------------------------------> 'start_service_discovery()' 'hci_discovery_filter_clear()' kfree(uuids); // DOUBLE FREE <-------------------------preempted--------------------------------> uuids = NULL; To fix it let's add locking around 'kfree()' call and NULL pointer assignment. Otherwise the following backtrace fires: [ ] ------------[ cut here ]------------ [ ] kernel BUG at mm/slub.c:547! [ ] Internal error: Oops - BUG: 00000000f2000800 [#1] PREEMPT SMP [ ] CPU: 3 UID: 0 PID: 246 Comm: bluetoothd Tainted: G O 6.12.19-kernel #1 [ ] Tainted: [O]=OOT_MODULE [ ] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ ] pc : __slab_free+0xf8/0x348 [ ] lr : __slab_free+0x48/0x348 ... [ ] Call trace: [ ] __slab_free+0xf8/0x348 [ ] kfree+0x164/0x27c [ ] start_service_discovery+0x1d0/0x2c0 [ ] hci_sock_sendmsg+0x518/0x924 [ ] __sock_sendmsg+0x54/0x60 [ ] sock_write_iter+0x98/0xf8 [ ] do_iter_readv_writev+0xe4/0x1c8 [ ] vfs_writev+0x128/0x2b0 [ ] do_writev+0xfc/0x118 [ ] __arm64_sys_writev+0x20/0x2c [ ] invoke_syscall+0x68/0xf0 [ ] el0_svc_common.constprop.0+0x40/0xe0 [ ] do_el0_svc+0x1c/0x28 [ ] el0_svc+0x30/0xd0 [ ] el0t_64_sync_handler+0x100/0x12c [ ] el0t_64_sync+0x194/0x198 [ ] Code: 8b0002e6 eb17031f 54fffbe1 d503201f (d4210000) [ ] ---[ end trace 0000000000000000 ]--- Fixes: ad383c2 ("Bluetooth: hci_sync: Enable advertising when LL privacy is enabled") Signed-off-by: Arseniy Krasnov <[email protected]> Signed-off-by: Luiz Augusto von Dentz <[email protected]> Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit 16852eccbdfaf41a666705e3f8be55cf2864c5ca)
1 parent 6a48392 commit b75ef21

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <linux/idr.h>
3030
#include <linux/leds.h>
3131
#include <linux/rculist.h>
32+
#include <linux/spinlock.h>
3233
#include <linux/srcu.h>
3334

3435
#include <net/bluetooth/hci.h>
@@ -93,6 +94,7 @@ struct discovery_state {
9394
u16 uuid_count;
9495
u8 (*uuids)[16];
9596
unsigned long name_resolve_timeout;
97+
spinlock_t lock;
9698
};
9799

98100
#define SUSPEND_NOTIFIER_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
@@ -873,6 +875,7 @@ static inline void iso_recv(struct hci_conn *hcon, struct sk_buff *skb,
873875

874876
static inline void discovery_init(struct hci_dev *hdev)
875877
{
878+
spin_lock_init(&hdev->discovery.lock);
876879
hdev->discovery.state = DISCOVERY_STOPPED;
877880
INIT_LIST_HEAD(&hdev->discovery.all);
878881
INIT_LIST_HEAD(&hdev->discovery.unknown);
@@ -887,8 +890,11 @@ static inline void hci_discovery_filter_clear(struct hci_dev *hdev)
887890
hdev->discovery.report_invalid_rssi = true;
888891
hdev->discovery.rssi = HCI_RSSI_INVALID;
889892
hdev->discovery.uuid_count = 0;
893+
894+
spin_lock(&hdev->discovery.lock);
890895
kfree(hdev->discovery.uuids);
891896
hdev->discovery.uuids = NULL;
897+
spin_unlock(&hdev->discovery.lock);
892898
}
893899

894900
bool hci_discovery_active(struct hci_dev *hdev);

0 commit comments

Comments
 (0)