]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.8-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 May 2024 07:06:40 +0000 (09:06 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 23 May 2024 07:06:40 +0000 (09:06 +0200)
added patches:
bluetooth-l2cap-fix-div-by-zero-in-l2cap_le_flowctl_init.patch
bluetooth-l2cap-fix-slab-use-after-free-in-l2cap_connect.patch

queue-6.8/bluetooth-l2cap-fix-div-by-zero-in-l2cap_le_flowctl_init.patch [new file with mode: 0644]
queue-6.8/bluetooth-l2cap-fix-slab-use-after-free-in-l2cap_connect.patch [new file with mode: 0644]
queue-6.8/series

diff --git a/queue-6.8/bluetooth-l2cap-fix-div-by-zero-in-l2cap_le_flowctl_init.patch b/queue-6.8/bluetooth-l2cap-fix-div-by-zero-in-l2cap_le_flowctl_init.patch
new file mode 100644 (file)
index 0000000..db4e483
--- /dev/null
@@ -0,0 +1,445 @@
+From a5b862c6a221459d54e494e88965b48dcfa6cc44 Mon Sep 17 00:00:00 2001
+From: Sungwoo Kim <iam@sung-woo.kim>
+Date: Sat, 4 May 2024 15:23:29 -0400
+Subject: Bluetooth: L2CAP: Fix div-by-zero in l2cap_le_flowctl_init()
+
+From: Sungwoo Kim <iam@sung-woo.kim>
+
+commit a5b862c6a221459d54e494e88965b48dcfa6cc44 upstream.
+
+l2cap_le_flowctl_init() can cause both div-by-zero and an integer
+overflow since hdev->le_mtu may not fall in the valid range.
+
+Move MTU from hci_dev to hci_conn to validate MTU and stop the connection
+process earlier if MTU is invalid.
+Also, add a missing validation in read_buffer_size() and make it return
+an error value if the validation fails.
+Now hci_conn_add() returns ERR_PTR() as it can fail due to the both a
+kzalloc failure and invalid MTU value.
+
+divide error: 0000 [#1] PREEMPT SMP KASAN NOPTI
+CPU: 0 PID: 67 Comm: kworker/u5:0 Tainted: G        W          6.9.0-rc5+ #20
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
+Workqueue: hci0 hci_rx_work
+RIP: 0010:l2cap_le_flowctl_init+0x19e/0x3f0 net/bluetooth/l2cap_core.c:547
+Code: e8 17 17 0c 00 66 41 89 9f 84 00 00 00 bf 01 00 00 00 41 b8 02 00 00 00 4c
+89 fe 4c 89 e2 89 d9 e8 27 17 0c 00 44 89 f0 31 d2 <66> f7 f3 89 c3 ff c3 4d 8d
+b7 88 00 00 00 4c 89 f0 48 c1 e8 03 42
+RSP: 0018:ffff88810bc0f858 EFLAGS: 00010246
+RAX: 00000000000002a0 RBX: 0000000000000000 RCX: dffffc0000000000
+RDX: 0000000000000000 RSI: ffff88810bc0f7c0 RDI: ffffc90002dcb66f
+RBP: ffff88810bc0f880 R08: aa69db2dda70ff01 R09: 0000ffaaaaaaaaaa
+R10: 0084000000ffaaaa R11: 0000000000000000 R12: ffff88810d65a084
+R13: dffffc0000000000 R14: 00000000000002a0 R15: ffff88810d65a000
+FS:  0000000000000000(0000) GS:ffff88811ac00000(0000) knlGS:0000000000000000
+CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000000020000100 CR3: 0000000103268003 CR4: 0000000000770ef0
+PKRU: 55555554
+Call Trace:
+ <TASK>
+ l2cap_le_connect_req net/bluetooth/l2cap_core.c:4902 [inline]
+ l2cap_le_sig_cmd net/bluetooth/l2cap_core.c:5420 [inline]
+ l2cap_le_sig_channel net/bluetooth/l2cap_core.c:5486 [inline]
+ l2cap_recv_frame+0xe59d/0x11710 net/bluetooth/l2cap_core.c:6809
+ l2cap_recv_acldata+0x544/0x10a0 net/bluetooth/l2cap_core.c:7506
+ hci_acldata_packet net/bluetooth/hci_core.c:3939 [inline]
+ hci_rx_work+0x5e5/0xb20 net/bluetooth/hci_core.c:4176
+ process_one_work kernel/workqueue.c:3254 [inline]
+ process_scheduled_works+0x90f/0x1530 kernel/workqueue.c:3335
+ worker_thread+0x926/0xe70 kernel/workqueue.c:3416
+ kthread+0x2e3/0x380 kernel/kthread.c:388
+ ret_from_fork+0x5c/0x90 arch/x86/kernel/process.c:147
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
+ </TASK>
+Modules linked in:
+---[ end trace 0000000000000000 ]---
+
+Fixes: 6ed58ec520ad ("Bluetooth: Use LE buffers for LE traffic")
+Suggested-by: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
+Signed-off-by: Sungwoo Kim <iam@sung-woo.kim>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/bluetooth/hci.h      |    9 ++++
+ include/net/bluetooth/hci_core.h |    1 
+ net/bluetooth/hci_conn.c         |   71 ++++++++++++++++++++++++++-------------
+ net/bluetooth/hci_event.c        |   31 ++++++++++-------
+ net/bluetooth/iso.c              |    2 -
+ net/bluetooth/l2cap_core.c       |   17 +--------
+ net/bluetooth/sco.c              |    6 +--
+ 7 files changed, 86 insertions(+), 51 deletions(-)
+
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -1665,6 +1665,15 @@ struct hci_cp_le_set_event_mask {
+       __u8     mask[8];
+ } __packed;
++/* BLUETOOTH CORE SPECIFICATION Version 5.4 | Vol 4, Part E
++ * 7.8.2 LE Read Buffer Size command
++ * MAX_LE_MTU is 0xffff.
++ * 0 is also valid. It means that no dedicated LE Buffer exists.
++ * It should use the HCI_Read_Buffer_Size command and mtu is shared
++ * between BR/EDR and LE.
++ */
++#define HCI_MIN_LE_MTU 0x001b
++
+ #define HCI_OP_LE_READ_BUFFER_SIZE    0x2002
+ struct hci_rp_le_read_buffer_size {
+       __u8     status;
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -706,6 +706,7 @@ struct hci_conn {
+       __u16           handle;
+       __u16           sync_handle;
+       __u16           state;
++      __u16           mtu;
+       __u8            mode;
+       __u8            type;
+       __u8            role;
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -909,11 +909,37 @@ struct hci_conn *hci_conn_add(struct hci
+ {
+       struct hci_conn *conn;
++      switch (type) {
++      case ACL_LINK:
++              if (!hdev->acl_mtu)
++                      return ERR_PTR(-ECONNREFUSED);
++              break;
++      case ISO_LINK:
++              if (hdev->iso_mtu)
++                      /* Dedicated ISO Buffer exists */
++                      break;
++              fallthrough;
++      case LE_LINK:
++              if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
++                      return ERR_PTR(-ECONNREFUSED);
++              if (!hdev->le_mtu && hdev->acl_mtu < HCI_MIN_LE_MTU)
++                      return ERR_PTR(-ECONNREFUSED);
++              break;
++      case SCO_LINK:
++      case ESCO_LINK:
++              if (!hdev->sco_pkts)
++                      /* Controller does not support SCO or eSCO over HCI */
++                      return ERR_PTR(-ECONNREFUSED);
++              break;
++      default:
++              return ERR_PTR(-ECONNREFUSED);
++      }
++
+       bt_dev_dbg(hdev, "dst %pMR handle 0x%4.4x", dst, handle);
+       conn = kzalloc(sizeof(*conn), GFP_KERNEL);
+       if (!conn)
+-              return NULL;
++              return ERR_PTR(-ENOMEM);
+       bacpy(&conn->dst, dst);
+       bacpy(&conn->src, &hdev->bdaddr);
+@@ -944,10 +970,12 @@ struct hci_conn *hci_conn_add(struct hci
+       switch (type) {
+       case ACL_LINK:
+               conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK;
++              conn->mtu = hdev->acl_mtu;
+               break;
+       case LE_LINK:
+               /* conn->src should reflect the local identity address */
+               hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
++              conn->mtu = hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
+               break;
+       case ISO_LINK:
+               /* conn->src should reflect the local identity address */
+@@ -959,6 +987,8 @@ struct hci_conn *hci_conn_add(struct hci
+               else if (conn->role == HCI_ROLE_MASTER)
+                       conn->cleanup = cis_cleanup;
++              conn->mtu = hdev->iso_mtu ? hdev->iso_mtu :
++                          hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
+               break;
+       case SCO_LINK:
+               if (lmp_esco_capable(hdev))
+@@ -966,9 +996,12 @@ struct hci_conn *hci_conn_add(struct hci
+                                       (hdev->esco_type & EDR_ESCO_MASK);
+               else
+                       conn->pkt_type = hdev->pkt_type & SCO_PTYPE_MASK;
++
++              conn->mtu = hdev->sco_mtu;
+               break;
+       case ESCO_LINK:
+               conn->pkt_type = hdev->esco_type & ~EDR_ESCO_MASK;
++              conn->mtu = hdev->sco_mtu;
+               break;
+       }
+@@ -1011,7 +1044,7 @@ struct hci_conn *hci_conn_add_unset(stru
+       handle = hci_conn_hash_alloc_unset(hdev);
+       if (unlikely(handle < 0))
+-              return NULL;
++              return ERR_PTR(-ECONNREFUSED);
+       return hci_conn_add(hdev, type, dst, role, handle);
+ }
+@@ -1317,8 +1350,8 @@ struct hci_conn *hci_connect_le(struct h
+               bacpy(&conn->dst, dst);
+       } else {
+               conn = hci_conn_add_unset(hdev, LE_LINK, dst, role);
+-              if (!conn)
+-                      return ERR_PTR(-ENOMEM);
++              if (IS_ERR(conn))
++                      return conn;
+               hci_conn_hold(conn);
+               conn->pending_sec_level = sec_level;
+       }
+@@ -1494,8 +1527,8 @@ static struct hci_conn *hci_add_bis(stru
+               return ERR_PTR(-EADDRINUSE);
+       conn = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
+-      if (!conn)
+-              return ERR_PTR(-ENOMEM);
++      if (IS_ERR(conn))
++              return conn;
+       conn->state = BT_CONNECT;
+@@ -1538,8 +1571,8 @@ struct hci_conn *hci_connect_le_scan(str
+       BT_DBG("requesting refresh of dst_addr");
+       conn = hci_conn_add_unset(hdev, LE_LINK, dst, HCI_ROLE_MASTER);
+-      if (!conn)
+-              return ERR_PTR(-ENOMEM);
++      if (IS_ERR(conn))
++              return conn;
+       if (hci_explicit_conn_params_set(hdev, dst, dst_type) < 0) {
+               hci_conn_del(conn);
+@@ -1586,8 +1619,8 @@ struct hci_conn *hci_connect_acl(struct
+       acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+       if (!acl) {
+               acl = hci_conn_add_unset(hdev, ACL_LINK, dst, HCI_ROLE_MASTER);
+-              if (!acl)
+-                      return ERR_PTR(-ENOMEM);
++              if (IS_ERR(acl))
++                      return acl;
+       }
+       hci_conn_hold(acl);
+@@ -1655,9 +1688,9 @@ struct hci_conn *hci_connect_sco(struct
+       sco = hci_conn_hash_lookup_ba(hdev, type, dst);
+       if (!sco) {
+               sco = hci_conn_add_unset(hdev, type, dst, HCI_ROLE_MASTER);
+-              if (!sco) {
++              if (IS_ERR(sco)) {
+                       hci_conn_drop(acl);
+-                      return ERR_PTR(-ENOMEM);
++                      return sco;
+               }
+       }
+@@ -1847,8 +1880,8 @@ struct hci_conn *hci_bind_cis(struct hci
+                                      qos->ucast.cis);
+       if (!cis) {
+               cis = hci_conn_add_unset(hdev, ISO_LINK, dst, HCI_ROLE_MASTER);
+-              if (!cis)
+-                      return ERR_PTR(-ENOMEM);
++              if (IS_ERR(cis))
++                      return cis;
+               cis->cleanup = cis_cleanup;
+               cis->dst_type = dst_type;
+               cis->iso_qos.ucast.cig = BT_ISO_QOS_CIG_UNSET;
+@@ -1983,14 +2016,8 @@ static void hci_iso_qos_setup(struct hci
+                             struct bt_iso_io_qos *qos, __u8 phy)
+ {
+       /* Only set MTU if PHY is enabled */
+-      if (!qos->sdu && qos->phy) {
+-              if (hdev->iso_mtu > 0)
+-                      qos->sdu = hdev->iso_mtu;
+-              else if (hdev->le_mtu > 0)
+-                      qos->sdu = hdev->le_mtu;
+-              else
+-                      qos->sdu = hdev->acl_mtu;
+-      }
++      if (!qos->sdu && qos->phy)
++              qos->sdu = conn->mtu;
+       /* Use the same PHY as ACL if set to any */
+       if (qos->phy == BT_ISO_PHY_ANY)
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -954,6 +954,9 @@ static u8 hci_cc_read_buffer_size(struct
+       BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
+              hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
++      if (!hdev->acl_mtu || !hdev->acl_pkts)
++              return HCI_ERROR_INVALID_PARAMETERS;
++
+       return rp->status;
+ }
+@@ -1263,6 +1266,9 @@ static u8 hci_cc_le_read_buffer_size(str
+       BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
++      if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
++              return HCI_ERROR_INVALID_PARAMETERS;
++
+       return rp->status;
+ }
+@@ -2342,8 +2348,8 @@ static void hci_cs_create_conn(struct hc
+               if (!conn) {
+                       conn = hci_conn_add_unset(hdev, ACL_LINK, &cp->bdaddr,
+                                                 HCI_ROLE_MASTER);
+-                      if (!conn)
+-                              bt_dev_err(hdev, "no memory for new connection");
++                      if (IS_ERR(conn))
++                              bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
+               }
+       }
+@@ -3154,8 +3160,8 @@ static void hci_conn_complete_evt(struct
+                                                     BDADDR_BREDR)) {
+                       conn = hci_conn_add_unset(hdev, ev->link_type,
+                                                 &ev->bdaddr, HCI_ROLE_SLAVE);
+-                      if (!conn) {
+-                              bt_dev_err(hdev, "no memory for new conn");
++                      if (IS_ERR(conn)) {
++                              bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
+                               goto unlock;
+                       }
+               } else {
+@@ -3343,8 +3349,8 @@ static void hci_conn_request_evt(struct
+       if (!conn) {
+               conn = hci_conn_add_unset(hdev, ev->link_type, &ev->bdaddr,
+                                         HCI_ROLE_SLAVE);
+-              if (!conn) {
+-                      bt_dev_err(hdev, "no memory for new connection");
++              if (IS_ERR(conn)) {
++                      bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
+                       goto unlock;
+               }
+       }
+@@ -3821,6 +3827,9 @@ static u8 hci_cc_le_read_buffer_size_v2(
+       BT_DBG("%s acl mtu %d:%d iso mtu %d:%d", hdev->name, hdev->acl_mtu,
+              hdev->acl_pkts, hdev->iso_mtu, hdev->iso_pkts);
++      if (hdev->le_mtu && hdev->le_mtu < HCI_MIN_LE_MTU)
++              return HCI_ERROR_INVALID_PARAMETERS;
++
+       return rp->status;
+ }
+@@ -5912,8 +5921,8 @@ static void le_conn_complete_evt(struct
+                       goto unlock;
+               conn = hci_conn_add_unset(hdev, LE_LINK, bdaddr, role);
+-              if (!conn) {
+-                      bt_dev_err(hdev, "no memory for new connection");
++              if (IS_ERR(conn)) {
++                      bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn));
+                       goto unlock;
+               }
+@@ -7042,7 +7051,7 @@ static void hci_le_cis_req_evt(struct hc
+       if (!cis) {
+               cis = hci_conn_add(hdev, ISO_LINK, &acl->dst, HCI_ROLE_SLAVE,
+                                  cis_handle);
+-              if (!cis) {
++              if (IS_ERR(cis)) {
+                       hci_le_reject_cis(hdev, ev->cis_handle);
+                       goto unlock;
+               }
+@@ -7151,7 +7160,7 @@ static void hci_le_big_sync_established_
+               if (!bis) {
+                       bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
+                                          HCI_ROLE_SLAVE, handle);
+-                      if (!bis)
++                      if (IS_ERR(bis))
+                               continue;
+               }
+@@ -7223,7 +7232,7 @@ static void hci_le_big_info_adv_report_e
+       pa_sync = hci_conn_add_unset(hdev, ISO_LINK, BDADDR_ANY,
+                                    HCI_ROLE_SLAVE);
+-      if (!pa_sync)
++      if (IS_ERR(pa_sync))
+               goto unlock;
+       pa_sync->sync_handle = le16_to_cpu(ev->sync_handle);
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -1264,7 +1264,7 @@ static int iso_sock_sendmsg(struct socke
+               return -ENOTCONN;
+       }
+-      mtu = iso_pi(sk)->conn->hcon->hdev->iso_mtu;
++      mtu = iso_pi(sk)->conn->hcon->mtu;
+       release_sock(sk);
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6241,7 +6241,7 @@ static int l2cap_finish_move(struct l2ca
+       BT_DBG("chan %p", chan);
+       chan->rx_state = L2CAP_RX_STATE_RECV;
+-      chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
++      chan->conn->mtu = chan->conn->hcon->mtu;
+       return l2cap_resegment(chan);
+ }
+@@ -6308,7 +6308,7 @@ static int l2cap_rx_state_wait_f(struct
+        */
+       chan->next_tx_seq = control->reqseq;
+       chan->unacked_frames = 0;
+-      chan->conn->mtu = chan->conn->hcon->hdev->acl_mtu;
++      chan->conn->mtu = chan->conn->hcon->mtu;
+       err = l2cap_resegment(chan);
+@@ -6848,18 +6848,7 @@ static struct l2cap_conn *l2cap_conn_add
+       BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan);
+-      switch (hcon->type) {
+-      case LE_LINK:
+-              if (hcon->hdev->le_mtu) {
+-                      conn->mtu = hcon->hdev->le_mtu;
+-                      break;
+-              }
+-              fallthrough;
+-      default:
+-              conn->mtu = hcon->hdev->acl_mtu;
+-              break;
+-      }
+-
++      conn->mtu = hcon->mtu;
+       conn->feat_mask = 0;
+       conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -126,7 +126,6 @@ static void sco_sock_clear_timer(struct
+ /* ---- SCO connections ---- */
+ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
+ {
+-      struct hci_dev *hdev = hcon->hdev;
+       struct sco_conn *conn = hcon->sco_data;
+       if (conn) {
+@@ -144,9 +143,10 @@ static struct sco_conn *sco_conn_add(str
+       hcon->sco_data = conn;
+       conn->hcon = hcon;
++      conn->mtu = hcon->mtu;
+-      if (hdev->sco_mtu > 0)
+-              conn->mtu = hdev->sco_mtu;
++      if (hcon->mtu > 0)
++              conn->mtu = hcon->mtu;
+       else
+               conn->mtu = 60;
diff --git a/queue-6.8/bluetooth-l2cap-fix-slab-use-after-free-in-l2cap_connect.patch b/queue-6.8/bluetooth-l2cap-fix-slab-use-after-free-in-l2cap_connect.patch
new file mode 100644 (file)
index 0000000..672a080
--- /dev/null
@@ -0,0 +1,118 @@
+From 4d7b41c0e43995b0e992b9f8903109275744b658 Mon Sep 17 00:00:00 2001
+From: Sungwoo Kim <iam@sung-woo.kim>
+Date: Tue, 30 Apr 2024 02:32:10 -0400
+Subject: Bluetooth: L2CAP: Fix slab-use-after-free in l2cap_connect()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sungwoo Kim <iam@sung-woo.kim>
+
+commit 4d7b41c0e43995b0e992b9f8903109275744b658 upstream.
+
+Extend a critical section to prevent chan from early freeing.
+Also make the l2cap_connect() return type void. Nothing is using the
+returned value but it is ugly to return a potentially freed pointer.
+Making it void will help with backports because earlier kernels did use
+the return value. Now the compile will break for kernels where this
+patch is not a complete fix.
+
+Call stack summary:
+
+[use]
+l2cap_bredr_sig_cmd
+  l2cap_connect
+  ┌ mutex_lock(&conn->chan_lock);
+  │ chan = pchan->ops->new_connection(pchan); <- alloc chan
+  │ __l2cap_chan_add(conn, chan);
+  │   l2cap_chan_hold(chan);
+  │   list_add(&chan->list, &conn->chan_l);   ... (1)
+  └ mutex_unlock(&conn->chan_lock);
+    chan->conf_state              ... (4) <- use after free
+
+[free]
+l2cap_conn_del
+┌ mutex_lock(&conn->chan_lock);
+│ foreach chan in conn->chan_l:            ... (2)
+│   l2cap_chan_put(chan);
+│     l2cap_chan_destroy
+│       kfree(chan)               ... (3) <- chan freed
+└ mutex_unlock(&conn->chan_lock);
+
+==================================================================
+BUG: KASAN: slab-use-after-free in instrument_atomic_read
+include/linux/instrumented.h:68 [inline]
+BUG: KASAN: slab-use-after-free in _test_bit
+include/asm-generic/bitops/instrumented-non-atomic.h:141 [inline]
+BUG: KASAN: slab-use-after-free in l2cap_connect+0xa67/0x11a0
+net/bluetooth/l2cap_core.c:4260
+Read of size 8 at addr ffff88810bf040a0 by task kworker/u3:1/311
+
+Fixes: 73ffa904b782 ("Bluetooth: Move conf_{req,rsp} stuff to struct l2cap_chan")
+Signed-off-by: Sungwoo Kim <iam@sung-woo.kim>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/l2cap_core.c |   21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -3905,13 +3905,12 @@ static inline int l2cap_command_rej(stru
+       return 0;
+ }
+-static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
+-                                      struct l2cap_cmd_hdr *cmd,
+-                                      u8 *data, u8 rsp_code, u8 amp_id)
++static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
++                        u8 *data, u8 rsp_code, u8 amp_id)
+ {
+       struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
+       struct l2cap_conn_rsp rsp;
+-      struct l2cap_chan *chan = NULL, *pchan;
++      struct l2cap_chan *chan = NULL, *pchan = NULL;
+       int result, status = L2CAP_CS_NO_INFO;
+       u16 dcid = 0, scid = __le16_to_cpu(req->scid);
+@@ -3924,7 +3923,7 @@ static struct l2cap_chan *l2cap_connect(
+                                        &conn->hcon->dst, ACL_LINK);
+       if (!pchan) {
+               result = L2CAP_CR_BAD_PSM;
+-              goto sendresp;
++              goto response;
+       }
+       mutex_lock(&conn->chan_lock);
+@@ -4011,17 +4010,15 @@ static struct l2cap_chan *l2cap_connect(
+       }
+ response:
+-      l2cap_chan_unlock(pchan);
+-      mutex_unlock(&conn->chan_lock);
+-      l2cap_chan_put(pchan);
+-
+-sendresp:
+       rsp.scid   = cpu_to_le16(scid);
+       rsp.dcid   = cpu_to_le16(dcid);
+       rsp.result = cpu_to_le16(result);
+       rsp.status = cpu_to_le16(status);
+       l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp);
++      if (!pchan)
++              return;
++
+       if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) {
+               struct l2cap_info_req info;
+               info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK);
+@@ -4044,7 +4041,9 @@ sendresp:
+               chan->num_conf_req++;
+       }
+-      return chan;
++      l2cap_chan_unlock(pchan);
++      mutex_unlock(&conn->chan_lock);
++      l2cap_chan_put(pchan);
+ }
+ static int l2cap_connect_req(struct l2cap_conn *conn,
index 124fb1ef0b627c1c1c65ec2601b9cc8e98a01923..3e4755ad1f00f7617c43ec15e9636f12ab78a228 100644 (file)
@@ -2,3 +2,5 @@ drm-amd-display-fix-division-by-zero-in-setup_dsc_config.patch
 net-ks8851-fix-another-tx-stall-caused-by-wrong-isr-flag-handling.patch
 ice-pass-vsi-pointer-into-ice_vc_isvalid_q_id.patch
 ice-remove-unnecessary-duplicate-checks-for-vf-vsi-id.patch
+bluetooth-l2cap-fix-slab-use-after-free-in-l2cap_connect.patch
+bluetooth-l2cap-fix-div-by-zero-in-l2cap_le_flowctl_init.patch