]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for all trees
authorSasha Levin <sashal@kernel.org>
Sun, 16 Nov 2025 17:36:33 +0000 (12:36 -0500)
committerSasha Levin <sashal@kernel.org>
Sun, 16 Nov 2025 17:36:33 +0000 (12:36 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.12/bluetooth-mgmt-fix-possible-uafs.patch [new file with mode: 0644]
queue-6.12/ext4-fix-out-of-bound-read-in-ext4_xattr_inode_dec_r.patch [new file with mode: 0644]
queue-6.12/ext4-introduce-itail-helper.patch [new file with mode: 0644]
queue-6.12/f2fs-fix-to-avoid-overflow-while-left-shift-operatio.patch [new file with mode: 0644]
queue-6.12/lib-crypto-arm-curve25519-disable-on-cpu_big_endian.patch [new file with mode: 0644]
queue-6.12/proc-fix-the-issue-of-proc_mem_open-returning-null.patch [new file with mode: 0644]
queue-6.12/series
queue-6.12/wifi-ath11k-clear-affinity-hint-before-calling-ath11.patch [new file with mode: 0644]
queue-6.17/lib-crypto-arm-curve25519-disable-on-cpu_big_endian.patch [new file with mode: 0644]
queue-6.17/series

diff --git a/queue-6.12/bluetooth-mgmt-fix-possible-uafs.patch b/queue-6.12/bluetooth-mgmt-fix-possible-uafs.patch
new file mode 100644 (file)
index 0000000..03abb3c
--- /dev/null
@@ -0,0 +1,776 @@
+From fde9607444ff7b540d0899f85e901c5ed52b35d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Nov 2025 16:07:51 +0800
+Subject: Bluetooth: MGMT: Fix possible UAFs
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 302a1f674c00dd5581ab8e493ef44767c5101aab ]
+
+This attemps to fix possible UAFs caused by struct mgmt_pending being
+freed while still being processed like in the following trace, in order
+to fix mgmt_pending_valid is introduce and use to check if the
+mgmt_pending hasn't been removed from the pending list, on the complete
+callbacks it is used to check and in addtion remove the cmd from the list
+while holding mgmt_pending_lock to avoid TOCTOU problems since if the cmd
+is left on the list it can still be accessed and freed.
+
+BUG: KASAN: slab-use-after-free in mgmt_add_adv_patterns_monitor_sync+0x35/0x50 net/bluetooth/mgmt.c:5223
+Read of size 8 at addr ffff8880709d4dc0 by task kworker/u11:0/55
+
+CPU: 0 UID: 0 PID: 55 Comm: kworker/u11:0 Not tainted 6.16.4 #2 PREEMPT(full)
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
+Workqueue: hci0 hci_cmd_sync_work
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
+ print_address_description mm/kasan/report.c:378 [inline]
+ print_report+0xca/0x240 mm/kasan/report.c:482
+ kasan_report+0x118/0x150 mm/kasan/report.c:595
+ mgmt_add_adv_patterns_monitor_sync+0x35/0x50 net/bluetooth/mgmt.c:5223
+ hci_cmd_sync_work+0x210/0x3a0 net/bluetooth/hci_sync.c:332
+ process_one_work kernel/workqueue.c:3238 [inline]
+ process_scheduled_works+0xade/0x17b0 kernel/workqueue.c:3321
+ worker_thread+0x8a0/0xda0 kernel/workqueue.c:3402
+ kthread+0x711/0x8a0 kernel/kthread.c:464
+ ret_from_fork+0x3fc/0x770 arch/x86/kernel/process.c:148
+ ret_from_fork_asm+0x1a/0x30 home/kwqcheii/source/fuzzing/kernel/kasan/linux-6.16.4/arch/x86/entry/entry_64.S:245
+ </TASK>
+
+Allocated by task 12210:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x3e/0x80 mm/kasan/common.c:68
+ poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
+ __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:394
+ kasan_kmalloc include/linux/kasan.h:260 [inline]
+ __kmalloc_cache_noprof+0x230/0x3d0 mm/slub.c:4364
+ kmalloc_noprof include/linux/slab.h:905 [inline]
+ kzalloc_noprof include/linux/slab.h:1039 [inline]
+ mgmt_pending_new+0x65/0x1e0 net/bluetooth/mgmt_util.c:269
+ mgmt_pending_add+0x35/0x140 net/bluetooth/mgmt_util.c:296
+ __add_adv_patterns_monitor+0x130/0x200 net/bluetooth/mgmt.c:5247
+ add_adv_patterns_monitor+0x214/0x360 net/bluetooth/mgmt.c:5364
+ hci_mgmt_cmd+0x9c9/0xef0 net/bluetooth/hci_sock.c:1719
+ hci_sock_sendmsg+0x6ca/0xef0 net/bluetooth/hci_sock.c:1839
+ sock_sendmsg_nosec net/socket.c:714 [inline]
+ __sock_sendmsg+0x219/0x270 net/socket.c:729
+ sock_write_iter+0x258/0x330 net/socket.c:1133
+ new_sync_write fs/read_write.c:593 [inline]
+ vfs_write+0x5c9/0xb30 fs/read_write.c:686
+ ksys_write+0x145/0x250 fs/read_write.c:738
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Freed by task 12221:
+ kasan_save_stack mm/kasan/common.c:47 [inline]
+ kasan_save_track+0x3e/0x80 mm/kasan/common.c:68
+ kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576
+ poison_slab_object mm/kasan/common.c:247 [inline]
+ __kasan_slab_free+0x62/0x70 mm/kasan/common.c:264
+ kasan_slab_free include/linux/kasan.h:233 [inline]
+ slab_free_hook mm/slub.c:2381 [inline]
+ slab_free mm/slub.c:4648 [inline]
+ kfree+0x18e/0x440 mm/slub.c:4847
+ mgmt_pending_free net/bluetooth/mgmt_util.c:311 [inline]
+ mgmt_pending_foreach+0x30d/0x380 net/bluetooth/mgmt_util.c:257
+ __mgmt_power_off+0x169/0x350 net/bluetooth/mgmt.c:9444
+ hci_dev_close_sync+0x754/0x1330 net/bluetooth/hci_sync.c:5290
+ hci_dev_do_close net/bluetooth/hci_core.c:501 [inline]
+ hci_dev_close+0x108/0x200 net/bluetooth/hci_core.c:526
+ sock_do_ioctl+0xd9/0x300 net/socket.c:1192
+ sock_ioctl+0x576/0x790 net/socket.c:1313
+ vfs_ioctl fs/ioctl.c:51 [inline]
+ __do_sys_ioctl fs/ioctl.c:907 [inline]
+ __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:893
+ do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
+ do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
+ entry_SYSCALL_64_after_hwframe+0x77/0x7f
+
+Fixes: cf75ad8b41d2 ("Bluetooth: hci_sync: Convert MGMT_SET_POWERED")
+Fixes: 2bd1b237616b ("Bluetooth: hci_sync: Convert MGMT_OP_SET_DISCOVERABLE to use cmd_sync")
+Fixes: f056a65783cc ("Bluetooth: hci_sync: Convert MGMT_OP_SET_CONNECTABLE to use cmd_sync")
+Fixes: 3244845c6307 ("Bluetooth: hci_sync: Convert MGMT_OP_SSP")
+Fixes: d81a494c43df ("Bluetooth: hci_sync: Convert MGMT_OP_SET_LE")
+Fixes: b338d91703fa ("Bluetooth: Implement support for Mesh")
+Fixes: 6f6ff38a1e14 ("Bluetooth: hci_sync: Convert MGMT_OP_SET_LOCAL_NAME")
+Fixes: 71efbb08b538 ("Bluetooth: hci_sync: Convert MGMT_OP_SET_PHY_CONFIGURATION")
+Fixes: b747a83690c8 ("Bluetooth: hci_sync: Refactor add Adv Monitor")
+Fixes: abfeea476c68 ("Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY")
+Fixes: 26ac4c56f03f ("Bluetooth: hci_sync: Convert MGMT_OP_SET_ADVERTISING")
+Reported-by: cen zhang <zzzccc427@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Chen Yu <xnguchen@sina.cn>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c      | 259 ++++++++++++++++++++++++++------------
+ net/bluetooth/mgmt_util.c |  46 +++++++
+ net/bluetooth/mgmt_util.h |   3 +
+ 3 files changed, 231 insertions(+), 77 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index c54cc701cdd48..83e33d9cfb33c 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -1318,8 +1318,7 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err)
+       struct mgmt_mode *cp;
+       /* Make sure cmd still outstanding. */
+-      if (err == -ECANCELED ||
+-          cmd != pending_find(MGMT_OP_SET_POWERED, hdev))
++      if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
+               return;
+       cp = cmd->param;
+@@ -1346,23 +1345,29 @@ static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err)
+                               mgmt_status(err));
+       }
+-      mgmt_pending_remove(cmd);
++      mgmt_pending_free(cmd);
+ }
+ static int set_powered_sync(struct hci_dev *hdev, void *data)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-      struct mgmt_mode *cp;
++      struct mgmt_mode cp;
++
++      mutex_lock(&hdev->mgmt_pending_lock);
+       /* Make sure cmd still outstanding. */
+-      if (cmd != pending_find(MGMT_OP_SET_POWERED, hdev))
++      if (!__mgmt_pending_listed(hdev, cmd)) {
++              mutex_unlock(&hdev->mgmt_pending_lock);
+               return -ECANCELED;
++      }
+-      cp = cmd->param;
++      memcpy(&cp, cmd->param, sizeof(cp));
++
++      mutex_unlock(&hdev->mgmt_pending_lock);
+       BT_DBG("%s", hdev->name);
+-      return hci_set_powered_sync(hdev, cp->val);
++      return hci_set_powered_sync(hdev, cp.val);
+ }
+ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
+@@ -1511,8 +1516,7 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data,
+       bt_dev_dbg(hdev, "err %d", err);
+       /* Make sure cmd still outstanding. */
+-      if (err == -ECANCELED ||
+-          cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
++      if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
+               return;
+       hci_dev_lock(hdev);
+@@ -1534,12 +1538,15 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data,
+       new_settings(hdev, cmd->sk);
+ done:
+-      mgmt_pending_remove(cmd);
++      mgmt_pending_free(cmd);
+       hci_dev_unlock(hdev);
+ }
+ static int set_discoverable_sync(struct hci_dev *hdev, void *data)
+ {
++      if (!mgmt_pending_listed(hdev, data))
++              return -ECANCELED;
++
+       BT_DBG("%s", hdev->name);
+       return hci_update_discoverable_sync(hdev);
+@@ -1686,8 +1693,7 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data,
+       bt_dev_dbg(hdev, "err %d", err);
+       /* Make sure cmd still outstanding. */
+-      if (err == -ECANCELED ||
+-          cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
++      if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
+               return;
+       hci_dev_lock(hdev);
+@@ -1702,7 +1708,7 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data,
+       new_settings(hdev, cmd->sk);
+ done:
+-      mgmt_pending_remove(cmd);
++      mgmt_pending_free(cmd);
+       hci_dev_unlock(hdev);
+ }
+@@ -1738,6 +1744,9 @@ static int set_connectable_update_settings(struct hci_dev *hdev,
+ static int set_connectable_sync(struct hci_dev *hdev, void *data)
+ {
++      if (!mgmt_pending_listed(hdev, data))
++              return -ECANCELED;
++
+       BT_DBG("%s", hdev->name);
+       return hci_update_connectable_sync(hdev);
+@@ -1914,14 +1923,17 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
+ {
+       struct cmd_lookup match = { NULL, hdev };
+       struct mgmt_pending_cmd *cmd = data;
+-      struct mgmt_mode *cp = cmd->param;
+-      u8 enable = cp->val;
++      struct mgmt_mode *cp;
++      u8 enable;
+       bool changed;
+       /* Make sure cmd still outstanding. */
+-      if (err == -ECANCELED || cmd != pending_find(MGMT_OP_SET_SSP, hdev))
++      if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
+               return;
++      cp = cmd->param;
++      enable = cp->val;
++
+       if (err) {
+               u8 mgmt_err = mgmt_status(err);
+@@ -1930,8 +1942,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
+                       new_settings(hdev, NULL);
+               }
+-              mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true,
+-                                   cmd_status_rsp, &mgmt_err);
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err);
+               return;
+       }
+@@ -1941,7 +1952,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
+               changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
+       }
+-      mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, true, settings_rsp, &match);
++      settings_rsp(cmd, &match);
+       if (changed)
+               new_settings(hdev, match.sk);
+@@ -1955,14 +1966,25 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
+ static int set_ssp_sync(struct hci_dev *hdev, void *data)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-      struct mgmt_mode *cp = cmd->param;
++      struct mgmt_mode cp;
+       bool changed = false;
+       int err;
+-      if (cp->val)
++      mutex_lock(&hdev->mgmt_pending_lock);
++
++      if (!__mgmt_pending_listed(hdev, cmd)) {
++              mutex_unlock(&hdev->mgmt_pending_lock);
++              return -ECANCELED;
++      }
++
++      memcpy(&cp, cmd->param, sizeof(cp));
++
++      mutex_unlock(&hdev->mgmt_pending_lock);
++
++      if (cp.val)
+               changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
+-      err = hci_write_ssp_mode_sync(hdev, cp->val);
++      err = hci_write_ssp_mode_sync(hdev, cp.val);
+       if (!err && changed)
+               hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
+@@ -2055,32 +2077,50 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
+ static void set_le_complete(struct hci_dev *hdev, void *data, int err)
+ {
++      struct mgmt_pending_cmd *cmd = data;
+       struct cmd_lookup match = { NULL, hdev };
+       u8 status = mgmt_status(err);
+       bt_dev_dbg(hdev, "err %d", err);
+-      if (status) {
+-              mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, cmd_status_rsp,
+-                                   &status);
++      if (err == -ECANCELED || !mgmt_pending_valid(hdev, data))
+               return;
++
++      if (status) {
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, status);
++              goto done;
+       }
+-      mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, true, settings_rsp, &match);
++      settings_rsp(cmd, &match);
+       new_settings(hdev, match.sk);
+       if (match.sk)
+               sock_put(match.sk);
++
++done:
++      mgmt_pending_free(cmd);
+ }
+ static int set_le_sync(struct hci_dev *hdev, void *data)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-      struct mgmt_mode *cp = cmd->param;
+-      u8 val = !!cp->val;
++      struct mgmt_mode cp;
++      u8 val;
+       int err;
++      mutex_lock(&hdev->mgmt_pending_lock);
++
++      if (!__mgmt_pending_listed(hdev, cmd)) {
++              mutex_unlock(&hdev->mgmt_pending_lock);
++              return -ECANCELED;
++      }
++
++      memcpy(&cp, cmd->param, sizeof(cp));
++      val = !!cp.val;
++
++      mutex_unlock(&hdev->mgmt_pending_lock);
++
+       if (!val) {
+               hci_clear_adv_instance_sync(hdev, NULL, 0x00, true);
+@@ -2122,7 +2162,12 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+       u8 status = mgmt_status(err);
+-      struct sock *sk = cmd->sk;
++      struct sock *sk;
++
++      if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
++              return;
++
++      sk = cmd->sk;
+       if (status) {
+               mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true,
+@@ -2137,24 +2182,37 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err)
+ static int set_mesh_sync(struct hci_dev *hdev, void *data)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-      struct mgmt_cp_set_mesh *cp = cmd->param;
+-      size_t len = cmd->param_len;
++      struct mgmt_cp_set_mesh cp;
++      size_t len;
++
++      mutex_lock(&hdev->mgmt_pending_lock);
++
++      if (!__mgmt_pending_listed(hdev, cmd)) {
++              mutex_unlock(&hdev->mgmt_pending_lock);
++              return -ECANCELED;
++      }
++
++      memcpy(&cp, cmd->param, sizeof(cp));
++
++      mutex_unlock(&hdev->mgmt_pending_lock);
++
++      len = cmd->param_len;
+       memset(hdev->mesh_ad_types, 0, sizeof(hdev->mesh_ad_types));
+-      if (cp->enable)
++      if (cp.enable)
+               hci_dev_set_flag(hdev, HCI_MESH);
+       else
+               hci_dev_clear_flag(hdev, HCI_MESH);
+-      hdev->le_scan_interval = __le16_to_cpu(cp->period);
+-      hdev->le_scan_window = __le16_to_cpu(cp->window);
++      hdev->le_scan_interval = __le16_to_cpu(cp.period);
++      hdev->le_scan_window = __le16_to_cpu(cp.window);
+-      len -= sizeof(*cp);
++      len -= sizeof(cp);
+       /* If filters don't fit, forward all adv pkts */
+       if (len <= sizeof(hdev->mesh_ad_types))
+-              memcpy(hdev->mesh_ad_types, cp->ad_types, len);
++              memcpy(hdev->mesh_ad_types, cp.ad_types, len);
+       hci_update_passive_scan_sync(hdev);
+       return 0;
+@@ -3801,15 +3859,16 @@ static int name_changed_sync(struct hci_dev *hdev, void *data)
+ static void set_name_complete(struct hci_dev *hdev, void *data, int err)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-      struct mgmt_cp_set_local_name *cp = cmd->param;
++      struct mgmt_cp_set_local_name *cp;
+       u8 status = mgmt_status(err);
+       bt_dev_dbg(hdev, "err %d", err);
+-      if (err == -ECANCELED ||
+-          cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev))
++      if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
+               return;
++      cp = cmd->param;
++
+       if (status) {
+               mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
+                               status);
+@@ -3821,16 +3880,27 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err)
+                       hci_cmd_sync_queue(hdev, name_changed_sync, NULL, NULL);
+       }
+-      mgmt_pending_remove(cmd);
++      mgmt_pending_free(cmd);
+ }
+ static int set_name_sync(struct hci_dev *hdev, void *data)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-      struct mgmt_cp_set_local_name *cp = cmd->param;
++      struct mgmt_cp_set_local_name cp;
++
++      mutex_lock(&hdev->mgmt_pending_lock);
++
++      if (!__mgmt_pending_listed(hdev, cmd)) {
++              mutex_unlock(&hdev->mgmt_pending_lock);
++              return -ECANCELED;
++      }
++
++      memcpy(&cp, cmd->param, sizeof(cp));
++
++      mutex_unlock(&hdev->mgmt_pending_lock);
+       if (lmp_bredr_capable(hdev)) {
+-              hci_update_name_sync(hdev, cp->name);
++              hci_update_name_sync(hdev, cp.name);
+               hci_update_eir_sync(hdev);
+       }
+@@ -3982,12 +4052,10 @@ int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip)
+ static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-      struct sk_buff *skb = cmd->skb;
++      struct sk_buff *skb;
+       u8 status = mgmt_status(err);
+-      if (err == -ECANCELED ||
+-          cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev))
+-              return;
++      skb = cmd->skb;
+       if (!status) {
+               if (!skb)
+@@ -4014,7 +4082,7 @@ static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err)
+       if (skb && !IS_ERR(skb))
+               kfree_skb(skb);
+-      mgmt_pending_remove(cmd);
++      mgmt_pending_free(cmd);
+ }
+ static int set_default_phy_sync(struct hci_dev *hdev, void *data)
+@@ -4022,7 +4090,9 @@ static int set_default_phy_sync(struct hci_dev *hdev, void *data)
+       struct mgmt_pending_cmd *cmd = data;
+       struct mgmt_cp_set_phy_configuration *cp = cmd->param;
+       struct hci_cp_le_set_default_phy cp_phy;
+-      u32 selected_phys = __le32_to_cpu(cp->selected_phys);
++      u32 selected_phys;
++
++      selected_phys = __le32_to_cpu(cp->selected_phys);
+       memset(&cp_phy, 0, sizeof(cp_phy));
+@@ -4162,7 +4232,7 @@ static int set_phy_configuration(struct sock *sk, struct hci_dev *hdev,
+               goto unlock;
+       }
+-      cmd = mgmt_pending_add(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data,
++      cmd = mgmt_pending_new(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data,
+                              len);
+       if (!cmd)
+               err = -ENOMEM;
+@@ -5252,7 +5322,17 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev,
+ {
+       struct mgmt_rp_add_adv_patterns_monitor rp;
+       struct mgmt_pending_cmd *cmd = data;
+-      struct adv_monitor *monitor = cmd->user_data;
++      struct adv_monitor *monitor;
++
++      /* This is likely the result of hdev being closed and mgmt_index_removed
++       * is attempting to clean up any pending command so
++       * hci_adv_monitors_clear is about to be called which will take care of
++       * freeing the adv_monitor instances.
++       */
++      if (status == -ECANCELED && !mgmt_pending_valid(hdev, cmd))
++              return;
++
++      monitor = cmd->user_data;
+       hci_dev_lock(hdev);
+@@ -5278,9 +5358,20 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev,
+ static int mgmt_add_adv_patterns_monitor_sync(struct hci_dev *hdev, void *data)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-      struct adv_monitor *monitor = cmd->user_data;
++      struct adv_monitor *mon;
++
++      mutex_lock(&hdev->mgmt_pending_lock);
++
++      if (!__mgmt_pending_listed(hdev, cmd)) {
++              mutex_unlock(&hdev->mgmt_pending_lock);
++              return -ECANCELED;
++      }
++
++      mon = cmd->user_data;
++
++      mutex_unlock(&hdev->mgmt_pending_lock);
+-      return hci_add_adv_monitor(hdev, monitor);
++      return hci_add_adv_monitor(hdev, mon);
+ }
+ static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
+@@ -5547,7 +5638,8 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
+                              status);
+ }
+-static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, int err)
++static void read_local_oob_data_complete(struct hci_dev *hdev, void *data,
++                                       int err)
+ {
+       struct mgmt_rp_read_local_oob_data mgmt_rp;
+       size_t rp_size = sizeof(mgmt_rp);
+@@ -5567,7 +5659,8 @@ static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, int e
+       bt_dev_dbg(hdev, "status %d", status);
+       if (status) {
+-              mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, status);
++              mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
++                              status);
+               goto remove;
+       }
+@@ -5872,17 +5965,12 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err)
+       bt_dev_dbg(hdev, "err %d", err);
+-      if (err == -ECANCELED)
+-              return;
+-
+-      if (cmd != pending_find(MGMT_OP_START_DISCOVERY, hdev) &&
+-          cmd != pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev) &&
+-          cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev))
++      if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
+               return;
+       mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err),
+                         cmd->param, 1);
+-      mgmt_pending_remove(cmd);
++      mgmt_pending_free(cmd);
+       hci_discovery_set_state(hdev, err ? DISCOVERY_STOPPED:
+                               DISCOVERY_FINDING);
+@@ -5890,6 +5978,9 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err)
+ static int start_discovery_sync(struct hci_dev *hdev, void *data)
+ {
++      if (!mgmt_pending_listed(hdev, data))
++              return -ECANCELED;
++
+       return hci_start_discovery_sync(hdev);
+ }
+@@ -6112,15 +6203,14 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-      if (err == -ECANCELED ||
+-          cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev))
++      if (err == -ECANCELED || !mgmt_pending_valid(hdev, cmd))
+               return;
+       bt_dev_dbg(hdev, "err %d", err);
+       mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_status(err),
+                         cmd->param, 1);
+-      mgmt_pending_remove(cmd);
++      mgmt_pending_free(cmd);
+       if (!err)
+               hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+@@ -6128,6 +6218,9 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err)
+ static int stop_discovery_sync(struct hci_dev *hdev, void *data)
+ {
++      if (!mgmt_pending_listed(hdev, data))
++              return -ECANCELED;
++
+       return hci_stop_discovery_sync(hdev);
+ }
+@@ -6337,14 +6430,18 @@ static void enable_advertising_instance(struct hci_dev *hdev, int err)
+ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)
+ {
++      struct mgmt_pending_cmd *cmd = data;
+       struct cmd_lookup match = { NULL, hdev };
+       u8 instance;
+       struct adv_info *adv_instance;
+       u8 status = mgmt_status(err);
++      if (err == -ECANCELED || !mgmt_pending_valid(hdev, data))
++              return;
++
+       if (status) {
+-              mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true,
+-                                   cmd_status_rsp, &status);
++              mgmt_cmd_status(cmd->sk, cmd->hdev->id, cmd->opcode, status);
++              mgmt_pending_free(cmd);
+               return;
+       }
+@@ -6353,8 +6450,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)
+       else
+               hci_dev_clear_flag(hdev, HCI_ADVERTISING);
+-      mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, true, settings_rsp,
+-                           &match);
++      settings_rsp(cmd, &match);
+       new_settings(hdev, match.sk);
+@@ -6386,10 +6482,23 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)
+ static int set_adv_sync(struct hci_dev *hdev, void *data)
+ {
+       struct mgmt_pending_cmd *cmd = data;
+-      struct mgmt_mode *cp = cmd->param;
+-      u8 val = !!cp->val;
++      struct mgmt_mode cp;
++      u8 val;
+-      if (cp->val == 0x02)
++      mutex_lock(&hdev->mgmt_pending_lock);
++
++      if (!__mgmt_pending_listed(hdev, cmd)) {
++              mutex_unlock(&hdev->mgmt_pending_lock);
++              return -ECANCELED;
++      }
++
++      memcpy(&cp, cmd->param, sizeof(cp));
++
++      mutex_unlock(&hdev->mgmt_pending_lock);
++
++      val = !!cp.val;
++
++      if (cp.val == 0x02)
+               hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
+       else
+               hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
+@@ -8142,10 +8251,6 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, void *data,
+       u8 status = mgmt_status(err);
+       u16 eir_len;
+-      if (err == -ECANCELED ||
+-          cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev))
+-              return;
+-
+       if (!status) {
+               if (!skb)
+                       status = MGMT_STATUS_FAILED;
+@@ -8252,7 +8357,7 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, void *data,
+               kfree_skb(skb);
+       kfree(mgmt_rp);
+-      mgmt_pending_remove(cmd);
++      mgmt_pending_free(cmd);
+ }
+ static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
+@@ -8261,7 +8366,7 @@ static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
+       struct mgmt_pending_cmd *cmd;
+       int err;
+-      cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
++      cmd = mgmt_pending_new(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
+                              cp, sizeof(*cp));
+       if (!cmd)
+               return -ENOMEM;
+diff --git a/net/bluetooth/mgmt_util.c b/net/bluetooth/mgmt_util.c
+index a88a07da39473..aa7b5585cb268 100644
+--- a/net/bluetooth/mgmt_util.c
++++ b/net/bluetooth/mgmt_util.c
+@@ -320,6 +320,52 @@ void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
+       mgmt_pending_free(cmd);
+ }
++bool __mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd)
++{
++      struct mgmt_pending_cmd *tmp;
++
++      lockdep_assert_held(&hdev->mgmt_pending_lock);
++
++      if (!cmd)
++              return false;
++
++      list_for_each_entry(tmp, &hdev->mgmt_pending, list) {
++              if (cmd == tmp)
++                      return true;
++      }
++
++      return false;
++}
++
++bool mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd)
++{
++      bool listed;
++
++      mutex_lock(&hdev->mgmt_pending_lock);
++      listed = __mgmt_pending_listed(hdev, cmd);
++      mutex_unlock(&hdev->mgmt_pending_lock);
++
++      return listed;
++}
++
++bool mgmt_pending_valid(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd)
++{
++      bool listed;
++
++      if (!cmd)
++              return false;
++
++      mutex_lock(&hdev->mgmt_pending_lock);
++
++      listed = __mgmt_pending_listed(hdev, cmd);
++      if (listed)
++              list_del(&cmd->list);
++
++      mutex_unlock(&hdev->mgmt_pending_lock);
++
++      return listed;
++}
++
+ void mgmt_mesh_foreach(struct hci_dev *hdev,
+                      void (*cb)(struct mgmt_mesh_tx *mesh_tx, void *data),
+                      void *data, struct sock *sk)
+diff --git a/net/bluetooth/mgmt_util.h b/net/bluetooth/mgmt_util.h
+index 024e51dd69375..bcba8c9d89528 100644
+--- a/net/bluetooth/mgmt_util.h
++++ b/net/bluetooth/mgmt_util.h
+@@ -65,6 +65,9 @@ struct mgmt_pending_cmd *mgmt_pending_new(struct sock *sk, u16 opcode,
+                                         void *data, u16 len);
+ void mgmt_pending_free(struct mgmt_pending_cmd *cmd);
+ void mgmt_pending_remove(struct mgmt_pending_cmd *cmd);
++bool __mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd);
++bool mgmt_pending_listed(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd);
++bool mgmt_pending_valid(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd);
+ void mgmt_mesh_foreach(struct hci_dev *hdev,
+                      void (*cb)(struct mgmt_mesh_tx *mesh_tx, void *data),
+                      void *data, struct sock *sk);
+-- 
+2.51.0
+
diff --git a/queue-6.12/ext4-fix-out-of-bound-read-in-ext4_xattr_inode_dec_r.patch b/queue-6.12/ext4-fix-out-of-bound-read-in-ext4_xattr_inode_dec_r.patch
new file mode 100644 (file)
index 0000000..e35b36d
--- /dev/null
@@ -0,0 +1,200 @@
+From 203119c647e317ce65d00d86b818154bafaadcbe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Nov 2025 17:55:37 +0800
+Subject: ext4: fix out-of-bound read in ext4_xattr_inode_dec_ref_all()
+
+From: Ye Bin <yebin10@huawei.com>
+
+[ Upstream commit 5701875f9609b000d91351eaa6bfd97fe2f157f4 ]
+
+There's issue as follows:
+BUG: KASAN: use-after-free in ext4_xattr_inode_dec_ref_all+0x6ff/0x790
+Read of size 4 at addr ffff88807b003000 by task syz-executor.0/15172
+
+CPU: 3 PID: 15172 Comm: syz-executor.0
+Call Trace:
+ __dump_stack lib/dump_stack.c:82 [inline]
+ dump_stack+0xbe/0xfd lib/dump_stack.c:123
+ print_address_description.constprop.0+0x1e/0x280 mm/kasan/report.c:400
+ __kasan_report.cold+0x6c/0x84 mm/kasan/report.c:560
+ kasan_report+0x3a/0x50 mm/kasan/report.c:585
+ ext4_xattr_inode_dec_ref_all+0x6ff/0x790 fs/ext4/xattr.c:1137
+ ext4_xattr_delete_inode+0x4c7/0xda0 fs/ext4/xattr.c:2896
+ ext4_evict_inode+0xb3b/0x1670 fs/ext4/inode.c:323
+ evict+0x39f/0x880 fs/inode.c:622
+ iput_final fs/inode.c:1746 [inline]
+ iput fs/inode.c:1772 [inline]
+ iput+0x525/0x6c0 fs/inode.c:1758
+ ext4_orphan_cleanup fs/ext4/super.c:3298 [inline]
+ ext4_fill_super+0x8c57/0xba40 fs/ext4/super.c:5300
+ mount_bdev+0x355/0x410 fs/super.c:1446
+ legacy_get_tree+0xfe/0x220 fs/fs_context.c:611
+ vfs_get_tree+0x8d/0x2f0 fs/super.c:1576
+ do_new_mount fs/namespace.c:2983 [inline]
+ path_mount+0x119a/0x1ad0 fs/namespace.c:3316
+ do_mount+0xfc/0x110 fs/namespace.c:3329
+ __do_sys_mount fs/namespace.c:3540 [inline]
+ __se_sys_mount+0x219/0x2e0 fs/namespace.c:3514
+ do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46
+ entry_SYSCALL_64_after_hwframe+0x67/0xd1
+
+Memory state around the buggy address:
+ ffff88807b002f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ ffff88807b002f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+>ffff88807b003000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+                   ^
+ ffff88807b003080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+ ffff88807b003100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
+
+Above issue happens as ext4_xattr_delete_inode() isn't check xattr
+is valid if xattr is in inode.
+To solve above issue call xattr_check_inode() check if xattr if valid
+in inode. In fact, we can directly verify in ext4_iget_extra_inode(),
+so that there is no divergent verification.
+
+Fixes: e50e5129f384 ("ext4: xattr-in-inode support")
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20250208063141.1539283-3-yebin@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Rajani Kantha <681739313@139.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/inode.c |  5 +++++
+ fs/ext4/xattr.c | 26 +-------------------------
+ fs/ext4/xattr.h |  7 +++++++
+ 3 files changed, 13 insertions(+), 25 deletions(-)
+
+diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
+index 4ad34eba00a77..ae513b14fd084 100644
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -4688,6 +4688,11 @@ static inline int ext4_iget_extra_inode(struct inode *inode,
+           *magic == cpu_to_le32(EXT4_XATTR_MAGIC)) {
+               int err;
++              err = xattr_check_inode(inode, IHDR(inode, raw_inode),
++                                      ITAIL(inode, raw_inode));
++              if (err)
++                      return err;
++
+               ext4_set_inode_state(inode, EXT4_STATE_XATTR);
+               err = ext4_find_inline_data_nolock(inode);
+               if (!err && ext4_has_inline_data(inode))
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index 6946c1fc790ab..efaad43a7aab7 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -312,7 +312,7 @@ __ext4_xattr_check_block(struct inode *inode, struct buffer_head *bh,
+       __ext4_xattr_check_block((inode), (bh),  __func__, __LINE__)
+-static inline int
++int
+ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
+                        void *end, const char *function, unsigned int line)
+ {
+@@ -320,9 +320,6 @@ __xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
+                           function, line);
+ }
+-#define xattr_check_inode(inode, header, end) \
+-      __xattr_check_inode((inode), (header), (end), __func__, __LINE__)
+-
+ static int
+ xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry,
+                void *end, int name_index, const char *name, int sorted)
+@@ -654,9 +651,6 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
+       raw_inode = ext4_raw_inode(&iloc);
+       header = IHDR(inode, raw_inode);
+       end = ITAIL(inode, raw_inode);
+-      error = xattr_check_inode(inode, header, end);
+-      if (error)
+-              goto cleanup;
+       entry = IFIRST(header);
+       error = xattr_find_entry(inode, &entry, end, name_index, name, 0);
+       if (error)
+@@ -787,7 +781,6 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+       struct ext4_xattr_ibody_header *header;
+       struct ext4_inode *raw_inode;
+       struct ext4_iloc iloc;
+-      void *end;
+       int error;
+       if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
+@@ -797,14 +790,9 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+               return error;
+       raw_inode = ext4_raw_inode(&iloc);
+       header = IHDR(inode, raw_inode);
+-      end = ITAIL(inode, raw_inode);
+-      error = xattr_check_inode(inode, header, end);
+-      if (error)
+-              goto cleanup;
+       error = ext4_xattr_list_entries(dentry, IFIRST(header),
+                                       buffer, buffer_size);
+-cleanup:
+       brelse(iloc.bh);
+       return error;
+ }
+@@ -872,7 +860,6 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
+       struct ext4_xattr_ibody_header *header;
+       struct ext4_xattr_entry *entry;
+       qsize_t ea_inode_refs = 0;
+-      void *end;
+       int ret;
+       lockdep_assert_held_read(&EXT4_I(inode)->xattr_sem);
+@@ -883,10 +870,6 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
+                       goto out;
+               raw_inode = ext4_raw_inode(&iloc);
+               header = IHDR(inode, raw_inode);
+-              end = ITAIL(inode, raw_inode);
+-              ret = xattr_check_inode(inode, header, end);
+-              if (ret)
+-                      goto out;
+               for (entry = IFIRST(header); !IS_LAST_ENTRY(entry);
+                    entry = EXT4_XATTR_NEXT(entry))
+@@ -2251,9 +2234,6 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
+       is->s.here = is->s.first;
+       is->s.end = ITAIL(inode, raw_inode);
+       if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
+-              error = xattr_check_inode(inode, header, is->s.end);
+-              if (error)
+-                      return error;
+               /* Find the named attribute. */
+               error = xattr_find_entry(inode, &is->s.here, is->s.end,
+                                        i->name_index, i->name, 0);
+@@ -2804,10 +2784,6 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+       min_offs = end - base;
+       total_ino = sizeof(struct ext4_xattr_ibody_header) + sizeof(u32);
+-      error = xattr_check_inode(inode, header, end);
+-      if (error)
+-              goto cleanup;
+-
+       ifree = ext4_xattr_free_space(base, &min_offs, base, &total_ino);
+       if (ifree >= isize_diff)
+               goto shift;
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index 5197f17ffd9a2..1fedf44d4fb65 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -209,6 +209,13 @@ extern int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode,
+ extern struct mb_cache *ext4_xattr_create_cache(void);
+ extern void ext4_xattr_destroy_cache(struct mb_cache *);
++extern int
++__xattr_check_inode(struct inode *inode, struct ext4_xattr_ibody_header *header,
++                  void *end, const char *function, unsigned int line);
++
++#define xattr_check_inode(inode, header, end) \
++      __xattr_check_inode((inode), (header), (end), __func__, __LINE__)
++
+ #ifdef CONFIG_EXT4_FS_SECURITY
+ extern int ext4_init_security(handle_t *handle, struct inode *inode,
+                             struct inode *dir, const struct qstr *qstr);
+-- 
+2.51.0
+
diff --git a/queue-6.12/ext4-introduce-itail-helper.patch b/queue-6.12/ext4-introduce-itail-helper.patch
new file mode 100644 (file)
index 0000000..15eaa86
--- /dev/null
@@ -0,0 +1,88 @@
+From 8eecdfb913a86ac0bf7ff124d5032d1a22b3e2e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Nov 2025 17:55:36 +0800
+Subject: ext4: introduce ITAIL helper
+
+From: Ye Bin <yebin10@huawei.com>
+
+[ Upstream commit 69f3a3039b0d0003de008659cafd5a1eaaa0a7a4 ]
+
+Introduce ITAIL helper to get the bound of xattr in inode.
+
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://patch.msgid.link/20250208063141.1539283-2-yebin@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Rajani Kantha <681739313@139.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext4/xattr.c | 10 +++++-----
+ fs/ext4/xattr.h |  3 +++
+ 2 files changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
+index ce986312bf685..6946c1fc790ab 100644
+--- a/fs/ext4/xattr.c
++++ b/fs/ext4/xattr.c
+@@ -653,7 +653,7 @@ ext4_xattr_ibody_get(struct inode *inode, int name_index, const char *name,
+               return error;
+       raw_inode = ext4_raw_inode(&iloc);
+       header = IHDR(inode, raw_inode);
+-      end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
++      end = ITAIL(inode, raw_inode);
+       error = xattr_check_inode(inode, header, end);
+       if (error)
+               goto cleanup;
+@@ -797,7 +797,7 @@ ext4_xattr_ibody_list(struct dentry *dentry, char *buffer, size_t buffer_size)
+               return error;
+       raw_inode = ext4_raw_inode(&iloc);
+       header = IHDR(inode, raw_inode);
+-      end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
++      end = ITAIL(inode, raw_inode);
+       error = xattr_check_inode(inode, header, end);
+       if (error)
+               goto cleanup;
+@@ -883,7 +883,7 @@ int ext4_get_inode_usage(struct inode *inode, qsize_t *usage)
+                       goto out;
+               raw_inode = ext4_raw_inode(&iloc);
+               header = IHDR(inode, raw_inode);
+-              end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
++              end = ITAIL(inode, raw_inode);
+               ret = xattr_check_inode(inode, header, end);
+               if (ret)
+                       goto out;
+@@ -2249,7 +2249,7 @@ int ext4_xattr_ibody_find(struct inode *inode, struct ext4_xattr_info *i,
+       header = IHDR(inode, raw_inode);
+       is->s.base = is->s.first = IFIRST(header);
+       is->s.here = is->s.first;
+-      is->s.end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
++      is->s.end = ITAIL(inode, raw_inode);
+       if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
+               error = xattr_check_inode(inode, header, is->s.end);
+               if (error)
+@@ -2800,7 +2800,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
+        */
+       base = IFIRST(header);
+-      end = (void *)raw_inode + EXT4_SB(inode->i_sb)->s_inode_size;
++      end = ITAIL(inode, raw_inode);
+       min_offs = end - base;
+       total_ino = sizeof(struct ext4_xattr_ibody_header) + sizeof(u32);
+diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
+index b25c2d7b5f991..5197f17ffd9a2 100644
+--- a/fs/ext4/xattr.h
++++ b/fs/ext4/xattr.h
+@@ -67,6 +67,9 @@ struct ext4_xattr_entry {
+               ((void *)raw_inode + \
+               EXT4_GOOD_OLD_INODE_SIZE + \
+               EXT4_I(inode)->i_extra_isize))
++#define ITAIL(inode, raw_inode) \
++      ((void *)(raw_inode) + \
++       EXT4_SB((inode)->i_sb)->s_inode_size)
+ #define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1))
+ /*
+-- 
+2.51.0
+
diff --git a/queue-6.12/f2fs-fix-to-avoid-overflow-while-left-shift-operatio.patch b/queue-6.12/f2fs-fix-to-avoid-overflow-while-left-shift-operatio.patch
new file mode 100644 (file)
index 0000000..971eead
--- /dev/null
@@ -0,0 +1,40 @@
+From 74e909c0d3843c92fd0e5d84193a38eb3a8d8324 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Nov 2025 14:47:40 +0800
+Subject: f2fs: fix to avoid overflow while left shift operation
+
+From: Chao Yu <chao@kernel.org>
+
+[ Upstream commit 0fe1c6bec54ea68ed8c987b3890f2296364e77bb ]
+
+Should cast type of folio->index from pgoff_t to loff_t to avoid overflow
+while left shift operation.
+
+Fixes: 3265d3db1f16 ("f2fs: support partial truncation on compressed inode")
+Signed-off-by: Chao Yu <chao@kernel.org>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+[ Modification: Using rpages[i]->index instead of folio->index due to
+it was changed since commit:1cda5bc0b2fe ("f2fs: Use a folio in
+f2fs_truncate_partial_cluster()") on 6.14 ]
+Signed-off-by: Rajani Kantha <681739313@139.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/f2fs/compress.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
+index b05bb7bfa14c5..fcd21bb060cd4 100644
+--- a/fs/f2fs/compress.c
++++ b/fs/f2fs/compress.c
+@@ -1236,7 +1236,7 @@ int f2fs_truncate_partial_cluster(struct inode *inode, u64 from, bool lock)
+               int i;
+               for (i = cluster_size - 1; i >= 0; i--) {
+-                      loff_t start = rpages[i]->index << PAGE_SHIFT;
++                      loff_t start = (loff_t)rpages[i]->index << PAGE_SHIFT;
+                       if (from <= start) {
+                               zero_user_segment(rpages[i], 0, PAGE_SIZE);
+-- 
+2.51.0
+
diff --git a/queue-6.12/lib-crypto-arm-curve25519-disable-on-cpu_big_endian.patch b/queue-6.12/lib-crypto-arm-curve25519-disable-on-cpu_big_endian.patch
new file mode 100644 (file)
index 0000000..e4ec633
--- /dev/null
@@ -0,0 +1,47 @@
+From 8a32791cb389933eadd18cb702d69c3598cc1af9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Nov 2025 12:29:36 -0800
+Subject: lib/crypto: arm/curve25519: Disable on CPU_BIG_ENDIAN
+
+From: Eric Biggers <ebiggers@kernel.org>
+
+commit 44e8241c51f762aafa50ed116da68fd6ecdcc954 upstream.
+
+On big endian arm kernels, the arm optimized Curve25519 code produces
+incorrect outputs and fails the Curve25519 test.  This has been true
+ever since this code was added.
+
+It seems that hardly anyone (or even no one?) actually uses big endian
+arm kernels.  But as long as they're ostensibly supported, we should
+disable this code on them so that it's not accidentally used.
+
+Note: for future-proofing, use !CPU_BIG_ENDIAN instead of
+CPU_LITTLE_ENDIAN.  Both of these are arch-specific options that could
+get removed in the future if big endian support gets dropped.
+
+Fixes: d8f1308a025f ("crypto: arm/curve25519 - wire up NEON implementation")
+Cc: stable@vger.kernel.org
+Acked-by: Ard Biesheuvel <ardb@kernel.org>
+Link: https://lore.kernel.org/r/20251104054906.716914-1-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/crypto/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig
+index f87e63b2212eb..df2ae5c6af953 100644
+--- a/arch/arm/crypto/Kconfig
++++ b/arch/arm/crypto/Kconfig
+@@ -4,7 +4,7 @@ menu "Accelerated Cryptographic Algorithms for CPU (arm)"
+ config CRYPTO_CURVE25519_NEON
+       tristate
+-      depends on KERNEL_MODE_NEON
++      depends on KERNEL_MODE_NEON && !CPU_BIG_ENDIAN
+       select CRYPTO_KPP
+       select CRYPTO_LIB_CURVE25519_GENERIC
+       select CRYPTO_ARCH_HAVE_LIB_CURVE25519
+-- 
+2.51.0
+
diff --git a/queue-6.12/proc-fix-the-issue-of-proc_mem_open-returning-null.patch b/queue-6.12/proc-fix-the-issue-of-proc_mem_open-returning-null.patch
new file mode 100644 (file)
index 0000000..d04699d
--- /dev/null
@@ -0,0 +1,133 @@
+From 23923381ba6c321463cf1ed5f71276063c6870b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Nov 2025 08:19:26 +0000
+Subject: proc: fix the issue of proc_mem_open returning NULL
+
+From: Penglei Jiang <superman.xpt@gmail.com>
+
+[ Upstream commit 65c66047259fad1b868d4454bc5af95b46a5f954 ]
+
+proc_mem_open() can return an errno, NULL, or mm_struct*.  If it fails to
+acquire mm, it returns NULL, but the caller does not check for the case
+when the return value is NULL.
+
+The following conditions lead to failure in acquiring mm:
+
+  - The task is a kernel thread (PF_KTHREAD)
+  - The task is exiting (PF_EXITING)
+
+Changes:
+
+  - Add documentation comments for the return value of proc_mem_open().
+  - Add checks in the caller to return -ESRCH when proc_mem_open()
+    returns NULL.
+
+Link: https://lkml.kernel.org/r/20250404063357.78891-1-superman.xpt@gmail.com
+Reported-by: syzbot+f9238a0a31f9b5603fef@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/000000000000f52642060d4e3750@google.com
+Signed-off-by: Penglei Jiang <superman.xpt@gmail.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Adrian Ratiu <adrian.ratiu@collabora.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: Felix Moessbauer <felix.moessbauer@siemens.com>
+Cc: Jeff layton <jlayton@kernel.org>
+Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
+Cc: Mateusz Guzik <mjguzik@gmail.com>
+Cc: Thomas Gleinxer <tglx@linutronix.de>
+Cc: xu xin <xu.xin16@zte.com.cn>
+Cc: Alexey Dobriyan <adobriyan@gmail.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+[ acsjakub: applied cleanly ]
+Signed-off-by: Jakub Acs <acsjakub@amazon.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/proc/base.c       | 12 +++++++++---
+ fs/proc/task_mmu.c   | 12 ++++++------
+ fs/proc/task_nommu.c |  4 ++--
+ 3 files changed, 17 insertions(+), 11 deletions(-)
+
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index a2541f5204af0..d060af34a6e83 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -828,7 +828,13 @@ static const struct file_operations proc_single_file_operations = {
+       .release        = single_release,
+ };
+-
++/*
++ * proc_mem_open() can return errno, NULL or mm_struct*.
++ *
++ *   - Returns NULL if the task has no mm (PF_KTHREAD or PF_EXITING)
++ *   - Returns mm_struct* on success
++ *   - Returns error code on failure
++ */
+ struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode)
+ {
+       struct task_struct *task = get_proc_task(inode);
+@@ -853,8 +859,8 @@ static int __mem_open(struct inode *inode, struct file *file, unsigned int mode)
+ {
+       struct mm_struct *mm = proc_mem_open(inode, mode);
+-      if (IS_ERR(mm))
+-              return PTR_ERR(mm);
++      if (IS_ERR_OR_NULL(mm))
++              return mm ? PTR_ERR(mm) : -ESRCH;
+       file->private_data = mm;
+       return 0;
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 8f5ad591d7625..08a06fd37f0e1 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -212,8 +212,8 @@ static int proc_maps_open(struct inode *inode, struct file *file,
+       priv->inode = inode;
+       priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
+-      if (IS_ERR(priv->mm)) {
+-              int err = PTR_ERR(priv->mm);
++      if (IS_ERR_OR_NULL(priv->mm)) {
++              int err = priv->mm ? PTR_ERR(priv->mm) : -ESRCH;
+               seq_release_private(inode, file);
+               return err;
+@@ -1316,8 +1316,8 @@ static int smaps_rollup_open(struct inode *inode, struct file *file)
+       priv->inode = inode;
+       priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
+-      if (IS_ERR(priv->mm)) {
+-              ret = PTR_ERR(priv->mm);
++      if (IS_ERR_OR_NULL(priv->mm)) {
++              ret = priv->mm ? PTR_ERR(priv->mm) : -ESRCH;
+               single_release(inode, file);
+               goto out_free;
+@@ -2049,8 +2049,8 @@ static int pagemap_open(struct inode *inode, struct file *file)
+       struct mm_struct *mm;
+       mm = proc_mem_open(inode, PTRACE_MODE_READ);
+-      if (IS_ERR(mm))
+-              return PTR_ERR(mm);
++      if (IS_ERR_OR_NULL(mm))
++              return mm ? PTR_ERR(mm) : -ESRCH;
+       file->private_data = mm;
+       return 0;
+ }
+diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
+index bce6745330003..59bfd61d653aa 100644
+--- a/fs/proc/task_nommu.c
++++ b/fs/proc/task_nommu.c
+@@ -260,8 +260,8 @@ static int maps_open(struct inode *inode, struct file *file,
+       priv->inode = inode;
+       priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
+-      if (IS_ERR(priv->mm)) {
+-              int err = PTR_ERR(priv->mm);
++      if (IS_ERR_OR_NULL(priv->mm)) {
++              int err = priv->mm ? PTR_ERR(priv->mm) : -ESRCH;
+               seq_release_private(inode, file);
+               return err;
+-- 
+2.51.0
+
index 2ce7c677e38730f0258be5f8ef05bc41142ddf3d..bba044cde794030b605f219ce0e64c7300af279d 100644 (file)
@@ -82,3 +82,10 @@ acpi-hmat-fix-lockdep-warning-for-hmem_register_reso.patch
 bpf-add-bpf_prog_run_data_pointers.patch
 bpf-account-for-current-allocated-stack-depth-in-wid.patch
 irqchip-riscv-intc-add-missing-free-callback-in-risc.patch
+wifi-ath11k-clear-affinity-hint-before-calling-ath11.patch
+proc-fix-the-issue-of-proc_mem_open-returning-null.patch
+ext4-introduce-itail-helper.patch
+lib-crypto-arm-curve25519-disable-on-cpu_big_endian.patch
+ext4-fix-out-of-bound-read-in-ext4_xattr_inode_dec_r.patch
+bluetooth-mgmt-fix-possible-uafs.patch
+f2fs-fix-to-avoid-overflow-while-left-shift-operatio.patch
diff --git a/queue-6.12/wifi-ath11k-clear-affinity-hint-before-calling-ath11.patch b/queue-6.12/wifi-ath11k-clear-affinity-hint-before-calling-ath11.patch
new file mode 100644 (file)
index 0000000..47a526c
--- /dev/null
@@ -0,0 +1,61 @@
+From 85e567a1d460759567568a4ea3ad2702755440df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Nov 2025 15:05:09 +0800
+Subject: wifi: ath11k: Clear affinity hint before calling
+ ath11k_pcic_free_irq() in error path
+
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+[ Upstream commit 68410c5bd381a81bcc92b808e7dc4e6b9ed25d11 ]
+
+If a shared IRQ is used by the driver due to platform limitation, then the
+IRQ affinity hint is set right after the allocation of IRQ vectors in
+ath11k_pci_alloc_msi(). This does no harm unless one of the functions
+requesting the IRQ fails and attempt to free the IRQ. This results in the
+below warning:
+
+WARNING: CPU: 7 PID: 349 at kernel/irq/manage.c:1929 free_irq+0x278/0x29c
+Call trace:
+ free_irq+0x278/0x29c
+ ath11k_pcic_free_irq+0x70/0x10c [ath11k]
+ ath11k_pci_probe+0x800/0x820 [ath11k_pci]
+ local_pci_probe+0x40/0xbc
+
+The warning is due to not clearing the affinity hint before freeing the
+IRQs.
+
+So to fix this issue, clear the IRQ affinity hint before calling
+ath11k_pcic_free_irq() in the error path. The affinity will be cleared once
+again further down the error path due to code organization, but that does
+no harm.
+
+Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-05266-QCAHSTSWPLZ_V2_TO_X86-1
+
+Cc: Baochen Qiang <quic_bqiang@quicinc.com>
+Fixes: 39564b475ac5 ("wifi: ath11k: fix boot failure with one MSI vector")
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Reviewed-by: Baochen Qiang <quic_bqiang@quicinc.com>
+Link: https://patch.msgid.link/20250225053447.16824-2-manivannan.sadhasivam@linaro.org
+Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
+Signed-off-by: Wenshan Lan <jetlan9@163.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath11k/pci.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
+index 6ebfa5d02e2e5..c1d576ff77faa 100644
+--- a/drivers/net/wireless/ath/ath11k/pci.c
++++ b/drivers/net/wireless/ath/ath11k/pci.c
+@@ -936,6 +936,8 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
+       return 0;
+ err_free_irq:
++      /* __free_irq() expects the caller to have cleared the affinity hint */
++      ath11k_pci_set_irq_affinity_hint(ab_pci, NULL);
+       ath11k_pcic_free_irq(ab);
+ err_ce_free:
+-- 
+2.51.0
+
diff --git a/queue-6.17/lib-crypto-arm-curve25519-disable-on-cpu_big_endian.patch b/queue-6.17/lib-crypto-arm-curve25519-disable-on-cpu_big_endian.patch
new file mode 100644 (file)
index 0000000..92f4559
--- /dev/null
@@ -0,0 +1,47 @@
+From f05932b8294d173b24c11609b8ba4c6943cf5ba8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 11 Nov 2025 12:29:23 -0800
+Subject: lib/crypto: arm/curve25519: Disable on CPU_BIG_ENDIAN
+
+From: Eric Biggers <ebiggers@kernel.org>
+
+commit 44e8241c51f762aafa50ed116da68fd6ecdcc954 upstream.
+
+On big endian arm kernels, the arm optimized Curve25519 code produces
+incorrect outputs and fails the Curve25519 test.  This has been true
+ever since this code was added.
+
+It seems that hardly anyone (or even no one?) actually uses big endian
+arm kernels.  But as long as they're ostensibly supported, we should
+disable this code on them so that it's not accidentally used.
+
+Note: for future-proofing, use !CPU_BIG_ENDIAN instead of
+CPU_LITTLE_ENDIAN.  Both of these are arch-specific options that could
+get removed in the future if big endian support gets dropped.
+
+Fixes: d8f1308a025f ("crypto: arm/curve25519 - wire up NEON implementation")
+Cc: stable@vger.kernel.org
+Acked-by: Ard Biesheuvel <ardb@kernel.org>
+Link: https://lore.kernel.org/r/20251104054906.716914-1-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/crypto/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/crypto/Kconfig b/arch/arm/crypto/Kconfig
+index 1e5f3cdf691c4..a00ab9265280f 100644
+--- a/arch/arm/crypto/Kconfig
++++ b/arch/arm/crypto/Kconfig
+@@ -4,7 +4,7 @@ menu "Accelerated Cryptographic Algorithms for CPU (arm)"
+ config CRYPTO_CURVE25519_NEON
+       tristate
+-      depends on KERNEL_MODE_NEON
++      depends on KERNEL_MODE_NEON && !CPU_BIG_ENDIAN
+       select CRYPTO_KPP
+       select CRYPTO_LIB_CURVE25519_GENERIC
+       select CRYPTO_ARCH_HAVE_LIB_CURVE25519
+-- 
+2.51.0
+
index 007e1a7b3355d9c8130ea02f49c2ed13b4abdf53..f302f61f938ad094d7df3e749fc7370af766ee31 100644 (file)
@@ -119,3 +119,4 @@ bpf-add-bpf_prog_run_data_pointers.patch
 bpf-account-for-current-allocated-stack-depth-in-wid.patch
 irqchip-riscv-intc-add-missing-free-callback-in-risc.patch
 posix-timers-plug-potential-memory-leak-in-do_timer_.patch
+lib-crypto-arm-curve25519-disable-on-cpu_big_endian.patch