From: Johan Hedberg Date: Mon, 24 Mar 2014 12:39:03 +0000 (+0200) Subject: Bluetooth: Fix potential NULL pointer dereference in SMP X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=0a66cf203676f794084c6a97189eb41565bfd6aa;p=linux-beck.git Bluetooth: Fix potential NULL pointer dereference in SMP If a sudden disconnection happens the l2cap_conn pointer may already have been cleaned up by the time hci_conn_security gets called, resulting in the following oops if we don't have a proper NULL check: BUG: unable to handle kernel NULL pointer dereference at 000000c8 IP: [] smp_conn_security+0x26/0x151 *pde = 00000000 Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC CPU: 1 PID: 673 Comm: memcheck-x86-li Not tainted 3.14.0-rc2+ #437 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 task: f0ef0520 ti: f0d6a000 task.ti: f0d6a000 EIP: 0060:[] EFLAGS: 00010246 CPU: 1 EIP is at smp_conn_security+0x26/0x151 EAX: f0ec1770 EBX: f0ec1770 ECX: 00000002 EDX: 00000002 ESI: 00000002 EDI: 00000000 EBP: f0d6bdc0 ESP: f0d6bda0 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 CR0: 80050033 CR2: 000000c8 CR3: 30f0f000 CR4: 00000690 Stack: f4f55000 00000002 f0d6bdcc c1097a2b c1319f40 f0ec1770 00000002 f0d6bdd0 f0d6bde8 c1312a82 f0d6bdfc c1312a82 c1319f84 00000008 f4d81c20 f0e5fd86 f0ec1770 f0d6bdfc f0d6be28 c131be3b c131bdc1 f0d25270 c131be3b 00000008 Call Trace: [] ? __kmalloc+0x118/0x128 [] ? mgmt_pending_add+0x49/0x9b [] hci_conn_security+0x4a/0x1dd [] ? hci_conn_security+0x4a/0x1dd [] ? mgmt_pending_add+0x8d/0x9b [] pair_device+0x1e1/0x206 [] ? pair_device+0x167/0x206 [] ? pair_device+0x1e1/0x206 [] mgmt_control+0x275/0x2d6 Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 8d618e4654a5..b8c31467a7ac 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -884,11 +884,17 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level) int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) { struct l2cap_conn *conn = hcon->l2cap_data; - struct smp_chan *smp = conn->smp_chan; + struct smp_chan *smp; __u8 authreq; BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); + /* This may be NULL if there's an unexpected disconnection */ + if (!conn) + return 1; + + smp = conn->smp_chan; + if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) return 1;