--- /dev/null
+From 02012aff754be0708a52368a013eb79fdf2e88e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 22:12:35 +0200
+Subject: batman-adv: tt: prevent TVLV entry number overflow
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 99d9958fa10fb684b2a8e2c48a8d704122721420 upstream.
+
+The helpers to prepare the buffers for the local and global TT based
+replies are trying to sum up all TT entries which can be found for each
+VLAN. In theory, this sum can be too big for an u16 and therefore overflow.
+A too small buffer would then be allocated for the TVLV.
+
+The too small buffer will be handled gracefully by
+batadv_tt_tvlv_generate() and is not causing a buffer overflow - just a
+truncated reply. But this overflow shouldn't have happened in the first and
+the too small buffer should never have been allocated when an overflow was
+detected.
+
+Cc: stable@kernel.org
+Fixes: 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/batman-adv/translation-table.c | 20 +++++++++++++++++---
+ 1 file changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index fb51088494dcc6..79da90b9cf0659 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -854,11 +854,18 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
+ u16 total_entries = 0;
+ u8 *tt_change_ptr;
+ int vlan_entries;
++ u16 sum_entries;
+
+ spin_lock_bh(&orig_node->vlan_list_lock);
+ hlist_for_each_entry(vlan, &orig_node->vlan_list, list) {
+ vlan_entries = atomic_read(&vlan->tt.num_entries);
+- total_entries += vlan_entries;
++
++ if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
++ *tt_len = 0;
++ goto out;
++ }
++
++ total_entries = sum_entries;
+ num_vlan++;
+ }
+
+@@ -945,15 +952,22 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+ struct batadv_softif_vlan *vlan;
+ size_t change_offset;
+ u16 num_vlan = 0;
+- u16 vlan_entries = 0;
+ u16 total_entries = 0;
+ u16 tvlv_len;
+ u8 *tt_change_ptr;
++ int vlan_entries;
++ u16 sum_entries;
+
+ spin_lock_bh(&bat_priv->softif_vlan_list_lock);
+ hlist_for_each_entry(vlan, &bat_priv->softif_vlan_list, list) {
+ vlan_entries = atomic_read(&vlan->tt.num_entries);
+- total_entries += vlan_entries;
++
++ if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
++ tvlv_len = 0;
++ goto out;
++ }
++
++ total_entries = sum_entries;
+ num_vlan++;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From dfe89e43a6a607759308754aedeab2cd1ee7345e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 22:11:09 +0200
+Subject: batman-adv: tt: reject oversized local TVLV buffers
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 1e9fab756f8395096d5bba7be0c373c4c8f5d165 upstream.
+
+The commit 3a359bf5c61d ("batman-adv: reject oversized global TT response
+buffers") added a check to ensure that a global return buffer size can be
+stored in an u16. The same buffer handling also exists for the local data
+buffer but was not touched.
+
+A similar check should be also be in place for the local TVLV buffer. It
+doesn't have the similar attack surface because it is only generated from
+locally discovered MAC addresses but the dynamic nature could still cause
+temporarily to large buffers.
+
+Cc: stable@kernel.org
+Fixes: 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific")
+[ Context ]
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/batman-adv/translation-table.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index fa6dece492d3ab..fb51088494dcc6 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -943,12 +943,12 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+ {
+ struct batadv_tvlv_tt_vlan_data *tt_vlan;
+ struct batadv_softif_vlan *vlan;
++ size_t change_offset;
+ u16 num_vlan = 0;
+ u16 vlan_entries = 0;
+ u16 total_entries = 0;
+ u16 tvlv_len;
+ u8 *tt_change_ptr;
+- int change_offset;
+
+ spin_lock_bh(&bat_priv->softif_vlan_list_lock);
+ hlist_for_each_entry(vlan, &bat_priv->softif_vlan_list, list) {
+@@ -964,8 +964,10 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+ if (*tt_len < 0)
+ *tt_len = batadv_tt_len(total_entries);
+
+- tvlv_len = *tt_len;
+- tvlv_len += change_offset;
++ if (check_add_overflow(*tt_len, change_offset, &tvlv_len)) {
++ tvlv_len = 0;
++ goto out;
++ }
+
+ *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
+ if (!*tt_data) {
+--
+2.53.0
+
drm-amd-display-use-krealloc_array-in-dal_vector_res.patch
net-9p-fix-refcount-leak-in-p9_read_work-error-handl.patch
netdevsim-fix-memory-leak-of-nsim_dev-fa_cookie.patch
+batman-adv-tt-reject-oversized-local-tvlv-buffers.patch
+batman-adv-tt-prevent-tvlv-entry-number-overflow.patch
+vfio-iommu_type1-replace-kfree-with-kvfree.patch
--- /dev/null
+From 9c332c79d76eecd1dcb9990ad02370af71cd31e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 12 Dec 2021 01:16:00 -0800
+Subject: vfio/iommu_type1: replace kfree with kvfree
+
+From: Jiacheng Shi <billsjc@sjtu.edu.cn>
+
+[ Upstream commit 2bed2ced40c97b8540ff38df0149e8ecb2bf4c65 ]
+
+Variables allocated by kvzalloc should not be freed by kfree.
+Because they may be allocated by vmalloc.
+So we replace kfree with kvfree here.
+
+Fixes: d6a4c185660c ("vfio iommu: Implementation of ioctl for dirty pages tracking")
+Signed-off-by: Jiacheng Shi <billsjc@sjtu.edu.cn>
+Link: https://lore.kernel.org/r/20211212091600.2560-1-billsjc@sjtu.edu.cn
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vfio/vfio_iommu_type1.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
+index b2a543e7cac454..eee8d2ab03d683 100644
+--- a/drivers/vfio/vfio_iommu_type1.c
++++ b/drivers/vfio/vfio_iommu_type1.c
+@@ -228,7 +228,7 @@ static int vfio_dma_bitmap_alloc(struct vfio_dma *dma, size_t pgsize)
+
+ static void vfio_dma_bitmap_free(struct vfio_dma *dma)
+ {
+- kfree(dma->bitmap);
++ kvfree(dma->bitmap);
+ dma->bitmap = NULL;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From aa89d06a63f2b16e8af824e5775e32b4e8f1b47e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 22:03:23 +0200
+Subject: batman-adv: tt: prevent TVLV entry number overflow
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 99d9958fa10fb684b2a8e2c48a8d704122721420 upstream.
+
+The helpers to prepare the buffers for the local and global TT based
+replies are trying to sum up all TT entries which can be found for each
+VLAN. In theory, this sum can be too big for an u16 and therefore overflow.
+A too small buffer would then be allocated for the TVLV.
+
+The too small buffer will be handled gracefully by
+batadv_tt_tvlv_generate() and is not causing a buffer overflow - just a
+truncated reply. But this overflow shouldn't have happened in the first and
+the too small buffer should never have been allocated when an overflow was
+detected.
+
+Cc: stable@kernel.org
+Fixes: 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/batman-adv/translation-table.c | 20 +++++++++++++++++---
+ 1 file changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index 3849c348ff0344..8ab1257bade048 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -850,11 +850,18 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
+ u16 total_entries = 0;
+ u8 *tt_change_ptr;
+ int vlan_entries;
++ u16 sum_entries;
+
+ spin_lock_bh(&orig_node->vlan_list_lock);
+ hlist_for_each_entry(vlan, &orig_node->vlan_list, list) {
+ vlan_entries = atomic_read(&vlan->tt.num_entries);
+- total_entries += vlan_entries;
++
++ if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
++ *tt_len = 0;
++ goto out;
++ }
++
++ total_entries = sum_entries;
+ num_vlan++;
+ }
+
+@@ -941,15 +948,22 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+ struct batadv_softif_vlan *vlan;
+ size_t change_offset;
+ u16 num_vlan = 0;
+- u16 vlan_entries = 0;
+ u16 total_entries = 0;
+ u16 tvlv_len;
+ u8 *tt_change_ptr;
++ int vlan_entries;
++ u16 sum_entries;
+
+ spin_lock_bh(&bat_priv->softif_vlan_list_lock);
+ hlist_for_each_entry(vlan, &bat_priv->softif_vlan_list, list) {
+ vlan_entries = atomic_read(&vlan->tt.num_entries);
+- total_entries += vlan_entries;
++
++ if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
++ tvlv_len = 0;
++ goto out;
++ }
++
++ total_entries = sum_entries;
+ num_vlan++;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 8bc28e5a230c15fa77b2f45d49ce0036a1cab9a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 22:02:01 +0200
+Subject: batman-adv: tt: reject oversized local TVLV buffers
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 1e9fab756f8395096d5bba7be0c373c4c8f5d165 upstream.
+
+The commit 3a359bf5c61d ("batman-adv: reject oversized global TT response
+buffers") added a check to ensure that a global return buffer size can be
+stored in an u16. The same buffer handling also exists for the local data
+buffer but was not touched.
+
+A similar check should be also be in place for the local TVLV buffer. It
+doesn't have the similar attack surface because it is only generated from
+locally discovered MAC addresses but the dynamic nature could still cause
+temporarily to large buffers.
+
+Cc: stable@kernel.org
+Fixes: 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific")
+[ Context ]
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/batman-adv/translation-table.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index e4d55b27f2551b..3849c348ff0344 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -939,12 +939,12 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+ {
+ struct batadv_tvlv_tt_vlan_data *tt_vlan;
+ struct batadv_softif_vlan *vlan;
++ size_t change_offset;
+ u16 num_vlan = 0;
+ u16 vlan_entries = 0;
+ u16 total_entries = 0;
+ u16 tvlv_len;
+ u8 *tt_change_ptr;
+- int change_offset;
+
+ spin_lock_bh(&bat_priv->softif_vlan_list_lock);
+ hlist_for_each_entry(vlan, &bat_priv->softif_vlan_list, list) {
+@@ -960,8 +960,10 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+ if (*tt_len < 0)
+ *tt_len = batadv_tt_len(total_entries);
+
+- tvlv_len = *tt_len;
+- tvlv_len += change_offset;
++ if (check_add_overflow(*tt_len, change_offset, &tvlv_len)) {
++ tvlv_len = 0;
++ goto out;
++ }
+
+ *tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
+ if (!*tt_data) {
+--
+2.53.0
+
--- /dev/null
+From 39e0a0b4e6be4402b29ce0b4f88a79a9aaa709f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 17:34:43 +0300
+Subject: iio: light: bh1780: fix PM runtime leak on error path
+
+From: Antoniu Miclaus <antoniu.miclaus@analog.com>
+
+commit dd72e6c3cdea05cad24e99710939086f7a113fb5 upstream.
+
+Move pm_runtime_put_autosuspend() before the error check to ensure
+the PM runtime reference count is always decremented after
+pm_runtime_get_sync(), regardless of whether the read operation
+succeeds or fails.
+
+Fixes: 1f0477f18306 ("iio: light: new driver for the ROHM BH1780")
+Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
+Reviewed-by: Linus Walleij <linusw@kernel.org>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+[ moved both pm_runtime_mark_last_busy() and pm_runtime_put_autosuspend() before the error check instead of just pm_runtime_put_autosuspend() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Elizaveta Tereshkina <etereshkina@astralinux.ru>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/light/bh1780.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/light/bh1780.c b/drivers/iio/light/bh1780.c
+index abbf2e662e7dbc..e0a72ff2ebf8b1 100644
+--- a/drivers/iio/light/bh1780.c
++++ b/drivers/iio/light/bh1780.c
+@@ -109,10 +109,10 @@ static int bh1780_read_raw(struct iio_dev *indio_dev,
+ case IIO_LIGHT:
+ pm_runtime_get_sync(&bh1780->client->dev);
+ value = bh1780_read_word(bh1780, BH1780_REG_DLOW);
+- if (value < 0)
+- return value;
+ pm_runtime_mark_last_busy(&bh1780->client->dev);
+ pm_runtime_put_autosuspend(&bh1780->client->dev);
++ if (value < 0)
++ return value;
+ *val = value;
+
+ return IIO_VAL_INT;
+--
+2.53.0
+
ip6_vti-set-netns_immutable-on-the-fallback-device.patch
drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
+batman-adv-tt-reject-oversized-local-tvlv-buffers.patch
+batman-adv-tt-prevent-tvlv-entry-number-overflow.patch
+iio-light-bh1780-fix-pm-runtime-leak-on-error-path.patch
+vfio-iommu_type1-replace-kfree-with-kvfree.patch
--- /dev/null
+From 9641c9aebf8835b18240983f810a8b5af2ac2bf2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 12 Dec 2021 01:16:00 -0800
+Subject: vfio/iommu_type1: replace kfree with kvfree
+
+From: Jiacheng Shi <billsjc@sjtu.edu.cn>
+
+[ Upstream commit 2bed2ced40c97b8540ff38df0149e8ecb2bf4c65 ]
+
+Variables allocated by kvzalloc should not be freed by kfree.
+Because they may be allocated by vmalloc.
+So we replace kfree with kvfree here.
+
+Fixes: d6a4c185660c ("vfio iommu: Implementation of ioctl for dirty pages tracking")
+Signed-off-by: Jiacheng Shi <billsjc@sjtu.edu.cn>
+Link: https://lore.kernel.org/r/20211212091600.2560-1-billsjc@sjtu.edu.cn
+Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vfio/vfio_iommu_type1.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
+index 6a89bbec738f62..2bc79eee63d524 100644
+--- a/drivers/vfio/vfio_iommu_type1.c
++++ b/drivers/vfio/vfio_iommu_type1.c
+@@ -262,7 +262,7 @@ static int vfio_dma_bitmap_alloc(struct vfio_dma *dma, size_t pgsize)
+
+ static void vfio_dma_bitmap_free(struct vfio_dma *dma)
+ {
+- kfree(dma->bitmap);
++ kvfree(dma->bitmap);
+ dma->bitmap = NULL;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 645cecb9c727b252ce4ae685f7fb45b1103e5596 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 21:45:29 +0200
+Subject: batman-adv: tt: prevent TVLV entry number overflow
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 99d9958fa10fb684b2a8e2c48a8d704122721420 upstream.
+
+The helpers to prepare the buffers for the local and global TT based
+replies are trying to sum up all TT entries which can be found for each
+VLAN. In theory, this sum can be too big for an u16 and therefore overflow.
+A too small buffer would then be allocated for the TVLV.
+
+The too small buffer will be handled gracefully by
+batadv_tt_tvlv_generate() and is not causing a buffer overflow - just a
+truncated reply. But this overflow shouldn't have happened in the first and
+the too small buffer should never have been allocated when an overflow was
+detected.
+
+Cc: stable@kernel.org
+Fixes: 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/batman-adv/translation-table.c | 20 +++++++++++++++++---
+ 1 file changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index e0503c8f24c353..53d2aadcafa154 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -850,11 +850,18 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
+ u16 total_entries = 0;
+ u8 *tt_change_ptr;
+ int vlan_entries;
++ u16 sum_entries;
+
+ spin_lock_bh(&orig_node->vlan_list_lock);
+ hlist_for_each_entry(vlan, &orig_node->vlan_list, list) {
+ vlan_entries = atomic_read(&vlan->tt.num_entries);
+- total_entries += vlan_entries;
++
++ if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
++ *tt_len = 0;
++ goto out;
++ }
++
++ total_entries = sum_entries;
+ num_vlan++;
+ }
+
+@@ -941,15 +948,22 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+ struct batadv_softif_vlan *vlan;
+ size_t change_offset;
+ u16 num_vlan = 0;
+- u16 vlan_entries = 0;
+ u16 total_entries = 0;
+ u16 tvlv_len;
+ u8 *tt_change_ptr;
++ int vlan_entries;
++ u16 sum_entries;
+
+ spin_lock_bh(&bat_priv->softif_vlan_list_lock);
+ hlist_for_each_entry(vlan, &bat_priv->softif_vlan_list, list) {
+ vlan_entries = atomic_read(&vlan->tt.num_entries);
+- total_entries += vlan_entries;
++
++ if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
++ tvlv_len = 0;
++ goto out;
++ }
++
++ total_entries = sum_entries;
+ num_vlan++;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 4d698ca25b014b21734bb6df02bf16b7e4b9adfa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:31:05 -0400
+Subject: KVM: nVMX: Add a helper to get highest pending from Posted Interrupt
+ vector
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit d83c36d822be44db4bad0c43bea99c8908f54117 upstream.
+
+Add a helper to retrieve the highest pending vector given a Posted
+Interrupt descriptor. While the actual operation is straightforward, it's
+surprisingly easy to mess up, e.g. if one tries to reuse lapic.c's
+find_highest_vector(), which doesn't work with PID.PIR due to the APIC's
+IRR and ISR component registers being physically discontiguous (they're
+4-byte registers aligned at 16-byte intervals).
+
+To make PIR handling more consistent with respect to IRR and ISR handling,
+return -1 to indicate "no interrupt pending".
+
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240607172609.3205077-2-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[ Nicholas Dudar: backport to 6.1.y. 6.1.y defines struct pi_desc in
+ posted_intr.h and predates the move to <asm/posted_intr.h>, so the helper
+ and the <linux/find.h> include go in posted_intr.h. ]
+Signed-off-by: Nicholas Dudar <main.kalliope@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/nested.c | 5 +++--
+ arch/x86/kvm/vmx/posted_intr.h | 10 ++++++++++
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
+index bdc462944cb082..7d8e18dbe8531b 100644
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -12,6 +12,7 @@
+ #include "mmu.h"
+ #include "nested.h"
+ #include "pmu.h"
++#include "posted_intr.h"
+ #include "sgx.h"
+ #include "trace.h"
+ #include "vmx.h"
+@@ -3818,8 +3819,8 @@ static int vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
+ if (!pi_test_and_clear_on(vmx->nested.pi_desc))
+ return 0;
+
+- max_irr = find_last_bit((unsigned long *)vmx->nested.pi_desc->pir, 256);
+- if (max_irr != 256) {
++ max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
++ if (max_irr > 0) {
+ vapic_page = vmx->nested.virtual_apic_map.hva;
+ if (!vapic_page)
+ goto mmio_needed;
+diff --git a/arch/x86/kvm/vmx/posted_intr.h b/arch/x86/kvm/vmx/posted_intr.h
+index 26992076552ef1..88cea0dac7204b 100644
+--- a/arch/x86/kvm/vmx/posted_intr.h
++++ b/arch/x86/kvm/vmx/posted_intr.h
+@@ -2,6 +2,8 @@
+ #ifndef __KVM_X86_VMX_POSTED_INTR_H
+ #define __KVM_X86_VMX_POSTED_INTR_H
+
++#include <linux/find.h>
++
+ #define POSTED_INTR_ON 0
+ #define POSTED_INTR_SN 1
+
+@@ -103,4 +105,12 @@ int vmx_pi_update_irte(struct kvm *kvm, unsigned int host_irq,
+ uint32_t guest_irq, bool set);
+ void vmx_pi_start_assignment(struct kvm *kvm);
+
++static inline int pi_find_highest_vector(struct pi_desc *pi_desc)
++{
++ int vec;
++
++ vec = find_last_bit((unsigned long *)pi_desc->pir, 256);
++ return vec < 256 ? vec : -1;
++}
++
+ #endif /* __KVM_X86_VMX_POSTED_INTR_H */
+--
+2.53.0
+
--- /dev/null
+From a17c10283ca19ad7d0a629310f8e27d80f2ec122 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:31:06 -0400
+Subject: KVM: nVMX: Check for pending posted interrupts when looking for
+ nested events
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 27c4fa42b11af780d49ce704f7fa67b3c2544df4 upstream.
+
+Check for pending (and notified!) posted interrupts when checking if L2
+has a pending wake event, as fully posted/notified virtual interrupt is a
+valid wake event for HLT.
+
+Note that KVM must check vmx->nested.pi_pending to avoid prematurely
+waking L2, e.g. even if KVM sees a non-zero PID.PIR and PID.0N=1, the
+virtual interrupt won't actually be recognized until a notification IRQ is
+received by the vCPU or the vCPU does (nested) VM-Enter.
+
+Fixes: 26844fee6ade ("KVM: x86: never write to memory from kvm_vcpu_check_block()")
+Cc: stable@vger.kernel.org
+Cc: Maxim Levitsky <mlevitsk@redhat.com>
+Reported-by: Jim Mattson <jmattson@google.com>
+Closes: https://lore.kernel.org/all/20231207010302.2240506-1-jmattson@google.com
+Link: https://lore.kernel.org/r/20240607172609.3205077-5-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[ Nicholas Dudar: backport to 6.1.y. Prerequisite for the next patch, which
+ folds its check into the vmx_has_nested_events() body this patch builds.
+ Applies cleanly. The for_injection path still returns preemption_timer ||
+ mtf, as the previous 6.1.y body did. ]
+Signed-off-by: Nicholas Dudar <main.kalliope@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/nested.c | 36 ++++++++++++++++++++++++++++++++++--
+ 1 file changed, 34 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
+index 7d8e18dbe8531b..ad07e83d2c1d5b 100644
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -3953,8 +3953,40 @@ static bool nested_vmx_preemption_timer_pending(struct kvm_vcpu *vcpu)
+
+ static bool vmx_has_nested_events(struct kvm_vcpu *vcpu, bool for_injection)
+ {
+- return nested_vmx_preemption_timer_pending(vcpu) ||
+- to_vmx(vcpu)->nested.mtf_pending;
++ struct vcpu_vmx *vmx = to_vmx(vcpu);
++ void *vapic = vmx->nested.virtual_apic_map.hva;
++ int max_irr, vppr;
++
++ if (nested_vmx_preemption_timer_pending(vcpu) ||
++ vmx->nested.mtf_pending)
++ return true;
++
++ /*
++ * Virtual Interrupt Delivery doesn't require manual injection. Either
++ * the interrupt is already in GUEST_RVI and will be recognized by CPU
++ * at VM-Entry, or there is a KVM_REQ_EVENT pending and KVM will move
++ * the interrupt from the PIR to RVI prior to entering the guest.
++ */
++ if (for_injection)
++ return false;
++
++ if (!nested_cpu_has_vid(get_vmcs12(vcpu)) ||
++ __vmx_interrupt_blocked(vcpu))
++ return false;
++
++ if (!vapic)
++ return false;
++
++ vppr = *((u32 *)(vapic + APIC_PROCPRI));
++
++ if (vmx->nested.pi_pending && vmx->nested.pi_desc &&
++ pi_test_on(vmx->nested.pi_desc)) {
++ max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
++ if (max_irr > 0 && (max_irr & 0xf0) > (vppr & 0xf0))
++ return true;
++ }
++
++ return false;
+ }
+
+ /*
+--
+2.53.0
+
--- /dev/null
+From 92d8cc54210672204f960849fc948f3614ea8702 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:31:07 -0400
+Subject: KVM: nVMX: Fold requested virtual interrupt check into
+ has_nested_events()
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 321ef62b0c5f6f57bb8500a2ca5986052675abbf upstream.
+
+Check for a Requested Virtual Interrupt, i.e. a virtual interrupt that is
+pending delivery, in vmx_has_nested_events() and drop the one-off
+kvm_x86_ops.guest_apic_has_interrupt() hook.
+
+In addition to dropping a superfluous hook, this fixes a bug where KVM
+would incorrectly treat virtual interrupts _for L2_ as always enabled due
+to kvm_arch_interrupt_allowed(), by way of vmx_interrupt_blocked(),
+treating IRQs as enabled if L2 is active and vmcs12 is configured to exit
+on IRQs, i.e. KVM would treat a virtual interrupt for L2 as a valid wake
+event based on L1's IRQ blocking status.
+
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20240607172609.3205077-6-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[ Nicholas Dudar: backport to 6.1.y. 6.1.y predates the vmx main.c /
+ x86_ops.h split, so drop .guest_apic_has_interrupt from vmx_x86_ops in
+ vmx.c rather than vt_x86_ops in main.c. The function is static in vmx.c, so
+ upstream's x86_ops.h prototype removal does not apply. 6.1.y keeps the
+ current hwapic_isr_update signature. ]
+Signed-off-by: Nicholas Dudar <main.kalliope@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/kvm-x86-ops.h | 1 -
+ arch/x86/include/asm/kvm_host.h | 1 -
+ arch/x86/kvm/vmx/nested.c | 4 ++++
+ arch/x86/kvm/vmx/vmx.c | 21 ---------------------
+ arch/x86/kvm/x86.c | 10 +---------
+ 5 files changed, 5 insertions(+), 32 deletions(-)
+
+diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h
+index c068565fe95474..1cfe83263b213b 100644
+--- a/arch/x86/include/asm/kvm-x86-ops.h
++++ b/arch/x86/include/asm/kvm-x86-ops.h
+@@ -81,7 +81,6 @@ KVM_X86_OP(check_apicv_inhibit_reasons)
+ KVM_X86_OP(refresh_apicv_exec_ctrl)
+ KVM_X86_OP_OPTIONAL(hwapic_irr_update)
+ KVM_X86_OP_OPTIONAL(hwapic_isr_update)
+-KVM_X86_OP_OPTIONAL_RET0(guest_apic_has_interrupt)
+ KVM_X86_OP_OPTIONAL(load_eoi_exitmap)
+ KVM_X86_OP_OPTIONAL(set_virtual_apic_mode)
+ KVM_X86_OP_OPTIONAL(set_apic_access_page_addr)
+diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
+index fe5c0f86ae389d..31395c43416dd7 100644
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -1549,7 +1549,6 @@ struct kvm_x86_ops {
+ void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
+ void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
+ void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr);
+- bool (*guest_apic_has_interrupt)(struct kvm_vcpu *vcpu);
+ void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
+ void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
+ void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu);
+diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
+index ad07e83d2c1d5b..f7a790a28b9eee 100644
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -3979,6 +3979,10 @@ static bool vmx_has_nested_events(struct kvm_vcpu *vcpu, bool for_injection)
+
+ vppr = *((u32 *)(vapic + APIC_PROCPRI));
+
++ max_irr = vmx_get_rvi();
++ if ((max_irr & 0xf0) > (vppr & 0xf0))
++ return true;
++
+ if (vmx->nested.pi_pending && vmx->nested.pi_desc &&
+ pi_test_on(vmx->nested.pi_desc)) {
+ max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
+diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
+index e5d162e97f5031..2e6454e4cca4b4 100644
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -4063,26 +4063,6 @@ void pt_update_intercept_for_msr(struct kvm_vcpu *vcpu)
+ }
+ }
+
+-static bool vmx_guest_apic_has_interrupt(struct kvm_vcpu *vcpu)
+-{
+- struct vcpu_vmx *vmx = to_vmx(vcpu);
+- void *vapic_page;
+- u32 vppr;
+- int rvi;
+-
+- if (WARN_ON_ONCE(!is_guest_mode(vcpu)) ||
+- !nested_cpu_has_vid(get_vmcs12(vcpu)) ||
+- WARN_ON_ONCE(!vmx->nested.virtual_apic_map.gfn))
+- return false;
+-
+- rvi = vmx_get_rvi();
+-
+- vapic_page = vmx->nested.virtual_apic_map.hva;
+- vppr = *((u32 *)(vapic_page + APIC_PROCPRI));
+-
+- return ((rvi & 0xf0) > (vppr & 0xf0));
+-}
+-
+ static void vmx_msr_filter_changed(struct kvm_vcpu *vcpu)
+ {
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+@@ -8266,7 +8246,6 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
+ .check_apicv_inhibit_reasons = vmx_check_apicv_inhibit_reasons,
+ .hwapic_irr_update = vmx_hwapic_irr_update,
+ .hwapic_isr_update = vmx_hwapic_isr_update,
+- .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
+ .sync_pir_to_irr = vmx_sync_pir_to_irr,
+ .deliver_interrupt = vmx_deliver_interrupt,
+ .dy_apicv_has_pending_interrupt = pi_has_pending_interrupt,
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 10ef8a4353b32e..208a713d7ecd75 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -13046,12 +13046,6 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm,
+ kvm_page_track_flush_slot(kvm, slot);
+ }
+
+-static inline bool kvm_guest_apic_has_interrupt(struct kvm_vcpu *vcpu)
+-{
+- return (is_guest_mode(vcpu) &&
+- static_call(kvm_x86_guest_apic_has_interrupt)(vcpu));
+-}
+-
+ static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
+ {
+ if (!list_empty_careful(&vcpu->async_pf.done))
+@@ -13077,9 +13071,7 @@ static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
+ static_call(kvm_x86_smi_allowed)(vcpu, false)))
+ return true;
+
+- if (kvm_arch_interrupt_allowed(vcpu) &&
+- (kvm_cpu_has_interrupt(vcpu) ||
+- kvm_guest_apic_has_interrupt(vcpu)))
++ if (kvm_arch_interrupt_allowed(vcpu) && kvm_cpu_has_interrupt(vcpu))
+ return true;
+
+ if (kvm_hv_has_stimer_pending(vcpu))
+--
+2.53.0
+
selftests-bpf-check-for-timeout-in-perf_link-test.patch
drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
+batman-adv-tt-prevent-tvlv-entry-number-overflow.patch
+kvm-nvmx-add-a-helper-to-get-highest-pending-from-po.patch
+kvm-nvmx-check-for-pending-posted-interrupts-when-lo.patch
+kvm-nvmx-fold-requested-virtual-interrupt-check-into.patch
--- /dev/null
+From 851deb0057ba0b1d96a60ebecc260e2696b3a840 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:58:44 +0200
+Subject: eventpoll: drop vestigial __ prefix from ep_remove_{file,epi}()
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit 0feaf644f7180c4a91b6b405a881afbfd958f1cf ]
+
+With __ep_remove() gone, the double-underscore on __ep_remove_file()
+and __ep_remove_epi() no longer contrasts with a __-less parent and
+just reads as noise. Rename both to ep_remove_file() and
+ep_remove_epi(). No functional change.
+
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Stable-dep-of: a6dc643c6931 ("eventpoll: fix ep_remove struct eventpoll / struct file UAF")
+Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/eventpoll.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index 3ac8a26c3522f6..dc747f382dd954 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -801,7 +801,7 @@ static void ep_free(struct eventpoll *ep)
+ * Called with &file->f_lock held,
+ * returns with it released
+ */
+-static void __ep_remove_file(struct eventpoll *ep, struct epitem *epi,
++static void ep_remove_file(struct eventpoll *ep, struct epitem *epi,
+ struct file *file)
+ {
+ struct epitems_head *to_free = NULL;
+@@ -825,7 +825,7 @@ static void __ep_remove_file(struct eventpoll *ep, struct epitem *epi,
+ free_ephead(to_free);
+ }
+
+-static bool __ep_remove_epi(struct eventpoll *ep, struct epitem *epi)
++static bool ep_remove_epi(struct eventpoll *ep, struct epitem *epi)
+ {
+ lockdep_assert_held(&ep->mtx);
+
+@@ -871,9 +871,9 @@ static void ep_remove_safe(struct eventpoll *ep, struct epitem *epi)
+ spin_unlock(&file->f_lock);
+ return;
+ }
+- __ep_remove_file(ep, epi, file);
++ ep_remove_file(ep, epi, file);
+
+- if (__ep_remove_epi(ep, epi))
++ if (ep_remove_epi(ep, epi))
+ WARN_ON_ONCE(ep_refcount_dec_and_test(ep));
+ }
+
+@@ -1118,8 +1118,8 @@ void eventpoll_release_file(struct file *file)
+ ep_unregister_pollwait(ep, epi);
+
+ spin_lock(&file->f_lock);
+- __ep_remove_file(ep, epi, file);
+- dispose = __ep_remove_epi(ep, epi);
++ ep_remove_file(ep, epi, file);
++ dispose = ep_remove_epi(ep, epi);
+
+ mutex_unlock(&ep->mtx);
+
+--
+2.53.0
+
--- /dev/null
+From 381447b51758bdc1f73a47bb030a8097d5d41077 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:58:47 +0200
+Subject: eventpoll: fix ep_remove struct eventpoll / struct file UAF
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit a6dc643c69311677c574a0f17a3f4d66a5f3744b ]
+
+ep_remove() (via ep_remove_file()) cleared file->f_ep under
+file->f_lock but then kept using @file inside the critical section
+(is_file_epoll(), hlist_del_rcu() through the head, spin_unlock).
+A concurrent __fput() taking the eventpoll_release() fastpath in
+that window observed the transient NULL, skipped
+eventpoll_release_file() and ran to f_op->release / file_free().
+
+For the epoll-watches-epoll case, f_op->release is
+ep_eventpoll_release() -> ep_clear_and_put() -> ep_free(), which
+kfree()s the watched struct eventpoll. Its embedded ->refs
+hlist_head is exactly where epi->fllink.pprev points, so the
+subsequent hlist_del_rcu()'s "*pprev = next" scribbles into freed
+kmalloc-192 memory.
+
+In addition, struct file is SLAB_TYPESAFE_BY_RCU, so the slot
+backing @file could be recycled by alloc_empty_file() --
+reinitializing f_lock and f_ep -- while ep_remove() is still
+nominally inside that lock. The upshot is an attacker-controllable
+kmem_cache_free() against the wrong slab cache.
+
+Pin @file via epi_fget() at the top of ep_remove() and gate the
+critical section on the pin succeeding. With the pin held @file
+cannot reach refcount zero, which holds __fput() off and
+transitively keeps the watched struct eventpoll alive across the
+hlist_del_rcu() and the f_lock use, closing both UAFs.
+
+If the pin fails @file has already reached refcount zero and its
+__fput() is in flight. Because we bailed before clearing f_ep,
+that path takes the eventpoll_release() slow path into
+eventpoll_release_file() and blocks on ep->mtx until the waiter
+side's ep_clear_and_put() drops it. The bailed epi's share of
+ep->refcount stays intact, so the trailing ep_refcount_dec_and_test()
+in ep_clear_and_put() cannot free the eventpoll out from under
+eventpoll_release_file(); the orphaned epi is then cleaned up
+there.
+
+A successful pin also proves we are not racing
+eventpoll_release_file() on this epi, so drop the now-redundant
+re-check of epi->dying under f_lock. The cheap lockless
+READ_ONCE(epi->dying) fast-path bailout stays.
+
+Fixes: 58c9b016e128 ("epoll: use refcount to reduce ep_mutex contention")
+Reported-by: Jaeyoung Chung <jjy600901@snu.ac.kr>
+Link: https://patch.msgid.link/20260423-work-epoll-uaf-v1-6-2470f9eec0f5@kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/eventpoll.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index 2993b76c21f682..22605fbc12ded5 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -883,22 +883,26 @@ static bool ep_remove_epi(struct eventpoll *ep, struct epitem *epi)
+ */
+ static void ep_remove(struct eventpoll *ep, struct epitem *epi)
+ {
+- struct file *file = epi->ffd.file;
++ struct file *file __free(fput) = NULL;
+
+ lockdep_assert_irqs_enabled();
+ lockdep_assert_held(&ep->mtx);
+
+ ep_unregister_pollwait(ep, epi);
+
+- /* sync with eventpoll_release_file() */
++ /* cheap sync with eventpoll_release_file() */
+ if (unlikely(READ_ONCE(epi->dying)))
+ return;
+
+- spin_lock(&file->f_lock);
+- if (epi->dying) {
+- spin_unlock(&file->f_lock);
++ /*
++ * If we manage to grab a reference it means we're not in
++ * eventpoll_release_file() and aren't going to be.
++ */
++ file = epi_fget(epi);
++ if (!file)
+ return;
+- }
++
++ spin_lock(&file->f_lock);
+ ep_remove_file(ep, epi, file);
+
+ if (ep_remove_epi(ep, epi))
+--
+2.53.0
+
--- /dev/null
+From 51131e558347cdc5cf60f668ec3e6c2a5cfb73f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:58:43 +0200
+Subject: eventpoll: kill __ep_remove()
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit e9e5cd40d7c403e19f21d0f7b8b8ba3a76b58330 ]
+
+Remove the boolean conditional in __ep_remove() and restructure the code
+so the check for racing with eventpoll_release_file() are only done in
+the ep_remove_safe() path where they belong.
+
+Link: https://patch.msgid.link/20260423-work-epoll-uaf-v1-3-2470f9eec0f5@kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Stable-dep-of: a6dc643c6931 ("eventpoll: fix ep_remove struct eventpoll / struct file UAF")
+Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/eventpoll.c | 67 ++++++++++++++++++++++----------------------------
+ 1 file changed, 30 insertions(+), 37 deletions(-)
+
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index 1cba4ae4a076bc..3ac8a26c3522f6 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -797,49 +797,18 @@ static void ep_free(struct eventpoll *ep)
+ kfree_rcu(ep, rcu);
+ }
+
+-static void __ep_remove_file(struct eventpoll *ep, struct epitem *epi, struct file *file);
+-static bool __ep_remove_epi(struct eventpoll *ep, struct epitem *epi);
+-
+-/*
+- * Removes a "struct epitem" from the eventpoll RB tree and deallocates
+- * all the associated resources. Must be called with "mtx" held.
+- * If the dying flag is set, do the removal only if force is true.
+- * This prevents ep_clear_and_put() from dropping all the ep references
+- * while running concurrently with eventpoll_release_file().
+- * Returns true if the eventpoll can be disposed.
+- */
+-static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
+-{
+- struct file *file = epi->ffd.file;
+-
+- lockdep_assert_irqs_enabled();
+-
+- /*
+- * Removes poll wait queue hooks.
+- */
+- ep_unregister_pollwait(ep, epi);
+-
+- /* Remove the current item from the list of epoll hooks */
+- spin_lock(&file->f_lock);
+- if (epi->dying && !force) {
+- spin_unlock(&file->f_lock);
+- return false;
+- }
+-
+- __ep_remove_file(ep, epi, file);
+- return __ep_remove_epi(ep, epi);
+-}
+-
+ /*
+ * Called with &file->f_lock held,
+ * returns with it released
+ */
+-static void __ep_remove_file(struct eventpoll *ep, struct epitem *epi, struct file *file)
++static void __ep_remove_file(struct eventpoll *ep, struct epitem *epi,
++ struct file *file)
+ {
+ struct epitems_head *to_free = NULL;
+ struct hlist_head *head = file->f_ep;
+
+ lockdep_assert_held(&ep->mtx);
++ lockdep_assert_held(&file->f_lock);
+
+ if (hlist_is_singular_node(&epi->fllink, head)) {
+ /* See eventpoll_release() for details. */
+@@ -886,7 +855,25 @@ static bool __ep_remove_epi(struct eventpoll *ep, struct epitem *epi)
+ */
+ static void ep_remove_safe(struct eventpoll *ep, struct epitem *epi)
+ {
+- if (__ep_remove(ep, epi, false))
++ struct file *file = epi->ffd.file;
++
++ lockdep_assert_irqs_enabled();
++ lockdep_assert_held(&ep->mtx);
++
++ ep_unregister_pollwait(ep, epi);
++
++ /* sync with eventpoll_release_file() */
++ if (unlikely(READ_ONCE(epi->dying)))
++ return;
++
++ spin_lock(&file->f_lock);
++ if (epi->dying) {
++ spin_unlock(&file->f_lock);
++ return;
++ }
++ __ep_remove_file(ep, epi, file);
++
++ if (__ep_remove_epi(ep, epi))
+ WARN_ON_ONCE(ep_refcount_dec_and_test(ep));
+ }
+
+@@ -1118,7 +1105,7 @@ void eventpoll_release_file(struct file *file)
+ spin_lock(&file->f_lock);
+ if (file->f_ep && file->f_ep->first) {
+ epi = hlist_entry(file->f_ep->first, struct epitem, fllink);
+- epi->dying = true;
++ WRITE_ONCE(epi->dying, true);
+ spin_unlock(&file->f_lock);
+
+ /*
+@@ -1127,7 +1114,13 @@ void eventpoll_release_file(struct file *file)
+ */
+ ep = epi->ep;
+ mutex_lock(&ep->mtx);
+- dispose = __ep_remove(ep, epi, true);
++
++ ep_unregister_pollwait(ep, epi);
++
++ spin_lock(&file->f_lock);
++ __ep_remove_file(ep, epi, file);
++ dispose = __ep_remove_epi(ep, epi);
++
+ mutex_unlock(&ep->mtx);
+
+ if (dispose && ep_refcount_dec_and_test(ep))
+--
+2.53.0
+
--- /dev/null
+From 9e9cee9f453d44ebed0952904ef11a4473962a93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:58:46 +0200
+Subject: eventpoll: move epi_fget() up
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit 86e87059e6d1fd5115a31949726450ed03c1073b ]
+
+We'll need it when removing files so move it up. No functional change.
+
+Link: https://patch.msgid.link/20260423-work-epoll-uaf-v1-5-2470f9eec0f5@kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Stable-dep-of: a6dc643c6931 ("eventpoll: fix ep_remove struct eventpoll / struct file UAF")
+[file_ref_get(&file->f_ref) from original commit left as
+ atomic_long_inc_not_zero(&file->f_count) due to v6.12.y missing commit
+ 90ee6ed776c0 ("fs: port files to file_ref") and its dependent commit
+ 08ef26ea9ab3 ("fs: add file_ref")]
+Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/eventpoll.c | 56 +++++++++++++++++++++++++-------------------------
+ 1 file changed, 28 insertions(+), 28 deletions(-)
+
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index 27280ba4f3d5be..2993b76c21f682 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -797,6 +797,34 @@ static void ep_free(struct eventpoll *ep)
+ kfree_rcu(ep, rcu);
+ }
+
++/*
++ * The ffd.file pointer may be in the process of being torn down due to
++ * being closed, but we may not have finished eventpoll_release() yet.
++ *
++ * Normally, even with the atomic_long_inc_not_zero, the file may have
++ * been free'd and then gotten re-allocated to something else (since
++ * files are not RCU-delayed, they are SLAB_TYPESAFE_BY_RCU).
++ *
++ * But for epoll, users hold the ep->mtx mutex, and as such any file in
++ * the process of being free'd will block in eventpoll_release_file()
++ * and thus the underlying file allocation will not be free'd, and the
++ * file re-use cannot happen.
++ *
++ * For the same reason we can avoid a rcu_read_lock() around the
++ * operation - 'ffd.file' cannot go away even if the refcount has
++ * reached zero (but we must still not call out to ->poll() functions
++ * etc).
++ */
++static struct file *epi_fget(const struct epitem *epi)
++{
++ struct file *file;
++
++ file = epi->ffd.file;
++ if (!atomic_long_inc_not_zero(&file->f_count))
++ file = NULL;
++ return file;
++}
++
+ /*
+ * Called with &file->f_lock held,
+ * returns with it released
+@@ -989,34 +1017,6 @@ static __poll_t __ep_eventpoll_poll(struct file *file, poll_table *wait, int dep
+ return res;
+ }
+
+-/*
+- * The ffd.file pointer may be in the process of being torn down due to
+- * being closed, but we may not have finished eventpoll_release() yet.
+- *
+- * Normally, even with the atomic_long_inc_not_zero, the file may have
+- * been free'd and then gotten re-allocated to something else (since
+- * files are not RCU-delayed, they are SLAB_TYPESAFE_BY_RCU).
+- *
+- * But for epoll, users hold the ep->mtx mutex, and as such any file in
+- * the process of being free'd will block in eventpoll_release_file()
+- * and thus the underlying file allocation will not be free'd, and the
+- * file re-use cannot happen.
+- *
+- * For the same reason we can avoid a rcu_read_lock() around the
+- * operation - 'ffd.file' cannot go away even if the refcount has
+- * reached zero (but we must still not call out to ->poll() functions
+- * etc).
+- */
+-static struct file *epi_fget(const struct epitem *epi)
+-{
+- struct file *file;
+-
+- file = epi->ffd.file;
+- if (!atomic_long_inc_not_zero(&file->f_count))
+- file = NULL;
+- return file;
+-}
+-
+ /*
+ * Differs from ep_eventpoll_poll() in that internal callers already have
+ * the ep->mtx so we need to start from depth=1, such that mutex_lock_nested()
+--
+2.53.0
+
--- /dev/null
+From 2ed0844a1214b3fa930312190f1ebb882dd4dca3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:58:45 +0200
+Subject: eventpoll: rename ep_remove_safe() back to ep_remove()
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit 0bade234723e40e4937be912e105785d6a51464e ]
+
+The current name is just confusing and doesn't clarify anything.
+
+Link: https://patch.msgid.link/20260423-work-epoll-uaf-v1-4-2470f9eec0f5@kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Stable-dep-of: a6dc643c6931 ("eventpoll: fix ep_remove struct eventpoll / struct file UAF")
+Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/eventpoll.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index dc747f382dd954..27280ba4f3d5be 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -853,7 +853,7 @@ static bool ep_remove_epi(struct eventpoll *ep, struct epitem *epi)
+ /*
+ * ep_remove variant for callers owing an additional reference to the ep
+ */
+-static void ep_remove_safe(struct eventpoll *ep, struct epitem *epi)
++static void ep_remove(struct eventpoll *ep, struct epitem *epi)
+ {
+ struct file *file = epi->ffd.file;
+
+@@ -900,7 +900,7 @@ static void ep_clear_and_put(struct eventpoll *ep)
+
+ /*
+ * Walks through the whole tree and try to free each "struct epitem".
+- * Note that ep_remove_safe() will not remove the epitem in case of a
++ * Note that ep_remove() will not remove the epitem in case of a
+ * racing eventpoll_release_file(); the latter will do the removal.
+ * At this point we are sure no poll callbacks will be lingering around.
+ * Since we still own a reference to the eventpoll struct, the loop can't
+@@ -909,7 +909,7 @@ static void ep_clear_and_put(struct eventpoll *ep)
+ for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = next) {
+ next = rb_next(rbp);
+ epi = rb_entry(rbp, struct epitem, rbn);
+- ep_remove_safe(ep, epi);
++ ep_remove(ep, epi);
+ cond_resched();
+ }
+
+@@ -1602,21 +1602,21 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
+ mutex_unlock(&tep->mtx);
+
+ /*
+- * ep_remove_safe() calls in the later error paths can't lead to
++ * ep_remove() calls in the later error paths can't lead to
+ * ep_free() as the ep file itself still holds an ep reference.
+ */
+ ep_get(ep);
+
+ /* now check if we've created too many backpaths */
+ if (unlikely(full_check && reverse_path_check())) {
+- ep_remove_safe(ep, epi);
++ ep_remove(ep, epi);
+ return -EINVAL;
+ }
+
+ if (epi->event.events & EPOLLWAKEUP) {
+ error = ep_create_wakeup_source(epi);
+ if (error) {
+- ep_remove_safe(ep, epi);
++ ep_remove(ep, epi);
+ return error;
+ }
+ }
+@@ -1640,7 +1640,7 @@ static int ep_insert(struct eventpoll *ep, const struct epoll_event *event,
+ * high memory pressure.
+ */
+ if (unlikely(!epq.epi)) {
+- ep_remove_safe(ep, epi);
++ ep_remove(ep, epi);
+ return -ENOMEM;
+ }
+
+@@ -2329,7 +2329,7 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds,
+ * The eventpoll itself is still alive: the refcount
+ * can't go to zero here.
+ */
+- ep_remove_safe(ep, epi);
++ ep_remove(ep, epi);
+ error = 0;
+ } else {
+ error = -ENOENT;
+--
+2.53.0
+
--- /dev/null
+From 94d7e05595a78e48b1e0b4c8341c2887bf3d2e74 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:58:42 +0200
+Subject: eventpoll: split __ep_remove()
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit 0f7bdfd413000985de09fc39eb9efa1e091a3ce0 ]
+
+Split __ep_remove() to delineate file removal from epoll item removal.
+
+Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
+Link: https://patch.msgid.link/20260423-work-epoll-uaf-v1-2-2470f9eec0f5@kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Stable-dep-of: a6dc643c6931 ("eventpoll: fix ep_remove struct eventpoll / struct file UAF")
+Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/eventpoll.c | 27 +++++++++++++++++++++++----
+ 1 file changed, 23 insertions(+), 4 deletions(-)
+
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index 8f9dc2f4891ff5..1cba4ae4a076bc 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -797,6 +797,9 @@ static void ep_free(struct eventpoll *ep)
+ kfree_rcu(ep, rcu);
+ }
+
++static void __ep_remove_file(struct eventpoll *ep, struct epitem *epi, struct file *file);
++static bool __ep_remove_epi(struct eventpoll *ep, struct epitem *epi);
++
+ /*
+ * Removes a "struct epitem" from the eventpoll RB tree and deallocates
+ * all the associated resources. Must be called with "mtx" held.
+@@ -808,8 +811,6 @@ static void ep_free(struct eventpoll *ep)
+ static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
+ {
+ struct file *file = epi->ffd.file;
+- struct epitems_head *to_free;
+- struct hlist_head *head;
+
+ lockdep_assert_irqs_enabled();
+
+@@ -825,8 +826,21 @@ static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
+ return false;
+ }
+
+- to_free = NULL;
+- head = file->f_ep;
++ __ep_remove_file(ep, epi, file);
++ return __ep_remove_epi(ep, epi);
++}
++
++/*
++ * Called with &file->f_lock held,
++ * returns with it released
++ */
++static void __ep_remove_file(struct eventpoll *ep, struct epitem *epi, struct file *file)
++{
++ struct epitems_head *to_free = NULL;
++ struct hlist_head *head = file->f_ep;
++
++ lockdep_assert_held(&ep->mtx);
++
+ if (hlist_is_singular_node(&epi->fllink, head)) {
+ /* See eventpoll_release() for details. */
+ WRITE_ONCE(file->f_ep, NULL);
+@@ -840,6 +854,11 @@ static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
+ hlist_del_rcu(&epi->fllink);
+ spin_unlock(&file->f_lock);
+ free_ephead(to_free);
++}
++
++static bool __ep_remove_epi(struct eventpoll *ep, struct epitem *epi)
++{
++ lockdep_assert_held(&ep->mtx);
+
+ rb_erase_cached(&epi->rbn, &ep->rbr);
+
+--
+2.53.0
+
--- /dev/null
+From 0465405e6dd7594206d3acdf685aecefde95ddd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:58:41 +0200
+Subject: eventpoll: use hlist_is_singular_node() in __ep_remove()
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit 3d9fd0abc94d8cd430cc7cd7d37ce5e5aae2cd2b ]
+
+Replace the open-coded "epi is the only entry in file->f_ep" check
+with hlist_is_singular_node(). Same semantics, and the helper avoids
+the head-cacheline access in the common false case.
+
+Link: https://patch.msgid.link/20260423-work-epoll-uaf-v1-1-2470f9eec0f5@kernel.org
+Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
+Stable-dep-of: a6dc643c6931 ("eventpoll: fix ep_remove struct eventpoll / struct file UAF")
+Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/eventpoll.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/eventpoll.c b/fs/eventpoll.c
+index a860cb54658a3b..8f9dc2f4891ff5 100644
+--- a/fs/eventpoll.c
++++ b/fs/eventpoll.c
+@@ -827,7 +827,7 @@ static bool __ep_remove(struct eventpoll *ep, struct epitem *epi, bool force)
+
+ to_free = NULL;
+ head = file->f_ep;
+- if (head->first == &epi->fllink && !epi->fllink.next) {
++ if (hlist_is_singular_node(&epi->fllink, head)) {
+ /* See eventpoll_release() for details. */
+ WRITE_ONCE(file->f_ep, NULL);
+ if (!is_file_epoll(file)) {
+--
+2.53.0
+
--- /dev/null
+From b783059f8941aeff714a79e69cb05b1e663b6da1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 17:34:43 +0300
+Subject: iio: light: bh1780: fix PM runtime leak on error path
+
+From: Antoniu Miclaus <antoniu.miclaus@analog.com>
+
+commit dd72e6c3cdea05cad24e99710939086f7a113fb5 upstream.
+
+Move pm_runtime_put_autosuspend() before the error check to ensure
+the PM runtime reference count is always decremented after
+pm_runtime_get_sync(), regardless of whether the read operation
+succeeds or fails.
+
+Fixes: 1f0477f18306 ("iio: light: new driver for the ROHM BH1780")
+Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
+Reviewed-by: Linus Walleij <linusw@kernel.org>
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+[ moved both pm_runtime_mark_last_busy() and pm_runtime_put_autosuspend() before the error check instead of just pm_runtime_put_autosuspend() ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Elizaveta Tereshkina <etereshkina@astralinux.ru>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iio/light/bh1780.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/iio/light/bh1780.c b/drivers/iio/light/bh1780.c
+index 475f44954f6110..f478f12640d536 100644
+--- a/drivers/iio/light/bh1780.c
++++ b/drivers/iio/light/bh1780.c
+@@ -109,10 +109,10 @@ static int bh1780_read_raw(struct iio_dev *indio_dev,
+ case IIO_LIGHT:
+ pm_runtime_get_sync(&bh1780->client->dev);
+ value = bh1780_read_word(bh1780, BH1780_REG_DLOW);
+- if (value < 0)
+- return value;
+ pm_runtime_mark_last_busy(&bh1780->client->dev);
+ pm_runtime_put_autosuspend(&bh1780->client->dev);
++ if (value < 0)
++ return value;
+ *val = value;
+
+ return IIO_VAL_INT;
+--
+2.53.0
+
--- /dev/null
+From 0932116d93c9eb0cc6462922ddc0dc47e69a07e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 17:20:12 +0200
+Subject: net: Drop the lock in skb_may_tx_timestamp()
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 983512f3a87fd8dc4c94dfa6b596b6e57df5aad7 ]
+
+skb_may_tx_timestamp() may acquire sock::sk_callback_lock. The lock must
+not be taken in IRQ context, only softirq is okay. A few drivers receive
+the timestamp via a dedicated interrupt and complete the TX timestamp
+from that handler. This will lead to a deadlock if the lock is already
+write-locked on the same CPU.
+
+Taking the lock can be avoided. The socket (pointed by the skb) will
+remain valid until the skb is released. The ->sk_socket and ->file
+member will be set to NULL once the user closes the socket which may
+happen before the timestamp arrives.
+If we happen to observe the pointer while the socket is closing but
+before the pointer is set to NULL then we may use it because both
+pointer (and the file's cred member) are RCU freed.
+
+Drop the lock. Use READ_ONCE() to obtain the individual pointer. Add a
+matching WRITE_ONCE() where the pointer are cleared.
+
+Link: https://lore.kernel.org/all/20260205145104.iWinkXHv@linutronix.de
+Fixes: b245be1f4db1a ("net-timestamp: no-payload only sysctl")
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://patch.msgid.link/20260220183858.N4ERjFW6@linutronix.de
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+[adapted sk_set_socket() in include/net/sock.h to fix the conflict from
+ not having commit 5d6b58c932ec ("net: lockless sock_i_ino()") and the
+ additional previous changes required by it.
+ It comes down to just now having the lines of
+ if (sock) {
+ WRITE_ONCE(sk->sk_uid, SOCK_INODE(sock)->i_uid);
+ WRITE_ONCE(sk->sk_ino, SOCK_INODE(sock)->i_ino);
+ }
+ below the changed line.
+ I've tested this on a device running an nfs-root and did some
+ additional network stress-testing.]
+Signed-off-by: Heiko Stuebner <heiko.stuebner@cherry.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/sock.h | 2 +-
+ net/core/skbuff.c | 23 ++++++++++++++++++-----
+ net/socket.c | 2 +-
+ 3 files changed, 20 insertions(+), 7 deletions(-)
+
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 0d77a87929f938..dffbaaa7fe493d 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -2040,7 +2040,7 @@ static inline int sk_rx_queue_get(const struct sock *sk)
+
+ static inline void sk_set_socket(struct sock *sk, struct socket *sock)
+ {
+- sk->sk_socket = sock;
++ WRITE_ONCE(sk->sk_socket, sock);
+ }
+
+ static inline wait_queue_head_t *sk_sleep(struct sock *sk)
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 4be699bd3a17f7..fede3aa3ddbc10 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -5525,15 +5525,28 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
+
+ static bool skb_may_tx_timestamp(struct sock *sk, bool tsonly)
+ {
+- bool ret;
++ struct socket *sock;
++ struct file *file;
++ bool ret = false;
+
+ if (likely(READ_ONCE(sysctl_tstamp_allow_data) || tsonly))
+ return true;
+
+- read_lock_bh(&sk->sk_callback_lock);
+- ret = sk->sk_socket && sk->sk_socket->file &&
+- file_ns_capable(sk->sk_socket->file, &init_user_ns, CAP_NET_RAW);
+- read_unlock_bh(&sk->sk_callback_lock);
++ /* The sk pointer remains valid as long as the skb is. The sk_socket and
++ * file pointer may become NULL if the socket is closed. Both structures
++ * (including file->cred) are RCU freed which means they can be accessed
++ * within a RCU read section.
++ */
++ rcu_read_lock();
++ sock = READ_ONCE(sk->sk_socket);
++ if (!sock)
++ goto out;
++ file = READ_ONCE(sock->file);
++ if (!file)
++ goto out;
++ ret = file_ns_capable(file, &init_user_ns, CAP_NET_RAW);
++out:
++ rcu_read_unlock();
+ return ret;
+ }
+
+diff --git a/net/socket.c b/net/socket.c
+index 5c5dd9f6605a94..723bc3a1ba5cdd 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -652,7 +652,7 @@ static void __sock_release(struct socket *sock, struct inode *inode)
+ iput(SOCK_INODE(sock));
+ return;
+ }
+- sock->file = NULL;
++ WRITE_ONCE(sock->file, NULL);
+ }
+
+ /**
+--
+2.53.0
+
drm-xe-display-fix-oops-in-suspend-shutdown-without-.patch
drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
+eventpoll-use-hlist_is_singular_node-in-__ep_remove.patch
+eventpoll-split-__ep_remove.patch
+eventpoll-kill-__ep_remove.patch
+eventpoll-drop-vestigial-__-prefix-from-ep_remove_-f.patch
+eventpoll-rename-ep_remove_safe-back-to-ep_remove.patch
+eventpoll-move-epi_fget-up.patch
+eventpoll-fix-ep_remove-struct-eventpoll-struct-file.patch
+iio-light-bh1780-fix-pm-runtime-leak-on-error-path.patch
+net-drop-the-lock-in-skb_may_tx_timestamp.patch
--- /dev/null
+From 1b2939af68d968ba49ed30d70caa6069408ed018 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 20:16:39 +0200
+Subject: batman-adv: tt: prevent TVLV entry number overflow
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 99d9958fa10fb684b2a8e2c48a8d704122721420 upstream.
+
+The helpers to prepare the buffers for the local and global TT based
+replies are trying to sum up all TT entries which can be found for each
+VLAN. In theory, this sum can be too big for an u16 and therefore overflow.
+A too small buffer would then be allocated for the TVLV.
+
+The too small buffer will be handled gracefully by
+batadv_tt_tvlv_generate() and is not causing a buffer overflow - just a
+truncated reply. But this overflow shouldn't have happened in the first and
+the too small buffer should never have been allocated when an overflow was
+detected.
+
+Cc: stable@kernel.org
+Fixes: 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/batman-adv/translation-table.c | 20 +++++++++++++++++---
+ 1 file changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index 4045ddefc29b47..7041cd69e20070 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -850,11 +850,18 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
+ u16 total_entries = 0;
+ u8 *tt_change_ptr;
+ int vlan_entries;
++ u16 sum_entries;
+
+ spin_lock_bh(&orig_node->vlan_list_lock);
+ hlist_for_each_entry(vlan, &orig_node->vlan_list, list) {
+ vlan_entries = atomic_read(&vlan->tt.num_entries);
+- total_entries += vlan_entries;
++
++ if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
++ *tt_len = 0;
++ goto out;
++ }
++
++ total_entries = sum_entries;
+ num_vlan++;
+ }
+
+@@ -941,15 +948,22 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+ struct batadv_softif_vlan *vlan;
+ size_t change_offset;
+ u16 num_vlan = 0;
+- u16 vlan_entries = 0;
+ u16 total_entries = 0;
+ u16 tvlv_len;
+ u8 *tt_change_ptr;
++ int vlan_entries;
++ u16 sum_entries;
+
+ spin_lock_bh(&bat_priv->softif_vlan_list_lock);
+ hlist_for_each_entry(vlan, &bat_priv->softif_vlan_list, list) {
+ vlan_entries = atomic_read(&vlan->tt.num_entries);
+- total_entries += vlan_entries;
++
++ if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
++ tvlv_len = 0;
++ goto out;
++ }
++
++ total_entries = sum_entries;
+ num_vlan++;
+ }
+
+--
+2.53.0
+
ip6_vti-set-netns_immutable-on-the-fallback-device.patch
drm-v3d-store-the-active-job-inside-the-queue-s-stat.patch
drm-v3d-skip-csd-when-it-has-zeroed-workgroups.patch
+batman-adv-tt-prevent-tvlv-entry-number-overflow.patch
--- /dev/null
+From 56dae8562b2e5c209ec70fd26768e059905c1e51 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jun 2026 16:47:50 -0400
+Subject: lockd: fix TEST handling when not all permissions are available.
+
+From: NeilBrown <neil@brown.name>
+
+[ Upstream commit 0b474240327cebeff08ad429e8ed3cfc6c8ee816 ]
+
+The F_GETLK fcntl can work with either read access or write access or
+both. It can query F_RDLCK and F_WRLCK locks in either case.
+
+However lockd currently treats F_GETLK similar to F_SETLK in that read
+access is required to query an F_RDLCK lock and write access is required
+to query a F_WRLCK lock.
+
+This is wrong and can cause problems - e.g. when qemu accesses a
+read-only (e.g. iso) filesystem image over NFS (though why it queries
+if it can get a write lock - I don't know. But it does, and this works
+with local filesystems).
+
+So we need TEST requests to be handled differently. To do this:
+
+- change nlm_do_fopen() to accept O_RDWR as a mode and in that case
+ succeed if either a O_RDONLY or O_WRONLY file can be opened.
+- change nlm_lookup_file() to accept a mode argument from caller,
+ instead of deducing base on lock time, and pass that on to nlm_do_fopen()
+- change nlm4svc_retrieve_args() and nlmsvc_retrieve_args() to detect
+ TEST requests and pass O_RDWR as a mode to nlm_lookup_file, passing
+ the same mode as before for other requests. Also set
+ lock->fl.c.flc_file to whichever file is available for TEST requests.
+- change nlmsvc_testlock() to also not calculate the mode, but to use
+ whatever was stored in lock->fl.c.flc_file.
+
+This behaviour of lockd - requesting O_WRONLY access to TEST for
+exclusive locks - has been present at least since git history began.
+However it was hidden until recently because knfsd ignored the access
+requested by lockd and required only READ access for all locking
+requests (unless the underlying filesystem provided an f_op->open
+function which checked access permissions).
+
+The commit mentioned in Fixes: below changed nfsd_permission() to NOT
+override the access request for LOCK requests and this exposed the bug
+that we are now fixing.
+
+Note that there is another issue that this patch does not address.
+The flock(.., LOCK_EX) call is permitted on a read-only file descriptor.
+Linux NFS maps this to NLM locking as whole-file byte-range locks.
+nfsd will see this as though it were fcntl( F_SETLK (F_WRLCK)) and will
+now require write access, which it might not be able to get.
+It is not clear if this is a problem in practice, or what the best
+solution might be. So no attempt is made to address it.
+
+Reported-by: Tj <tj.iam.tj@proton.me>
+Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1128861
+Fixes: 4cc9b9f2bf4d ("nfsd: refine and rename NFSD_MAY_LOCK")
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: NeilBrown <neil@brown.name>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/lockd/svc4proc.c | 13 ++++++++++---
+ fs/lockd/svclock.c | 4 +---
+ fs/lockd/svcproc.c | 15 ++++++++++++---
+ fs/lockd/svcsubs.c | 35 +++++++++++++++++++++++++----------
+ include/linux/lockd/lockd.h | 2 +-
+ 5 files changed, 49 insertions(+), 20 deletions(-)
+
+diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
+index 4b6f18d977343d..75e020a8bfd072 100644
+--- a/fs/lockd/svc4proc.c
++++ b/fs/lockd/svc4proc.c
+@@ -26,6 +26,8 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
+ struct nlm_host *host = NULL;
+ struct nlm_file *file = NULL;
+ struct nlm_lock *lock = &argp->lock;
++ bool is_test = (rqstp->rq_proc == NLMPROC_TEST ||
++ rqstp->rq_proc == NLMPROC_TEST_MSG);
+ __be32 error = 0;
+
+ /* nfsd callbacks must have been installed for this procedure */
+@@ -46,15 +48,20 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
+ if (filp != NULL) {
+ int mode = lock_to_openmode(&lock->fl);
+
++ if (is_test)
++ mode = O_RDWR;
++
+ lock->fl.c.flc_flags = FL_POSIX;
+
+- error = nlm_lookup_file(rqstp, &file, lock);
++ error = nlm_lookup_file(rqstp, &file, lock, mode);
+ if (error)
+ goto no_locks;
+ *filp = file;
+-
+ /* Set up the missing parts of the file_lock structure */
+- lock->fl.c.flc_file = file->f_file[mode];
++ if (is_test)
++ lock->fl.c.flc_file = nlmsvc_file_file(file);
++ else
++ lock->fl.c.flc_file = file->f_file[mode];
+ lock->fl.c.flc_pid = current->tgid;
+ lock->fl.fl_start = (loff_t)lock->lock_start;
+ lock->fl.fl_end = lock->lock_len ?
+diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
+index abc65dc79f8543..382bf0d93ed1c1 100644
+--- a/fs/lockd/svclock.c
++++ b/fs/lockd/svclock.c
+@@ -619,7 +619,6 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
+ struct nlm_lock *conflock)
+ {
+ int error;
+- int mode;
+ __be32 ret;
+
+ dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n",
+@@ -637,14 +636,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
+ goto out;
+ }
+
+- mode = lock_to_openmode(&lock->fl);
+ locks_init_lock(&conflock->fl);
+ /* vfs_test_lock only uses start, end, and owner, but tests flc_file */
+ conflock->fl.c.flc_file = lock->fl.c.flc_file;
+ conflock->fl.fl_start = lock->fl.fl_start;
+ conflock->fl.fl_end = lock->fl.fl_end;
+ conflock->fl.c.flc_owner = lock->fl.c.flc_owner;
+- error = vfs_test_lock(file->f_file[mode], &conflock->fl);
++ error = vfs_test_lock(lock->fl.c.flc_file, &conflock->fl);
+ if (error) {
+ ret = nlm_lck_denied_nolocks;
+ goto out;
+diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
+index 5817ef272332d9..d98e8d684376b7 100644
+--- a/fs/lockd/svcproc.c
++++ b/fs/lockd/svcproc.c
+@@ -55,6 +55,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
+ struct nlm_host *host = NULL;
+ struct nlm_file *file = NULL;
+ struct nlm_lock *lock = &argp->lock;
++ bool is_test = (rqstp->rq_proc == NLMPROC_TEST ||
++ rqstp->rq_proc == NLMPROC_TEST_MSG);
+ int mode;
+ __be32 error = 0;
+
+@@ -70,15 +72,22 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
+
+ /* Obtain file pointer. Not used by FREE_ALL call. */
+ if (filp != NULL) {
+- error = cast_status(nlm_lookup_file(rqstp, &file, lock));
++ mode = lock_to_openmode(&lock->fl);
++
++ if (is_test)
++ mode = O_RDWR;
++
++ error = cast_status(nlm_lookup_file(rqstp, &file, lock, mode));
+ if (error != 0)
+ goto no_locks;
+ *filp = file;
+
+ /* Set up the missing parts of the file_lock structure */
+- mode = lock_to_openmode(&lock->fl);
+ lock->fl.c.flc_flags = FL_POSIX;
+- lock->fl.c.flc_file = file->f_file[mode];
++ if (is_test)
++ lock->fl.c.flc_file = nlmsvc_file_file(file);
++ else
++ lock->fl.c.flc_file = file->f_file[mode];
+ lock->fl.c.flc_pid = current->tgid;
+ lock->fl.fl_lmops = &nlmsvc_lock_operations;
+ nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid);
+diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
+index dd0214dcb69503..b83e6ecd5be34f 100644
+--- a/fs/lockd/svcsubs.c
++++ b/fs/lockd/svcsubs.c
+@@ -82,18 +82,35 @@ int lock_to_openmode(struct file_lock *lock)
+ *
+ * We have to make sure we have the right credential to open
+ * the file.
++ *
++ * mode can be O_RDONLY(0), O_WRONLY(1) or O_RDWR(2). The latter
++ * means success can be achieved with EITHER O_RDONLY or O_WRONLY.
++ * It does NOT mean both read and write are required.
+ */
+ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
+ struct nlm_file *file, int mode)
+ {
+- struct file **fp = &file->f_file[mode];
+- __be32 nfserr;
++ __be32 nfserr = nlm_lck_denied_nolocks;
++ __be32 deferred = 0;
++ struct file **fp;
++ int m;
+
+- if (*fp)
+- return 0;
+- nfserr = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, mode);
+- if (nfserr)
+- dprintk("lockd: open failed (error %d)\n", nfserr);
++ for (m = O_RDONLY ; m <= O_WRONLY ; m++) {
++ if (mode != O_RDWR && mode != m)
++ continue;
++
++ fp = &file->f_file[m];
++ if (*fp)
++ return 0;
++ nfserr = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, m);
++ if (!nfserr)
++ return 0;
++ if (nfserr == nlm_drop_reply)
++ deferred = nfserr;
++ }
++ if (deferred)
++ return deferred;
++ dprintk("lockd: open failed (error %d)\n", ntohl(nfserr));
+ return nfserr;
+ }
+
+@@ -103,17 +120,15 @@ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
+ */
+ __be32
+ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
+- struct nlm_lock *lock)
++ struct nlm_lock *lock, int mode)
+ {
+ struct nlm_file *file;
+ unsigned int hash;
+ __be32 nfserr;
+- int mode;
+
+ nlm_debug_print_fh("nlm_lookup_file", &lock->fh);
+
+ hash = file_hash(&lock->fh);
+- mode = lock_to_openmode(&lock->fl);
+
+ /* Lock file table */
+ mutex_lock(&nlm_file_mutex);
+diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
+index 330e38776bb20d..fe5cdd4d66f484 100644
+--- a/include/linux/lockd/lockd.h
++++ b/include/linux/lockd/lockd.h
+@@ -294,7 +294,7 @@ void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);
+ * File handling for the server personality
+ */
+ __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
+- struct nlm_lock *);
++ struct nlm_lock *, int);
+ void nlm_release_file(struct nlm_file *);
+ void nlmsvc_put_lockowner(struct nlm_lockowner *);
+ void nlmsvc_release_lockowner(struct nlm_lock *);
+--
+2.53.0
+
io_uring-net-avoid-msghdr-on-op_connect-op_bind-asyn.patch
arm64-entry-fix-arm64-specific-rseq-brokenness.patch
+lockd-fix-test-handling-when-not-all-permissions-are.patch