]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
add bluetooth regression reverts for 6.1 to be queued up later
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Nov 2024 15:09:21 +0000 (16:09 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Nov 2024 15:09:21 +0000 (16:09 +0100)
bt-regression-fix-6.1/revert-bluetooth-af_bluetooth-fix-deadlock.patch [new file with mode: 0644]
bt-regression-fix-6.1/revert-bluetooth-fix-use-after-free-in-accessing-skb-after-sending-it.patch [new file with mode: 0644]
bt-regression-fix-6.1/revert-bluetooth-hci_conn-consolidate-code-for-aborting-connections.patch [new file with mode: 0644]
bt-regression-fix-6.1/revert-bluetooth-hci_core-fix-possible-buffer-overflow.patch [new file with mode: 0644]
bt-regression-fix-6.1/revert-bluetooth-hci_sync-fix-overwriting-request-callback.patch [new file with mode: 0644]
bt-regression-fix-6.1/series [new file with mode: 0644]

diff --git a/bt-regression-fix-6.1/revert-bluetooth-af_bluetooth-fix-deadlock.patch b/bt-regression-fix-6.1/revert-bluetooth-af_bluetooth-fix-deadlock.patch
new file mode 100644 (file)
index 0000000..731dfea
--- /dev/null
@@ -0,0 +1,68 @@
+From 1b8851da51113f6a7f01297823eaf22b4b772063 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Wed, 13 Nov 2024 15:43:55 +0100
+Subject: Revert "Bluetooth: af_bluetooth: Fix deadlock"
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+This reverts commit cb8adca52f306563d958a863bb0cbae9c184d1ae which is
+commit f7b94bdc1ec107c92262716b073b3e816d4784fb upstream.
+
+It is reported to cause regressions in the 6.1.y tree, so revert it for
+now.
+
+Link: https://lore.kernel.org/all/CADRbXaDqx6S+7tzdDPPEpRu9eDLrHQkqoWTTGfKJSRxY=hT5MQ@mail.gmail.com/
+Reported-by: Jeremy Lainé <jeremy.laine@m4x.org>
+Cc: Salvatore Bonaccorso <carnil@debian.org>
+Cc: Mike <user.service2016@gmail.com>
+Cc: Marcel Holtmann <marcel@holtmann.org>
+Cc: Johan Hedberg <johan.hedberg@gmail.com>
+Cc: Paul Menzel <pmenzel@molgen.mpg.de>
+Cc: Pauli Virtanen <pav@iki.fi>
+Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Cc: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/af_bluetooth.c |   10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/net/bluetooth/af_bluetooth.c
++++ b/net/bluetooth/af_bluetooth.c
+@@ -307,11 +307,14 @@ int bt_sock_recvmsg(struct socket *sock,
+       if (flags & MSG_OOB)
+               return -EOPNOTSUPP;
++      lock_sock(sk);
++
+       skb = skb_recv_datagram(sk, flags, &err);
+       if (!skb) {
+               if (sk->sk_shutdown & RCV_SHUTDOWN)
+                       err = 0;
++              release_sock(sk);
+               return err;
+       }
+@@ -337,6 +340,8 @@ int bt_sock_recvmsg(struct socket *sock,
+       skb_free_datagram(sk, skb);
++      release_sock(sk);
++
+       if (flags & MSG_TRUNC)
+               copied = skblen;
+@@ -559,11 +564,10 @@ int bt_sock_ioctl(struct socket *sock, u
+               if (sk->sk_state == BT_LISTEN)
+                       return -EINVAL;
+-              spin_lock(&sk->sk_receive_queue.lock);
++              lock_sock(sk);
+               skb = skb_peek(&sk->sk_receive_queue);
+               amount = skb ? skb->len : 0;
+-              spin_unlock(&sk->sk_receive_queue.lock);
+-
++              release_sock(sk);
+               err = put_user(amount, (int __user *)arg);
+               break;
diff --git a/bt-regression-fix-6.1/revert-bluetooth-fix-use-after-free-in-accessing-skb-after-sending-it.patch b/bt-regression-fix-6.1/revert-bluetooth-fix-use-after-free-in-accessing-skb-after-sending-it.patch
new file mode 100644 (file)
index 0000000..f42686e
--- /dev/null
@@ -0,0 +1,39 @@
+From bb6015962fa5e0f3b624c605e502fc0b29c325ff Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Wed, 13 Nov 2024 15:42:18 +0100
+Subject: Revert "Bluetooth: fix use-after-free in accessing skb after sending it"
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+This reverts commit 715264ad09fd4004e347cdb79fa58a4f2344f13f which is
+commit 947ec0d002dce8577b655793dcc6fc78d67b7cb6 upstream.
+
+It is reported to cause regressions in the 6.1.y tree, so revert it for
+now.
+
+Link: https://lore.kernel.org/all/CADRbXaDqx6S+7tzdDPPEpRu9eDLrHQkqoWTTGfKJSRxY=hT5MQ@mail.gmail.com/
+Reported-by: Jeremy Lainé <jeremy.laine@m4x.org>
+Cc: Salvatore Bonaccorso <carnil@debian.org>
+Cc: Mike <user.service2016@gmail.com>
+Cc: Marcel Holtmann <marcel@holtmann.org>
+Cc: Johan Hedberg <johan.hedberg@gmail.com>
+Cc: Paul Menzel <pmenzel@molgen.mpg.de>
+Cc: Pauli Virtanen <pav@iki.fi>
+Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Cc: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/hci_core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -4146,7 +4146,7 @@ static void hci_send_cmd_sync(struct hci
+       if (hci_req_status_pend(hdev) &&
+           !hci_dev_test_and_set_flag(hdev, HCI_CMD_PENDING)) {
+               kfree_skb(hdev->req_skb);
+-              hdev->req_skb = skb_clone(hdev->sent_cmd, GFP_KERNEL);
++              hdev->req_skb = skb_clone(skb, GFP_KERNEL);
+       }
+       atomic_dec(&hdev->cmd_cnt);
diff --git a/bt-regression-fix-6.1/revert-bluetooth-hci_conn-consolidate-code-for-aborting-connections.patch b/bt-regression-fix-6.1/revert-bluetooth-hci_conn-consolidate-code-for-aborting-connections.patch
new file mode 100644 (file)
index 0000000..40df222
--- /dev/null
@@ -0,0 +1,333 @@
+From 898205b3df400a1d9e8311778fae9219e526c444 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Wed, 13 Nov 2024 15:45:02 +0100
+Subject: Revert "Bluetooth: hci_conn: Consolidate code for aborting connections"
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+This reverts commit 6083089ab00631617f9eac678df3ab050a9d837a which is
+commit a13f316e90fdb1fb6df6582e845aa9b3270f3581 upstream.
+
+It is reported to cause regressions in the 6.1.y tree, so revert it for
+now.
+
+Link: https://lore.kernel.org/all/CADRbXaDqx6S+7tzdDPPEpRu9eDLrHQkqoWTTGfKJSRxY=hT5MQ@mail.gmail.com/
+Reported-by: Jeremy Lainé <jeremy.laine@m4x.org>
+Cc: Salvatore Bonaccorso <carnil@debian.org>
+Cc: Mike <user.service2016@gmail.com>
+Cc: Marcel Holtmann <marcel@holtmann.org>
+Cc: Johan Hedberg <johan.hedberg@gmail.com>
+Cc: Paul Menzel <pmenzel@molgen.mpg.de>
+Cc: Pauli Virtanen <pav@iki.fi>
+Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Cc: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/bluetooth/hci_core.h |    2 
+ net/bluetooth/hci_conn.c         |  156 +++++++++++++++++++++++++++++++--------
+ net/bluetooth/hci_sync.c         |   23 ++---
+ net/bluetooth/mgmt.c             |   15 +++
+ 4 files changed, 148 insertions(+), 48 deletions(-)
+
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -734,7 +734,6 @@ struct hci_conn {
+       unsigned long   flags;
+       enum conn_reasons conn_reason;
+-      __u8            abort_reason;
+       __u32           clock;
+       __u16           clock_accuracy;
+@@ -754,6 +753,7 @@ struct hci_conn {
+       struct delayed_work auto_accept_work;
+       struct delayed_work idle_work;
+       struct delayed_work le_conn_timeout;
++      struct work_struct  le_scan_cleanup;
+       struct device   dev;
+       struct dentry   *debugfs;
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -174,6 +174,57 @@ static void hci_conn_cleanup(struct hci_
+       hci_dev_put(hdev);
+ }
++static void le_scan_cleanup(struct work_struct *work)
++{
++      struct hci_conn *conn = container_of(work, struct hci_conn,
++                                           le_scan_cleanup);
++      struct hci_dev *hdev = conn->hdev;
++      struct hci_conn *c = NULL;
++
++      BT_DBG("%s hcon %p", hdev->name, conn);
++
++      hci_dev_lock(hdev);
++
++      /* Check that the hci_conn is still around */
++      rcu_read_lock();
++      list_for_each_entry_rcu(c, &hdev->conn_hash.list, list) {
++              if (c == conn)
++                      break;
++      }
++      rcu_read_unlock();
++
++      if (c == conn) {
++              hci_connect_le_scan_cleanup(conn, 0x00);
++              hci_conn_cleanup(conn);
++      }
++
++      hci_dev_unlock(hdev);
++      hci_dev_put(hdev);
++      hci_conn_put(conn);
++}
++
++static void hci_connect_le_scan_remove(struct hci_conn *conn)
++{
++      BT_DBG("%s hcon %p", conn->hdev->name, conn);
++
++      /* We can't call hci_conn_del/hci_conn_cleanup here since that
++       * could deadlock with another hci_conn_del() call that's holding
++       * hci_dev_lock and doing cancel_delayed_work_sync(&conn->disc_work).
++       * Instead, grab temporary extra references to the hci_dev and
++       * hci_conn and perform the necessary cleanup in a separate work
++       * callback.
++       */
++
++      hci_dev_hold(conn->hdev);
++      hci_conn_get(conn);
++
++      /* Even though we hold a reference to the hdev, many other
++       * things might get cleaned up meanwhile, including the hdev's
++       * own workqueue, so we can't use that for scheduling.
++       */
++      schedule_work(&conn->le_scan_cleanup);
++}
++
+ static void hci_acl_create_connection(struct hci_conn *conn)
+ {
+       struct hci_dev *hdev = conn->hdev;
+@@ -625,6 +676,13 @@ static void hci_conn_timeout(struct work
+       if (refcnt > 0)
+               return;
++      /* LE connections in scanning state need special handling */
++      if (conn->state == BT_CONNECT && conn->type == LE_LINK &&
++          test_bit(HCI_CONN_SCANNING, &conn->flags)) {
++              hci_connect_le_scan_remove(conn);
++              return;
++      }
++
+       hci_abort_conn(conn, hci_proto_disconn_ind(conn));
+ }
+@@ -996,6 +1054,7 @@ struct hci_conn *hci_conn_add(struct hci
+       INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept);
+       INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle);
+       INIT_DELAYED_WORK(&conn->le_conn_timeout, le_conn_timeout);
++      INIT_WORK(&conn->le_scan_cleanup, le_scan_cleanup);
+       atomic_set(&conn->refcnt, 0);
+@@ -2781,46 +2840,81 @@ u32 hci_conn_get_phy(struct hci_conn *co
+       return phys;
+ }
+-static int abort_conn_sync(struct hci_dev *hdev, void *data)
++int hci_abort_conn(struct hci_conn *conn, u8 reason)
+ {
+-      struct hci_conn *conn;
+-      u16 handle = PTR_ERR(data);
++      int r = 0;
+-      conn = hci_conn_hash_lookup_handle(hdev, handle);
+-      if (!conn)
++      if (test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
+               return 0;
+-      return hci_abort_conn_sync(hdev, conn, conn->abort_reason);
+-}
+-
+-int hci_abort_conn(struct hci_conn *conn, u8 reason)
+-{
+-      struct hci_dev *hdev = conn->hdev;
++      switch (conn->state) {
++      case BT_CONNECTED:
++      case BT_CONFIG:
++              if (conn->type == AMP_LINK) {
++                      struct hci_cp_disconn_phy_link cp;
++
++                      cp.phy_handle = HCI_PHY_HANDLE(conn->handle);
++                      cp.reason = reason;
++                      r = hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK,
++                                       sizeof(cp), &cp);
++              } else {
++                      struct hci_cp_disconnect dc;
+-      /* If abort_reason has already been set it means the connection is
+-       * already being aborted so don't attempt to overwrite it.
+-       */
+-      if (conn->abort_reason)
+-              return 0;
++                      dc.handle = cpu_to_le16(conn->handle);
++                      dc.reason = reason;
++                      r = hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT,
++                                       sizeof(dc), &dc);
++              }
+-      bt_dev_dbg(hdev, "handle 0x%2.2x reason 0x%2.2x", conn->handle, reason);
++              conn->state = BT_DISCONN;
+-      conn->abort_reason = reason;
++              break;
++      case BT_CONNECT:
++              if (conn->type == LE_LINK) {
++                      if (test_bit(HCI_CONN_SCANNING, &conn->flags))
++                              break;
++                      r = hci_send_cmd(conn->hdev,
++                                       HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
++              } else if (conn->type == ACL_LINK) {
++                      if (conn->hdev->hci_ver < BLUETOOTH_VER_1_2)
++                              break;
++                      r = hci_send_cmd(conn->hdev,
++                                       HCI_OP_CREATE_CONN_CANCEL,
++                                       6, &conn->dst);
++              }
++              break;
++      case BT_CONNECT2:
++              if (conn->type == ACL_LINK) {
++                      struct hci_cp_reject_conn_req rej;
++
++                      bacpy(&rej.bdaddr, &conn->dst);
++                      rej.reason = reason;
++
++                      r = hci_send_cmd(conn->hdev,
++                                       HCI_OP_REJECT_CONN_REQ,
++                                       sizeof(rej), &rej);
++              } else if (conn->type == SCO_LINK || conn->type == ESCO_LINK) {
++                      struct hci_cp_reject_sync_conn_req rej;
++
++                      bacpy(&rej.bdaddr, &conn->dst);
++
++                      /* SCO rejection has its own limited set of
++                       * allowed error values (0x0D-0x0F) which isn't
++                       * compatible with most values passed to this
++                       * function. To be safe hard-code one of the
++                       * values that's suitable for SCO.
++                       */
++                      rej.reason = HCI_ERROR_REJ_LIMITED_RESOURCES;
+-      /* If the connection is pending check the command opcode since that
+-       * might be blocking on hci_cmd_sync_work while waiting its respective
+-       * event so we need to hci_cmd_sync_cancel to cancel it.
+-       */
+-      if (conn->state == BT_CONNECT && hdev->req_status == HCI_REQ_PEND) {
+-              switch (hci_skb_event(hdev->sent_cmd)) {
+-              case HCI_EV_LE_CONN_COMPLETE:
+-              case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
+-              case HCI_EVT_LE_CIS_ESTABLISHED:
+-                      hci_cmd_sync_cancel(hdev, -ECANCELED);
+-                      break;
++                      r = hci_send_cmd(conn->hdev,
++                                       HCI_OP_REJECT_SYNC_CONN_REQ,
++                                       sizeof(rej), &rej);
+               }
++              break;
++      default:
++              conn->state = BT_CLOSED;
++              break;
+       }
+-      return hci_cmd_sync_queue(hdev, abort_conn_sync, ERR_PTR(conn->handle),
+-                                NULL);
++      return r;
+ }
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -5293,27 +5293,22 @@ static int hci_disconnect_sync(struct hc
+ }
+ static int hci_le_connect_cancel_sync(struct hci_dev *hdev,
+-                                    struct hci_conn *conn, u8 reason)
++                                    struct hci_conn *conn)
+ {
+-      /* Return reason if scanning since the connection shall probably be
+-       * cleanup directly.
+-       */
+       if (test_bit(HCI_CONN_SCANNING, &conn->flags))
+-              return reason;
++              return 0;
+-      if (conn->role == HCI_ROLE_SLAVE ||
+-          test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
++      if (test_and_set_bit(HCI_CONN_CANCEL, &conn->flags))
+               return 0;
+       return __hci_cmd_sync_status(hdev, HCI_OP_LE_CREATE_CONN_CANCEL,
+                                    0, NULL, HCI_CMD_TIMEOUT);
+ }
+-static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn,
+-                                 u8 reason)
++static int hci_connect_cancel_sync(struct hci_dev *hdev, struct hci_conn *conn)
+ {
+       if (conn->type == LE_LINK)
+-              return hci_le_connect_cancel_sync(hdev, conn, reason);
++              return hci_le_connect_cancel_sync(hdev, conn);
+       if (hdev->hci_ver < BLUETOOTH_VER_1_2)
+               return 0;
+@@ -5366,11 +5361,9 @@ int hci_abort_conn_sync(struct hci_dev *
+       case BT_CONFIG:
+               return hci_disconnect_sync(hdev, conn, reason);
+       case BT_CONNECT:
+-              err = hci_connect_cancel_sync(hdev, conn, reason);
++              err = hci_connect_cancel_sync(hdev, conn);
+               /* Cleanup hci_conn object if it cannot be cancelled as it
+-               * likelly means the controller and host stack are out of sync
+-               * or in case of LE it was still scanning so it can be cleanup
+-               * safely.
++               * likelly means the controller and host stack are out of sync.
+                */
+               if (err) {
+                       hci_dev_lock(hdev);
+@@ -6285,7 +6278,7 @@ int hci_le_create_conn_sync(struct hci_d
+ done:
+       if (err == -ETIMEDOUT)
+-              hci_le_connect_cancel_sync(hdev, conn, 0x00);
++              hci_le_connect_cancel_sync(hdev, conn);
+       /* Re-enable advertising after the connection attempt is finished. */
+       hci_resume_advertising_sync(hdev);
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -3600,6 +3600,18 @@ unlock:
+       return err;
+ }
++static int abort_conn_sync(struct hci_dev *hdev, void *data)
++{
++      struct hci_conn *conn;
++      u16 handle = PTR_ERR(data);
++
++      conn = hci_conn_hash_lookup_handle(hdev, handle);
++      if (!conn)
++              return 0;
++
++      return hci_abort_conn_sync(hdev, conn, HCI_ERROR_REMOTE_USER_TERM);
++}
++
+ static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
+                             u16 len)
+ {
+@@ -3650,7 +3662,8 @@ static int cancel_pair_device(struct soc
+                                             le_addr_type(addr->type));
+       if (conn->conn_reason == CONN_REASON_PAIR_DEVICE)
+-              hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
++              hci_cmd_sync_queue(hdev, abort_conn_sync, ERR_PTR(conn->handle),
++                                 NULL);
+ unlock:
+       hci_dev_unlock(hdev);
diff --git a/bt-regression-fix-6.1/revert-bluetooth-hci_core-fix-possible-buffer-overflow.patch b/bt-regression-fix-6.1/revert-bluetooth-hci_core-fix-possible-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..85d3f9f
--- /dev/null
@@ -0,0 +1,39 @@
+From ed41cfef23ae134993de32a77ed6a30df2b5bb2a Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Wed, 13 Nov 2024 15:44:07 +0100
+Subject: Revert "Bluetooth: hci_core: Fix possible buffer overflow"
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+This reverts commit 68644bf5ec6baaff40fc39b3529c874bfda709bd which is
+commit 81137162bfaa7278785b24c1fd2e9e74f082e8e4 upstream.
+
+It is reported to cause regressions in the 6.1.y tree, so revert it for
+now.
+
+Link: https://lore.kernel.org/all/CADRbXaDqx6S+7tzdDPPEpRu9eDLrHQkqoWTTGfKJSRxY=hT5MQ@mail.gmail.com/
+Reported-by: Jeremy Lainé <jeremy.laine@m4x.org>
+Cc: Salvatore Bonaccorso <carnil@debian.org>
+Cc: Mike <user.service2016@gmail.com>
+Cc: Marcel Holtmann <marcel@holtmann.org>
+Cc: Johan Hedberg <johan.hedberg@gmail.com>
+Cc: Paul Menzel <pmenzel@molgen.mpg.de>
+Cc: Pauli Virtanen <pav@iki.fi>
+Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Cc: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/hci_core.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -869,7 +869,7 @@ int hci_get_dev_info(void __user *arg)
+       else
+               flags = hdev->flags;
+-      strscpy(di.name, hdev->name, sizeof(di.name));
++      strcpy(di.name, hdev->name);
+       di.bdaddr   = hdev->bdaddr;
+       di.type     = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4);
+       di.flags    = flags;
diff --git a/bt-regression-fix-6.1/revert-bluetooth-hci_sync-fix-overwriting-request-callback.patch b/bt-regression-fix-6.1/revert-bluetooth-hci_sync-fix-overwriting-request-callback.patch
new file mode 100644 (file)
index 0000000..0a5eca1
--- /dev/null
@@ -0,0 +1,251 @@
+From 9cb0d1e2bf8f7faeb42466768b46f0cf2da80941 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Wed, 13 Nov 2024 15:42:48 +0100
+Subject: Revert "Bluetooth: hci_sync: Fix overwriting request callback"
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+This reverts commit da77c1d39bc527b31890bfa0405763c82828defb which is
+commit 2615fd9a7c2507eb3be3fbe49dcec88a2f56454a upstream.
+
+It is reported to cause regressions in the 6.1.y tree, so revert it for
+now.
+
+Link: https://lore.kernel.org/all/CADRbXaDqx6S+7tzdDPPEpRu9eDLrHQkqoWTTGfKJSRxY=hT5MQ@mail.gmail.com/
+Reported-by: Jeremy Lainé <jeremy.laine@m4x.org>
+Cc: Salvatore Bonaccorso <carnil@debian.org>
+Cc: Mike <user.service2016@gmail.com>
+Cc: Marcel Holtmann <marcel@holtmann.org>
+Cc: Johan Hedberg <johan.hedberg@gmail.com>
+Cc: Paul Menzel <pmenzel@molgen.mpg.de>
+Cc: Pauli Virtanen <pav@iki.fi>
+Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Cc: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/bluetooth/hci_core.h |    1 
+ net/bluetooth/hci_conn.c         |    2 -
+ net/bluetooth/hci_core.c         |   46 +++++++++++----------------------------
+ net/bluetooth/hci_event.c        |   18 +++++++--------
+ net/bluetooth/hci_sync.c         |   21 ++---------------
+ 5 files changed, 27 insertions(+), 61 deletions(-)
+
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -544,7 +544,6 @@ struct hci_dev {
+       __u32                   req_status;
+       __u32                   req_result;
+       struct sk_buff          *req_skb;
+-      struct sk_buff          *req_rsp;
+       void                    *smp_data;
+       void                    *smp_bredr_data;
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -2816,7 +2816,7 @@ int hci_abort_conn(struct hci_conn *conn
+               case HCI_EV_LE_CONN_COMPLETE:
+               case HCI_EV_LE_ENHANCED_CONN_COMPLETE:
+               case HCI_EVT_LE_CIS_ESTABLISHED:
+-                      hci_cmd_sync_cancel(hdev, ECANCELED);
++                      hci_cmd_sync_cancel(hdev, -ECANCELED);
+                       break;
+               }
+       }
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -1452,8 +1452,8 @@ static void hci_cmd_timeout(struct work_
+       struct hci_dev *hdev = container_of(work, struct hci_dev,
+                                           cmd_timer.work);
+-      if (hdev->req_skb) {
+-              u16 opcode = hci_skb_opcode(hdev->req_skb);
++      if (hdev->sent_cmd) {
++              u16 opcode = hci_skb_opcode(hdev->sent_cmd);
+               bt_dev_err(hdev, "command 0x%4.4x tx timeout", opcode);
+@@ -2762,7 +2762,6 @@ void hci_release_dev(struct hci_dev *hde
+       ida_simple_remove(&hci_index_ida, hdev->id);
+       kfree_skb(hdev->sent_cmd);
+-      kfree_skb(hdev->req_skb);
+       kfree_skb(hdev->recv_event);
+       kfree(hdev);
+ }
+@@ -3092,33 +3091,21 @@ int __hci_cmd_send(struct hci_dev *hdev,
+ EXPORT_SYMBOL(__hci_cmd_send);
+ /* Get data from the previously sent command */
+-static void *hci_cmd_data(struct sk_buff *skb, __u16 opcode)
++void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
+ {
+       struct hci_command_hdr *hdr;
+-      if (!skb || skb->len < HCI_COMMAND_HDR_SIZE)
++      if (!hdev->sent_cmd)
+               return NULL;
+-      hdr = (void *)skb->data;
++      hdr = (void *) hdev->sent_cmd->data;
+       if (hdr->opcode != cpu_to_le16(opcode))
+               return NULL;
+-      return skb->data + HCI_COMMAND_HDR_SIZE;
+-}
++      BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
+-/* Get data from the previously sent command */
+-void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
+-{
+-      void *data;
+-
+-      /* Check if opcode matches last sent command */
+-      data = hci_cmd_data(hdev->sent_cmd, opcode);
+-      if (!data)
+-              /* Check if opcode matches last request */
+-              data = hci_cmd_data(hdev->req_skb, opcode);
+-
+-      return data;
++      return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE;
+ }
+ /* Get data from last received event */
+@@ -4014,19 +4001,17 @@ void hci_req_cmd_complete(struct hci_dev
+       if (!status && !hci_req_is_complete(hdev))
+               return;
+-      skb = hdev->req_skb;
+-
+       /* If this was the last command in a request the complete
+-       * callback would be found in hdev->req_skb instead of the
++       * callback would be found in hdev->sent_cmd instead of the
+        * command queue (hdev->cmd_q).
+        */
+-      if (skb && bt_cb(skb)->hci.req_flags & HCI_REQ_SKB) {
+-              *req_complete_skb = bt_cb(skb)->hci.req_complete_skb;
++      if (bt_cb(hdev->sent_cmd)->hci.req_flags & HCI_REQ_SKB) {
++              *req_complete_skb = bt_cb(hdev->sent_cmd)->hci.req_complete_skb;
+               return;
+       }
+-      if (skb && bt_cb(skb)->hci.req_complete) {
+-              *req_complete = bt_cb(skb)->hci.req_complete;
++      if (bt_cb(hdev->sent_cmd)->hci.req_complete) {
++              *req_complete = bt_cb(hdev->sent_cmd)->hci.req_complete;
+               return;
+       }
+@@ -4143,11 +4128,8 @@ static void hci_send_cmd_sync(struct hci
+               return;
+       }
+-      if (hci_req_status_pend(hdev) &&
+-          !hci_dev_test_and_set_flag(hdev, HCI_CMD_PENDING)) {
+-              kfree_skb(hdev->req_skb);
+-              hdev->req_skb = skb_clone(skb, GFP_KERNEL);
+-      }
++      if (hci_req_status_pend(hdev))
++              hci_dev_set_flag(hdev, HCI_CMD_PENDING);
+       atomic_dec(&hdev->cmd_cnt);
+ }
+--- a/net/bluetooth/hci_event.c
++++ b/net/bluetooth/hci_event.c
+@@ -4354,7 +4354,7 @@ static void hci_cmd_status_evt(struct hc
+        * (since for this kind of commands there will not be a command
+        * complete event).
+        */
+-      if (ev->status || (hdev->req_skb && !hci_skb_event(hdev->req_skb))) {
++      if (ev->status || (hdev->sent_cmd && !hci_skb_event(hdev->sent_cmd))) {
+               hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
+                                    req_complete_skb);
+               if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
+@@ -7171,10 +7171,10 @@ static void hci_le_meta_evt(struct hci_d
+       bt_dev_dbg(hdev, "subevent 0x%2.2x", ev->subevent);
+       /* Only match event if command OGF is for LE */
+-      if (hdev->req_skb &&
+-          hci_opcode_ogf(hci_skb_opcode(hdev->req_skb)) == 0x08 &&
+-          hci_skb_event(hdev->req_skb) == ev->subevent) {
+-              *opcode = hci_skb_opcode(hdev->req_skb);
++      if (hdev->sent_cmd &&
++          hci_opcode_ogf(hci_skb_opcode(hdev->sent_cmd)) == 0x08 &&
++          hci_skb_event(hdev->sent_cmd) == ev->subevent) {
++              *opcode = hci_skb_opcode(hdev->sent_cmd);
+               hci_req_cmd_complete(hdev, *opcode, 0x00, req_complete,
+                                    req_complete_skb);
+       }
+@@ -7561,10 +7561,10 @@ void hci_event_packet(struct hci_dev *hd
+       }
+       /* Only match event if command OGF is not for LE */
+-      if (hdev->req_skb &&
+-          hci_opcode_ogf(hci_skb_opcode(hdev->req_skb)) != 0x08 &&
+-          hci_skb_event(hdev->req_skb) == event) {
+-              hci_req_cmd_complete(hdev, hci_skb_opcode(hdev->req_skb),
++      if (hdev->sent_cmd &&
++          hci_opcode_ogf(hci_skb_opcode(hdev->sent_cmd)) != 0x08 &&
++          hci_skb_event(hdev->sent_cmd) == event) {
++              hci_req_cmd_complete(hdev, hci_skb_opcode(hdev->sent_cmd),
+                                    status, &req_complete, &req_complete_skb);
+               req_evt = event;
+       }
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -31,10 +31,6 @@ static void hci_cmd_sync_complete(struct
+       hdev->req_result = result;
+       hdev->req_status = HCI_REQ_DONE;
+-      /* Free the request command so it is not used as response */
+-      kfree_skb(hdev->req_skb);
+-      hdev->req_skb = NULL;
+-
+       if (skb) {
+               struct sock *sk = hci_skb_sk(skb);
+@@ -42,7 +38,7 @@ static void hci_cmd_sync_complete(struct
+               if (sk)
+                       sock_put(sk);
+-              hdev->req_rsp = skb_get(skb);
++              hdev->req_skb = skb_get(skb);
+       }
+       wake_up_interruptible(&hdev->req_wait_q);
+@@ -190,8 +186,8 @@ struct sk_buff *__hci_cmd_sync_sk(struct
+       hdev->req_status = 0;
+       hdev->req_result = 0;
+-      skb = hdev->req_rsp;
+-      hdev->req_rsp = NULL;
++      skb = hdev->req_skb;
++      hdev->req_skb = NULL;
+       bt_dev_dbg(hdev, "end: err %d", err);
+@@ -4941,11 +4937,6 @@ int hci_dev_open_sync(struct hci_dev *hd
+                       hdev->sent_cmd = NULL;
+               }
+-              if (hdev->req_skb) {
+-                      kfree_skb(hdev->req_skb);
+-                      hdev->req_skb = NULL;
+-              }
+-
+               clear_bit(HCI_RUNNING, &hdev->flags);
+               hci_sock_dev_event(hdev, HCI_DEV_CLOSE);
+@@ -5107,12 +5098,6 @@ int hci_dev_close_sync(struct hci_dev *h
+               hdev->sent_cmd = NULL;
+       }
+-      /* Drop last request */
+-      if (hdev->req_skb) {
+-              kfree_skb(hdev->req_skb);
+-              hdev->req_skb = NULL;
+-      }
+-
+       clear_bit(HCI_RUNNING, &hdev->flags);
+       hci_sock_dev_event(hdev, HCI_DEV_CLOSE);
diff --git a/bt-regression-fix-6.1/series b/bt-regression-fix-6.1/series
new file mode 100644 (file)
index 0000000..f02660b
--- /dev/null
@@ -0,0 +1,5 @@
+revert-bluetooth-fix-use-after-free-in-accessing-skb-after-sending-it.patch
+revert-bluetooth-hci_sync-fix-overwriting-request-callback.patch
+revert-bluetooth-af_bluetooth-fix-deadlock.patch
+revert-bluetooth-hci_core-fix-possible-buffer-overflow.patch
+revert-bluetooth-hci_conn-consolidate-code-for-aborting-connections.patch