diff mbox series

[v4] Bluetooth: L2CAP: Fix slab-use-after-free Read in l2cap_send_cmd

Message ID 20250117184202.3895460-1-luiz.dentz@gmail.com
State New
Headers show
Series [v4] Bluetooth: L2CAP: Fix slab-use-after-free Read in l2cap_send_cmd | expand

Commit Message

Luiz Augusto von Dentz Jan. 17, 2025, 6:42 p.m. UTC
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>

After the hci sync command releases l2cap_conn, the hci receive data work
queue references the released l2cap_conn when sending to the upper layer.
Add hci dev lock to the hci receive data work queue to synchronize the two.

[1]
BUG: KASAN: slab-use-after-free in l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954
Read of size 8 at addr ffff8880271a4000 by task kworker/u9:2/5837

CPU: 0 UID: 0 PID: 5837 Comm: kworker/u9:2 Not tainted 6.13.0-rc5-syzkaller-00163-gab75170520d4 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
Workqueue: hci1 hci_rx_work
Call Trace:
 <TASK>
 __dump_stack lib/dump_stack.c:94 [inline]
 dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
 print_address_description mm/kasan/report.c:378 [inline]
 print_report+0x169/0x550 mm/kasan/report.c:489
 kasan_report+0x143/0x180 mm/kasan/report.c:602
 l2cap_build_cmd net/bluetooth/l2cap_core.c:2964 [inline]
 l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954
 l2cap_sig_send_rej net/bluetooth/l2cap_core.c:5502 [inline]
 l2cap_sig_channel net/bluetooth/l2cap_core.c:5538 [inline]
 l2cap_recv_frame+0x221f/0x10db0 net/bluetooth/l2cap_core.c:6817
 hci_acldata_packet net/bluetooth/hci_core.c:3797 [inline]
 hci_rx_work+0x508/0xdb0 net/bluetooth/hci_core.c:4040
 process_one_work kernel/workqueue.c:3229 [inline]
 process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
 worker_thread+0x870/0xd30 kernel/workqueue.c:3391
 kthread+0x2f0/0x390 kernel/kthread.c:389
 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
 </TASK>

Allocated by task 5837:
 kasan_save_stack mm/kasan/common.c:47 [inline]
 kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
 poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
 __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:394
 kasan_kmalloc include/linux/kasan.h:260 [inline]
 __kmalloc_cache_noprof+0x243/0x390 mm/slub.c:4329
 kmalloc_noprof include/linux/slab.h:901 [inline]
 kzalloc_noprof include/linux/slab.h:1037 [inline]
 l2cap_conn_add+0xa9/0x8e0 net/bluetooth/l2cap_core.c:6860
 l2cap_connect_cfm+0x115/0x1090 net/bluetooth/l2cap_core.c:7239
 hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
 hci_remote_features_evt+0x68e/0xac0 net/bluetooth/hci_event.c:3726
 hci_event_func net/bluetooth/hci_event.c:7473 [inline]
 hci_event_packet+0xac2/0x1540 net/bluetooth/hci_event.c:7525
 hci_rx_work+0x3f3/0xdb0 net/bluetooth/hci_core.c:4035
 process_one_work kernel/workqueue.c:3229 [inline]
 process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
 worker_thread+0x870/0xd30 kernel/workqueue.c:3391
 kthread+0x2f0/0x390 kernel/kthread.c:389
 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244

Freed by task 54:
 kasan_save_stack mm/kasan/common.c:47 [inline]
 kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
 kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:582
 poison_slab_object mm/kasan/common.c:247 [inline]
 __kasan_slab_free+0x59/0x70 mm/kasan/common.c:264
 kasan_slab_free include/linux/kasan.h:233 [inline]
 slab_free_hook mm/slub.c:2353 [inline]
 slab_free mm/slub.c:4613 [inline]
 kfree+0x196/0x430 mm/slub.c:4761
 l2cap_connect_cfm+0xcc/0x1090 net/bluetooth/l2cap_core.c:7235
 hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
 hci_conn_failed+0x287/0x400 net/bluetooth/hci_conn.c:1266
 hci_abort_conn_sync+0x56c/0x11f0 net/bluetooth/hci_sync.c:5603
 hci_cmd_sync_work+0x22b/0x400 net/bluetooth/hci_sync.c:332
 process_one_work kernel/workqueue.c:3229 [inline]
 process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
 worker_thread+0x870/0xd30 kernel/workqueue.c:3391
 kthread+0x2f0/0x390 kernel/kthread.c:389
 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244

Reported-by: syzbot+31c2f641b850a348a734@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=31c2f641b850a348a734
Tested-by: syzbot+31c2f641b850a348a734@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
---
 net/bluetooth/l2cap_core.c | 45 ++++++++++++++++++++++++++++++++++----
 1 file changed, 41 insertions(+), 4 deletions(-)

Comments

bluez.test.bot@gmail.com Jan. 17, 2025, 7:29 p.m. UTC | #1
This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=926566

---Test result---

Test Summary:
CheckPatch                    PENDING   0.35 seconds
GitLint                       PENDING   0.37 seconds
SubjectPrefix                 PASS      0.40 seconds
BuildKernel                   PASS      24.99 seconds
CheckAllWarning               PASS      27.40 seconds
CheckSparse                   PASS      30.47 seconds
BuildKernel32                 PASS      24.53 seconds
TestRunnerSetup               PASS      435.76 seconds
TestRunner_l2cap-tester       PASS      21.04 seconds
TestRunner_iso-tester         PASS      30.19 seconds
TestRunner_bnep-tester        PASS      4.86 seconds
TestRunner_mgmt-tester        FAIL      118.99 seconds
TestRunner_rfcomm-tester      PASS      7.59 seconds
TestRunner_sco-tester         PASS      9.44 seconds
TestRunner_ioctl-tester       PASS      8.04 seconds
TestRunner_mesh-tester        PASS      6.00 seconds
TestRunner_smp-tester         PASS      7.00 seconds
TestRunner_userchan-tester    PASS      5.01 seconds
IncrementalBuild              PENDING   0.65 seconds

Details
##############################
Test: CheckPatch - PENDING
Desc: Run checkpatch.pl script
Output:

##############################
Test: GitLint - PENDING
Desc: Run gitlint
Output:

##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 490, Passed: 484 (98.8%), Failed: 2, Not Run: 4

Failed Test Cases
LL Privacy - Add Device 3 (AL is full)               Failed       0.210 seconds
LL Privacy - Set Flags 3 (2 Devices to RL)           Failed       0.179 seconds
##############################
Test: IncrementalBuild - PENDING
Desc: Incremental build with the patches in the series
Output:



---
Regards,
Linux Bluetooth
Luiz Augusto von Dentz Jan. 17, 2025, 8:48 p.m. UTC | #2
#syz test

On Fri, Jan 17, 2025 at 1:42 PM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
>
> After the hci sync command releases l2cap_conn, the hci receive data work
> queue references the released l2cap_conn when sending to the upper layer.
> Add hci dev lock to the hci receive data work queue to synchronize the two.
>
> [1]
> BUG: KASAN: slab-use-after-free in l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954
> Read of size 8 at addr ffff8880271a4000 by task kworker/u9:2/5837
>
> CPU: 0 UID: 0 PID: 5837 Comm: kworker/u9:2 Not tainted 6.13.0-rc5-syzkaller-00163-gab75170520d4 #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
> Workqueue: hci1 hci_rx_work
> Call Trace:
>  <TASK>
>  __dump_stack lib/dump_stack.c:94 [inline]
>  dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
>  print_address_description mm/kasan/report.c:378 [inline]
>  print_report+0x169/0x550 mm/kasan/report.c:489
>  kasan_report+0x143/0x180 mm/kasan/report.c:602
>  l2cap_build_cmd net/bluetooth/l2cap_core.c:2964 [inline]
>  l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954
>  l2cap_sig_send_rej net/bluetooth/l2cap_core.c:5502 [inline]
>  l2cap_sig_channel net/bluetooth/l2cap_core.c:5538 [inline]
>  l2cap_recv_frame+0x221f/0x10db0 net/bluetooth/l2cap_core.c:6817
>  hci_acldata_packet net/bluetooth/hci_core.c:3797 [inline]
>  hci_rx_work+0x508/0xdb0 net/bluetooth/hci_core.c:4040
>  process_one_work kernel/workqueue.c:3229 [inline]
>  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
>  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
>  kthread+0x2f0/0x390 kernel/kthread.c:389
>  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
>  </TASK>
>
> Allocated by task 5837:
>  kasan_save_stack mm/kasan/common.c:47 [inline]
>  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>  __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:394
>  kasan_kmalloc include/linux/kasan.h:260 [inline]
>  __kmalloc_cache_noprof+0x243/0x390 mm/slub.c:4329
>  kmalloc_noprof include/linux/slab.h:901 [inline]
>  kzalloc_noprof include/linux/slab.h:1037 [inline]
>  l2cap_conn_add+0xa9/0x8e0 net/bluetooth/l2cap_core.c:6860
>  l2cap_connect_cfm+0x115/0x1090 net/bluetooth/l2cap_core.c:7239
>  hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
>  hci_remote_features_evt+0x68e/0xac0 net/bluetooth/hci_event.c:3726
>  hci_event_func net/bluetooth/hci_event.c:7473 [inline]
>  hci_event_packet+0xac2/0x1540 net/bluetooth/hci_event.c:7525
>  hci_rx_work+0x3f3/0xdb0 net/bluetooth/hci_core.c:4035
>  process_one_work kernel/workqueue.c:3229 [inline]
>  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
>  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
>  kthread+0x2f0/0x390 kernel/kthread.c:389
>  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
>
> Freed by task 54:
>  kasan_save_stack mm/kasan/common.c:47 [inline]
>  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
>  kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:582
>  poison_slab_object mm/kasan/common.c:247 [inline]
>  __kasan_slab_free+0x59/0x70 mm/kasan/common.c:264
>  kasan_slab_free include/linux/kasan.h:233 [inline]
>  slab_free_hook mm/slub.c:2353 [inline]
>  slab_free mm/slub.c:4613 [inline]
>  kfree+0x196/0x430 mm/slub.c:4761
>  l2cap_connect_cfm+0xcc/0x1090 net/bluetooth/l2cap_core.c:7235
>  hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
>  hci_conn_failed+0x287/0x400 net/bluetooth/hci_conn.c:1266
>  hci_abort_conn_sync+0x56c/0x11f0 net/bluetooth/hci_sync.c:5603
>  hci_cmd_sync_work+0x22b/0x400 net/bluetooth/hci_sync.c:332
>  process_one_work kernel/workqueue.c:3229 [inline]
>  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
>  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
>  kthread+0x2f0/0x390 kernel/kthread.c:389
>  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
>
> Reported-by: syzbot+31c2f641b850a348a734@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=31c2f641b850a348a734
> Tested-by: syzbot+31c2f641b850a348a734@syzkaller.appspotmail.com
> Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> ---
>  net/bluetooth/l2cap_core.c | 45 ++++++++++++++++++++++++++++++++++----
>  1 file changed, 41 insertions(+), 4 deletions(-)
>
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 27b4c4a2ba1f..cc730135e5d9 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -951,11 +951,18 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn)
>  static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
>                            void *data)
>  {
> -       struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
> +       struct sk_buff *skb;
>         u8 flags;
>
> +       /* Check if hchan has been dropped since it means hci_chan_del has
> +        * been called.
> +        */
> +       if (!conn->hchan)
> +               return;
> +
>         BT_DBG("code 0x%2.2x", code);
>
> +       skb = l2cap_build_cmd(conn, code, ident, len, data);
>         if (!skb)
>                 return;
>
> @@ -1751,12 +1758,16 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
>  {
>         struct l2cap_conn *conn = hcon->l2cap_data;
>         struct l2cap_chan *chan, *l;
> +       struct hci_chan *hchan;
>
>         if (!conn)
>                 return;
>
>         BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
>
> +       hchan = conn->hchan;
> +       conn->hchan = NULL;
> +
>         kfree_skb(conn->rx_skb);
>
>         skb_queue_purge(&conn->pending_rx);
> @@ -1792,13 +1803,12 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
>
>         mutex_unlock(&conn->chan_lock);
>
> -       hci_chan_del(conn->hchan);
> +       hci_chan_del(hchan);
>
>         if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
>                 cancel_delayed_work_sync(&conn->info_timer);
>
>         hcon->l2cap_data = NULL;
> -       conn->hchan = NULL;
>         l2cap_conn_put(conn);
>  }
>
> @@ -6785,6 +6795,12 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
>         u16 cid, len;
>         __le16 psm;
>
> +       /* Check if hchan has been dropped then drop any packets as well */
> +       if (!conn->hchan) {
> +               kfree_skb(skb);
> +               return;
> +       }
> +
>         if (hcon->state != BT_CONNECTED) {
>                 BT_DBG("queueing pending rx skb");
>                 skb_queue_tail(&conn->pending_rx, skb);
> @@ -7466,14 +7482,33 @@ static void l2cap_recv_reset(struct l2cap_conn *conn)
>         conn->rx_len = 0;
>  }
>
> +static struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *c)
> +{
> +       BT_DBG("conn %p orig refcnt %u", c, kref_read(&c->ref));
> +
> +       if (!kref_get_unless_zero(&c->ref))
> +               return NULL;
> +
> +       return c;
> +}
> +
>  void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
>  {
> -       struct l2cap_conn *conn = hcon->l2cap_data;
> +       struct l2cap_conn *conn;
>         int len;
>
> +       /* Lock hdev to access l2cap_data to avoid race with l2cap_conn_del */
> +       hci_dev_lock(hcon->hdev);
> +
> +       conn = hcon->l2cap_data;
> +
>         if (!conn)
>                 conn = l2cap_conn_add(hcon);
>
> +       conn = l2cap_conn_hold_unless_zero(conn);
> +
> +       hci_dev_unlock(hcon->hdev);
> +
>         if (!conn)
>                 goto drop;
>
> @@ -7565,6 +7600,8 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
>                 break;
>         }
>
> +       l2cap_conn_put(conn);
> +
>  drop:
>         kfree_skb(skb);
>  }
> --
> 2.47.1
>
Hillf Danton Jan. 19, 2025, 3:56 a.m. UTC | #3
On Fri, 17 Jan 2025 13:42:02 -0500
> 
> After the hci sync command releases l2cap_conn, the hci receive data work
> queue references the released l2cap_conn when sending to the upper layer.
> Add hci dev lock to the hci receive data work queue to synchronize the two.
> 
> [1]
> BUG: KASAN: slab-use-after-free in l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954
> Read of size 8 at addr ffff8880271a4000 by task kworker/u9:2/5837
> 
> CPU: 0 UID: 0 PID: 5837 Comm: kworker/u9:2 Not tainted 6.13.0-rc5-syzkaller-00163-gab75170520d4 #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
> Workqueue: hci1 hci_rx_work
> Call Trace:
>  <TASK>
>  __dump_stack lib/dump_stack.c:94 [inline]
>  dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
>  print_address_description mm/kasan/report.c:378 [inline]
>  print_report+0x169/0x550 mm/kasan/report.c:489
>  kasan_report+0x143/0x180 mm/kasan/report.c:602
>  l2cap_build_cmd net/bluetooth/l2cap_core.c:2964 [inline]
>  l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954
>  l2cap_sig_send_rej net/bluetooth/l2cap_core.c:5502 [inline]
>  l2cap_sig_channel net/bluetooth/l2cap_core.c:5538 [inline]
>  l2cap_recv_frame+0x221f/0x10db0 net/bluetooth/l2cap_core.c:6817
>  hci_acldata_packet net/bluetooth/hci_core.c:3797 [inline]
>  hci_rx_work+0x508/0xdb0 net/bluetooth/hci_core.c:4040
>  process_one_work kernel/workqueue.c:3229 [inline]
>  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
>  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
>  kthread+0x2f0/0x390 kernel/kthread.c:389
>  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
>  </TASK>
> 
> Allocated by task 5837:
>  kasan_save_stack mm/kasan/common.c:47 [inline]
>  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
>  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
>  __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:394
>  kasan_kmalloc include/linux/kasan.h:260 [inline]
>  __kmalloc_cache_noprof+0x243/0x390 mm/slub.c:4329
>  kmalloc_noprof include/linux/slab.h:901 [inline]
>  kzalloc_noprof include/linux/slab.h:1037 [inline]
>  l2cap_conn_add+0xa9/0x8e0 net/bluetooth/l2cap_core.c:6860
>  l2cap_connect_cfm+0x115/0x1090 net/bluetooth/l2cap_core.c:7239
>  hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
>  hci_remote_features_evt+0x68e/0xac0 net/bluetooth/hci_event.c:3726
>  hci_event_func net/bluetooth/hci_event.c:7473 [inline]
>  hci_event_packet+0xac2/0x1540 net/bluetooth/hci_event.c:7525
>  hci_rx_work+0x3f3/0xdb0 net/bluetooth/hci_core.c:4035
>  process_one_work kernel/workqueue.c:3229 [inline]
>  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
>  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
>  kthread+0x2f0/0x390 kernel/kthread.c:389
>  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> 
> Freed by task 54:
>  kasan_save_stack mm/kasan/common.c:47 [inline]
>  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
>  kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:582
>  poison_slab_object mm/kasan/common.c:247 [inline]
>  __kasan_slab_free+0x59/0x70 mm/kasan/common.c:264
>  kasan_slab_free include/linux/kasan.h:233 [inline]
>  slab_free_hook mm/slub.c:2353 [inline]
>  slab_free mm/slub.c:4613 [inline]
>  kfree+0x196/0x430 mm/slub.c:4761
>  l2cap_connect_cfm+0xcc/0x1090 net/bluetooth/l2cap_core.c:7235
>  hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
>  hci_conn_failed+0x287/0x400 net/bluetooth/hci_conn.c:1266
>  hci_abort_conn_sync+0x56c/0x11f0 net/bluetooth/hci_sync.c:5603
>  hci_cmd_sync_work+0x22b/0x400 net/bluetooth/hci_sync.c:332
>  process_one_work kernel/workqueue.c:3229 [inline]
>  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
>  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
>  kthread+0x2f0/0x390 kernel/kthread.c:389
>  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
>  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> 
> Reported-by: syzbot+31c2f641b850a348a734@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=31c2f641b850a348a734
> Tested-by: syzbot+31c2f641b850a348a734@syzkaller.appspotmail.com
> Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> ---
>  net/bluetooth/l2cap_core.c | 45 ++++++++++++++++++++++++++++++++++----
>  1 file changed, 41 insertions(+), 4 deletions(-)
> 
> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> index 27b4c4a2ba1f..cc730135e5d9 100644
> --- a/net/bluetooth/l2cap_core.c
> +++ b/net/bluetooth/l2cap_core.c
> @@ -951,11 +951,18 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn)
>  static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
>  			   void *data)
>  {
> -	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
> +	struct sk_buff *skb;
>  	u8 flags;
>  
> +	/* Check if hchan has been dropped since it means hci_chan_del has
> +	 * been called.
> +	 */
> +	if (!conn->hchan)
> +		return;
> +
This does not work because nothing prevents ->hchan from being freed after this check.

>  	BT_DBG("code 0x%2.2x", code);
>  
> +	skb = l2cap_build_cmd(conn, code, ident, len, data);
>  	if (!skb)
>  		return;
>  
> @@ -1751,12 +1758,16 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
>  {
>  	struct l2cap_conn *conn = hcon->l2cap_data;
>  	struct l2cap_chan *chan, *l;
> +	struct hci_chan *hchan;
>  
>  	if (!conn)
>  		return;
>  
>  	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
>  
> +	hchan = conn->hchan;
> +	conn->hchan = NULL;
> +
>  	kfree_skb(conn->rx_skb);
>  
>  	skb_queue_purge(&conn->pending_rx);
> @@ -1792,13 +1803,12 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
> 
>  	mutex_unlock(&conn->chan_lock);
> 
> -	hci_chan_del(conn->hchan);
> +	hci_chan_del(hchan);
> 
>  	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
>  		cancel_delayed_work_sync(&conn->info_timer);
> 
>  	hcon->l2cap_data = NULL;
> -	conn->hchan = NULL;
>  	l2cap_conn_put(conn);
>  }
Luiz Augusto von Dentz Jan. 21, 2025, 6:08 p.m. UTC | #4
#syz test

On Fri, Jan 17, 2025 at 3:48 PM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> #syz test
>
> On Fri, Jan 17, 2025 at 1:42 PM Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
> >
> > From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> >
> > After the hci sync command releases l2cap_conn, the hci receive data work
> > queue references the released l2cap_conn when sending to the upper layer.
> > Add hci dev lock to the hci receive data work queue to synchronize the two.
> >
> > [1]
> > BUG: KASAN: slab-use-after-free in l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954
> > Read of size 8 at addr ffff8880271a4000 by task kworker/u9:2/5837
> >
> > CPU: 0 UID: 0 PID: 5837 Comm: kworker/u9:2 Not tainted 6.13.0-rc5-syzkaller-00163-gab75170520d4 #0
> > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
> > Workqueue: hci1 hci_rx_work
> > Call Trace:
> >  <TASK>
> >  __dump_stack lib/dump_stack.c:94 [inline]
> >  dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
> >  print_address_description mm/kasan/report.c:378 [inline]
> >  print_report+0x169/0x550 mm/kasan/report.c:489
> >  kasan_report+0x143/0x180 mm/kasan/report.c:602
> >  l2cap_build_cmd net/bluetooth/l2cap_core.c:2964 [inline]
> >  l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954
> >  l2cap_sig_send_rej net/bluetooth/l2cap_core.c:5502 [inline]
> >  l2cap_sig_channel net/bluetooth/l2cap_core.c:5538 [inline]
> >  l2cap_recv_frame+0x221f/0x10db0 net/bluetooth/l2cap_core.c:6817
> >  hci_acldata_packet net/bluetooth/hci_core.c:3797 [inline]
> >  hci_rx_work+0x508/0xdb0 net/bluetooth/hci_core.c:4040
> >  process_one_work kernel/workqueue.c:3229 [inline]
> >  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
> >  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
> >  kthread+0x2f0/0x390 kernel/kthread.c:389
> >  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
> >  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> >  </TASK>
> >
> > Allocated by task 5837:
> >  kasan_save_stack mm/kasan/common.c:47 [inline]
> >  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
> >  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
> >  __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:394
> >  kasan_kmalloc include/linux/kasan.h:260 [inline]
> >  __kmalloc_cache_noprof+0x243/0x390 mm/slub.c:4329
> >  kmalloc_noprof include/linux/slab.h:901 [inline]
> >  kzalloc_noprof include/linux/slab.h:1037 [inline]
> >  l2cap_conn_add+0xa9/0x8e0 net/bluetooth/l2cap_core.c:6860
> >  l2cap_connect_cfm+0x115/0x1090 net/bluetooth/l2cap_core.c:7239
> >  hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
> >  hci_remote_features_evt+0x68e/0xac0 net/bluetooth/hci_event.c:3726
> >  hci_event_func net/bluetooth/hci_event.c:7473 [inline]
> >  hci_event_packet+0xac2/0x1540 net/bluetooth/hci_event.c:7525
> >  hci_rx_work+0x3f3/0xdb0 net/bluetooth/hci_core.c:4035
> >  process_one_work kernel/workqueue.c:3229 [inline]
> >  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
> >  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
> >  kthread+0x2f0/0x390 kernel/kthread.c:389
> >  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
> >  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> >
> > Freed by task 54:
> >  kasan_save_stack mm/kasan/common.c:47 [inline]
> >  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
> >  kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:582
> >  poison_slab_object mm/kasan/common.c:247 [inline]
> >  __kasan_slab_free+0x59/0x70 mm/kasan/common.c:264
> >  kasan_slab_free include/linux/kasan.h:233 [inline]
> >  slab_free_hook mm/slub.c:2353 [inline]
> >  slab_free mm/slub.c:4613 [inline]
> >  kfree+0x196/0x430 mm/slub.c:4761
> >  l2cap_connect_cfm+0xcc/0x1090 net/bluetooth/l2cap_core.c:7235
> >  hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
> >  hci_conn_failed+0x287/0x400 net/bluetooth/hci_conn.c:1266
> >  hci_abort_conn_sync+0x56c/0x11f0 net/bluetooth/hci_sync.c:5603
> >  hci_cmd_sync_work+0x22b/0x400 net/bluetooth/hci_sync.c:332
> >  process_one_work kernel/workqueue.c:3229 [inline]
> >  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
> >  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
> >  kthread+0x2f0/0x390 kernel/kthread.c:389
> >  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
> >  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> >
> > Reported-by: syzbot+31c2f641b850a348a734@syzkaller.appspotmail.com
> > Closes: https://syzkaller.appspot.com/bug?extid=31c2f641b850a348a734
> > Tested-by: syzbot+31c2f641b850a348a734@syzkaller.appspotmail.com
> > Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> > Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> > ---
> >  net/bluetooth/l2cap_core.c | 45 ++++++++++++++++++++++++++++++++++----
> >  1 file changed, 41 insertions(+), 4 deletions(-)
> >
> > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> > index 27b4c4a2ba1f..cc730135e5d9 100644
> > --- a/net/bluetooth/l2cap_core.c
> > +++ b/net/bluetooth/l2cap_core.c
> > @@ -951,11 +951,18 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn)
> >  static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
> >                            void *data)
> >  {
> > -       struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
> > +       struct sk_buff *skb;
> >         u8 flags;
> >
> > +       /* Check if hchan has been dropped since it means hci_chan_del has
> > +        * been called.
> > +        */
> > +       if (!conn->hchan)
> > +               return;
> > +
> >         BT_DBG("code 0x%2.2x", code);
> >
> > +       skb = l2cap_build_cmd(conn, code, ident, len, data);
> >         if (!skb)
> >                 return;
> >
> > @@ -1751,12 +1758,16 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
> >  {
> >         struct l2cap_conn *conn = hcon->l2cap_data;
> >         struct l2cap_chan *chan, *l;
> > +       struct hci_chan *hchan;
> >
> >         if (!conn)
> >                 return;
> >
> >         BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
> >
> > +       hchan = conn->hchan;
> > +       conn->hchan = NULL;
> > +
> >         kfree_skb(conn->rx_skb);
> >
> >         skb_queue_purge(&conn->pending_rx);
> > @@ -1792,13 +1803,12 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
> >
> >         mutex_unlock(&conn->chan_lock);
> >
> > -       hci_chan_del(conn->hchan);
> > +       hci_chan_del(hchan);
> >
> >         if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
> >                 cancel_delayed_work_sync(&conn->info_timer);
> >
> >         hcon->l2cap_data = NULL;
> > -       conn->hchan = NULL;
> >         l2cap_conn_put(conn);
> >  }
> >
> > @@ -6785,6 +6795,12 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
> >         u16 cid, len;
> >         __le16 psm;
> >
> > +       /* Check if hchan has been dropped then drop any packets as well */
> > +       if (!conn->hchan) {
> > +               kfree_skb(skb);
> > +               return;
> > +       }
> > +
> >         if (hcon->state != BT_CONNECTED) {
> >                 BT_DBG("queueing pending rx skb");
> >                 skb_queue_tail(&conn->pending_rx, skb);
> > @@ -7466,14 +7482,33 @@ static void l2cap_recv_reset(struct l2cap_conn *conn)
> >         conn->rx_len = 0;
> >  }
> >
> > +static struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *c)
> > +{
> > +       BT_DBG("conn %p orig refcnt %u", c, kref_read(&c->ref));
> > +
> > +       if (!kref_get_unless_zero(&c->ref))
> > +               return NULL;
> > +
> > +       return c;
> > +}
> > +
> >  void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> >  {
> > -       struct l2cap_conn *conn = hcon->l2cap_data;
> > +       struct l2cap_conn *conn;
> >         int len;
> >
> > +       /* Lock hdev to access l2cap_data to avoid race with l2cap_conn_del */
> > +       hci_dev_lock(hcon->hdev);
> > +
> > +       conn = hcon->l2cap_data;
> > +
> >         if (!conn)
> >                 conn = l2cap_conn_add(hcon);
> >
> > +       conn = l2cap_conn_hold_unless_zero(conn);
> > +
> > +       hci_dev_unlock(hcon->hdev);
> > +
> >         if (!conn)
> >                 goto drop;
> >
> > @@ -7565,6 +7600,8 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> >                 break;
> >         }
> >
> > +       l2cap_conn_put(conn);
> > +
> >  drop:
> >         kfree_skb(skb);
> >  }
> > --
> > 2.47.1
> >
>
>
> --
> Luiz Augusto von Dentz
syzbot Jan. 22, 2025, 3:17 a.m. UTC | #5
Hello,

syzbot has tested the proposed patch but the reproducer is still triggering an issue:
KASAN: slab-use-after-free Read in hci_send_acl

Bluetooth: Unknown BR/EDR signaling command 0x10
Bluetooth: Wrong link type (-22)
==================================================================
BUG: KASAN: slab-use-after-free in hci_send_acl+0x4d/0xd00 net/bluetooth/hci_core.c:3232
Read of size 8 at addr ffff88802f536f18 by task kworker/u9:5/6557

CPU: 0 UID: 0 PID: 6557 Comm: kworker/u9:5 Not tainted 6.13.0-syzkaller-02469-gd0f93ac2c384-dirty #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 12/27/2024
Workqueue: hci4 hci_rx_work
Call Trace:
 <TASK>
 __dump_stack lib/dump_stack.c:94 [inline]
 dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
 print_address_description mm/kasan/report.c:378 [inline]
 print_report+0x169/0x550 mm/kasan/report.c:489
 kasan_report+0x143/0x180 mm/kasan/report.c:602
 hci_send_acl+0x4d/0xd00 net/bluetooth/hci_core.c:3232
 l2cap_sig_send_rej net/bluetooth/l2cap_core.c:5500 [inline]
 l2cap_sig_channel net/bluetooth/l2cap_core.c:5536 [inline]
 l2cap_recv_frame+0x221f/0x10db0 net/bluetooth/l2cap_core.c:6815
 l2cap_recv_acldata+0x700/0x1a70 net/bluetooth/l2cap_core.c:7522
 hci_acldata_packet net/bluetooth/hci_core.c:3797 [inline]
 hci_rx_work+0x508/0xdb0 net/bluetooth/hci_core.c:4040
 process_one_work kernel/workqueue.c:3236 [inline]
 process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3317
 worker_thread+0x870/0xd30 kernel/workqueue.c:3398
 kthread+0x7a9/0x920 kernel/kthread.c:464
 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:148
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
 </TASK>

Allocated by task 54:
 kasan_save_stack mm/kasan/common.c:47 [inline]
 kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
 poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
 __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:394
 kasan_kmalloc include/linux/kasan.h:260 [inline]
 __kmalloc_cache_noprof+0x243/0x390 mm/slub.c:4329
 kmalloc_noprof include/linux/slab.h:901 [inline]
 kzalloc_noprof include/linux/slab.h:1037 [inline]
 hci_chan_create+0xc8/0x310 net/bluetooth/hci_conn.c:2838
 l2cap_conn_add+0x69/0x8e0 net/bluetooth/l2cap_core.c:6854
 l2cap_connect_cfm+0x115/0x1090 net/bluetooth/l2cap_core.c:7237
 hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
 hci_remote_features_evt+0x68e/0xac0 net/bluetooth/hci_event.c:3726
 hci_event_func net/bluetooth/hci_event.c:7473 [inline]
 hci_event_packet+0xac2/0x1540 net/bluetooth/hci_event.c:7525
 hci_rx_work+0x3f3/0xdb0 net/bluetooth/hci_core.c:4035
 process_one_work kernel/workqueue.c:3236 [inline]
 process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3317
 worker_thread+0x870/0xd30 kernel/workqueue.c:3398
 kthread+0x7a9/0x920 kernel/kthread.c:464
 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:148
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244

Freed by task 6554:
 kasan_save_stack mm/kasan/common.c:47 [inline]
 kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
 kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:582
 poison_slab_object mm/kasan/common.c:247 [inline]
 __kasan_slab_free+0x59/0x70 mm/kasan/common.c:264
 kasan_slab_free include/linux/kasan.h:233 [inline]
 slab_free_hook mm/slub.c:2353 [inline]
 slab_free mm/slub.c:4613 [inline]
 kfree+0x196/0x430 mm/slub.c:4761
 hci_chan_list_flush net/bluetooth/hci_conn.c:2878 [inline]
 hci_conn_cleanup net/bluetooth/hci_conn.c:149 [inline]
 hci_conn_del+0x4b5/0xc40 net/bluetooth/hci_conn.c:1164
 hci_conn_failed+0x319/0x400 net/bluetooth/hci_conn.c:1267
 hci_abort_conn_sync+0x56c/0x11f0 net/bluetooth/hci_sync.c:5604
 hci_cmd_sync_work+0x22b/0x400 net/bluetooth/hci_sync.c:332
 process_one_work kernel/workqueue.c:3236 [inline]
 process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3317
 worker_thread+0x870/0xd30 kernel/workqueue.c:3398
 kthread+0x7a9/0x920 kernel/kthread.c:464
 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:148
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244

The buggy address belongs to the object at ffff88802f536f00
 which belongs to the cache kmalloc-128 of size 128
The buggy address is located 24 bytes inside of
 freed 128-byte region [ffff88802f536f00, ffff88802f536f80)

The buggy address belongs to the physical page:
page: refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff88802f536d00 pfn:0x2f536
flags: 0xfff00000000200(workingset|node=0|zone=1|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 00fff00000000200 ffff88801ac41a00 ffffea000187a110 ffffea0001882ad0
raw: ffff88802f536d00 0000000000100005 00000001f5000000 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 0, migratetype Unmovable, gfp_mask 0x52cc0(GFP_KERNEL|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP), pid 6482, tgid 6482 (udevd), ts 109120173001, free_ts 109113912385
 set_page_owner include/linux/page_owner.h:32 [inline]
 post_alloc_hook+0x1f3/0x230 mm/page_alloc.c:1558
 prep_new_page mm/page_alloc.c:1566 [inline]
 get_page_from_freelist+0x365c/0x37a0 mm/page_alloc.c:3476
 __alloc_pages_noprof+0x292/0x710 mm/page_alloc.c:4753
 alloc_pages_mpol_noprof+0x3e1/0x780 mm/mempolicy.c:2269
 alloc_slab_page+0x6a/0x110 mm/slub.c:2423
 allocate_slab+0x5a/0x2b0 mm/slub.c:2589
 new_slab mm/slub.c:2642 [inline]
 ___slab_alloc+0xc27/0x14a0 mm/slub.c:3830
 __slab_alloc+0x58/0xa0 mm/slub.c:3920
 __slab_alloc_node mm/slub.c:3995 [inline]
 slab_alloc_node mm/slub.c:4156 [inline]
 __kmalloc_cache_noprof+0x27b/0x390 mm/slub.c:4324
 kmalloc_noprof include/linux/slab.h:901 [inline]
 kzalloc_noprof include/linux/slab.h:1037 [inline]
 kernfs_get_open_node fs/kernfs/file.c:525 [inline]
 kernfs_fop_open+0x826/0xd10 fs/kernfs/file.c:700
 do_dentry_open+0xbe1/0x1b70 fs/open.c:938
 vfs_open+0x3e/0x330 fs/open.c:1068
 do_open fs/namei.c:3828 [inline]
 path_openat+0x2c84/0x3590 fs/namei.c:3987
 do_filp_open+0x27f/0x4e0 fs/namei.c:4014
 do_sys_openat2+0x13e/0x1d0 fs/open.c:1395
 do_sys_open fs/open.c:1410 [inline]
 __do_sys_openat fs/open.c:1426 [inline]
 __se_sys_openat fs/open.c:1421 [inline]
 __x64_sys_openat+0x247/0x2a0 fs/open.c:1421
page last free pid 6511 tgid 6511 stack trace:
 reset_page_owner include/linux/page_owner.h:25 [inline]
 free_pages_prepare mm/page_alloc.c:1127 [inline]
 free_unref_folios+0xe39/0x18b0 mm/page_alloc.c:2706
 folios_put_refs+0x76c/0x860 mm/swap.c:962
 free_pages_and_swap_cache+0x5c8/0x690 mm/swap_state.c:335
 __tlb_batch_free_encoded_pages mm/mmu_gather.c:136 [inline]
 tlb_batch_pages_flush mm/mmu_gather.c:149 [inline]
 tlb_flush_mmu_free mm/mmu_gather.c:366 [inline]
 tlb_flush_mmu+0x3a3/0x680 mm/mmu_gather.c:373
 tlb_finish_mmu+0xd4/0x200 mm/mmu_gather.c:465
 exit_mmap+0x4d5/0xca0 mm/mmap.c:1685
 __mmput+0x115/0x3c0 kernel/fork.c:1345
 exit_mm+0x220/0x310 kernel/exit.c:570
 do_exit+0x9ad/0x28e0 kernel/exit.c:925
 do_group_exit+0x207/0x2c0 kernel/exit.c:1087
 get_signal+0x16b2/0x1750 kernel/signal.c:3036
 arch_do_signal_or_restart+0x96/0x860 arch/x86/kernel/signal.c:337
 exit_to_user_mode_loop kernel/entry/common.c:111 [inline]
 exit_to_user_mode_prepare include/linux/entry-common.h:329 [inline]
 __syscall_exit_to_user_mode_work kernel/entry/common.c:207 [inline]
 syscall_exit_to_user_mode+0xce/0x340 kernel/entry/common.c:218
 do_syscall_64+0x100/0x230 arch/x86/entry/common.c:89
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Memory state around the buggy address:
 ffff88802f536e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 fc fc fc
 ffff88802f536e80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff88802f536f00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                            ^
 ffff88802f536f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 ffff88802f537000: 00 00 00 00 fc fc fc fc fa fb fb fb fc fc fc fc
==================================================================


Tested on:

commit:         d0f93ac2 Merge tag 'docs-6.14' of git://git.lwn.net/li..
git tree:       upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=112b8ab0580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=11ecbacf9de73733
dashboard link: https://syzkaller.appspot.com/bug?extid=31c2f641b850a348a734
compiler:       Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40
patch:          https://syzkaller.appspot.com/x/patch.diff?x=16e82238580000
Luiz Augusto von Dentz Jan. 22, 2025, 5:04 p.m. UTC | #6
#syz test

On Tue, Jan 21, 2025 at 1:08 PM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> #syz test
>
> On Fri, Jan 17, 2025 at 3:48 PM Luiz Augusto von Dentz
> <luiz.dentz@gmail.com> wrote:
> >
> > #syz test
> >
> > On Fri, Jan 17, 2025 at 1:42 PM Luiz Augusto von Dentz
> > <luiz.dentz@gmail.com> wrote:
> > >
> > > From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> > >
> > > After the hci sync command releases l2cap_conn, the hci receive data work
> > > queue references the released l2cap_conn when sending to the upper layer.
> > > Add hci dev lock to the hci receive data work queue to synchronize the two.
> > >
> > > [1]
> > > BUG: KASAN: slab-use-after-free in l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954
> > > Read of size 8 at addr ffff8880271a4000 by task kworker/u9:2/5837
> > >
> > > CPU: 0 UID: 0 PID: 5837 Comm: kworker/u9:2 Not tainted 6.13.0-rc5-syzkaller-00163-gab75170520d4 #0
> > > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
> > > Workqueue: hci1 hci_rx_work
> > > Call Trace:
> > >  <TASK>
> > >  __dump_stack lib/dump_stack.c:94 [inline]
> > >  dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120
> > >  print_address_description mm/kasan/report.c:378 [inline]
> > >  print_report+0x169/0x550 mm/kasan/report.c:489
> > >  kasan_report+0x143/0x180 mm/kasan/report.c:602
> > >  l2cap_build_cmd net/bluetooth/l2cap_core.c:2964 [inline]
> > >  l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954
> > >  l2cap_sig_send_rej net/bluetooth/l2cap_core.c:5502 [inline]
> > >  l2cap_sig_channel net/bluetooth/l2cap_core.c:5538 [inline]
> > >  l2cap_recv_frame+0x221f/0x10db0 net/bluetooth/l2cap_core.c:6817
> > >  hci_acldata_packet net/bluetooth/hci_core.c:3797 [inline]
> > >  hci_rx_work+0x508/0xdb0 net/bluetooth/hci_core.c:4040
> > >  process_one_work kernel/workqueue.c:3229 [inline]
> > >  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
> > >  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
> > >  kthread+0x2f0/0x390 kernel/kthread.c:389
> > >  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
> > >  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> > >  </TASK>
> > >
> > > Allocated by task 5837:
> > >  kasan_save_stack mm/kasan/common.c:47 [inline]
> > >  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
> > >  poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
> > >  __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:394
> > >  kasan_kmalloc include/linux/kasan.h:260 [inline]
> > >  __kmalloc_cache_noprof+0x243/0x390 mm/slub.c:4329
> > >  kmalloc_noprof include/linux/slab.h:901 [inline]
> > >  kzalloc_noprof include/linux/slab.h:1037 [inline]
> > >  l2cap_conn_add+0xa9/0x8e0 net/bluetooth/l2cap_core.c:6860
> > >  l2cap_connect_cfm+0x115/0x1090 net/bluetooth/l2cap_core.c:7239
> > >  hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
> > >  hci_remote_features_evt+0x68e/0xac0 net/bluetooth/hci_event.c:3726
> > >  hci_event_func net/bluetooth/hci_event.c:7473 [inline]
> > >  hci_event_packet+0xac2/0x1540 net/bluetooth/hci_event.c:7525
> > >  hci_rx_work+0x3f3/0xdb0 net/bluetooth/hci_core.c:4035
> > >  process_one_work kernel/workqueue.c:3229 [inline]
> > >  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
> > >  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
> > >  kthread+0x2f0/0x390 kernel/kthread.c:389
> > >  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
> > >  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> > >
> > > Freed by task 54:
> > >  kasan_save_stack mm/kasan/common.c:47 [inline]
> > >  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
> > >  kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:582
> > >  poison_slab_object mm/kasan/common.c:247 [inline]
> > >  __kasan_slab_free+0x59/0x70 mm/kasan/common.c:264
> > >  kasan_slab_free include/linux/kasan.h:233 [inline]
> > >  slab_free_hook mm/slub.c:2353 [inline]
> > >  slab_free mm/slub.c:4613 [inline]
> > >  kfree+0x196/0x430 mm/slub.c:4761
> > >  l2cap_connect_cfm+0xcc/0x1090 net/bluetooth/l2cap_core.c:7235
> > >  hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline]
> > >  hci_conn_failed+0x287/0x400 net/bluetooth/hci_conn.c:1266
> > >  hci_abort_conn_sync+0x56c/0x11f0 net/bluetooth/hci_sync.c:5603
> > >  hci_cmd_sync_work+0x22b/0x400 net/bluetooth/hci_sync.c:332
> > >  process_one_work kernel/workqueue.c:3229 [inline]
> > >  process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310
> > >  worker_thread+0x870/0xd30 kernel/workqueue.c:3391
> > >  kthread+0x2f0/0x390 kernel/kthread.c:389
> > >  ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
> > >  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
> > >
> > > Reported-by: syzbot+31c2f641b850a348a734@syzkaller.appspotmail.com
> > > Closes: https://syzkaller.appspot.com/bug?extid=31c2f641b850a348a734
> > > Tested-by: syzbot+31c2f641b850a348a734@syzkaller.appspotmail.com
> > > Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> > > Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
> > > ---
> > >  net/bluetooth/l2cap_core.c | 45 ++++++++++++++++++++++++++++++++++----
> > >  1 file changed, 41 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> > > index 27b4c4a2ba1f..cc730135e5d9 100644
> > > --- a/net/bluetooth/l2cap_core.c
> > > +++ b/net/bluetooth/l2cap_core.c
> > > @@ -951,11 +951,18 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn)
> > >  static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
> > >                            void *data)
> > >  {
> > > -       struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
> > > +       struct sk_buff *skb;
> > >         u8 flags;
> > >
> > > +       /* Check if hchan has been dropped since it means hci_chan_del has
> > > +        * been called.
> > > +        */
> > > +       if (!conn->hchan)
> > > +               return;
> > > +
> > >         BT_DBG("code 0x%2.2x", code);
> > >
> > > +       skb = l2cap_build_cmd(conn, code, ident, len, data);
> > >         if (!skb)
> > >                 return;
> > >
> > > @@ -1751,12 +1758,16 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
> > >  {
> > >         struct l2cap_conn *conn = hcon->l2cap_data;
> > >         struct l2cap_chan *chan, *l;
> > > +       struct hci_chan *hchan;
> > >
> > >         if (!conn)
> > >                 return;
> > >
> > >         BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
> > >
> > > +       hchan = conn->hchan;
> > > +       conn->hchan = NULL;
> > > +
> > >         kfree_skb(conn->rx_skb);
> > >
> > >         skb_queue_purge(&conn->pending_rx);
> > > @@ -1792,13 +1803,12 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
> > >
> > >         mutex_unlock(&conn->chan_lock);
> > >
> > > -       hci_chan_del(conn->hchan);
> > > +       hci_chan_del(hchan);
> > >
> > >         if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
> > >                 cancel_delayed_work_sync(&conn->info_timer);
> > >
> > >         hcon->l2cap_data = NULL;
> > > -       conn->hchan = NULL;
> > >         l2cap_conn_put(conn);
> > >  }
> > >
> > > @@ -6785,6 +6795,12 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
> > >         u16 cid, len;
> > >         __le16 psm;
> > >
> > > +       /* Check if hchan has been dropped then drop any packets as well */
> > > +       if (!conn->hchan) {
> > > +               kfree_skb(skb);
> > > +               return;
> > > +       }
> > > +
> > >         if (hcon->state != BT_CONNECTED) {
> > >                 BT_DBG("queueing pending rx skb");
> > >                 skb_queue_tail(&conn->pending_rx, skb);
> > > @@ -7466,14 +7482,33 @@ static void l2cap_recv_reset(struct l2cap_conn *conn)
> > >         conn->rx_len = 0;
> > >  }
> > >
> > > +static struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *c)
> > > +{
> > > +       BT_DBG("conn %p orig refcnt %u", c, kref_read(&c->ref));
> > > +
> > > +       if (!kref_get_unless_zero(&c->ref))
> > > +               return NULL;
> > > +
> > > +       return c;
> > > +}
> > > +
> > >  void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> > >  {
> > > -       struct l2cap_conn *conn = hcon->l2cap_data;
> > > +       struct l2cap_conn *conn;
> > >         int len;
> > >
> > > +       /* Lock hdev to access l2cap_data to avoid race with l2cap_conn_del */
> > > +       hci_dev_lock(hcon->hdev);
> > > +
> > > +       conn = hcon->l2cap_data;
> > > +
> > >         if (!conn)
> > >                 conn = l2cap_conn_add(hcon);
> > >
> > > +       conn = l2cap_conn_hold_unless_zero(conn);
> > > +
> > > +       hci_dev_unlock(hcon->hdev);
> > > +
> > >         if (!conn)
> > >                 goto drop;
> > >
> > > @@ -7565,6 +7600,8 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
> > >                 break;
> > >         }
> > >
> > > +       l2cap_conn_put(conn);
> > > +
> > >  drop:
> > >         kfree_skb(skb);
> > >  }
> > > --
> > > 2.47.1
> > >
> >
> >
> > --
> > Luiz Augusto von Dentz
>
>
>
> --
> Luiz Augusto von Dentz
diff mbox series

Patch

diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 27b4c4a2ba1f..cc730135e5d9 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -951,11 +951,18 @@  static u8 l2cap_get_ident(struct l2cap_conn *conn)
 static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
 			   void *data)
 {
-	struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
+	struct sk_buff *skb;
 	u8 flags;
 
+	/* Check if hchan has been dropped since it means hci_chan_del has
+	 * been called.
+	 */
+	if (!conn->hchan)
+		return;
+
 	BT_DBG("code 0x%2.2x", code);
 
+	skb = l2cap_build_cmd(conn, code, ident, len, data);
 	if (!skb)
 		return;
 
@@ -1751,12 +1758,16 @@  static void l2cap_conn_del(struct hci_conn *hcon, int err)
 {
 	struct l2cap_conn *conn = hcon->l2cap_data;
 	struct l2cap_chan *chan, *l;
+	struct hci_chan *hchan;
 
 	if (!conn)
 		return;
 
 	BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
 
+	hchan = conn->hchan;
+	conn->hchan = NULL;
+
 	kfree_skb(conn->rx_skb);
 
 	skb_queue_purge(&conn->pending_rx);
@@ -1792,13 +1803,12 @@  static void l2cap_conn_del(struct hci_conn *hcon, int err)
 
 	mutex_unlock(&conn->chan_lock);
 
-	hci_chan_del(conn->hchan);
+	hci_chan_del(hchan);
 
 	if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT)
 		cancel_delayed_work_sync(&conn->info_timer);
 
 	hcon->l2cap_data = NULL;
-	conn->hchan = NULL;
 	l2cap_conn_put(conn);
 }
 
@@ -6785,6 +6795,12 @@  static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
 	u16 cid, len;
 	__le16 psm;
 
+	/* Check if hchan has been dropped then drop any packets as well */
+	if (!conn->hchan) {
+		kfree_skb(skb);
+		return;
+	}
+
 	if (hcon->state != BT_CONNECTED) {
 		BT_DBG("queueing pending rx skb");
 		skb_queue_tail(&conn->pending_rx, skb);
@@ -7466,14 +7482,33 @@  static void l2cap_recv_reset(struct l2cap_conn *conn)
 	conn->rx_len = 0;
 }
 
+static struct l2cap_conn *l2cap_conn_hold_unless_zero(struct l2cap_conn *c)
+{
+	BT_DBG("conn %p orig refcnt %u", c, kref_read(&c->ref));
+
+	if (!kref_get_unless_zero(&c->ref))
+		return NULL;
+
+	return c;
+}
+
 void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 {
-	struct l2cap_conn *conn = hcon->l2cap_data;
+	struct l2cap_conn *conn;
 	int len;
 
+	/* Lock hdev to access l2cap_data to avoid race with l2cap_conn_del */
+	hci_dev_lock(hcon->hdev);
+
+	conn = hcon->l2cap_data;
+
 	if (!conn)
 		conn = l2cap_conn_add(hcon);
 
+	conn = l2cap_conn_hold_unless_zero(conn);
+
+	hci_dev_unlock(hcon->hdev);
+
 	if (!conn)
 		goto drop;
 
@@ -7565,6 +7600,8 @@  void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
 		break;
 	}
 
+	l2cap_conn_put(conn);
+
 drop:
 	kfree_skb(skb);
 }