--- /dev/null
+From f865c143629d4094866a811dba5f329250bad486 Mon Sep 17 00:00:00 2001
+From: Zhan Xusheng <zhanxusheng1024@gmail.com>
+Date: Sat, 18 Jul 2026 13:09:22 +0800
+Subject: audit: fix potential integer overflow in audit_log_n_string()
+
+From: Zhan Xusheng <zhanxusheng1024@gmail.com>
+
+commit f865c143629d4094866a811dba5f329250bad486 upstream.
+
+audit_log_n_string() computes new_len as "slen + 3" (enclosing quotes
+plus the NUL terminator) and stores it into an int, while slen is a
+size_t. For a sufficiently large slen the addition can overflow and/or
+the result be truncated when assigned to the int new_len, so the
+"new_len > avail" check can be bypassed and the subsequent
+memcpy(ptr, string, slen) can write past the skb tail.
+
+This is the same class of bug that was fixed for the hex sibling in
+commit 65dfde57d1e2 ("audit: fix potential integer overflow in
+audit_log_n_hex()"); both helpers are reached through
+audit_log_n_untrustedstring() with the same length source.
+
+Make new_len a size_t and use check_add_overflow() to catch the
+overflow, mirroring the audit_log_n_hex() fix. No functional change for
+the in-tree callers, which all pass bounded lengths.
+
+Cc: stable@vger.kernel.org
+Fixes: 168b7173959f ("AUDIT: Clean up logging of untrusted strings")
+Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/audit.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/kernel/audit.c
++++ b/kernel/audit.c
+@@ -2115,7 +2115,8 @@ void audit_log_n_hex(struct audit_buffer
+ void audit_log_n_string(struct audit_buffer *ab, const char *string,
+ size_t slen)
+ {
+- int avail, new_len;
++ int avail;
++ size_t new_len;
+ unsigned char *ptr;
+ struct sk_buff *skb;
+
+@@ -2125,7 +2126,13 @@ void audit_log_n_string(struct audit_buf
+ BUG_ON(!ab->skb);
+ skb = ab->skb;
+ avail = skb_tailroom(skb);
+- new_len = slen + 3; /* enclosing quotes + null terminator */
++
++ /* enclosing quotes + null terminator */
++ if (check_add_overflow(slen, 3, &new_len)) {
++ audit_log_format(ab, "?");
++ return;
++ }
++
+ if (new_len > avail) {
+ avail = audit_expand(ab, new_len);
+ if (!avail)
--- /dev/null
+From 246df90b5f1a8a6e6abbd2f058b029558720adec Mon Sep 17 00:00:00 2001
+From: Luxiao Xu <rakukuip@gmail.com>
+Date: Tue, 21 Jul 2026 23:37:41 +0800
+Subject: audit: fix potential use-after-free in audit_del_rule()
+
+From: Luxiao Xu <rakukuip@gmail.com>
+
+commit 246df90b5f1a8a6e6abbd2f058b029558720adec upstream.
+
+`audit_del_rule()` destroys `e->rule.exe` via `audit_remove_mark_rule()`
+before unlinking the rule from RCU-visible filter lists and waiting for a
+grace period. Concurrent readers in `audit_filter()` and
+`audit_filter_rules()` still dereference `e->rule.exe`, while the fsnotify
+mark can be freed on an independent lifetime path. This creates a
+use-after-free window during rule deletion.
+
+Fix this by unlinking the rule from the RCU-visible lists and invoking
+`synchronize_rcu()` before calling `audit_remove_mark_rule()` (and other
+rule removal helpers). This ensures that all existing RCU readers have
+exited the critical section before any underlying resources are destroyed.
+
+Cc: stable@vger.kernel.org
+Fixes: 34d99af52ad4 ("audit: implement audit by executable")
+Reported-by: Vega <vega@nebusec.ai>
+Assisted-by: Codex:gpt-5.4
+Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
+Signed-off-by: Ren Wei <enjou1224z@gmail.com>
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/auditfilter.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/kernel/auditfilter.c
++++ b/kernel/auditfilter.c
+@@ -1047,6 +1047,10 @@ int audit_del_rule(struct audit_entry *e
+ goto out;
+ }
+
++ list_del_rcu(&e->list);
++ list_del(&e->rule.list);
++ synchronize_rcu();
++
+ if (e->rule.watch)
+ audit_remove_watch_rule(&e->rule);
+
+@@ -1064,8 +1068,6 @@ int audit_del_rule(struct audit_entry *e
+ audit_signals--;
+ #endif
+
+- list_del_rcu(&e->list);
+- list_del(&e->rule.list);
+ call_rcu(&e->rcu, audit_free_rule_rcu);
+
+ out:
--- /dev/null
+From b186c18c4843dd58adc29443369bddc71cb626a3 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 27 Jul 2026 17:57:32 +0200
+Subject: Bluetooth: btmtk: Fix short read errors in btmtk_usb_uhw_reg_read()
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit b186c18c4843dd58adc29443369bddc71cb626a3 upstream.
+
+If btmtk_usb_uhw_reg_read() gets a "short" read from a device, it will
+accidentally treat that as a "real" read and populate the returned value
+with some unknown and probably totally invalid data.
+
+Fix this logic error up by calling usb_control_msg_recv() which
+guarantees a "full" read happens, and then simplify the error checking
+for when btmtk_usb_uhw_reg_read() is called.
+
+Note, one caller of btmtk_usb_uhw_reg_read() does not check the return
+value, but as we pre-initialize the return value as 0, an incorrect read
+will not do anything wrong.
+
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/bluetooth/btmtk.c | 50 ++++++++++++++++++++--------------------------
+ 1 file changed, 22 insertions(+), 28 deletions(-)
+
+--- a/drivers/bluetooth/btmtk.c
++++ b/drivers/bluetooth/btmtk.c
+@@ -763,30 +763,24 @@ static int btmtk_usb_uhw_reg_write(struc
+ static int btmtk_usb_uhw_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
+ {
+ struct btmtk_data *data = hci_get_priv(hdev);
+- int pipe, err;
+- void *buf;
+-
+- buf = kzalloc(4, GFP_KERNEL);
+- if (!buf)
+- return -ENOMEM;
++ u8 buf[sizeof(u32)];
++ int err;
+
+- pipe = usb_rcvctrlpipe(data->udev, 0);
+- err = usb_control_msg(data->udev, pipe, 0x01,
+- 0xDE,
+- reg >> 16, reg & 0xffff,
+- buf, 4, USB_CTRL_GET_TIMEOUT);
+- if (err < 0) {
++ *val = 0;
++ err = usb_control_msg_recv(data->udev, 0, 0x01,
++ 0xDE,
++ reg >> 16, reg & 0xffff,
++ buf, sizeof(buf), USB_CTRL_GET_TIMEOUT,
++ GFP_KERNEL);
++ if (err) {
+ bt_dev_err(hdev, "Failed to read uhw reg(%d)", err);
+- goto err_free_buf;
++ return err;
+ }
+
+ *val = get_unaligned_le32(buf);
+ bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val);
+
+-err_free_buf:
+- kfree(buf);
+-
+- return err;
++ return 0;
+ }
+
+ static int btmtk_usb_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
+@@ -836,7 +830,7 @@ int btmtk_usb_subsys_reset(struct hci_de
+
+ if (dev_id == 0x7922) {
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ val |= 0x00002020;
+ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, val);
+@@ -846,7 +840,7 @@ int btmtk_usb_subsys_reset(struct hci_de
+ if (err < 0)
+ return err;
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ val |= BIT(0);
+ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, val);
+@@ -855,14 +849,14 @@ int btmtk_usb_subsys_reset(struct hci_de
+ msleep(100);
+ } else if (dev_id == 0x7925) {
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ val |= (1 << 5);
+ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val);
+ if (err < 0)
+ return err;
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ val &= 0xFFFF00FF;
+ val |= (1 << 13);
+@@ -873,7 +867,7 @@ int btmtk_usb_subsys_reset(struct hci_de
+ if (err < 0)
+ return err;
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ val |= (1 << 0);
+ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val);
+@@ -883,13 +877,13 @@ int btmtk_usb_subsys_reset(struct hci_de
+ if (err < 0)
+ return err;
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT1, 0x000000FF);
+ if (err < 0)
+ return err;
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT1, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ msleep(100);
+ } else {
+@@ -899,7 +893,7 @@ int btmtk_usb_subsys_reset(struct hci_de
+ if (err < 0)
+ return err;
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_WDT_STATUS, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ /* Reset the bluetooth chip via USB interface. */
+ err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, 1);
+@@ -909,13 +903,13 @@ int btmtk_usb_subsys_reset(struct hci_de
+ if (err < 0)
+ return err;
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT1, 0x000000FF);
+ if (err < 0)
+ return err;
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT1, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ /* MT7921 need to delay 20ms between toggle reset bit */
+ msleep(20);
+@@ -923,7 +917,7 @@ int btmtk_usb_subsys_reset(struct hci_de
+ if (err < 0)
+ return err;
+ err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
+- if (err < 0)
++ if (err)
+ return err;
+ }
+
--- /dev/null
+From cac43d360c928bc0cbbd18809632388265649761 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Mon, 27 Jul 2026 17:57:34 +0200
+Subject: Bluetooth: btusb: Fix short read errors in btusb_qca_send_vendor_req()
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+commit cac43d360c928bc0cbbd18809632388265649761 upstream.
+
+If btusb_qca_send_vendor_req() gets a "short" read from a device, it
+will accidentally treat that as a "real" read and populate the returned
+value with some unknown and probably totally invalid data.
+
+Fix this logic error up by calling usb_control_msg_recv() which
+guarantees a "full" read happens, and then simplify the error checking
+for when btusb_qca_send_vendor_req() is called.
+
+Cc: stable <stable@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/bluetooth/btusb.c | 30 +++++++++---------------------
+ 1 file changed, 9 insertions(+), 21 deletions(-)
+
+--- a/drivers/bluetooth/btusb.c
++++ b/drivers/bluetooth/btusb.c
+@@ -3345,28 +3345,16 @@ static const char *qca_get_fw_subdirecto
+ static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
+ void *data, u16 size)
+ {
+- int pipe, err;
+- u8 *buf;
+-
+- buf = kmalloc(size, GFP_KERNEL);
+- if (!buf)
+- return -ENOMEM;
++ int err;
+
+ /* Found some of USB hosts have IOT issues with ours so that we should
+ * not wait until HCI layer is ready.
+ */
+- pipe = usb_rcvctrlpipe(udev, 0);
+- err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN,
+- 0, 0, buf, size, USB_CTRL_GET_TIMEOUT);
+- if (err < 0) {
++ err = usb_control_msg_recv(udev, 0, request, USB_TYPE_VENDOR | USB_DIR_IN,
++ 0, 0, data, size, USB_CTRL_GET_TIMEOUT,
++ GFP_KERNEL);
++ if (err)
+ dev_err(&udev->dev, "Failed to access otp area (%d)", err);
+- goto done;
+- }
+-
+- memcpy(data, buf, size);
+-
+-done:
+- kfree(buf);
+
+ return err;
+ }
+@@ -3573,7 +3561,7 @@ static bool btusb_qca_need_patch(struct
+ struct qca_version ver;
+
+ if (btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
+- sizeof(ver)) < 0)
++ sizeof(ver)))
+ return false;
+ /* only low ROM versions need patches */
+ return !(le32_to_cpu(ver.rom_version) & ~0xffffU);
+@@ -3591,7 +3579,7 @@ static int btusb_setup_qca(struct hci_de
+
+ err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
+ sizeof(ver));
+- if (err < 0)
++ if (err)
+ return err;
+
+ ver_rom = le32_to_cpu(ver.rom_version);
+@@ -3614,7 +3602,7 @@ static int btusb_setup_qca(struct hci_de
+
+ err = btusb_qca_send_vendor_req(udev, QCA_CHECK_STATUS, &status,
+ sizeof(status));
+- if (err < 0)
++ if (err)
+ return err;
+
+ if (!(status & QCA_PATCH_UPDATED)) {
+@@ -3625,7 +3613,7 @@ static int btusb_setup_qca(struct hci_de
+
+ err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
+ sizeof(ver));
+- if (err < 0)
++ if (err)
+ return err;
+
+ btdata->qca_dump.fw_version = le32_to_cpu(ver.patch_version);
--- /dev/null
+From cdc36db204ffd97b947d64374cf23a210dc74777 Mon Sep 17 00:00:00 2001
+From: Chengfeng Ye <nicoyip.dev@gmail.com>
+Date: Thu, 23 Jul 2026 23:34:40 +0800
+Subject: Bluetooth: hci_sync: Fix advertising data UAFs
+
+From: Chengfeng Ye <nicoyip.dev@gmail.com>
+
+commit cdc36db204ffd97b947d64374cf23a210dc74777 upstream.
+
+hci_find_adv_instance() returns an adv_info pointer that is valid only
+while hdev->lock is held. The advertising command-sync paths perform
+instance lookups without that lock and, in some cases, retain the pointer
+while waiting for a controller response.
+
+An advertising termination event can therefore interleave as follows:
+
+ hci_cmd_sync_work hci_rx_work
+ hci_find_adv_instance()
+ __hci_cmd_sync_status()
+ wait for controller reply hci_dev_lock()
+ hci_remove_adv_instance()
+ kfree(adv)
+ adv->scan_rsp_changed = false
+
+KASAN reported:
+
+ BUG: KASAN: slab-use-after-free in hci_set_ext_scan_rsp_data_sync+0x2e1/0x300
+ Write of size 1 at addr ffff88810a45d21d by task kworker/u17:0/88
+ Workqueue: hci0 hci_cmd_sync_work
+ Call Trace:
+ hci_set_ext_scan_rsp_data_sync+0x2e1/0x300
+ hci_schedule_adv_instance_sync+0x390/0x4c0
+ hci_cmd_sync_work+0x173/0x300
+ Allocated by task 87:
+ hci_add_adv_instance+0x538/0xac0
+ add_advertising+0x885/0x1160
+ Freed by task 89:
+ kfree+0x131/0x3c0
+ hci_remove_adv_instance+0x1d8/0x3b0
+ hci_le_ext_adv_term_evt+0x17b/0x730
+
+Protect the instance lookup and payload construction in the extended
+advertising, scan response, and periodic advertising data paths. Snapshot
+the advertising parameters under hdev->lock, but release the lock before
+waiting for the controller.
+
+Clear advertising-data dirty bits before issuing their commands and
+restore them after a failure using a fresh lookup. Likewise, update the
+reported transmit power through a fresh lookup after the parameter command
+completes. No adv_info pointer then survives an HCI command wait.
+
+Fixes: cba6b758711c ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2")
+Cc: stable@vger.kernel.org
+Suggested-by: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
+Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/hci_sync.c | 131 ++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 97 insertions(+), 34 deletions(-)
+
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -1233,10 +1233,11 @@ static int hci_set_adv_set_random_addr_s
+ }
+
+ static int
+-hci_set_ext_adv_params_sync(struct hci_dev *hdev, struct adv_info *adv,
++hci_set_ext_adv_params_sync(struct hci_dev *hdev, u8 instance,
+ const struct hci_cp_le_set_ext_adv_params *cp,
+ struct hci_rp_le_set_ext_adv_params *rp)
+ {
++ struct adv_info *adv;
+ struct sk_buff *skb;
+
+ skb = __hci_cmd_sync(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS, sizeof(*cp),
+@@ -1264,11 +1265,15 @@ hci_set_ext_adv_params_sync(struct hci_d
+
+ if (!rp->status) {
+ hdev->adv_addr_type = cp->own_addr_type;
+- if (!cp->handle) {
++ if (!instance) {
+ /* Store in hdev for instance 0 */
+ hdev->adv_tx_power = rp->tx_power;
+- } else if (adv) {
+- adv->tx_power = rp->tx_power;
++ } else {
++ hci_dev_lock(hdev);
++ adv = hci_find_adv_instance(hdev, instance);
++ if (adv)
++ adv->tx_power = rp->tx_power;
++ hci_dev_unlock(hdev);
+ }
+ }
+
+@@ -1284,9 +1289,13 @@ static int hci_set_ext_adv_data_sync(str
+ int err;
+
+ if (instance) {
++ hci_dev_lock(hdev);
++
+ adv = hci_find_adv_instance(hdev, instance);
+- if (!adv || !adv->adv_data_changed)
++ if (!adv || !adv->adv_data_changed) {
++ hci_dev_unlock(hdev);
+ return 0;
++ }
+ }
+
+ len = eir_create_adv_data(hdev, instance, pdu->data,
+@@ -1297,16 +1306,27 @@ static int hci_set_ext_adv_data_sync(str
+ pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE;
+ pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG;
+
++ if (adv) {
++ adv->adv_data_changed = false;
++ hci_dev_unlock(hdev);
++ }
++
+ err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_DATA,
+ struct_size(pdu, data, len), pdu,
+ HCI_CMD_TIMEOUT);
+- if (err)
++ if (err) {
++ if (instance) {
++ hci_dev_lock(hdev);
++ adv = hci_find_adv_instance(hdev, instance);
++ if (adv)
++ adv->adv_data_changed = true;
++ hci_dev_unlock(hdev);
++ }
++
+ return err;
++ }
+
+- /* Update data if the command succeed */
+- if (adv) {
+- adv->adv_data_changed = false;
+- } else {
++ if (!instance) {
+ memcpy(hdev->adv_data, pdu->data, len);
+ hdev->adv_data_len = len;
+ }
+@@ -1360,22 +1380,22 @@ int hci_setup_ext_adv_instance_sync(stru
+ struct adv_info *adv;
+ bool secondary_adv;
+
+- if (instance > 0) {
+- adv = hci_find_adv_instance(hdev, instance);
+- if (!adv)
+- return -EINVAL;
+- } else {
+- adv = NULL;
+- }
+-
+ /* Updating parameters of an active instance will return a
+- * Command Disallowed error, so we must first disable the
+- * instance if it is active.
++ * Command Disallowed error, so disable it before taking a snapshot.
+ */
+- if (adv) {
++ if (instance > 0) {
+ err = hci_disable_ext_adv_instance_sync(hdev, instance);
+ if (err)
+ return err;
++
++ hci_dev_lock(hdev);
++ adv = hci_find_adv_instance(hdev, instance);
++ if (!adv) {
++ hci_dev_unlock(hdev);
++ return -EINVAL;
++ }
++ } else {
++ adv = NULL;
+ }
+
+ flags = hci_adv_instance_flags(hdev, instance);
+@@ -1386,8 +1406,11 @@ int hci_setup_ext_adv_instance_sync(stru
+ connectable = (flags & MGMT_ADV_FLAG_CONNECTABLE) ||
+ mgmt_get_connectable(hdev);
+
+- if (!is_advertising_allowed(hdev, connectable))
++ if (!is_advertising_allowed(hdev, connectable)) {
++ if (instance)
++ hci_dev_unlock(hdev);
+ return -EPERM;
++ }
+
+ /* Set require_privacy to true only when non-connectable
+ * advertising is used and it is not periodic.
+@@ -1398,8 +1421,11 @@ int hci_setup_ext_adv_instance_sync(stru
+ err = hci_get_random_address(hdev, require_privacy,
+ adv_use_rpa(hdev, flags), adv,
+ &own_addr_type, &random_addr);
+- if (err < 0)
++ if (err < 0) {
++ if (instance)
++ hci_dev_unlock(hdev);
+ return err;
++ }
+
+ memset(&cp, 0, sizeof(cp));
+
+@@ -1450,6 +1476,9 @@ int hci_setup_ext_adv_instance_sync(stru
+ cp.channel_map = hdev->le_adv_channel_map;
+ cp.handle = adv ? adv->handle : instance;
+
++ if (instance)
++ hci_dev_unlock(hdev);
++
+ if (flags & MGMT_ADV_FLAG_SEC_2M) {
+ cp.primary_phy = HCI_ADV_PHY_1M;
+ cp.secondary_phy = HCI_ADV_PHY_2M;
+@@ -1462,12 +1491,12 @@ int hci_setup_ext_adv_instance_sync(stru
+ cp.secondary_phy = HCI_ADV_PHY_1M;
+ }
+
+- err = hci_set_ext_adv_params_sync(hdev, adv, &cp, &rp);
++ err = hci_set_ext_adv_params_sync(hdev, instance, &cp, &rp);
+ if (err)
+ return err;
+
+ /* Update adv data as tx power is known now */
+- err = hci_set_ext_adv_data_sync(hdev, cp.handle);
++ err = hci_set_ext_adv_data_sync(hdev, instance);
+ if (err)
+ return err;
+
+@@ -1475,9 +1504,14 @@ int hci_setup_ext_adv_instance_sync(stru
+ own_addr_type == ADDR_LE_DEV_RANDOM_RESOLVED) &&
+ bacmp(&random_addr, BDADDR_ANY)) {
+ /* Check if random address need to be updated */
+- if (adv) {
+- if (!bacmp(&random_addr, &adv->random_addr))
++ if (instance) {
++ hci_dev_lock(hdev);
++ adv = hci_find_adv_instance(hdev, instance);
++ if (!adv || !bacmp(&random_addr, &adv->random_addr)) {
++ hci_dev_unlock(hdev);
+ return 0;
++ }
++ hci_dev_unlock(hdev);
+ } else {
+ if (!bacmp(&random_addr, &hdev->random_addr))
+ return 0;
+@@ -1499,9 +1533,13 @@ static int hci_set_ext_scan_rsp_data_syn
+ int err;
+
+ if (instance) {
++ hci_dev_lock(hdev);
++
+ adv = hci_find_adv_instance(hdev, instance);
+- if (!adv || !adv->scan_rsp_changed)
++ if (!adv || !adv->scan_rsp_changed) {
++ hci_dev_unlock(hdev);
+ return 0;
++ }
+ }
+
+ len = eir_create_scan_rsp(hdev, instance, pdu->data);
+@@ -1511,15 +1549,27 @@ static int hci_set_ext_scan_rsp_data_syn
+ pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE;
+ pdu->frag_pref = LE_SET_ADV_DATA_NO_FRAG;
+
++ if (adv) {
++ adv->scan_rsp_changed = false;
++ hci_dev_unlock(hdev);
++ }
++
+ err = __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA,
+ struct_size(pdu, data, len), pdu,
+ HCI_CMD_TIMEOUT);
+- if (err)
++ if (err) {
++ if (instance) {
++ hci_dev_lock(hdev);
++ adv = hci_find_adv_instance(hdev, instance);
++ if (adv)
++ adv->scan_rsp_changed = true;
++ hci_dev_unlock(hdev);
++ }
++
+ return err;
++ }
+
+- if (adv) {
+- adv->scan_rsp_changed = false;
+- } else {
++ if (!instance) {
+ memcpy(hdev->scan_rsp_data, pdu->data, len);
+ hdev->scan_rsp_data_len = len;
+ }
+@@ -1534,8 +1584,14 @@ static int __hci_set_scan_rsp_data_sync(
+
+ memset(&cp, 0, sizeof(cp));
+
++ if (instance)
++ hci_dev_lock(hdev);
++
+ len = eir_create_scan_rsp(hdev, instance, cp.data);
+
++ if (instance)
++ hci_dev_unlock(hdev);
++
+ if (hdev->scan_rsp_data_len == len &&
+ !memcmp(cp.data, hdev->scan_rsp_data, len))
+ return 0;
+@@ -1670,9 +1726,13 @@ static int hci_set_per_adv_data_sync(str
+ struct adv_info *adv = NULL;
+
+ if (instance) {
++ hci_dev_lock(hdev);
++
+ adv = hci_find_adv_instance(hdev, instance);
+- if (!adv || !adv->periodic)
++ if (!adv || !adv->periodic) {
++ hci_dev_unlock(hdev);
+ return 0;
++ }
+ }
+
+ len = eir_create_per_adv_data(hdev, instance, pdu->data);
+@@ -1681,6 +1741,9 @@ static int hci_set_per_adv_data_sync(str
+ pdu->handle = adv ? adv->handle : instance;
+ pdu->operation = LE_SET_ADV_DATA_OP_COMPLETE;
+
++ if (adv)
++ hci_dev_unlock(hdev);
++
+ return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_PER_ADV_DATA,
+ struct_size(pdu, data, len), pdu,
+ HCI_CMD_TIMEOUT);
+@@ -6449,7 +6512,7 @@ static int hci_le_ext_directed_advertisi
+ if (err)
+ return err;
+
+- err = hci_set_ext_adv_params_sync(hdev, NULL, &cp, &rp);
++ err = hci_set_ext_adv_params_sync(hdev, 0, &cp, &rp);
+ if (err)
+ return err;
+
--- /dev/null
+From 47778d2c2087b5d192398f6fddf692d16a5431cf Mon Sep 17 00:00:00 2001
+From: Sangho Lee <kudo3228@gmail.com>
+Date: Thu, 23 Jul 2026 12:28:06 +0900
+Subject: Bluetooth: HIDP: reject frames without a transaction header
+
+From: Sangho Lee <kudo3228@gmail.com>
+
+commit 47778d2c2087b5d192398f6fddf692d16a5431cf upstream.
+
+hidp_recv_ctrl_frame() and hidp_recv_intr_frame() read skb->data[0]
+before checking that the L2CAP SDU contains a transaction header. A
+connected HIDP peer can send an empty basic-mode SDU and make both paths
+use an uninitialized byte from skb tailroom.
+
+KMSAN reports the use in hidp_session_run(), with the uninitialized value
+originating in __alloc_skb() through vhci_write(). The control path
+produces two reports and the interrupt path produces one.
+
+The byte can also be controlled by a malformed lower-layer packet. If an
+HCI ACL packet contains an L2CAP PDU with a declared zero-length payload
+followed by an extra 0x15 byte, l2cap_recv_acldata() reduces skb->len to
+the declared PDU length before dispatch. The current HIDP path nevertheless
+consumes the extra byte as HIDP_TRANS_HID_CONTROL |
+HIDP_CTRL_VIRTUAL_CABLE_UNPLUG and terminates the HIDP session. With this
+change, the same packet is discarded and a subsequent feature report
+request succeeds.
+
+Pull the transaction header with skb_pull_data() and discard frames that
+do not contain it.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sangho Lee <kudo3228@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/hidp/core.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+--- a/net/bluetooth/hidp/core.c
++++ b/net/bluetooth/hidp/core.c
+@@ -563,16 +563,18 @@ static int hidp_process_data(struct hidp
+ static void hidp_recv_ctrl_frame(struct hidp_session *session,
+ struct sk_buff *skb)
+ {
+- unsigned char hdr, type, param;
++ unsigned char type, param;
++ u8 *hdr;
+ int free_skb = 1;
+
+ BT_DBG("session %p skb %p len %u", session, skb, skb->len);
+
+- hdr = skb->data[0];
+- skb_pull(skb, 1);
++ hdr = skb_pull_data(skb, 1);
++ if (!hdr)
++ goto free;
+
+- type = hdr & HIDP_HEADER_TRANS_MASK;
+- param = hdr & HIDP_HEADER_PARAM_MASK;
++ type = *hdr & HIDP_HEADER_TRANS_MASK;
++ param = *hdr & HIDP_HEADER_PARAM_MASK;
+
+ switch (type) {
+ case HIDP_TRANS_HANDSHAKE:
+@@ -593,6 +595,7 @@ static void hidp_recv_ctrl_frame(struct
+ break;
+ }
+
++free:
+ if (free_skb)
+ kfree_skb(skb);
+ }
+@@ -600,14 +603,15 @@ static void hidp_recv_ctrl_frame(struct
+ static void hidp_recv_intr_frame(struct hidp_session *session,
+ struct sk_buff *skb)
+ {
+- unsigned char hdr;
++ u8 *hdr;
+
+ BT_DBG("session %p skb %p len %u", session, skb, skb->len);
+
+- hdr = skb->data[0];
+- skb_pull(skb, 1);
++ hdr = skb_pull_data(skb, 1);
++ if (!hdr)
++ goto free;
+
+- if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
++ if (*hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
+ hidp_set_timer(session);
+
+ if (session->input)
+@@ -619,9 +623,10 @@ static void hidp_recv_intr_frame(struct
+ BT_DBG("report len %d", skb->len);
+ }
+ } else {
+- BT_DBG("Unsupported protocol header 0x%02x", hdr);
++ BT_DBG("Unsupported protocol header 0x%02x", *hdr);
+ }
+
++free:
+ kfree_skb(skb);
+ }
+
--- /dev/null
+From 34f53d27b81a16a02828c8fdfa4e02badc326f17 Mon Sep 17 00:00:00 2001
+From: Sangho Lee <kudo3228@gmail.com>
+Date: Thu, 23 Jul 2026 12:28:07 +0900
+Subject: Bluetooth: HIDP: validate numbered report payloads
+
+From: Sangho Lee <kudo3228@gmail.com>
+
+commit 34f53d27b81a16a02828c8fdfa4e02badc326f17 upstream.
+
+When hidp_get_raw_report() waits for a numbered report,
+hidp_process_data() compares the expected report number with skb->data[0].
+A connected HIDP peer can reply with only a DATA transaction header,
+leaving the skb empty after the header is removed.
+
+KMSAN reports an uninitialized-value use in hidp_session_run(), with the
+value originating in __alloc_skb() through vhci_write(). The transaction
+header checks remove the empty-frame reports, but this report remains until
+the payload check is added.
+
+The comparison can also consume a peer-controlled byte beyond the declared
+L2CAP PDU. A DATA | FEATURE response followed by an extra 0x01 byte made
+the current code accept that byte as report ID 1 and complete
+HIDIOCGFEATURE with a zero-byte result. With this change the malformed
+response is rejected with -EIO, while a subsequent valid response still
+succeeds.
+
+Require a payload byte before comparing a numbered report ID. Unnumbered
+reports continue to accept an empty payload.
+
+Fixes: 0ff1731a1ae5 ("HID: bt: Add support for hidraw HIDIOCGFEATURE and HIDIOCSFEATURE")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sangho Lee <kudo3228@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/hidp/core.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/net/bluetooth/hidp/core.c
++++ b/net/bluetooth/hidp/core.c
+@@ -546,9 +546,10 @@ static int hidp_process_data(struct hidp
+ }
+
+ if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
+- param == session->waiting_report_type) {
++ param == session->waiting_report_type) {
+ if (session->waiting_report_number < 0 ||
+- session->waiting_report_number == skb->data[0]) {
++ (skb->len &&
++ session->waiting_report_number == skb->data[0])) {
+ /* hidp_get_raw_report() is waiting on this report. */
+ session->report_return = skb;
+ done_with_skb = 0;
--- /dev/null
+From 8f2f62855a41d1730fb9e8122912bd2c8d6bed5d Mon Sep 17 00:00:00 2001
+From: Zihan Xi <zihanx@nebusec.ai>
+Date: Fri, 24 Jul 2026 00:43:46 +0800
+Subject: Bluetooth: mgmt: fix pending command UAF in EIR updates
+
+From: Zihan Xi <zihanx@nebusec.ai>
+
+commit 8f2f62855a41d1730fb9e8122912bd2c8d6bed5d upstream.
+
+MGMT_OP_SET_LOCAL_NAME is handled asynchronously on powered controllers
+and can run set_name_sync(). When the controller is BR/EDR capable,
+set_name_sync() updates the local name and then rebuilds EIR data through
+eir_create(). The EIR builder walks hdev->uuids, but the UUID list can
+be changed and entries can be freed by MGMT_OP_ADD_UUID and
+MGMT_OP_REMOVE_UUID.
+
+pending_eir_or_class() is meant to serialize management commands that
+can change EIR or the class of device, but it did not include
+MGMT_OP_SET_LOCAL_NAME. In addition, it walked hdev->mgmt_pending
+without hdev->mgmt_pending_lock even though pending commands are added
+and removed under that mutex. A racing command completion can therefore
+remove and free a pending command while pending_eir_or_class() is still
+inspecting it, leading to a use-after-free in the pending-command list or
+allowing a local name update to rebuild EIR while UUID entries are being
+removed.
+
+Take hdev->mgmt_pending_lock while scanning hdev->mgmt_pending and treat
+MGMT_OP_SET_LOCAL_NAME as an EIR/class-affecting pending command on the
+powered asynchronous path. Check for a conflicting pending command before
+copying the new short name so a rejected SET_LOCAL_NAME request does not
+modify hdev->short_name.
+
+Fixes: 6fe26f694c82 ("Bluetooth: MGMT: Protect mgmt_pending list with its own lock")
+Cc: stable@vger.kernel.org
+Reported-by: Vega <vega@nebusec.ai>
+Assisted-by: Codex:gpt-5.4
+Signed-off-by: Zihan Xi <zihanx@nebusec.ai>
+Signed-off-by: Ren Wei <enjou1224z@gmail.com>
+Reported-by: Vega <vega@nebusec.ai>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/mgmt.c | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -2699,18 +2699,28 @@ static int mgmt_hci_cmd_sync(struct sock
+ static bool pending_eir_or_class(struct hci_dev *hdev)
+ {
+ struct mgmt_pending_cmd *cmd;
++ bool pending = false;
++
++ mutex_lock(&hdev->mgmt_pending_lock);
+
+ list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
+ switch (cmd->opcode) {
+ case MGMT_OP_ADD_UUID:
+ case MGMT_OP_REMOVE_UUID:
+ case MGMT_OP_SET_DEV_CLASS:
++ case MGMT_OP_SET_LOCAL_NAME:
+ case MGMT_OP_SET_POWERED:
+- return true;
++ pending = true;
++ break;
+ }
++
++ if (pending)
++ break;
+ }
+
+- return false;
++ mutex_unlock(&hdev->mgmt_pending_lock);
++
++ return pending;
+ }
+
+ static const u8 bluetooth_base_uuid[] = {
+@@ -4046,6 +4056,12 @@ static int set_local_name(struct sock *s
+ goto failed;
+ }
+
++ if (hdev_is_powered(hdev) && pending_eir_or_class(hdev)) {
++ err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
++ MGMT_STATUS_BUSY);
++ goto failed;
++ }
++
+ memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
+
+ if (!hdev_is_powered(hdev)) {
--- /dev/null
+From d0a7b48ad0921bd88effaee10bf970ab1d5d0ddd Mon Sep 17 00:00:00 2001
+From: Zihan Xi <xizh2024@lzu.edu.cn>
+Date: Tue, 21 Jul 2026 22:36:07 +0800
+Subject: Bluetooth: mgmt: fix UAF in pair command cancellation
+
+From: Zihan Xi <xizh2024@lzu.edu.cn>
+
+commit d0a7b48ad0921bd88effaee10bf970ab1d5d0ddd upstream.
+
+The pairing completion and authentication failure callbacks look up the
+pending MGMT_OP_PAIR_DEVICE command by walking hdev->mgmt_pending. The
+lookup returned a command that was still linked on the shared pending list,
+without keeping mgmt_pending_lock held for the later dereference and
+removal.
+
+A concurrent MGMT_OP_CANCEL_PAIR_DEVICE request can remove and free the
+same pending command before the callback uses it. The reverse race is also
+possible when cancel_pair_device() gets a command from pending_find() and a
+callback removes it before the cancel path dereferences it. This can lead
+to a use-after-free and a second list_del().
+
+Make the pairing lookup helpers transfer ownership of the pending command
+by removing it from hdev->mgmt_pending while holding mgmt_pending_lock.
+The callbacks and cancel path then complete the command and free it
+directly, so racing paths cannot find or free the same command again. Take
+a temporary hci_conn reference in cancel_pair_device() because the command
+completion drops the reference stored in the pending command.
+
+Fixes: e9a416b5ce0c ("Bluetooth: Add mgmt_pair_device command")
+Cc: stable@vger.kernel.org
+Reported-by: Vega <vega@nebusec.ai>
+Assisted-by: Codex:gpt-5.4
+Signed-off-by: Zihan Xi <xizh2024@lzu.edu.cn>
+Reviewed-by: Ren Wei <enjou1224z@gmail.com>
+Reported-by: Vega <vega@nebusec.ai>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/mgmt.c | 64 ++++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 46 insertions(+), 18 deletions(-)
+
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -3527,11 +3527,13 @@ static int set_io_capability(struct sock
+ NULL, 0);
+ }
+
+-static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
++static struct mgmt_pending_cmd *remove_pairing(struct hci_conn *conn)
+ {
+ struct hci_dev *hdev = conn->hdev;
+ struct mgmt_pending_cmd *cmd;
+
++ mutex_lock(&hdev->mgmt_pending_lock);
++
+ list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
+ if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
+ continue;
+@@ -3539,9 +3541,39 @@ static struct mgmt_pending_cmd *find_pai
+ if (cmd->user_data != conn)
+ continue;
+
++ list_del(&cmd->list);
++ mutex_unlock(&hdev->mgmt_pending_lock);
+ return cmd;
+ }
+
++ mutex_unlock(&hdev->mgmt_pending_lock);
++
++ return NULL;
++}
++
++static struct mgmt_pending_cmd *remove_pairing_by_addr(struct hci_dev *hdev,
++ bdaddr_t *bdaddr)
++{
++ struct mgmt_pending_cmd *cmd;
++ struct hci_conn *conn;
++
++ mutex_lock(&hdev->mgmt_pending_lock);
++
++ list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
++ if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
++ continue;
++
++ conn = cmd->user_data;
++ if (bacmp(bdaddr, &conn->dst) != 0)
++ continue;
++
++ list_del(&cmd->list);
++ mutex_unlock(&hdev->mgmt_pending_lock);
++ return cmd;
++ }
++
++ mutex_unlock(&hdev->mgmt_pending_lock);
++
+ return NULL;
+ }
+
+@@ -3579,10 +3611,10 @@ void mgmt_smp_complete(struct hci_conn *
+ u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
+ struct mgmt_pending_cmd *cmd;
+
+- cmd = find_pairing(conn);
++ cmd = remove_pairing(conn);
+ if (cmd) {
+ cmd->cmd_complete(cmd, status);
+- mgmt_pending_remove(cmd);
++ mgmt_pending_free(cmd);
+ }
+ }
+
+@@ -3592,14 +3624,14 @@ static void pairing_complete_cb(struct h
+
+ BT_DBG("status %u", status);
+
+- cmd = find_pairing(conn);
++ cmd = remove_pairing(conn);
+ if (!cmd) {
+ BT_DBG("Unable to find a pending command");
+ return;
+ }
+
+ cmd->cmd_complete(cmd, mgmt_status(status));
+- mgmt_pending_remove(cmd);
++ mgmt_pending_free(cmd);
+ }
+
+ static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
+@@ -3611,14 +3643,14 @@ static void le_pairing_complete_cb(struc
+ if (!status)
+ return;
+
+- cmd = find_pairing(conn);
++ cmd = remove_pairing(conn);
+ if (!cmd) {
+ BT_DBG("Unable to find a pending command");
+ return;
+ }
+
+ cmd->cmd_complete(cmd, mgmt_status(status));
+- mgmt_pending_remove(cmd);
++ mgmt_pending_free(cmd);
+ }
+
+ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
+@@ -3775,23 +3807,17 @@ static int cancel_pair_device(struct soc
+ goto unlock;
+ }
+
+- cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
++ cmd = remove_pairing_by_addr(hdev, &addr->bdaddr);
+ if (!cmd) {
+ err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
+ MGMT_STATUS_INVALID_PARAMS);
+ goto unlock;
+ }
+
+- conn = cmd->user_data;
+-
+- if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
+- err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
+- MGMT_STATUS_INVALID_PARAMS);
+- goto unlock;
+- }
++ conn = hci_conn_get(cmd->user_data);
+
+ cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
+- mgmt_pending_remove(cmd);
++ mgmt_pending_free(cmd);
+
+ err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
+ addr, sizeof(*addr));
+@@ -3809,6 +3835,8 @@ static int cancel_pair_device(struct soc
+ if (conn->conn_reason == CONN_REASON_PAIR_DEVICE)
+ hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
+
++ hci_conn_put(conn);
++
+ unlock:
+ hci_dev_unlock(hdev);
+ return err;
+@@ -10135,14 +10163,14 @@ void mgmt_auth_failed(struct hci_conn *c
+ ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
+ ev.status = status;
+
+- cmd = find_pairing(conn);
++ cmd = remove_pairing(conn);
+
+ mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
+ cmd ? cmd->sk : NULL);
+
+ if (cmd) {
+ cmd->cmd_complete(cmd, status);
+- mgmt_pending_remove(cmd);
++ mgmt_pending_free(cmd);
+ }
+ }
+
--- /dev/null
+From abd93c85c8667add738ee82aeab95dd9fc8265a2 Mon Sep 17 00:00:00 2001
+From: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
+Date: Sat, 25 Jul 2026 16:52:30 -0300
+Subject: Bluetooth: SCO: give the socket its own sco_conn reference
+
+From: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
+
+commit abd93c85c8667add738ee82aeab95dd9fc8265a2 upstream.
+
+sco_conn_del() drops a reference it does not own. It takes one transient
+reference via sco_conn_hold_unless_zero() and releases it with the
+sco_conn_put() that follows sco_sock_hold(); the additional put in the
+!sk branch releases a second one:
+
+ conn = sco_conn_hold_unless_zero(conn);
+ ...
+ sk = sco_sock_hold(conn);
+ sco_conn_unlock(conn);
+ sco_conn_put(conn);
+
+ if (!sk) {
+ sco_conn_put(conn);
+ return;
+ }
+
+When close() races the controller's Disconnection Complete, sco_chan_del()
+clears conn->sk and drops the socket's reference while sco_conn_del() is
+running. sco_conn_del() then sees sk == NULL, its own put drops the count
+to zero and frees the conn, and the second put writes to the freed kref:
+
+ BUG: KASAN: slab-use-after-free in sco_conn_put.part.0+0x1a/0x190
+ Write of size 4 at addr ffff8881099dec74 by task kworker/u17:3/413
+ Workqueue: hci1 hci_rx_work
+ Call Trace:
+ sco_conn_put.part.0+0x1a/0x190
+ hci_disconn_complete_evt+0x1ee/0x3e0
+ hci_event_packet+0x54a/0x650
+ hci_rx_work+0x321/0x3d0
+ Allocated by task 413:
+ sco_conn_add+0x72/0x1a0
+ sco_connect_cfm+0x88/0x670
+ Freed by task 413:
+ sco_conn_del.isra.0+0x3f/0xf0
+ hci_disconn_complete_evt+0x1ee/0x3e0
+ refcount_t: underflow; use-after-free.
+
+The root cause is that the socket stores the connection without holding a
+reference of its own. __sco_chan_add() does:
+
+ sco_pi(sk)->conn = conn;
+
+so the socket borrows whatever reference its caller happened to hold, and
+the callers paper over that with ad-hoc holds and puts. Give the socket a
+counted reference instead: __sco_chan_add() takes one and it is released
+together with the channel (sco_chan_del()) and in sco_sock_destruct().
+With the socket holding its own reference, sco_conn_del() no longer needs
+the extra put and the redundant hold in sco_conn_ready() goes away.
+
+Making the socket own its reference means the connection is now actually
+freed on the error paths of sco_connect() where it used to leak, which in
+turn runs sco_conn_free() and its hci_conn_drop(conn->hcon). To keep the
+hci_conn accounting balanced, make that ownership explicit as well:
+sco_conn_add() consumes one hci_conn reference and the sco_conn owns it for
+its lifetime. sco_connect() hands over the reference returned by
+hci_connect_sco() and no longer drops it on the error paths;
+sco_connect_cfm(), which is not given a reference, takes one with
+hci_conn_hold() before handing it to sco_conn_add() (and drops it again if
+the allocation fails); and the explicit hci_conn_hold() in sco_conn_ready()
+is removed. Every reference then has a single, clear owner.
+
+Fixes: e6720779ae61 ("Bluetooth: SCO: Use kref to track lifetime of sco_conn")
+Cc: stable@vger.kernel.org
+Suggested-by: Pauli Virtanen <pav@iki.fi>
+Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/sco.c | 22 +++++++++++++---------
+ 1 file changed, 13 insertions(+), 9 deletions(-)
+
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -190,6 +190,9 @@ static void sco_sock_clear_timer(struct
+ }
+
+ /* ---- SCO connections ---- */
++/* Consumes a reference on @hcon, which the returned sco_conn owns until it is
++ * freed. On failure (NULL return) the reference is left for the caller to drop.
++ */
+ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
+ {
+ struct sco_conn *conn = hcon->sco_data;
+@@ -200,6 +203,9 @@ static struct sco_conn *sco_conn_add(str
+ sco_conn_lock(conn);
+ conn->hcon = hcon;
+ sco_conn_unlock(conn);
++ } else {
++ /* conn already owns a reference on hcon */
++ hci_conn_drop(hcon);
+ }
+ return conn;
+ }
+@@ -267,10 +273,8 @@ static void sco_conn_del(struct hci_conn
+ sco_conn_unlock(conn);
+ sco_conn_put(conn);
+
+- if (!sk) {
+- sco_conn_put(conn);
++ if (!sk)
+ return;
+- }
+
+ /* Kill socket */
+ lock_sock(sk);
+@@ -285,7 +289,7 @@ static void __sco_chan_add(struct sco_co
+ {
+ BT_DBG("conn %p", conn);
+
+- sco_pi(sk)->conn = conn;
++ sco_pi(sk)->conn = sco_conn_hold(conn);
+ conn->sk = sk;
+
+ if (parent)
+@@ -368,15 +372,15 @@ static int sco_connect(struct sock *sk)
+ */
+ if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND) {
+ release_sock(sk);
+- hci_conn_drop(hcon);
++ sco_conn_put(conn);
+ err = -EBADFD;
+ goto unlock;
+ }
+
+ err = sco_chan_add(conn, sk, NULL);
++ sco_conn_put(conn);
+ if (err) {
+ release_sock(sk);
+- hci_conn_drop(hcon);
+ goto unlock;
+ }
+
+@@ -1452,8 +1456,6 @@ static void sco_conn_ready(struct sco_co
+ bacpy(&sco_pi(sk)->src, &conn->hcon->src);
+ bacpy(&sco_pi(sk)->dst, &conn->hcon->dst);
+
+- sco_conn_hold(conn);
+- hci_conn_hold(conn->hcon);
+ __sco_chan_add(conn, sk, parent);
+
+ if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
+@@ -1509,10 +1511,12 @@ static void sco_connect_cfm(struct hci_c
+ if (!status) {
+ struct sco_conn *conn;
+
+- conn = sco_conn_add(hcon);
++ conn = sco_conn_add(hci_conn_hold(hcon));
+ if (conn) {
+ sco_conn_ready(conn);
+ sco_conn_put(conn);
++ } else {
++ hci_conn_drop(hcon);
+ }
+ } else
+ sco_conn_del(hcon, bt_to_errno(status));
--- /dev/null
+From a10ea943356b9d70c5616a0a06f6fa97cfdaccb1 Mon Sep 17 00:00:00 2001
+From: Hidayath Khan <hidayath@linux.ibm.com>
+Date: Mon, 27 Jul 2026 11:35:30 +0200
+Subject: dibs: fix use-after-free of dmb_node in loopback attach/detach/unregister
+
+From: Hidayath Khan <hidayath@linux.ibm.com>
+
+commit a10ea943356b9d70c5616a0a06f6fa97cfdaccb1 upstream.
+
+dibs_lo_attach_dmb(), dibs_lo_detach_dmb() and dibs_lo_unregister_dmb()
+look up the dmb_node under dmb_ht_lock, drop the lock and only then
+operate on the node's refcount. Nothing keeps the node alive across
+that window: __dibs_lo_unregister_dmb() removes the node from the hash
+table under the write lock and immediately frees it.
+
+A concurrent final put can therefore free the node between the lookup
+and the refcount operation:
+
+CPU0 (attach) CPU1 (owner unregisters)
+
+read_lock_bh(&dmb_ht_lock)
+find dmb_node (refcnt == 1)
+read_unlock_bh(&dmb_ht_lock)
+ refcount_dec_and_test() 1 -> 0
+ write_lock_bh(&dmb_ht_lock)
+ hash_del(&dmb_node->list)
+ write_unlock_bh(&dmb_ht_lock)
+ kfree(dmb_node)
+refcount_inc_not_zero(&dmb_node->refcnt) <-- use-after-free
+
+The same window exists for the refcount_dec_and_test() calls in the
+detach and unregister paths.
+
+Close the race structurally by making hash table membership and the
+refcount transitions atomic with respect to each other:
+
+- Perform the final refcount_dec_and_test() and hash_del() in a single
+ dmb_ht_lock write-side critical section, in both the unregister and
+ the detach path. Freeing the node still happens after the lock is
+ dropped, which is safe because a node whose refcount reached zero has
+ left the hash table and can no longer be found.
+
+- This establishes the invariant that any node found in the hash table
+ holds at least one reference, and that the final reference can only
+ be dropped under the write lock. dibs_lo_attach_dmb() can thus take
+ its reference with a plain refcount_inc() while still holding the
+ read lock; refcount_inc_not_zero() is no longer needed.
+
+__dibs_lo_unregister_dmb() no longer touches the hash table and is
+renamed to dibs_lo_free_dmb() accordingly.
+
+Note: commit cc21191b584c ("dibs: Move data path to dibs layer") moved
+the code to its current location; the race was introduced earlier by
+commit c3a910f2380f ("net/smc: implement DMB-merged operations of
+loopback-ism").
+
+Tested SMC-D via ISM and dibs loopback.
+
+Cc: stable@vger.kernel.org
+Fixes: c3a910f2380f ("net/smc: implement DMB-merged operations of loopback-ism")
+Reported-by: Rahul Chandelkar <rc@rexion.ai>
+Signed-off-by: Hidayath Khan <hidayath@linux.ibm.com>
+Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
+Link: https://patch.msgid.link/20260727093530.968834-1-hidayath@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/dibs/dibs_loopback.c | 47 +++++++++++++++++++++----------------------
+ 1 file changed, 24 insertions(+), 23 deletions(-)
+
+--- a/drivers/dibs/dibs_loopback.c
++++ b/drivers/dibs/dibs_loopback.c
+@@ -118,14 +118,9 @@ err_bit:
+ return rc;
+ }
+
+-static void __dibs_lo_unregister_dmb(struct dibs_lo_dev *ldev,
+- struct dibs_lo_dmb_node *dmb_node)
++static void dibs_lo_free_dmb(struct dibs_lo_dev *ldev,
++ struct dibs_lo_dmb_node *dmb_node)
+ {
+- /* remove dmb from hash table */
+- write_lock_bh(&ldev->dmb_ht_lock);
+- hash_del(&dmb_node->list);
+- write_unlock_bh(&ldev->dmb_ht_lock);
+-
+ clear_bit(dmb_node->sba_idx, ldev->sba_idx_mask);
+ folio_put(virt_to_folio(dmb_node->cpu_addr));
+ kfree(dmb_node);
+@@ -139,27 +134,33 @@ static int dibs_lo_unregister_dmb(struct
+ struct dibs_lo_dmb_node *dmb_node = NULL, *tmp_node;
+ struct dibs_lo_dev *ldev;
+ unsigned long flags;
++ bool last;
+
+ ldev = dibs->drv_priv;
+
+ /* find dmb from hash table */
+- read_lock_bh(&ldev->dmb_ht_lock);
++ write_lock_bh(&ldev->dmb_ht_lock);
+ hash_for_each_possible(ldev->dmb_ht, tmp_node, list, dmb->dmb_tok) {
+ if (tmp_node->token == dmb->dmb_tok) {
+ dmb_node = tmp_node;
+ break;
+ }
+ }
+- read_unlock_bh(&ldev->dmb_ht_lock);
+- if (!dmb_node)
++ if (!dmb_node) {
++ write_unlock_bh(&ldev->dmb_ht_lock);
+ return -EINVAL;
++ }
++ last = refcount_dec_and_test(&dmb_node->refcnt);
++ if (last)
++ hash_del(&dmb_node->list);
++ write_unlock_bh(&ldev->dmb_ht_lock);
+
+- if (refcount_dec_and_test(&dmb_node->refcnt)) {
++ if (last) {
+ spin_lock_irqsave(&dibs->lock, flags);
+ dibs->dmb_clientid_arr[dmb_node->sba_idx] = NO_DIBS_CLIENT;
+ spin_unlock_irqrestore(&dibs->lock, flags);
+
+- __dibs_lo_unregister_dmb(ldev, dmb_node);
++ dibs_lo_free_dmb(ldev, dmb_node);
+ }
+ return 0;
+ }
+@@ -188,14 +189,9 @@ static int dibs_lo_attach_dmb(struct dib
+ read_unlock_bh(&ldev->dmb_ht_lock);
+ return -EINVAL;
+ }
++ refcount_inc(&dmb_node->refcnt);
+ read_unlock_bh(&ldev->dmb_ht_lock);
+
+- if (!refcount_inc_not_zero(&dmb_node->refcnt))
+- /* the dmb is being unregistered, but has
+- * not been removed from the hash table.
+- */
+- return -EINVAL;
+-
+ /* provide dmb information */
+ dmb->idx = dmb_node->sba_idx;
+ dmb->dmb_tok = dmb_node->token;
+@@ -209,11 +205,12 @@ static int dibs_lo_detach_dmb(struct dib
+ {
+ struct dibs_lo_dmb_node *dmb_node = NULL, *tmp_node;
+ struct dibs_lo_dev *ldev;
++ bool last;
+
+ ldev = dibs->drv_priv;
+
+ /* find dmb_node according to dmb->dmb_tok */
+- read_lock_bh(&ldev->dmb_ht_lock);
++ write_lock_bh(&ldev->dmb_ht_lock);
+ hash_for_each_possible(ldev->dmb_ht, tmp_node, list, token) {
+ if (tmp_node->token == token) {
+ dmb_node = tmp_node;
+@@ -221,13 +218,17 @@ static int dibs_lo_detach_dmb(struct dib
+ }
+ }
+ if (!dmb_node) {
+- read_unlock_bh(&ldev->dmb_ht_lock);
++ write_unlock_bh(&ldev->dmb_ht_lock);
+ return -EINVAL;
+ }
+- read_unlock_bh(&ldev->dmb_ht_lock);
++ last = refcount_dec_and_test(&dmb_node->refcnt);
++ if (last)
++ hash_del(&dmb_node->list);
++ write_unlock_bh(&ldev->dmb_ht_lock);
++
++ if (last)
++ dibs_lo_free_dmb(ldev, dmb_node);
+
+- if (refcount_dec_and_test(&dmb_node->refcnt))
+- __dibs_lo_unregister_dmb(ldev, dmb_node);
+ return 0;
+ }
+
--- /dev/null
+From c1f3e770eec26d6f96dd6d2ea30555ba7c09a244 Mon Sep 17 00:00:00 2001
+From: Nathan Chancellor <nathan@kernel.org>
+Date: Tue, 23 Jun 2026 13:23:46 -0700
+Subject: fortify: Disable -Wstringop-overread in tests
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+commit c1f3e770eec26d6f96dd6d2ea30555ba7c09a244 upstream.
+
+clang recently added support for -Wstringop-overread [1], which is on by
+default like -Wfortify-source. This breaks the usage of -Werror in the
+fortify tests, resulting in the following false positive warnings in the
+kernel build:
+
+ warning: unsafe memcmp() usage lacked '__read_overflow2' warning in lib/test_fortify/read_overflow2-memcmp.c
+ warning: unsafe memcmp() usage lacked '__read_overflow' warning in lib/test_fortify/read_overflow-memcmp.c
+ warning: unsafe memchr() usage lacked '__read_overflow' warning in lib/test_fortify/read_overflow-memchr.c
+
+Examining the fortify test logs shows a warning like the following in
+each of the failed logs:
+
+ In file included from lib/test_fortify/read_overflow2-memcmp.c:5:
+ lib/test_fortify/test_fortify.h:34:2: error: 'memcmp' reading 17 bytes from a region of size 16 [-Werror,-Wstringop-overread]
+ 34 | TEST;
+ | ^
+ lib/test_fortify/read_overflow2-memcmp.c:3:2: note: expanded from macro 'TEST'
+ 3 | memcmp(large, small, sizeof(small) + 1)
+ | ^
+ 1 error generated.
+
+Disable -Wstringop-overread for the fortify tests, as it defeats the
+purpose of testing the Linux specific implementation of fortify, like
+-Wfortify-source.
+
+Cc: stable@vger.kernel.org
+Closes: https://github.com/ClangBuiltLinux/linux/issues/2168
+Link: https://github.com/llvm/llvm-project/commit/86f2e71cb8d165b59ad31a442b2391e23826133e [1]
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Link: https://patch.msgid.link/20260623-fix-test_fortify-for-clang-stringop-overread-v1-1-15ee8342a953@kernel.org
+Signed-off-by: Kees Cook <kees@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ lib/test_fortify/Makefile | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/lib/test_fortify/Makefile
++++ b/lib/test_fortify/Makefile
+@@ -1,6 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+
+ ccflags-y := $(call cc-disable-warning,fortify-source)
++ccflags-y += $(call cc-disable-warning,stringop-overread)
+
+ quiet_cmd_test_fortify = TEST $@
+ cmd_test_fortify = $(CONFIG_SHELL) $(src)/test_fortify.sh \
--- /dev/null
+From 40de8160ca7f67d14619ee0351ce5d68fc4a237a Mon Sep 17 00:00:00 2001
+From: "Kiryl Shutsemau (Meta)" <kas@kernel.org>
+Date: Wed, 15 Jul 2026 15:42:33 +0100
+Subject: fs/proc/task_mmu: fix PAGEMAP_SCAN written state for PMD holes
+
+From: Kiryl Shutsemau (Meta) <kas@kernel.org>
+
+commit 40de8160ca7f67d14619ee0351ce5d68fc4a237a upstream.
+
+PAGEMAP_SCAN reports an unpopulated PTE in a uffd-wp VMA as written, but a
+range with no page table at all -- a PMD hole -- is skipped:
+pagemap_scan_pte_hole() tests p->cur_vma_category, which never carries
+PAGE_IS_WRITTEN, so the hole is neither reported nor (under
+PM_SCAN_WP_MATCHING) armed.
+
+In a uffd-wp VMA, WP_UNPOPULATED installs uffd-wp markers when protecting
+a range, allocating page tables as needed, so an unpopulated slot is
+treated as written -- see the pte_none() handling in
+pagemap_page_category(). A missing marker therefore means the range was
+zapped, e.g. via MADV_DONTNEED. This applies to anon and shmem VMAs.
+
+An anonymous THP is write-protected in place as a huge PMD, so a full-PMD
+MADV_DONTNEED clears it to pmd_none -- a hole with no page table -- and
+pagemap_scan_pte_hole() misses it. For a MAP_PRIVATE|MAP_ANON mapping
+MADV_DONTNEED has fill-with-zeros semantics, so a write-tracking
+checkpoint/migration tool (e.g. CRIU) treats the range as unchanged and
+keeps its previous contents; after restore or live migration the process
+reads stale data instead of zeroes -- data corruption.
+
+Report a hole in a non-hugetlb uffd-wp VMA as written, matching the
+pte_none handling in pagemap_page_category(); the existing
+PM_SCAN_WP_MATCHING path then arms it via uffd_wp_range().
+
+hugetlb is excluded: pagemap_hugetlb_category() reports an empty hugetlb
+entry (huge_pte_none) as not-written, unlike pagemap_page_category(),
+which reports pte_none as written. pagemap_scan_pte_hole() fires for a
+hugetlb slot only when it has no page table; keeping that not-written
+matches how an allocated-but-empty hugetlb entry reads, so the hole and
+the empty-entry cases agree within the VMA.
+
+Link: https://lore.kernel.org/20260715144234.442721-2-kirill@shutemov.name
+Fixes: 2bad466cc9d9 ("mm/uffd: UFFD_FEATURE_WP_UNPOPULATED")
+Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
+Reported-by: Sashiko AI review <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260707151349.92143-1-kirill@shutemov.name
+Tested-by: Muhammad Usama Anjum <usama.anjum@arm.com>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Cc: Peter Xu <peterx@redhat.com>
+Cc: Jann Horn <jannh@google.com>
+Cc: Liam R. Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes <ljs@kernel.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Pedro Falcato <pfalcato@suse.de>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Zenghui Yu <zenghui.yu@linux.dev>
+Assisted-by: Claude:claude-fable-5
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/proc/task_mmu.c | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -2918,12 +2918,28 @@ static int pagemap_scan_pte_hole(unsigne
+ {
+ struct pagemap_scan_private *p = walk->private;
+ struct vm_area_struct *vma = walk->vma;
++ unsigned long categories;
+ int ret, err;
+
+- if (!vma || !pagemap_scan_is_interesting_page(p->cur_vma_category, p))
++ if (!vma)
+ return 0;
+
+- ret = pagemap_scan_output(p->cur_vma_category, p, addr, &end);
++ /*
++ * In a uffd-wp VMA an unpopulated range is treated as written:
++ * uffd-wp registration populates page tables and installs markers
++ * with WP_UNPOPULATED, so a missing marker means the range was
++ * zapped. See the pte_none() handling in pagemap_page_category().
++ *
++ * hugetlb differs, see pagemap_hugetlb_category().
++ */
++ categories = p->cur_vma_category;
++ if (userfaultfd_wp(vma) && !is_vm_hugetlb_page(vma))
++ categories |= PAGE_IS_WRITTEN;
++
++ if (!pagemap_scan_is_interesting_page(categories, p))
++ return 0;
++
++ ret = pagemap_scan_output(categories, p, addr, &end);
+ if (addr == end)
+ return ret;
+
--- /dev/null
+From 36f6999ecde3976731a8bfc0b8e667da6f593069 Mon Sep 17 00:00:00 2001
+From: Farhan Ali <alifm@linux.ibm.com>
+Date: Thu, 23 Jul 2026 15:14:05 -0700
+Subject: KVM: s390: pci: Fix memory accounting for pinned/unpinned pages
+
+From: Farhan Ali <alifm@linux.ibm.com>
+
+commit 36f6999ecde3976731a8bfc0b8e667da6f593069 upstream.
+
+The account_mem() and unaccount_mem() functions call get_uid() which
+increments the reference count of struct user_struct on every invocation.
+But we don't decrement the count by calling free_uid(). It also
+accounted/unaccounted the pages against the current->mm. But its possible
+the unaccount_mem() can be called from a different process context than the
+one that originally pinned the pages.
+
+Let's fix this by storing the pinning process user_struct and mm_struct
+when accounting for pinned pages, and subsequently free these resources
+when the pages are unpinned.
+
+Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding")
+Cc: stable@vger.kernel.org
+Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
+Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
+Tested-by: Matthew Rosato <mjrosato@linux.ibm.com>
+[borntraeger@linux.ibm.com: Fixed whitespace]
+Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kvm/pci.c | 43 ++++++++++++++++++++++++++++++++-----------
+ arch/s390/kvm/pci.h | 2 ++
+ 2 files changed, 34 insertions(+), 11 deletions(-)
+
+--- a/arch/s390/kvm/pci.c
++++ b/arch/s390/kvm/pci.c
+@@ -191,33 +191,54 @@ static int kvm_zpci_clear_airq(struct zp
+ return cc ? -EIO : 0;
+ }
+
+-static inline void unaccount_mem(unsigned long nr_pages)
++static inline void unaccount_mem(struct kvm_zdev *kzdev, unsigned long nr_pages)
+ {
+- struct user_struct *user = get_uid(current_user());
++ struct user_struct *user = kzdev->user_account;
++ struct mm_struct *mm_account = kzdev->mm_account;
+
+- if (user)
++ if (user) {
+ atomic_long_sub(nr_pages, &user->locked_vm);
+- if (current->mm)
+- atomic64_sub(nr_pages, ¤t->mm->pinned_vm);
++ free_uid(user);
++ kzdev->user_account = NULL;
++ }
++
++ if (mm_account) {
++ atomic64_sub(nr_pages, &mm_account->pinned_vm);
++ mmdrop(mm_account);
++ kzdev->mm_account = NULL;
++ }
+ }
+
+-static inline int account_mem(unsigned long nr_pages)
++static inline int account_mem(struct kvm_zdev *kzdev, unsigned long nr_pages)
+ {
+ struct user_struct *user = get_uid(current_user());
+ unsigned long page_limit, cur_pages, new_pages;
++ int rc = 0;
+
+ page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+
+ cur_pages = atomic_long_read(&user->locked_vm);
+ do {
+ new_pages = cur_pages + nr_pages;
+- if (new_pages > page_limit)
+- return -ENOMEM;
++ if (new_pages > page_limit) {
++ rc = -ENOMEM;
++ goto out;
++ }
+ } while (!atomic_long_try_cmpxchg(&user->locked_vm, &cur_pages, new_pages));
+
+- atomic64_add(nr_pages, ¤t->mm->pinned_vm);
++ if (current->mm) {
++ mmgrab(current->mm);
++ atomic64_add(nr_pages, ¤t->mm->pinned_vm);
++ }
++
++ kzdev->user_account = user;
++ kzdev->mm_account = current->mm;
+
+ return 0;
++
++out:
++ free_uid(user);
++ return rc;
+ }
+
+ static int kvm_s390_pci_aif_enable(struct zpci_dev *zdev, struct zpci_fib *fib,
+@@ -280,7 +301,7 @@ static int kvm_s390_pci_aif_enable(struc
+ }
+
+ /* Account for pinned pages, roll back on failure */
+- if (account_mem(pcount))
++ if (account_mem(zdev->kzdev, pcount))
+ goto unpin2;
+
+ /* AISB must be allocated before we can fill in GAITE */
+@@ -401,7 +422,7 @@ static int kvm_s390_pci_aif_disable(stru
+ pcount++;
+ }
+ if (pcount > 0)
+- unaccount_mem(pcount);
++ unaccount_mem(kzdev, pcount);
+ out:
+ mutex_unlock(&aift->aift_lock);
+
+--- a/arch/s390/kvm/pci.h
++++ b/arch/s390/kvm/pci.h
+@@ -22,6 +22,8 @@ struct kvm_zdev {
+ struct kvm *kvm;
+ struct zpci_fib fib;
+ struct list_head entry;
++ struct user_struct *user_account;
++ struct mm_struct *mm_account;
+ };
+
+ struct zpci_gaite {
--- /dev/null
+From f86842e4d6c482300f4567f492d512c9ccf5bc4f Mon Sep 17 00:00:00 2001
+From: Farhan Ali <alifm@linux.ibm.com>
+Date: Thu, 23 Jul 2026 15:14:06 -0700
+Subject: KVM: s390: pci: Fix missing error codes and memory unaccounting
+
+From: Farhan Ali <alifm@linux.ibm.com>
+
+commit f86842e4d6c482300f4567f492d512c9ccf5bc4f upstream.
+
+In kvm_s390_pci_aif_enable() two error paths failed to set an error code,
+causing the function to return 0 on failure. It also failed to rollback
+memory accounting on failure. Fix both by propagating an error code on
+failure and calling unaccount_mem() in the cleanup path.
+
+Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding")
+Cc: stable@vger.kernel.org
+Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
+Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
+Tested-by: Matthew Rosato <mjrosato@linux.ibm.com>
+Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kvm/pci.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/kvm/pci.c
++++ b/arch/s390/kvm/pci.c
+@@ -301,14 +301,17 @@ static int kvm_s390_pci_aif_enable(struc
+ }
+
+ /* Account for pinned pages, roll back on failure */
+- if (account_mem(zdev->kzdev, pcount))
++ rc = account_mem(zdev->kzdev, pcount);
++ if (rc)
+ goto unpin2;
+
+ /* AISB must be allocated before we can fill in GAITE */
+ mutex_lock(&aift->aift_lock);
+ bit = airq_iv_alloc_bit(aift->sbv);
+- if (bit == -1UL)
++ if (bit == -1UL) {
++ rc = -ENOMEM;
+ goto unlock;
++ }
+ zdev->aisb = bit; /* store the summary bit number */
+ zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA |
+ AIRQ_IV_BITLOCK |
+@@ -352,6 +355,8 @@ static int kvm_s390_pci_aif_enable(struc
+ return rc;
+
+ unlock:
++ if (pcount > 0)
++ unaccount_mem(zdev->kzdev, pcount);
+ mutex_unlock(&aift->aift_lock);
+ unpin2:
+ if (fib->fmt0.sum == 1)
--- /dev/null
+From 8bf09b9b7d3232806df95f409581f8a9fd99a3fa Mon Sep 17 00:00:00 2001
+From: Farhan Ali <alifm@linux.ibm.com>
+Date: Thu, 23 Jul 2026 15:14:07 -0700
+Subject: KVM: s390: pci: Fix NULL dereference on AIBV allocation failure
+
+From: Farhan Ali <alifm@linux.ibm.com>
+
+commit 8bf09b9b7d3232806df95f409581f8a9fd99a3fa upstream.
+
+The airq_iv_create() can return NULL on failure, but the return value was
+never checked. If it fails, zdev->aibv will be NULL and fail when
+dereferenced in kvm_zpci_set_airq(). Add a NULL check and free the
+previously allocated AISB bit and zdev->aisb on failure.
+
+Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding")
+Cc: stable@vger.kernel.org
+Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
+Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
+Tested-by: Matthew Rosato <mjrosato@linux.ibm.com>
+Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kvm/pci.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/s390/kvm/pci.c
++++ b/arch/s390/kvm/pci.c
+@@ -318,6 +318,11 @@ static int kvm_s390_pci_aif_enable(struc
+ AIRQ_IV_GUESTVEC,
+ phys_to_virt(fib->fmt0.aibv));
+
++ if (!zdev->aibv) {
++ rc = -ENOMEM;
++ goto free_aisb;
++ }
++
+ spin_lock_irq(&aift->gait_lock);
+ gaite = aift->gait + zdev->aisb;
+
+@@ -354,6 +359,9 @@ static int kvm_s390_pci_aif_enable(struc
+ rc = kvm_zpci_set_airq(zdev);
+ return rc;
+
++free_aisb:
++ airq_iv_free_bit(aift->sbv, zdev->aisb);
++ zdev->aisb = 0;
+ unlock:
+ if (pcount > 0)
+ unaccount_mem(zdev->kzdev, pcount);
--- /dev/null
+From 8fa01be5a6149404adb82c0979a78f6347edd3ef Mon Sep 17 00:00:00 2001
+From: Farhan Ali <alifm@linux.ibm.com>
+Date: Thu, 23 Jul 2026 15:14:04 -0700
+Subject: KVM: s390: pci: Reject adapter interrupt forwarding if already enabled
+
+From: Farhan Ali <alifm@linux.ibm.com>
+
+commit 8fa01be5a6149404adb82c0979a78f6347edd3ef upstream.
+
+The MPCIFC instruction doesn't allow registering adapter interrupts without
+first unregistering. So reject any request to enable interrupt forwarding
+if its already enabled for the zPCI device. This also fixes overwriting and
+thus leaking resources when the ioctl is called multiple times for the same
+device.
+
+Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding")
+Cc: stable@vger.kernel.org
+Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
+Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
+Tested-by: Matthew Rosato <mjrosato@linux.ibm.com>
+Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kvm/pci.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/arch/s390/kvm/pci.c
++++ b/arch/s390/kvm/pci.c
+@@ -238,6 +238,10 @@ static int kvm_s390_pci_aif_enable(struc
+ if (zdev->gisa == 0)
+ return -EINVAL;
+
++ /* AIF already enabled for the device */
++ if (zdev->kzdev->fib.fmt0.aibv != 0)
++ return -EINVAL;
++
+ kvm = zdev->kzdev->kvm;
+ msi_vecs = min_t(unsigned int, fib->fmt0.noi, zdev->max_msi);
+
--- /dev/null
+From 868d32ac72cba21c5c6d8a66a814b7c25a3a5c01 Mon Sep 17 00:00:00 2001
+From: Farhan Ali <alifm@linux.ibm.com>
+Date: Thu, 23 Jul 2026 15:14:09 -0700
+Subject: KVM: s390: pci: Validate AIBV and AISB before pinning guest pages
+
+From: Farhan Ali <alifm@linux.ibm.com>
+
+commit 868d32ac72cba21c5c6d8a66a814b7c25a3a5c01 upstream.
+
+The AIBV holds one bit per MSI-X vector for a given function. The size of
+the bit vector is derived from the NOI and the AIBVO. If the size of the
+AIBV exceeds a single page boundary, then reject the request as we cannot
+safely pin the guest AIBV.
+
+Similarly reject the request if the AISB address is not 8-byte aligned as
+the architecture requires doubleword alignment for the summary bit address.
+Since the AISBO can address up to 64 bits, the size of the AISB can only be
+8 bytes for the function. This also ensures the AISB doesn't exceed a
+single page boundary.
+
+Fixes: 3c5a1b6f0a18 ("KVM: s390: pci: provide routines for enabling/disabling interrupt forwarding")
+Cc: stable@vger.kernel.org
+Reviewed-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
+Signed-off-by: Farhan Ali <alifm@linux.ibm.com>
+Tested-by: Matthew Rosato <mjrosato@linux.ibm.com>
+Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/s390/kvm/pci.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+--- a/arch/s390/kvm/pci.c
++++ b/arch/s390/kvm/pci.c
+@@ -245,7 +245,7 @@ static int kvm_s390_pci_aif_enable(struc
+ bool assist)
+ {
+ struct page *pages[1], *aibv_page, *aisb_page = NULL;
+- unsigned int msi_vecs, idx;
++ unsigned int msi_vecs, idx, size;
+ struct zpci_gaite *gaite;
+ unsigned long hva, bit;
+ struct kvm *kvm;
+@@ -272,6 +272,14 @@ static int kvm_s390_pci_aif_enable(struc
+ return gisc;
+
+ /* Replace AIBV address */
++ size = BITS_TO_LONGS(msi_vecs + fib->fmt0.aibvo) * sizeof(unsigned long);
++ npages = DIV_ROUND_UP((fib->fmt0.aibv & ~PAGE_MASK) + size, PAGE_SIZE);
++ /* AIBV cannot span more than 1 page */
++ if (npages > 1) {
++ rc = -EINVAL;
++ goto out;
++ }
++
+ idx = srcu_read_lock(&kvm->srcu);
+ hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aibv));
+ npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM, pages);
+@@ -287,6 +295,12 @@ static int kvm_s390_pci_aif_enable(struc
+
+ /* Pin the guest AISB if one was specified */
+ if (fib->fmt0.sum == 1) {
++ /* AISB must be dword aligned */
++ if (fib->fmt0.aisb & 0x7) {
++ rc = -EINVAL;
++ goto unpin1;
++ }
++
+ idx = srcu_read_lock(&kvm->srcu);
+ hva = gfn_to_hva(kvm, gpa_to_gfn((gpa_t)fib->fmt0.aisb));
+ npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM,
--- /dev/null
+From 7d3aae206663c4e006b25a1c7a20a4029e67da76 Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Fri, 10 Jul 2026 09:20:51 -0700
+Subject: KVM: SVM: Update x2APIC MSR intercepts if AVIC is inhibited while L2 is active
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 7d3aae206663c4e006b25a1c7a20a4029e67da76 upstream.
+
+Always update x2APIC MSR intercepts for L1 when AVIC is deactivated, even
+if L2 is active and KVM is using a separate MSR bitmap to run L2. If AVIC
+is fully enabled prior to running L2, and is then inhibited while L2 is
+active (for a VM-scoped inhibit), then KVM will run L1 with AVIC disabled,
+but with x2APIC MSR intercepts disabled, i.e. will allow L1 to read most of
+the host's APIC state, send arbitrary interrupts, change task priority, and
+ultimately trivially DoS the host.
+
+E.g. sending a self-IPI in L1 on HYPERV_REENLIGHTENMENT_VECTOR, 0xee, with
+CONFIG_HYPERV=n in the host kernel as a "safe" PoC, yields:
+
+ Spurious interrupt (vector 0xee) on CPU#425. Acked
+
+And hacking KVM to abuse kvm_set_posted_intr_wakeup_handler() to register a
+handler and WARN on POSTED_INTR_WAKEUP_VECTOR yields:
+
+ ------------[ cut here ]------------
+ WARNING: arch/x86/kvm/svm/svm.c:5594 at pi_wakeup_handler+0x9/0x10 [kvm_amd], CPU#156: nested_x2apic_t/316940
+ CPU: 156 UID: 0 PID: 316940 Comm: nested_x2apic_t Tainted: G S U
+ Tainted: [S]=CPU_OUT_OF_SPEC, [U]=USER
+ Hardware name: Google Astoria-Turin/astoria, BIOS 0.20260209.0-0 02/09/2026
+ RIP: 0010:pi_wakeup_handler+0x9/0x10 [kvm_amd]
+ Call Trace:
+ <IRQ>
+ sysvec_kvm_posted_intr_wakeup_ipi+0x64/0x80
+ </IRQ>
+ <TASK>
+ asm_sysvec_kvm_posted_intr_wakeup_ipi+0x1a/0x20
+ RIP: 0010:vcpu_run+0x1430/0x1e40 [kvm]
+ kvm_arch_vcpu_ioctl_run+0x2c1/0x600 [kvm]
+ kvm_vcpu_ioctl+0x580/0x6b0 [kvm]
+ __se_sys_ioctl+0x6d/0xb0
+ do_syscall_64+0x10a/0x480
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ RIP: 0033:0x46ff4b
+ </TASK>
+ ---[ end trace 0000000000000000 ]---
+
+Fixes: 091abbf578f9 ("KVM: x86: nSVM: optimize svm_set_x2apic_msr_interception")
+Cc: stable@vger.kernel.org
+Cc: Yosry Ahmed <yosry@kernel.org>
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Link: https://patch.msgid.link/20260729213558.639074-1-pbonzini@redhat.com/
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/svm/avic.c | 8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/arch/x86/kvm/svm/avic.c
++++ b/arch/x86/kvm/svm/avic.c
+@@ -220,14 +220,6 @@ static void avic_deactivate_vmcb(struct
+ if (!sev_es_guest(svm->vcpu.kvm))
+ svm_set_intercept(svm, INTERCEPT_CR8_WRITE);
+
+- /*
+- * If running nested and the guest uses its own MSR bitmap, there
+- * is no need to update L0's msr bitmap
+- */
+- if (is_guest_mode(&svm->vcpu) &&
+- vmcb12_is_intercept(&svm->nested.ctl, INTERCEPT_MSR_PROT))
+- return;
+-
+ /* Enabling MSR intercept for x2APIC registers */
+ avic_set_x2apic_msr_interception(svm, true);
+ }
--- /dev/null
+From 0e65cd9e5d41c34f86b7c347967bedac54926041 Mon Sep 17 00:00:00 2001
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Tue, 21 Jul 2026 18:31:49 +0200
+Subject: KVM: VMX: add memory clobber to asm for VMX instructions
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+commit 0e65cd9e5d41c34f86b7c347967bedac54926041 upstream.
+
+VMCLEAR/VMREAD/VMWRITE/VMPTRLD access the internal VMCS cache, which
+is not visible to the compiler; without a memory clobber, the compiler
+can reorder them in troublesome ways because "asm volatile" and "asm goto"
+only protect against removal of the asm. For example, placing a VMWRITE
+before the corresponding VMCS pointer is loaded can lead to corruption.
+While none of this has been observed, it is better to prevent than cure.
+
+Likewise, INVEPT and INVVPID access the TLB and, even though in their
+case the effect is only visible to the next VMLAUNCH/VMRESUME, it is
+technically correct to add the clobber there too. So avoid any urge to
+special case them, and simply hardcode "memory" into the clobber list
+of vmx_asm1() and vmx_asm2(). __vmcs_readl() open-codes its own asm,
+so add the clobber there as well.
+
+Link: https://lore.kernel.org/kvm/CABgObfbL3t21yVeSwiLSjjOUER+rTYDPHYAH9YU4TWGRjx6XHg@mail.gmail.com/
+Cc: Sean Christopherson <seanjc@google.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/vmx/vmx_ops.h | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/x86/kvm/vmx/vmx_ops.h
++++ b/arch/x86/kvm/vmx/vmx_ops.h
+@@ -101,7 +101,7 @@ static __always_inline unsigned long __v
+
+ : [output] "=r" (value)
+ : [field] "r" (field)
+- : "cc"
++ : "cc", "memory"
+ : do_fail, do_exception);
+
+ return value;
+@@ -146,7 +146,7 @@ do_exception:
+
+ : ASM_CALL_CONSTRAINT, [output] "=&r" (value)
+ : [field] "r" (field)
+- : "cc");
++ : "cc", "memory");
+ return value;
+
+ #endif /* CONFIG_CC_HAS_ASM_GOTO_OUTPUT */
+@@ -194,7 +194,7 @@ do { \
+ ".byte 0x2e\n\t" /* branch not taken hint */ \
+ "jna %l[error]\n\t" \
+ _ASM_EXTABLE(1b, %l[fault]) \
+- : : op1 : "cc" : error, fault); \
++ : : op1 : "cc", "memory" : error, fault); \
+ return; \
+ error: \
+ instrumentation_begin(); \
+@@ -211,7 +211,7 @@ do { \
+ ".byte 0x2e\n\t" /* branch not taken hint */ \
+ "jna %l[error]\n\t" \
+ _ASM_EXTABLE(1b, %l[fault]) \
+- : : op1, op2 : "cc" : error, fault); \
++ : : op1, op2 : "cc", "memory" : error, fault);\
+ return; \
+ error: \
+ instrumentation_begin(); \
--- /dev/null
+From dd9623f58ec702a07b2d67179d6fcea79c52231a Mon Sep 17 00:00:00 2001
+From: Xiangfeng Cai <caixiangfeng@bytedance.com>
+Date: Tue, 14 Jul 2026 01:14:55 +0800
+Subject: mm/hugetlb: fix list corruption in allocate_file_region_entries()
+
+From: Xiangfeng Cai <caixiangfeng@bytedance.com>
+
+commit dd9623f58ec702a07b2d67179d6fcea79c52231a upstream.
+
+allocate_file_region_entries() tops up resv->region_cache with freshly
+allocated file_region descriptors. The allocation uses GFP_KERNEL, so
+resv->lock is dropped around it: the new entries are gathered on a
+stack-local list head, allocated_regions, and spliced into
+resv->region_cache once the lock is re-acquired.
+
+The splice used list_splice(), which moves the entries but does not
+re-initialize the source head, so allocated_regions is left pointing at an
+entry that now lives on resv->region_cache. The top-up runs in a while
+loop that re-checks the cache deficit after re-acquiring the lock. For a
+shared mapping the resv_map is shared by every mapper of the hugetlbfs
+inode, so a concurrent region_chg()/region_add()/region_del() on the same
+resv_map can consume cache entries during the unlocked window and force a
+second iteration. That iteration calls list_add() on the stale head and
+corrupts the list; with CONFIG_DEBUG_LIST the __list_add_valid() check
+trips:
+
+ list_add corruption. next->prev should be prev (ffffc900011ff7f8),
+ but was ffff88814c281460. (next=ffff88814c545640).
+ kernel BUG at lib/list_debug.c:31!
+ allocate_file_region_entries+0x191/0x420
+ region_chg+0x267/0x300
+ hugetlb_reserve_pages+0x387/0xc80
+ hugetlbfs_file_mmap+0x2ce/0x3f0
+ mmap_region+0x1348/0x1a80
+ do_mmap+0x85e/0xb90
+ vm_mmap_pgoff+0x18c/0x330
+ ksys_mmap_pgoff+0x2a1/0x3e0
+ do_syscall_64+0xd7/0x420
+
+Without CONFIG_DEBUG_LIST the bad list_add() silently links a kernel-stack
+address into resv->region_cache, leading to later use-after-free.
+
+This was observed as a real host panic on a dense KVM host where a QEMU
+guest-RAM hugetlbfs file was mapped MAP_SHARED by both QEMU and a separate
+SPDK/DPDK vhost-user target, generating concurrent region_* traffic on one
+shared resv_map.
+
+Use list_splice_init() so the source head is re-initialized empty after
+each splice, making the retry loop safe.
+
+Link: https://lore.kernel.org/20260713171456.300518-2-caixiangfeng@bytedance.com
+Fixes: d3ec7b6e09e5 ("mm/hugetlb: use list_splice to merge two list at once")
+Signed-off-by: Xiangfeng Cai <caixiangfeng@bytedance.com>
+Reviewed-by: Muchun Song <muchun.song@linux.dev>
+Cc: Baoquan He <baoquan.he@linux.dev>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Oscar Salvador <osalvador@suse.de>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: Wei Yang <richard.weiyang@linux.alibaba.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/hugetlb.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -705,7 +705,7 @@ static int allocate_file_region_entries(
+
+ spin_lock(&resv->lock);
+
+- list_splice(&allocated_regions, &resv->region_cache);
++ list_splice_init(&allocated_regions, &resv->region_cache);
+ resv->region_cache_count += to_allocate;
+ }
+
--- /dev/null
+From 63867c82d0c0c2d182016a32b1cc0103116b0ea5 Mon Sep 17 00:00:00 2001
+From: Kefeng Wang <wangkefeng.wang@huawei.com>
+Date: Mon, 6 Jul 2026 19:19:58 +0800
+Subject: mm: migrate_device: fix pte_pfn/pte_dirty called on non-present PTE
+
+From: Kefeng Wang <wangkefeng.wang@huawei.com>
+
+commit 63867c82d0c0c2d182016a32b1cc0103116b0ea5 upstream.
+
+pte_pfn() and pte_dirty() have undefined behaviour when called on a
+non-present PTE. In migrate_vma_collect_pmd(), these functions may be
+invoked on non-present entries (e.g., device-private entries), leading
+to potential crashes from pte_pfn() or incorrect dirty folio accounting
+from pte_dirty(). Fix both by guarding with pte_present() checks.
+
+Link: https://lore.kernel.org/20260708003955.4024340-1-wangkefeng.wang@huawei.com
+Link: https://lore.kernel.org/20260706111958.3649651-1-wangkefeng.wang@huawei.com
+Fixes: fd35ca3d12cc ("mm/migrate_device.c: copy pte dirty bit to page")
+Fixes: 6c287605fd56 ("mm: remember exclusively mapped anonymous pages with PG_anon_exclusive")
+Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
+Reviewed-by: Balbir Singh <balbirs@nvidia.com>
+Acked-by: Zi Yan <ziy@nvidia.com>
+Cc: Alistair Popple <apopple@nvidia.com>
+Cc: Byungchul Park <byungchul@sk.com>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Gregory Price <gourry@gourry.net>
+Cc: "Huang, Ying" <ying.huang@linux.alibaba.com>
+Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
+Cc: Matthew Brost <matthew.brost@intel.com>
+Cc: Rakie Kim <rakie.kim@sk.com>
+Cc: Ying Huang <ying.huang@linux.alibaba.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/migrate_device.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/mm/migrate_device.c
++++ b/mm/migrate_device.c
+@@ -209,7 +209,8 @@ again:
+ bool anon_exclusive;
+ pte_t swp_pte;
+
+- flush_cache_page(vma, addr, pte_pfn(pte));
++ if (pte_present(pte))
++ flush_cache_page(vma, addr, pte_pfn(pte));
+ anon_exclusive = folio_test_anon(folio) &&
+ PageAnonExclusive(page);
+ if (anon_exclusive) {
+@@ -230,7 +231,7 @@ again:
+ migrate->cpages++;
+
+ /* Set the dirty flag on the folio now the pte is gone. */
+- if (pte_dirty(pte))
++ if (pte_present(pte) && pte_dirty(pte))
+ folio_mark_dirty(folio);
+
+ /* Setup special migration page table entry */
--- /dev/null
+From 89b1b79c308818a715e75f28744b70d8940a07c9 Mon Sep 17 00:00:00 2001
+From: Zi Yan <ziy@nvidia.com>
+Date: Thu, 9 Jul 2026 15:12:01 -0400
+Subject: mm/percpu-km: fix bitmap overflow and accounting in pcpu_create_chunk()
+
+From: Zi Yan <ziy@nvidia.com>
+
+commit 89b1b79c308818a715e75f28744b70d8940a07c9 upstream.
+
+In pcpu_create_chunk(), nr_pages is the total contiguous backing
+allocation, i.e., nr_units * pcpu_unit_pages, but pcpu_chunk_populated()
+uses it to set chunk->populated, whose size is pcpu_unit_pages, bitmap.
+Since bit N in chunk->populated means page offset N inside every unit is
+backed. When nr_units > 1, the function writes beyond chunk->populated.
+Fix it by using chunk->nr_pages.
+
+It also fixes the global pcpu_nr_empty_pop_pages accounting, since
+pcpu_balance_free() only iterates up to chunk->nr_pages.
+
+Commit a63d4ac4ab609 ("percpu: make percpu-km set chunk->populated bitmap
+properly") introduced the bitmap overflow issue. Later, commit
+b539b87fed37f ("percpu: implmeent pcpu_nr_empty_pop_pages and
+chunk->nr_populated") added pcpu_nr_empty_pop_pages and caused the
+accounting issue.
+
+Link: https://lore.kernel.org/20260709-fix-pcpu_create_chunk-in-percpu-km-v1-1-1f64745a84cc@nvidia.com
+Fixes: a63d4ac4ab609 ("percpu: make percpu-km set chunk->populated bitmap properly")
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260703-keep-subpage-private-zero-at-free-v2-0-2970fe777dd6%40nvidia.com?part=1
+Assisted-by: Codex:GPT-5
+Signed-off-by: Zi Yan <ziy@nvidia.com>
+Acked-by: Dennis Zhou <dennis@kernel.org>
+Cc: Christoph Lameter <cl@linux.com>
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Zi Yan <ziy@nvidia.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/percpu-km.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/mm/percpu-km.c
++++ b/mm/percpu-km.c
+@@ -75,7 +75,7 @@ static struct pcpu_chunk *pcpu_create_ch
+ chunk->base_addr = page_address(pages);
+
+ spin_lock_irqsave(&pcpu_lock, flags);
+- pcpu_chunk_populated(chunk, 0, nr_pages);
++ pcpu_chunk_populated(chunk, 0, chunk->nr_pages);
+ spin_unlock_irqrestore(&pcpu_lock, flags);
+
+ pcpu_stats_chunk_alloc();
--- /dev/null
+From 7441d6348c70738e9ed307510db171c7a9b3f4bf Mon Sep 17 00:00:00 2001
+From: Aboorva Devarajan <aboorvad@linux.ibm.com>
+Date: Thu, 9 Jul 2026 01:49:54 +0530
+Subject: mm/util: don't read __page_2 for order-1 folios in snapshot_page()
+
+From: Aboorva Devarajan <aboorvad@linux.ibm.com>
+
+commit 7441d6348c70738e9ed307510db171c7a9b3f4bf upstream.
+
+snapshot_page() currently reads __page_2 after checking nr_pages > 1, but
+it should only do so when nr_pages > 2.
+
+If an order-1 folio is allocated at the end of a vmemmap section,
+__page_2 will not exist and reading it will cause a fault.
+
+During DLPAR memory remove on a 22 TB ppc64le LPAR, snapshot_page() oopsed
+on the page isolation path while reading an order-1 folio's __page_2 from
+an adjacent absent section (unmapped vmemmap).
+
+Fix this to avoid reading memmap that doesn't exist (e.g., a vmemmap
+hole).
+
+Link: https://lore.kernel.org/20260708201954.686111-1-aboorvad@linux.ibm.com
+Fixes: 31a31da8a618 ("mm: move _pincount in folio to page[2] on 32bit")
+Signed-off-by: Aboorva Devarajan <aboorvad@linux.ibm.com>
+Reported-by: Sourabh Jain <sourabhjain@linux.ibm.com>
+Acked-by: David Hildenbrand (Arm) <david@kernel.org>
+Reviewed-by: Lorenzo Stoakes <ljs@kernel.org>
+Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
+Reviewed-by: Luiz Capitulino <luizcap@redhat.com>
+Cc: Liam R. Howlett <liam@infradead.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org> # v6.15+
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/util.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/mm/util.c
++++ b/mm/util.c
+@@ -1263,7 +1263,7 @@ again:
+ if (ps->idx < MAX_FOLIO_NR_PAGES) {
+ memcpy(&ps->folio_snapshot, foliop, 2 * sizeof(struct page));
+ nr_pages = folio_nr_pages(&ps->folio_snapshot);
+- if (nr_pages > 1)
++ if (nr_pages > 2)
+ memcpy(&ps->folio_snapshot.__page_2, &foliop->__page_2,
+ sizeof(struct page));
+ set_ps_flags(ps, foliop, page);
--- /dev/null
+From ea3034b2b00fa50c8d2518d0804c9d427bbafa86 Mon Sep 17 00:00:00 2001
+From: Gregory Price <gourry@gourry.net>
+Date: Sat, 27 Jun 2026 16:22:43 -0400
+Subject: mm/vmstat: fold stranded per-cpu node stats when a node comes online
+
+From: Gregory Price <gourry@gourry.net>
+
+commit ea3034b2b00fa50c8d2518d0804c9d427bbafa86 upstream.
+
+A per-node vmstat counter is pgdat->vm_stat[] plus per-cpu deltas. A
+balanced counter can sit split as global=+N / per-cpu=-N.
+
+The folds reconciling the split only walk online nodes, so when
+try_offline_node() marks a node offline the per-cpu deltas are stranded.
+
+A subsequent online resets the per-cpu area but not pgdat->vm_stat[],
+orphaning the +N permanently. All NR_VM_NODE_STAT_ITEMS are affected.
+
+The existing code zeroes the per-cpu counters and causes a permanent skew.
+Fold the stranded deltas instead, before the node rejoins the online set.
+The node is not online yet and the hotplug lock is held, so the remote
+access to per-cpu values is safe.
+
+Discovered when node compaction hung for a nearly empty node, as the math
+to determine throttling broke. Reproduced by repeated memory
+hotplug/unplug cycles on a node under pressure: NR_ISOLATED_ANON ratchets
+up and never returns to zero.
+
+Link: https://lore.kernel.org/20260627202243.758289-1-gourry@gourry.net
+Fixes: 75ef71840539 ("mm, vmstat: add infrastructure for per-node vmstats")
+Signed-off-by: Gregory Price <gourry@gourry.net>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Mel Gorman <mgorman@techsingularity.net>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/mm_init.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/mm/mm_init.c
++++ b/mm/mm_init.c
+@@ -1565,7 +1565,7 @@ void __ref free_area_init_core_hotplug(s
+ {
+ int nid = pgdat->node_id;
+ enum zone_type z;
+- int cpu;
++ int cpu, i;
+
+ pgdat_init_internals(pgdat);
+
+@@ -1583,10 +1583,17 @@ void __ref free_area_init_core_hotplug(s
+ pgdat->node_start_pfn = 0;
+ pgdat->node_present_pages = 0;
+
+- for_each_online_cpu(cpu) {
+- struct per_cpu_nodestat *p;
++ /*
++ * Hot-unplug can leave per-cpu vmstat deltas unfolded (folders skip
++ * offline nodes) - reconcile this at online. Foreign access to counters
++ * is safe: the node is not online yet and we hold the hotplug lock.
++ */
++ for_each_possible_cpu(cpu) {
++ struct per_cpu_nodestat *p = per_cpu_ptr(pgdat->per_cpu_nodestats, cpu);
+
+- p = per_cpu_ptr(pgdat->per_cpu_nodestats, cpu);
++ for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
++ if (p->vm_node_stat_diff[i])
++ node_page_state_add(p->vm_node_stat_diff[i], pgdat, i);
+ memset(p, 0, sizeof(*p));
+ }
+
--- /dev/null
+From 74b21f52c5c5a71a05c0ff70e513f4f04ff28b17 Mon Sep 17 00:00:00 2001
+From: Charles Vosburgh <trilobyte777@gmail.com>
+Date: Mon, 27 Jul 2026 19:17:30 -0400
+Subject: sctp: validate Adaptation Indication parameter length
+
+From: Charles Vosburgh <trilobyte777@gmail.com>
+
+commit 74b21f52c5c5a71a05c0ff70e513f4f04ff28b17 upstream.
+
+The Adaptation Layer Indication parameter contains a fixed 32-bit
+Adaptation Code Point after its parameter header. However,
+sctp_verify_param() accepts a header-only parameter because the generic
+parameter walker only requires the header to be present.
+
+sctp_process_param() then reads adaptation_ind beyond the declared
+parameter. When the malformed parameter is last in an INIT, the read
+starts at the receive skb tail, and the value is copied into the state
+cookie returned in the INIT ACK. This may disclose four receive-buffer
+tail bytes.
+
+Require the declared parameter length to match the fixed structure size
+and abort the association through the existing invalid parameter length
+path otherwise.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Charles Vosburgh <trilobyte777@gmail.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260727-sctp-adaptation-length-v1-1-0ab58b2810a5@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/sm_make_chunk.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/net/sctp/sm_make_chunk.c
++++ b/net/sctp/sm_make_chunk.c
+@@ -2168,7 +2168,13 @@ static enum sctp_ierror sctp_verify_para
+ case SCTP_PARAM_HEARTBEAT_INFO:
+ case SCTP_PARAM_UNRECOGNIZED_PARAMETERS:
+ case SCTP_PARAM_ECN_CAPABLE:
++ break;
+ case SCTP_PARAM_ADAPTATION_LAYER_IND:
++ if (ntohs(param.p->length) != sizeof(*param.aind)) {
++ sctp_process_inv_paramlength(asoc, param.p,
++ chunk, err_chunk);
++ retval = SCTP_IERROR_ABORT;
++ }
+ break;
+
+ case SCTP_PARAM_SUPPORTED_EXT:
--- /dev/null
+From e3a0127eee04db8769e53c8102c4e76aa49be8c3 Mon Sep 17 00:00:00 2001
+From: Jori Koolstra <jkoolstra@xs4all.nl>
+Date: Fri, 10 Jul 2026 19:17:35 +0200
+Subject: selftest: fix headers in fclog.c
+
+From: Jori Koolstra <jkoolstra@xs4all.nl>
+
+commit e3a0127eee04db8769e53c8102c4e76aa49be8c3 upstream.
+
+fclog.c does not compile because it is missing fcntl.h, needed for
+O_RDONLY etc.
+
+There are also some redundant includes that are also in
+kselftest_harness.h.
+
+Link: https://lore.kernel.org/20260710171741.837308-1-jkoolstra@xs4all.nl
+Signed-off-by: Jori Koolstra <jkoolstra@xs4all.nl>
+Cc: Aleksa Sarai <cyphar@cyphar.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: Wei Yang <richard.weiyang@gmail.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/filesystems/fclog.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/tools/testing/selftests/filesystems/fclog.c
++++ b/tools/testing/selftests/filesystems/fclog.c
+@@ -6,10 +6,8 @@
+
+ #include <assert.h>
+ #include <errno.h>
++#include <fcntl.h>
+ #include <sched.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+ #include <unistd.h>
+ #include <sys/mount.h>
+
pinctrl-devicetree-don-t-free-uninitialized-dev_name-on-error-path.patch
erofs-cap-lzma-stream-pool-size.patch
pinctrl-bm1880-add-missing-select-generic_pinconf.patch
+fortify-disable-wstringop-overread-in-tests.patch
+mm-migrate_device-fix-pte_pfn-pte_dirty-called-on-non-present-pte.patch
+mm-util-don-t-read-__page_2-for-order-1-folios-in-snapshot_page.patch
+selftest-fix-headers-in-fclog.c.patch
+fs-proc-task_mmu-fix-pagemap_scan-written-state-for-pmd-holes.patch
+mm-percpu-km-fix-bitmap-overflow-and-accounting-in-pcpu_create_chunk.patch
+mm-hugetlb-fix-list-corruption-in-allocate_file_region_entries.patch
+mm-vmstat-fold-stranded-per-cpu-node-stats-when-a-node-comes-online.patch
+tracing-probes-reject-arg0-in-meta-argument-expansion.patch
+tracing-fprobe-roll-back-on-enable_trace_fprobe-failure.patch
+kvm-vmx-add-memory-clobber-to-asm-for-vmx-instructions.patch
+kvm-svm-update-x2apic-msr-intercepts-if-avic-is-inhibited-while-l2-is-active.patch
+kvm-s390-pci-reject-adapter-interrupt-forwarding-if-already-enabled.patch
+kvm-s390-pci-fix-memory-accounting-for-pinned-unpinned-pages.patch
+kvm-s390-pci-fix-missing-error-codes-and-memory-unaccounting.patch
+kvm-s390-pci-fix-null-dereference-on-aibv-allocation-failure.patch
+kvm-s390-pci-validate-aibv-and-aisb-before-pinning-guest-pages.patch
+dibs-fix-use-after-free-of-dmb_node-in-loopback-attach-detach-unregister.patch
+sctp-validate-adaptation-indication-parameter-length.patch
+audit-fix-potential-integer-overflow-in-audit_log_n_string.patch
+audit-fix-potential-use-after-free-in-audit_del_rule.patch
+bluetooth-btusb-fix-short-read-errors-in-btusb_qca_send_vendor_req.patch
+bluetooth-btmtk-fix-short-read-errors-in-btmtk_usb_uhw_reg_read.patch
+bluetooth-mgmt-fix-pending-command-uaf-in-eir-updates.patch
+bluetooth-sco-give-the-socket-its-own-sco_conn-reference.patch
+bluetooth-mgmt-fix-uaf-in-pair-command-cancellation.patch
+bluetooth-hci_sync-fix-advertising-data-uafs.patch
+bluetooth-hidp-reject-frames-without-a-transaction-header.patch
+bluetooth-hidp-validate-numbered-report-payloads.patch
--- /dev/null
+From aca0cd1bf16574327ef64f3178e5f5e37a61ef0b Mon Sep 17 00:00:00 2001
+From: Raushan Patel <raushan.jhon@gmail.com>
+Date: Fri, 24 Jul 2026 12:12:08 +0530
+Subject: tracing/fprobe: Roll back on enable_trace_fprobe() failure
+
+From: Raushan Patel <raushan.jhon@gmail.com>
+
+commit aca0cd1bf16574327ef64f3178e5f5e37a61ef0b upstream.
+
+enable_trace_fprobe() sets the file link or the TP_FLAG_PROFILE flag and
+then registers each trace_fprobe in the probe list. If
+__register_trace_fprobe() fails partway through, the function returns
+immediately without unregistering the trace_fprobes it already registered
+or undoing the file link / flag it set, leaving the event half-enabled and
+leaking the registered fprobe(s).
+
+enable_trace_kprobe() already handles this with a rollback path. Do the
+same for fprobe: on failure, unregister all probes and clear the file link
+or profile flag.
+
+Link: https://lore.kernel.org/all/20260724064208.480030-1-raushan.jhon@gmail.com/
+
+Fixes: 334e5519c375 ("tracing/probes: Add fprobe events for tracing function entry and exit.")
+Cc: stable@vger.kernel.org
+Signed-off-by: Raushan Patel <raushan.jhon@gmail.com>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/trace_fprobe.c | 12 +++++++++++-
+ 1 file changed, 11 insertions(+), 1 deletion(-)
+
+--- a/kernel/trace/trace_fprobe.c
++++ b/kernel/trace/trace_fprobe.c
+@@ -1481,11 +1481,21 @@ static int enable_trace_fprobe(struct tr
+ list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list) {
+ ret = __register_trace_fprobe(tf);
+ if (ret < 0)
+- return ret;
++ goto err;
+ }
+ }
+
+ return 0;
++
++err:
++ /* Failed to enable one of them. Roll back all */
++ list_for_each_entry(tf, trace_probe_probe_list(tp), tp.list)
++ __unregister_trace_fprobe(tf);
++ if (file)
++ trace_probe_remove_file(tp, file);
++ else
++ trace_probe_clear_flag(tp, TP_FLAG_PROFILE);
++ return ret;
+ }
+
+ /*
--- /dev/null
+From 00a8ce2a2a9fa17674e1feec4d9105c1a5d6a419 Mon Sep 17 00:00:00 2001
+From: Raushan Patel <raushan.jhon@gmail.com>
+Date: Fri, 24 Jul 2026 11:14:35 +0530
+Subject: tracing/probes: Reject $arg0 in meta argument expansion
+
+From: Raushan Patel <raushan.jhon@gmail.com>
+
+commit 00a8ce2a2a9fa17674e1feec4d9105c1a5d6a419 upstream.
+
+traceprobe_expand_meta_args() parses $argN with simple_strtoul() and
+calls sprint_nth_btf_arg(n - 1, ...). For $arg0, n is 0 so the index is
+-1. Because ctx->nr_params is signed, the "idx >= nr_params" guard in
+sprint_nth_btf_arg() does not catch the negative index, and
+ctx->params[-1].name_off is read out of bounds.
+
+The normal per-argument path (parse_probe_vars()) already rejects
+$arg0 via its argument-number check, but meta-argument expansion runs
+before per-argument parsing and substitutes the value first, bypassing
+that check.
+
+Reject $arg0 explicitly during expansion.
+
+Link: https://lore.kernel.org/all/20260724054435.146279-1-raushan.jhon@gmail.com/
+
+Fixes: 18b1e870a496 ("tracing/probes: Add $arg* meta argument for all function args")
+Cc: stable@vger.kernel.org
+Signed-off-by: Raushan Patel <raushan.jhon@gmail.com>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/trace/trace_probe.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/kernel/trace/trace_probe.c
++++ b/kernel/trace/trace_probe.c
+@@ -1906,7 +1906,11 @@ const char **traceprobe_expand_meta_args
+ trace_probe_log_err(0, BAD_VAR);
+ return ERR_PTR(-ENOENT);
+ }
+- /* Note: $argN starts from $arg1 */
++ /* Note: $argN starts from $arg1, so $arg0 is invalid. */
++ if (n == 0) {
++ trace_probe_log_err(0, BAD_ARG_NUM);
++ return ERR_PTR(-EINVAL);
++ }
+ ret = sprint_nth_btf_arg(n - 1, type, buf + used,
+ bufsize - used, ctx);
+ if (ret < 0)