--- /dev/null
+From 9092c214fb76e695a77cc426b15e3a8282c4ebd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 13:51:47 -0300
+Subject: ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit afb2a3a9d8369d18122a0d7cd294eba9a98259c6 ]
+
+byt_cht_es8316_init() enables MCLK before configuring the codec sysclk
+and creating the headset jack. If either of those later steps fails, the
+function returns without disabling MCLK, leaving the clock enabled after
+card registration fails.
+
+Track whether this driver enabled MCLK and disable it on the init error
+paths. Add the matching DAI link exit callback so the same clock enable
+is also balanced when ASoC cleans up a successfully initialized link.
+
+Fixes: a03bdaa565cb ("ASoC: Intel: add machine driver for BYT/CHT + ES8316")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260519-asoc-bytcht-es8316-mclk-leak-v1-1-b4a11cdc2afd@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/bytcht_es8316.c | 29 ++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
+index a258a410dd8dfe..ebb63194c44317 100644
+--- a/sound/soc/intel/boards/bytcht_es8316.c
++++ b/sound/soc/intel/boards/bytcht_es8316.c
+@@ -39,6 +39,7 @@ struct byt_cht_es8316_private {
+ struct gpio_desc *speaker_en_gpio;
+ struct device *codec_dev;
+ bool speaker_en;
++ bool mclk_enabled;
+ };
+
+ enum {
+@@ -169,6 +170,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
+ },
+ };
+
++static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
++{
++ if (!priv->mclk_enabled)
++ return;
++
++ clk_disable_unprepare(priv->mclk);
++ priv->mclk_enabled = false;
++}
++
+ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ {
+ struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
+@@ -225,12 +235,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret)
+ dev_err(card->dev, "unable to enable MCLK\n");
++ else
++ priv->mclk_enabled = true;
+
+ ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(runtime, 0), 0, 19200000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set codec clock %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ ret = snd_soc_card_jack_new(card, "Headset",
+@@ -239,13 +251,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ARRAY_SIZE(byt_cht_es8316_jack_pins));
+ if (ret) {
+ dev_err(card->dev, "jack creation failed %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_soc_component_set_jack(codec, &priv->jack, NULL);
+
+ return 0;
++
++err_disable_mclk:
++ byt_cht_es8316_disable_mclk(priv);
++ return ret;
++}
++
++static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
++{
++ struct snd_soc_card *card = runtime->card;
++ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
++
++ byt_cht_es8316_disable_mclk(priv);
+ }
+
+ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+@@ -359,6 +383,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .init = byt_cht_es8316_init,
++ .exit = byt_cht_es8316_exit,
+ SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
+ },
+ };
+--
+2.53.0
+
--- /dev/null
+From 99097967b8448ea12a6eb9c660d3e25919ada1a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 11:21:39 +0800
+Subject: Bluetooth: 6lowpan: check skb_clone() return value in
+ send_mcast_pkt()
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+[ Upstream commit 3c40d381ce04f9575a5d8b542898183c3b4b38dc ]
+
+The skb_clone() function can return NULL if memory allocation fails.
+send_mcast_pkt() calls skb_clone() without checking the return value, which
+can lead to a NULL pointer dereference in send_pkt() when it dereferences
+skb->data.
+Add a NULL check after skb_clone() and skip the peer if the clone fails.
+
+Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/6lowpan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
+index 9486d66863264f..4ab9a31163b8b9 100644
+--- a/net/bluetooth/6lowpan.c
++++ b/net/bluetooth/6lowpan.c
+@@ -514,6 +514,8 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
+ int ret;
+
+ local_skb = skb_clone(skb, GFP_ATOMIC);
++ if (!local_skb)
++ continue;
+
+ BT_DBG("xmit %s to %pMR type %d IP %pI6c chan %p",
+ netdev->name,
+--
+2.53.0
+
--- /dev/null
+From 6de26b442267ad5e492d04210eda6dc221d170dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 18:51:52 +0800
+Subject: Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit 00e1950716c6ed67d74777b2db286b0fa23b4be9 ]
+
+l2cap_ecred_reconf_rsp() returns early on success without clearing
+chan->ident. Every other L2CAP response handler (l2cap_ecred_conn_rsp,
+l2cap_le_connect_rsp, l2cap_config_rsp) clears chan->ident after a
+successful transaction to prevent the channel from matching subsequent
+responses with the recycled ident value.
+
+A remote attacker that completed a reconfiguration as the peer can
+replay a failure response with the stale ident, causing the kernel to
+match and destroy the already-established channel via
+l2cap_chan_del(chan, ECONNRESET).
+
+Clear chan->ident for all matching channels on success, and harden the
+failure path by using l2cap_chan_hold_unless_zero() consistent with
+other L2CAP handlers (l2cap_le_command_rej, __l2cap_get_chan_by_ident).
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 45e1e8192e3b63..f30624d20bb09c 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6432,14 +6432,20 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("result 0x%4.4x", result);
+
+- if (!result)
++ if (!result) {
++ list_for_each_entry(chan, &conn->chan_l, list) {
++ if (chan->ident == cmd->ident)
++ chan->ident = 0;
++ }
+ return 0;
++ }
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
+ if (chan->ident != cmd->ident)
+ continue;
+
+- l2cap_chan_hold(chan);
++ if (!l2cap_chan_hold_unless_zero(chan))
++ continue;
+ l2cap_chan_lock(chan);
+
+ l2cap_chan_del(chan, ECONNRESET);
+--
+2.53.0
+
--- /dev/null
+From 97edb9709a81e78c204c6860da277bb0d1ca6831 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 May 2026 12:09:42 -0400
+Subject: Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 41c2713b204e6cb6a94587bc6bf6935107df5479 ]
+
+If dcid is received for an already-assigned destination CID the spec
+requires that both channels to be discarded, but calling l2cap_chan_del
+may invalidate the tmp cursor created by list_for_each_entry_safe and
+in fact it is the wrong procedure as the chan->dcid may be assigned
+previously it really needs to be disconnected.
+
+Calling l2cap_chan_clone directly may still lead to l2cap_chan_del so
+instead schedule l2cap_chan_timeout with delay 0 to close the channel
+asynchronously.
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index f30624d20bb09c..89e770f359ef20 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6232,6 +6232,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ cmd_len -= sizeof(*rsp);
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
++ struct l2cap_chan *orig;
+ u16 dcid;
+
+ if (chan->ident != cmd->ident ||
+@@ -6253,8 +6254,10 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
+
++ orig = __l2cap_get_chan_by_dcid(conn, dcid);
++
+ /* Check if dcid is already in use */
+- if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
++ if (dcid && orig) {
+ /* If a device receives a
+ * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
+ * already-assigned Destination CID, then both the
+@@ -6263,10 +6266,24 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ */
+ l2cap_chan_del(chan, ECONNREFUSED);
+ l2cap_chan_unlock(chan);
+- chan = __l2cap_get_chan_by_dcid(conn, dcid);
+- l2cap_chan_lock(chan);
+- l2cap_chan_del(chan, ECONNRESET);
+- l2cap_chan_unlock(chan);
++
++ /* Check that the dcid channel mode is
++ * L2CAP_MODE_EXT_FLOWCTL since this procedure is only
++ * valid for that mode and shouldn't disconnect a dcid
++ * in other modes.
++ */
++ if (orig->mode == L2CAP_MODE_EXT_FLOWCTL) {
++ l2cap_chan_lock(orig);
++ /* Disconnect the original channel as it may be
++ * considered connected since dcid has already
++ * been assigned; don't call l2cap_chan_close
++ * directly since that could lead to
++ * l2cap_chan_del and then removing the channel
++ * from the list while we're iterating over it.
++ */
++ __set_chan_timer(orig, 0);
++ l2cap_chan_unlock(orig);
++ }
+ continue;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 8387223e3a1ab5fa9a207ab58062fb01bcd83491 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 12:21:47 +0000
+Subject: ipv4: free net->ipv4.sysctl_local_reserved_ports after
+ unregister_net_sysctl_table()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 87a1e0fe7776da7ab411be332b4be58ac8840d10 ]
+
+ipv4_sysctl_exit_net() is currently freeing net->ipv4.sysctl_local_reserved_ports
+too soon.
+
+Only after unregister_net_sysctl_table() we can be sure no threads can possibly
+use the sysctls, including /proc/sys/net/ipv4/ip_local_reserved_ports.
+
+Fixes: 122ff243f5f1 ("ipv4: make ip_local_reserved_ports per netns")
+Reported-by: Ji'an Zhou <eilaimemedsnaimel@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260521122147.3584624-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/sysctl_net_ipv4.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 59ba518a85b9c9..56c60af2a32f25 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -1362,10 +1362,10 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net)
+ {
+ struct ctl_table *table;
+
+- kfree(net->ipv4.sysctl_local_reserved_ports);
+ table = net->ipv4.ipv4_hdr->ctl_table_arg;
+ unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
+ kfree(table);
++ kfree(net->ipv4.sysctl_local_reserved_ports);
+ }
+
+ static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
+--
+2.53.0
+
--- /dev/null
+From 7683b3ae63a7c9806a2d9fed11de389935ce74c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 21:10:31 +0530
+Subject: ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress()
+
+From: Rahul Chandelkar <rc@rexion.ai>
+
+[ Upstream commit 9d5e7a46a9f6d8f503b41bfefef70659845f1679 ]
+
+ipv6_rpl_srh_decompress() computes:
+
+ outhdr->hdrlen = (((n + 1) * sizeof(struct in6_addr)) >> 3);
+
+hdrlen is __u8. For n >= 127 the result exceeds 255 and silently
+truncates. With n=127 (cmpri=15, cmpre=15, pad=0, hdrlen=16):
+
+ (128 * 16) >> 3 = 256, truncated to 0 as __u8
+
+The caller in ipv6_rpl_srh_rcv() then places the compressed header
+at buf + ((ohdr->hdrlen + 1) << 3). With hdrlen=0 this is buf + 8,
+but the decompressed region occupies buf[0..2055] (8-byte header
+plus 128 full addresses). The compressed header overlaps the
+decompressed data, and ipv6_rpl_srh_compress() writes into this
+overlap, corrupting the routing header of the forwarded packet.
+
+The existing guard at exthdrs.c:546 checks (n + 1) > 255, which
+prevents n+1 from overflowing unsigned char (the segments_left
+field), but does not prevent the computed hdrlen from overflowing
+__u8. n=127 passes because 128 <= 255, yet hdrlen=256 does not
+fit.
+
+Tighten the bound to (n + 1) > 127. This caps n at 126, giving
+hdrlen = (127 * 16) >> 3 = 254, which fits in __u8. The compressed
+header then lands at buf + ((254 + 1) << 3) = buf + 2040, exactly
+past the decompressed region (buf[0..2039]). No overlap. 127
+segments is well beyond any realistic RPL deployment.
+
+Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
+Signed-off-by: Rahul Chandelkar <rc@rexion.ai>
+Link: https://patch.msgid.link/20260525154031.2290876-1-rc@rexion.ai
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/exthdrs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
+index 924f3d7901f09c..1bef03e2d8fc98 100644
+--- a/net/ipv6/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -544,7 +544,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
+ * unsigned char which is segments_left field. Should not be
+ * higher than that.
+ */
+- if (r || (n + 1) > 255) {
++ if (r || (n + 1) > 127) {
+ kfree_skb(skb);
+ return -1;
+ }
+--
+2.53.0
+
--- /dev/null
+From a0005d47f58bc6f93e86a11077474ff6486760e2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 20:49:56 +0530
+Subject: kernel/fork: validate exit_signal in kernel_clone()
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit 09e7827e785729f391c8d46dc71becce70d296ab ]
+
+When a child process exits, it sends exit_signal to its parent via
+do_notify_parent(). The clone() syscall constructs exit_signal as:
+
+(lower_32_bits(clone_flags) & CSIGNAL)
+
+CSIGNAL is 0xff, so values in the range 65-255 are possible. However,
+valid_signal() only accepts signals up to _NSIG (64 on x86_64). A
+non-zero non-valid exit_signal acts the same as exit_signal == 0: the
+parent process is not signaled when the child terminates.
+
+The syzkaller reproducer triggers this by calling clone() with flags=0x80,
+resulting in exit_signal = (0x80 & CSIGNAL) = 128, which exceeds _NSIG and
+is not a valid signal.
+
+The v1 of this patch added the check only in the clone() syscall handler,
+which is incomplete. kernel_clone() has other callers such as
+sys_ia32_clone() which would remain unprotected. Move the check to
+kernel_clone() to cover all callers.
+
+Since the valid_signal() check is now in kernel_clone() and covers all
+callers including clone3(), the same check in copy_clone_args_from_user()
+becomes redundant and is removed. The higher 32bits check for clone3() is
+kept as it is clone3() specific.
+
+Note that this is a user-visible change: previously, passing an invalid
+exit_signal to clone() was silently accepted. The man page for clone()
+does not document any defined behavior for invalid exit_signal values, so
+rejecting them with -EINVAL is the correct behavior. It is unlikely that
+any sane application relies on passing an invalid exit_signal.
+
+[oleg@redhat.com: the comment above kernel_clone() should be updated]
+ Link: https://lore.kernel.org/abwvgU17W8wuW2-J@redhat.com
+Link: https://lore.kernel.org/20260316151956.563558-1-kartikey406@gmail.com
+Fixes: 3f2c788a1314 ("fork: prevent accidental access to clone3 features")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Reported-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=bbe6b99feefc3a0842de
+Tested-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/all/20260307064202.353405-1-kartikey406@gmail.com/T/ [v1]
+Link: https://lore.kernel.org/all/20260316104536.558108-1-kartikey406@gmail.com/T/ [v2]
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Ben Segall <bsegall@google.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Juri Lelli <juri.lelli@redhat.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: Liam Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
+Cc: Mel Gorman <mgorman@suse.de>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Valentin Schneider <vschneid@redhat.com>
+Cc: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/fork.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 531de2d1b3bfeb..d35416380c6344 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -2535,8 +2535,6 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
+ *
+ * It copies the process, and if successful kick-starts
+ * it and waits for it to finish using the VM if required.
+- *
+- * args->exit_signal is expected to be checked for sanity by the caller.
+ */
+ pid_t kernel_clone(struct kernel_clone_args *args)
+ {
+@@ -2561,6 +2559,9 @@ pid_t kernel_clone(struct kernel_clone_args *args)
+ (args->pidfd == args->parent_tid))
+ return -EINVAL;
+
++ if (!valid_signal(args->exit_signal))
++ return -EINVAL;
++
+ /*
+ * Determine whether and which event to report to ptracer. When
+ * called from kernel_thread or CLONE_UNTRACED is explicitly
+@@ -2737,11 +2738,9 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
+ return -EINVAL;
+
+ /*
+- * Verify that higher 32bits of exit_signal are unset and that
+- * it is a valid signal
++ * Verify that higher 32bits of exit_signal are unset
+ */
+- if (unlikely((args.exit_signal & ~((u64)CSIGNAL)) ||
+- !valid_signal(args.exit_signal)))
++ if (unlikely(args.exit_signal & ~((u64)CSIGNAL)))
+ return -EINVAL;
+
+ if ((args.flags & CLONE_INTO_CGROUP) &&
+--
+2.53.0
+
--- /dev/null
+From 200d1491cb96e9d7785abdab3eda2a5a4047d664 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 07:11:45 -0700
+Subject: net/iucv: fix locking in .getsockopt
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 3589d20a666caf30ad100c960a2de7de390fce88 ]
+
+Mirror iucv_sock_setsockopt() and wrap the whole switch in
+lock_sock()/release_sock(). The pre-existing SO_MSGLIMIT-only lock
+becomes redundant and is removed.
+
+Any AF_IUCV HIPER user can potentially crash the kernel by racing
+recvmsg() with getsockopt(SO_MSGSIZE): the SO_MSGSIZE arm dereferences
+iucv->hs_dev->mtu after iucv_sock_close() (called from the racing
+recvmsg()) has set hs_dev to NULL, producing a NULL pointer dereference
+oops.
+
+Suggested-by: Stanislav Fomichev <sdf.kernel@gmail.com>
+Fixes: 51363b8751a6 ("af_iucv: allow retrieval of maximum message size")
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
+Tested-by: Alexandra Winter <wintera@linux.ibm.com>
+Link: https://patch.msgid.link/20260521-af_iucv_fix2-v1-1-f16b1c510aa9@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/iucv/af_iucv.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index 3d0424e4ae6c9c..8c08f07ce46551 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -1550,7 +1550,7 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+ struct sock *sk = sock->sk;
+ struct iucv_sock *iucv = iucv_sk(sk);
+ unsigned int val;
+- int len;
++ int len, rc;
+
+ if (level != SOL_IUCV)
+ return -ENOPROTOOPT;
+@@ -1563,26 +1563,34 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+
+ len = min_t(unsigned int, len, sizeof(int));
+
++ rc = 0;
++
++ lock_sock(sk);
+ switch (optname) {
+ case SO_IPRMDATA_MSG:
+ val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0;
+ break;
+ case SO_MSGLIMIT:
+- lock_sock(sk);
+ val = (iucv->path != NULL) ? iucv->path->msglim /* connected */
+ : iucv->msglimit; /* default */
+- release_sock(sk);
+ break;
+ case SO_MSGSIZE:
+- if (sk->sk_state == IUCV_OPEN)
+- return -EBADFD;
++ if (sk->sk_state == IUCV_OPEN) {
++ rc = -EBADFD;
++ break;
++ }
+ val = (iucv->hs_dev) ? iucv->hs_dev->mtu -
+ sizeof(struct af_iucv_trans_hdr) - ETH_HLEN :
+ 0x7fffffff;
+ break;
+ default:
+- return -ENOPROTOOPT;
++ rc = -ENOPROTOOPT;
++ break;
+ }
++ release_sock(sk);
++
++ if (rc)
++ return rc;
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+--
+2.53.0
+
--- /dev/null
+From 6a11c8990d2307fb8af17ef7e5915d8464a1986a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:36 +0200
+Subject: net: netlink: don't set nsid on local notifications
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 88b126b39f9757e9debc322d4679239e9af089c7 ]
+
+In most cases, notifications on sockets with NETLINK_LISTEN_ALL_NSID
+do not contain NSID in their ancillary data in case the event is local
+to the listener.
+
+However, when a self-referential NSID is allocated for a namespace,
+every local notification starts sending this ID to the user space.
+
+This is problematic, because the listener cannot tell if those
+notifications are local or not anymore without making extra requests
+to figure out if the provided NSID is local or not. The listener
+can also not figure out the local NSID beforehand as it can be
+allocated at any point in time by other processes, changing the
+structure of the future notifications for everyone.
+
+The value is practically not useful, since it's the namespace's own
+ID that the application has to obtain from other sources in order to
+figure out if it's the same or not. So, for the application it's
+just an extra busy work with no benefits. Moreover, applications
+that do not know about this quirk may be mishandling notifications
+with NSID set as notifications from remote namespaces. This is the
+case for ovs-vswitchd and the iproute2's 'ip monitor' that stops
+printing 'current' and starts printing the nsid number mid-session.
+
+Lack of clear documentation for this behavior is also not helping.
+
+A search though open-source projects doesn't reveal any projects
+that use NETNSA_NSID_NOT_ASSIGNED and rely on metadata to contain
+self-referential NSIDs (expected, since the value is not useful).
+Quite the opposite, as already mentioned, there are few applications
+that rely on NSID to not be present in local events.
+
+Since the value is not useful and actively harmful in some cases,
+let's not report it for local events, making the notifications more
+consistent.
+
+Also adding some blank lines for readability.
+
+Fixes: 59324cf35aba ("netlink: allow to listen "all" netns")
+Reported-by: Matteo Perin <matteo.perin@canonical.com>
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-3-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index e8301a36926275..e091b65c9d2b8c 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1478,10 +1478,14 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++
+ NETLINK_CB(p->skb2).nsid_is_set = false;
+- NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+- if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+- NETLINK_CB(p->skb2).nsid_is_set = true;
++ if (!net_eq(sock_net(sk), p->net)) {
++ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
++ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
++ NETLINK_CB(p->skb2).nsid_is_set = true;
++ }
++
+ val = netlink_broadcast_deliver(sk, p->skb2);
+ if (val < 0) {
+ netlink_overrun(sk);
+--
+2.53.0
+
--- /dev/null
+From e1c9cea05f136a683f0b2f38c317ccfc608060f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:35 +0200
+Subject: net: netlink: fix sending unassigned nsid after assigned one
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 70f8592ee90585272018a725054b6eb2ab7e99ca ]
+
+If the current skb is not shared, it is re-used directly for all the
+sockets subscribed to the notification. If we have remote all-nsid
+socket receiving a message first, then the 'nsid_is_set' will be
+set to 'true'. If the nsid is NOT_ASSIGNED for the next socket in
+the list, the 'nsid_is_set' will remain 'true' and the negative value
+is be delivered to the user space. All subsequent nsid values will be
+delivered as well, since there is no code path that sets the flag
+back to 'false'.
+
+Fix that by always dropping the flag to 'false' first.
+
+Fixes: 7212462fa6fd ("netlink: don't send unknown nsid")
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-2-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 42b7b8574f0994..e8301a36926275 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1478,6 +1478,7 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++ NETLINK_CB(p->skb2).nsid_is_set = false;
+ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+ NETLINK_CB(p->skb2).nsid_is_set = true;
+--
+2.53.0
+
--- /dev/null
+From 6108f7bd8568b3eef23632da7db59c43bbbd6681 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:49 -0400
+Subject: net/sched: Revert "net/sched: Restrict conditions for adding
+ duplicating netems to qdisc tree"
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit eda0b7f203bb166c98d1418b204135bd566ac83b ]
+
+This reverts commit ec8e0e3d7adef940cdf9475e2352c0680189d14e.
+
+The original patch rejects any tree containing two netems when
+either has duplication set, even when they sit on unrelated classes
+of the same classful parent. That broke configurations that have
+worked since netem was introduced.
+
+The re-entrancy problem the original commit was trying to solve is
+handled by later patch using tc_depth flag.
+
+Doing this revert will (re)expose the original bug with multiple
+netem duplication. When this patch is backported make sure
+and get the full series.
+
+Fixes: ec8e0e3d7ade ("net/sched: Restrict conditions for adding duplicating netems to qdisc tree")
+Reported-by: Ji-Soo Chung <jschung2@proton.me>
+Reported-by: Gerlinde <lrGerlinde@mailfence.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220774
+Reported-by: zyc zyc <zyc199902@zohomail.cn>
+Closes: https://lore.kernel.org/all/19adda5a1e2.12410b78222774.9191120410578703463@zohomail.cn/
+Reported-by: Manas Ghandat <ghandatmanas@gmail.com>
+Closes: https://lore.kernel.org/netdev/f69b2c8f-8325-4c2e-a011-6dbc089f30e4@gmail.com/
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-3-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_netem.c | 40 ----------------------------------------
+ 1 file changed, 40 deletions(-)
+
+diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
+index 3e3bced82c564d..3dc6411b0a33c7 100644
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -985,41 +985,6 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+ return 0;
+ }
+
+-static const struct Qdisc_class_ops netem_class_ops;
+-
+-static int check_netem_in_tree(struct Qdisc *sch, bool duplicates,
+- struct netlink_ext_ack *extack)
+-{
+- struct Qdisc *root, *q;
+- unsigned int i;
+-
+- root = qdisc_root_sleeping(sch);
+-
+- if (sch != root && root->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(root))->duplicate)
+- goto err;
+- }
+-
+- if (!qdisc_dev(root))
+- return 0;
+-
+- hash_for_each(qdisc_dev(root)->qdisc_hash, i, q, hash) {
+- if (sch != q && q->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(q))->duplicate)
+- goto err;
+- }
+- }
+-
+- return 0;
+-
+-err:
+- NL_SET_ERR_MSG(extack,
+- "netem: cannot mix duplicating netems with other netems in tree");
+- return -EINVAL;
+-}
+-
+ /* Parse netlink message to set options */
+ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
+@@ -1087,11 +1052,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ q->gap = qopt->gap;
+ q->counter = 0;
+ q->loss = qopt->loss;
+-
+- ret = check_netem_in_tree(sch, qopt->duplicate, extack);
+- if (ret)
+- goto unlock;
+-
+ q->duplicate = qopt->duplicate;
+
+ /* for compatibility with earlier versions.
+--
+2.53.0
+
--- /dev/null
+From c7d3001ab6725bfcfb1afea386cd399ac7757355 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 16:56:39 +0200
+Subject: net/smc: Do not re-initialize smc hashtables
+
+From: Alexandra Winter <wintera@linux.ibm.com>
+
+[ Upstream commit 9e4389b0038781f19f97895186ed941ff8ac1678 ]
+
+INIT_HLIST_HEAD(&smc_v*_hashinfo.ht) are called after smc_nl_init(),
+proto_register() and sock_register(). This can lead to smc_v*_hashinfo.ht
+being reset even though hash entries already exist and are being used,
+possibly resulting in a corrupted list.
+
+Remove unnecessary and dangerous re-initialisation of smc_v*_hashinfo.ht in
+smc_init(); it is implicitly initialised to zero anyhow. Add
+HLIST_HEAD_INIT to the definitions for clarity.
+
+Fixes: f16a7dd5cf27 ("smc: netlink interface for SMC sockets")
+Suggested-by: Halil Pasic <pasic@linux.ibm.com>
+Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
+Acked-by: Halil Pasic <pasic@linux.ibm.com>
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Link: https://patch.msgid.link/20260521145639.10317-1-wintera@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index d64cfd651c7a16..8e1e38bc0df4b0 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -71,10 +71,12 @@ static void smc_set_keepalive(struct sock *sk, int val)
+
+ static struct smc_hashinfo smc_v4_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v4_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ static struct smc_hashinfo smc_v6_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v6_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ int smc_hash_sk(struct sock *sk)
+@@ -2586,8 +2588,6 @@ static int __init smc_init(void)
+ pr_err("%s: sock_register fails with %d\n", __func__, rc);
+ goto out_proto6;
+ }
+- INIT_HLIST_HEAD(&smc_v4_hashinfo.ht);
+- INIT_HLIST_HEAD(&smc_v6_hashinfo.ht);
+
+ rc = smc_ib_register_client();
+ if (rc) {
+--
+2.53.0
+
--- /dev/null
+From 726842b11ce35b013de3eccf92eb12f6977b88d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 22:52:07 +0200
+Subject: netfilter: ebtables: fix OOB read in compat_mtw_from_user
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit f438d1786d657d57790c5d138d6db3fc9fdac392 ]
+
+Luxiao Xu says:
+
+ The function compat_mtw_from_user() converts ebtables extensions from
+ 32-bit user structures to kernel native structures. However, it lacks
+ proper validation of the user-supplied match_size/target_size.
+
+ When certain extensions are processed, the kernel-side translation
+ logic may perform memory accesses based on the extension's expected
+ size. If the user provides a size smaller than what the extension
+ requires, it results in an out-of-bounds read as reported by KASAN.
+
+ This fix introduces a check to ensure match_size is at least as large
+ as the extension's required compatsize. This covers matches, watchers,
+ and targets, while maintaining compatibility with standard targets.
+
+AFAIU this is relevant for matches that need to go though
+match->compat_from_user() call. Those that use plain memcpy with the
+user-provided size are ok because the caller checks that size vs the
+start of the next rule entry offset (which itself is checked vs. total
+size copied from userspace).
+
+The ->compat_from_user() callbacks assume they can read compatsize bytes,
+so they need this extra check.
+
+Based on an earlier patch from Luxiao Xu.
+
+Fixes: 81e675c227ec ("netfilter: ebtables: add CONFIG_COMPAT support")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/netfilter/ebtables.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index 14a06d8b1a2d0e..e86695f1ed95b6 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -1838,6 +1838,25 @@ enum compat_mwt {
+ EBT_COMPAT_TARGET,
+ };
+
++static bool match_size_ok(const struct xt_match *match, unsigned int match_size)
++{
++ u16 csize;
++
++ if (match->matchsize == -1) /* cannot validate ebt_among */
++ return true;
++
++ csize = match->compatsize ? : match->matchsize;
++
++ return match_size >= csize;
++}
++
++static bool tgt_size_ok(const struct xt_target *tgt, unsigned int tgt_size)
++{
++ u16 csize = tgt->compatsize ? : tgt->targetsize;
++
++ return tgt_size >= csize;
++}
++
+ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ enum compat_mwt compat_mwt,
+ struct ebt_entries_buf_state *state,
+@@ -1863,6 +1882,11 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+
++ if (!match_size_ok(match, match_size)) {
++ module_put(match->me);
++ return -EINVAL;
++ }
++
+ off = ebt_compat_match_offset(match, match_size);
+ if (dst) {
+ if (match->compat_from_user)
+@@ -1882,6 +1906,12 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ mwt->u.revision);
+ if (IS_ERR(wt))
+ return PTR_ERR(wt);
++
++ if (!tgt_size_ok(wt, match_size)) {
++ module_put(wt->me);
++ return -EINVAL;
++ }
++
+ off = xt_compat_target_offset(wt);
+
+ if (dst) {
+--
+2.53.0
+
--- /dev/null
+From a423456ef8237a1b0351d7014b8346e020b59428 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 12:36:14 -0700
+Subject: netfilter: synproxy: refresh tcphdr after skb_ensure_writable
+
+From: Chris Mason <clm@meta.com>
+
+[ Upstream commit 92170e6afe927ab2792a3f71902845789c8e31b1 ]
+
+synproxy_tstamp_adjust() rewrites the TCP timestamp option in place
+and then patches the TCP checksum via inet_proto_csum_replace4() on
+the caller-supplied tcphdr pointer. Both ipv4_synproxy_hook() and
+ipv6_synproxy_hook() obtain that pointer with skb_header_pointer()
+before calling in, so it may either alias skb->head directly or
+point at the caller's on-stack _tcph buffer.
+
+Between obtaining the pointer and using it, the function calls
+skb_ensure_writable(skb, optend), which on a cloned or non-linear
+skb invokes pskb_expand_head() and frees the old skb->head. After
+that point the cached th is stale:
+
+ caller (ipv[46]_synproxy_hook)
+ th = skb_header_pointer(skb, ..., &_tcph)
+ synproxy_tstamp_adjust(skb, protoff, th, ...)
+ skb_ensure_writable(skb, optend)
+ pskb_expand_head() /* kfree(old skb->head) */
+ ...
+ inet_proto_csum_replace4(&th->check, ...)
+ /* writes into freed head, or
+ into the caller's stack copy
+ leaving the on-wire checksum
+ stale */
+
+The option bytes are written through skb->data and are fine; only
+the checksum update goes through th and so lands in the wrong
+place. The result is either a write into freed slab memory or a
+packet leaving with a checksum that does not match its payload.
+
+Fix by re-deriving th from skb->data + protoff immediately after
+skb_ensure_writable() succeeds, so the subsequent checksum update
+targets the linear, writable header.
+
+Fixes: 48b1de4c110a ("netfilter: add SYNPROXY core/target")
+Assisted-by: kres (claude-opus-4-7)
+Signed-off-by: Chris Mason <clm@meta.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_synproxy_core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 2dfc5dae065638..0a97b1a0f53e45 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -199,6 +199,8 @@ synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,
+ if (skb_ensure_writable(skb, optend))
+ return 0;
+
++ th = (struct tcphdr *)(skb->data + protoff);
++
+ while (optoff < optend) {
+ unsigned char *op = skb->data + optoff;
+
+--
+2.53.0
+
--- /dev/null
+From b0a577765533a520b2c41a8309930711a56a96f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 20:10:08 +0200
+Subject: netfilter: xt_cpu: prefer raw_smp_processor_id
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit c376f07e16c02239ed44cabb97145d03f65b4d15 ]
+
+With PREEMPT_RCU we get splat:
+
+BUG: using smp_processor_id() in preemptible [..]
+caller is cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+CPU: 1 .. Comm: syz.3.1377 #0 PREEMPT(full)
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
+ check_preemption_disabled+0xd3/0xe0 lib/smp_processor_id.c:47
+ cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+ [..]
+
+Just use raw version instead.
+This is similar to 14d14a5d2957 ("netfilter: nft_meta: use raw_smp_processor_id()").
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Reported-by: syzbot+690d3e3ffa7335ac10eb@syzkaller.appspotmail.com
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/xt_cpu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_cpu.c b/net/netfilter/xt_cpu.c
+index 3bdc302a0f9137..9cb259902a586b 100644
+--- a/net/netfilter/xt_cpu.c
++++ b/net/netfilter/xt_cpu.c
+@@ -34,7 +34,7 @@ static bool cpu_mt(const struct sk_buff *skb, struct xt_action_param *par)
+ {
+ const struct xt_cpu_info *info = par->matchinfo;
+
+- return (info->cpu == smp_processor_id()) ^ info->invert;
++ return (info->cpu == raw_smp_processor_id()) ^ info->invert;
+ }
+
+ static struct xt_match cpu_mt_reg __read_mostly = {
+--
+2.53.0
+
--- /dev/null
+From 2e53644607b94bed67568d7d64845dc3525c39ce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:41 +0000
+Subject: nfc: llcp: Fix use-after-free in llcp_sock_release()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit f4268b466190dae95a7585f69b4f1f8ad097632c ]
+
+llcp_sock_release() unconditionally unlinks the socket from the local
+sockets list. However, if the socket is still in connecting state, it
+is on the connecting list.
+
+Fix this by checking the socket state and unlinking from the correct list.
+
+Fixes: b4011239a08e ("NFC: llcp: Fix non blocking sockets connections")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-1-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_sock.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index dc96d751eb278f..57dea580c02912 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -628,6 +628,8 @@ static int llcp_sock_release(struct socket *sock)
+
+ if (sock->type == SOCK_RAW)
+ nfc_llcp_sock_unlink(&local->raw_sockets, sk);
++ else if (sk->sk_state == LLCP_CONNECTING)
++ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ else
+ nfc_llcp_sock_unlink(&local->sockets, sk);
+
+--
+2.53.0
+
--- /dev/null
+From 22e49b9395b9e8ee28179cd4097f4c14c6bc9d1c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:42 +0000
+Subject: nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit b493ea2765cc17cb8aa7e7544a4b6dcb05b6ed77 ]
+
+A race condition exists in the NFC LLCP connection state machine where
+the connection acceptance packet (CC) can be processed concurrently with
+socket release. This can lead to a use-after-free of the socket object.
+
+When nfc_llcp_recv_cc() moves the socket from the connecting_sockets
+list to the sockets list, it does so without holding the socket lock.
+If llcp_sock_release() is executing concurrently, it might have already
+unlinked the socket and dropped its references, which can result in
+nfc_llcp_recv_cc() linking a freed socket into the live list.
+
+Fix this by holding lock_sock() during the state transition and list
+movement in nfc_llcp_recv_cc(). After acquiring the lock, check if
+the socket is still hashed to ensure it hasn't already been unlinked
+and marked for destruction by the release path. This aligns the locking
+pattern with recv_hdlc() and recv_disc().
+
+Fixes: a69f32af86e3 ("NFC: Socket linked list")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-2-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_core.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
+index e04634f22b49f4..c7de44637e0187 100644
+--- a/net/nfc/llcp_core.c
++++ b/net/nfc/llcp_core.c
+@@ -1225,6 +1225,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+
+ sk = &llcp_sock->sk;
+
++ lock_sock(sk);
++
++ /* Check if socket was destroyed whilst waiting for the lock */
++ if (!sk_hashed(sk)) {
++ release_sock(sk);
++ nfc_llcp_sock_put(llcp_sock);
++ return;
++ }
++
+ /* Unlink from connecting and link to the client array */
+ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ nfc_llcp_sock_link(&local->sockets, sk);
+@@ -1236,6 +1245,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+ sk->sk_state = LLCP_CONNECTED;
+ sk->sk_state_change(sk);
+
++ release_sock(sk);
++
+ nfc_llcp_sock_put(llcp_sock);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From f10f48b7faffd49b71f57136c74e78144f3c2f18 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Mar 2022 20:25:22 +0100
+Subject: nfc: llcp: protect nfc_llcp_sock_unlink() calls
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+
+[ Upstream commit a06b8044169f6d5c3eb34772c13d2c0c1b205352 ]
+
+nfc_llcp_sock_link() is called in all paths (bind/connect) as a last
+action, still protected with lock_sock(). When cleaning up in
+llcp_sock_release(), call nfc_llcp_sock_unlink() in a mirrored way:
+earlier and still under the lock_sock().
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: f4268b466190 ("nfc: llcp: Fix use-after-free in llcp_sock_release()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_sock.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index 6e1fba2084930e..dc96d751eb278f 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -626,6 +626,11 @@ static int llcp_sock_release(struct socket *sock)
+ }
+ }
+
++ if (sock->type == SOCK_RAW)
++ nfc_llcp_sock_unlink(&local->raw_sockets, sk);
++ else
++ nfc_llcp_sock_unlink(&local->sockets, sk);
++
+ if (llcp_sock->reserved_ssap < LLCP_SAP_MAX)
+ nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);
+
+@@ -638,11 +643,6 @@ static int llcp_sock_release(struct socket *sock)
+ if (sk->sk_state == LLCP_DISCONNECTING)
+ return err;
+
+- if (sock->type == SOCK_RAW)
+- nfc_llcp_sock_unlink(&local->raw_sockets, sk);
+- else
+- nfc_llcp_sock_unlink(&local->sockets, sk);
+-
+ out:
+ sock_orphan(sk);
+ sock_put(sk);
+--
+2.53.0
+
--- /dev/null
+From 38f6064f86d9a5679bd76961f4f70c45327d83f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 May 2026 19:55:18 +0800
+Subject: nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems
+
+From: Carl Lee <carl.lee@amd.com>
+
+[ Upstream commit f23bf992d65a42007c517b060ca35cebdea3525a ]
+
+Some ACPI-based platforms report incorrect IRQ trigger types (e.g.
+IRQF_TRIGGER_HIGH), which can lead to interrupt storms.
+
+Use the historically working rising-edge trigger on ACPI systems to
+avoid this regression.
+
+Device Tree-based systems continue to use the firmware-provided
+trigger type.
+
+Fixes: 57be33f85e36 ("nfc: nxp-nci: remove interrupt trigger type")
+Signed-off-by: Carl Lee <carl.lee@amd.com>
+Tested-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Luca Stefani <luca.stefani.ge1@gmail.com>
+Link: https://patch.msgid.link/20260516-nfc-nxp-nci-i2c-restore-irq-trigger-fallback-v3-1-37ba4b6e9086@amd.com
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/nxp-nci/i2c.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
+index 237b344a30bbd8..989b4a0e5b1982 100644
+--- a/drivers/nfc/nxp-nci/i2c.c
++++ b/drivers/nfc/nxp-nci/i2c.c
+@@ -16,6 +16,7 @@
+ #include <linux/delay.h>
+ #include <linux/i2c.h>
+ #include <linux/interrupt.h>
++#include <linux/irq.h>
+ #include <linux/module.h>
+ #include <linux/nfc.h>
+ #include <linux/gpio/consumer.h>
+@@ -268,6 +269,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
+ {
+ struct device *dev = &client->dev;
+ struct nxp_nci_i2c_phy *phy;
++ unsigned long irqflags;
+ int r;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+@@ -304,9 +306,26 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
+ if (r < 0)
+ return r;
+
++ /*
++ * ACPI platforms may report incorrect IRQ trigger types
++ * (e.g. level-high), which can lead to interrupt storms.
++ *
++ * Use the historically stable rising-edge trigger for ACPI devices.
++ *
++ * On non-ACPI systems (e.g. Device Tree), prefer the firmware-
++ * provided trigger type, falling back to rising-edge if not set.
++ */
++ if (ACPI_COMPANION(dev)) {
++ irqflags = IRQF_TRIGGER_RISING;
++ } else {
++ irqflags = irq_get_trigger_type(client->irq);
++ if (!irqflags)
++ irqflags = IRQF_TRIGGER_RISING;
++ }
++
+ r = request_threaded_irq(client->irq, NULL,
+ nxp_nci_i2c_irq_thread_fn,
+- IRQF_ONESHOT,
++ irqflags | IRQF_ONESHOT,
+ NXP_NCI_I2C_DRIVER_NAME, phy);
+ if (r < 0)
+ nfc_err(&client->dev, "Unable to register IRQ handler\n");
+--
+2.53.0
+
--- /dev/null
+From 19ad278c66758b38a247e8ae918b93d14526c765 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 11:24:11 +0800
+Subject: sctp: fix race between sctp_wait_for_connect and peeloff
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit f14fe6395a8b3d961a61e138ad7b36ba3626dd4e ]
+
+sctp_wait_for_connect() drops and re-acquires the socket lock while
+waiting for the association to reach ESTABLISHED state. During this
+window, another thread can peeloff the association to a new socket via
+getsockopt(SCTP_SOCKOPT_PEELOFF), changing asoc->base.sk. After
+re-acquiring the old socket lock, sctp_wait_for_connect() returns
+success without noticing the migration — the caller then accesses
+the association under the wrong lock in sctp_datamsg_from_user().
+
+Add the same sk != asoc->base.sk check that sctp_wait_for_sndbuf()
+already has, returning an error if the association was migrated while
+we slept.
+
+Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260527032411.60959-1-kipreyyy@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/socket.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 8c7bdf01e32a17..150235d861411d 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -9133,6 +9133,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
+ release_sock(sk);
+ current_timeo = schedule_timeout(current_timeo);
+ lock_sock(sk);
++ if (sk != asoc->base.sk)
++ goto do_error;
+
+ *timeo_p = current_timeo;
+ }
+--
+2.53.0
+
net-sched-cls_fw-fix-null-dereference-of-old-filters.patch
phy-renesas-rcar-gen3-usb2-fix-the-use-of-msleep-dur.patch
net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
+nfc-llcp-protect-nfc_llcp_sock_unlink-calls.patch
+nfc-llcp-fix-use-after-free-in-llcp_sock_release.patch
+nfc-llcp-fix-use-after-free-race-in-nfc_llcp_recv_cc.patch
+xfrm-check-for-underflow-in-xfrm_state_mtu.patch
+nfc-nxp-nci-i2c-use-rising-edge-irq-on-acpi-systems.patch
+kernel-fork-validate-exit_signal-in-kernel_clone.patch
+netfilter-synproxy-refresh-tcphdr-after-skb_ensure_w.patch
+netfilter-xt_cpu-prefer-raw_smp_processor_id.patch
+netfilter-ebtables-fix-oob-read-in-compat_mtw_from_u.patch
+tun-free-page-on-short-frame-rejection-in-tun_xdp_on.patch
+net-netlink-fix-sending-unassigned-nsid-after-assign.patch
+net-netlink-don-t-set-nsid-on-local-notifications.patch
+net-smc-do-not-re-initialize-smc-hashtables.patch
+net-iucv-fix-locking-in-.getsockopt.patch
+ipv4-free-net-ipv4.sysctl_local_reserved_ports-after.patch
+asoc-intel-bytcht_es8316-fix-mclk-leak-on-init-error.patch
+tunnels-load-network-headers-after-skb_cow-in-iptunn.patch
+vxlan-do-not-reuse-cached-ip_hdr-value-after-skb_tun.patch
+tunnels-do-not-assume-transport-header-in-iptunnel_p.patch
+bluetooth-6lowpan-check-skb_clone-return-value-in-se.patch
+ipv6-rpl-fix-hdrlen-overflow-in-ipv6_rpl_srh_decompr.patch
+net-sched-revert-net-sched-restrict-conditions-for-a.patch
+bluetooth-l2cap-clear-chan-ident-on-ecred-reconfigur.patch
+bluetooth-l2cap-fix-possible-crash-on-l2cap_ecred_co.patch
+sctp-fix-race-between-sctp_wait_for_connect-and-peel.patch
--- /dev/null
+From df2478f5320d5c625cdb8ee9859c75537f567e6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 09:00:21 -0700
+Subject: tun: free page on short-frame rejection in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f4feb1e20058e407cb00f45aff47f5b7e19a6bbf ]
+
+tun_xdp_one() returns -EINVAL on a frame shorter than ETH_HLEN without
+freeing the page that vhost_net_build_xdp() allocated for it.
+tun_sendmsg() discards that -EINVAL and still returns total_len, so
+vhost_tx_batch() takes the success path and never frees the page; each
+short frame in a batch leaks one page-frag chunk.
+
+A local process that can open /dev/net/tun and /dev/vhost-net can hit
+this path: it attaches a tun/tap device as the vhost-net backend and
+feeds TX descriptors whose length minus the virtio-net header is below
+ETH_HLEN. Each kick leaks the page-frag chunks for that batch, and a
+tight submission loop exhausts host memory and triggers an OOM panic.
+Free the page before returning -EINVAL, matching the XDP-program error
+path in the same function.
+
+Fixes: 049584807f1d ("tun: add missing verification for short frame")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260520160020.375349-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 3a89f9457fa242..930086d79f97c8 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2472,8 +2472,10 @@ static int tun_xdp_one(struct tun_struct *tun,
+ bool skb_xdp = false;
+ struct page *page;
+
+- if (unlikely(datasize < ETH_HLEN))
++ if (unlikely(datasize < ETH_HLEN)) {
++ put_page(virt_to_head_page(xdp->data));
+ return -EINVAL;
++ }
+
+ xdp_prog = rcu_dereference(tun->xdp_prog);
+ if (xdp_prog) {
+--
+2.53.0
+
--- /dev/null
+From b1d31f837a05d19b580fbd4d11ad8b16c23ae3da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 11:55:12 +0000
+Subject: tunnels: do not assume transport header in
+ iptunnel_pmtud_check_icmp()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 509323077ef79a26ba0c60bb556e45c12c398b2d ]
+
+In some cases, iptunnel_pmtud_check_icmp() can be called while
+skb transport header is not set.
+
+This triggers an out-of-bound access, because
+(typeof(skb->transport_header))~0U is 65535.
+
+Access the icmp header based on IPv4 network header,
+after making sure icmp->type is present in skb linear part.
+
+Note that iptunnel_pmtud_check_icmpv6()) is fine.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Reported-by: Damiano Melotti <melotti@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260522115512.1519110-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 05c7bb78fe96f0..712555c56a1836 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -262,7 +262,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct icmphdr *icmph = icmp_hdr(skb);
+ const struct iphdr *iph = ip_hdr(skb);
+
+ if (mtu < 576 || iph->frag_off != htons(IP_DF))
+@@ -273,9 +272,17 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ ipv4_is_lbcast(iph->saddr) || ipv4_is_multicast(iph->saddr))
+ return 0;
+
+- if (iph->protocol == IPPROTO_ICMP && icmp_is_err(icmph->type))
+- return 0;
++ if (iph->protocol == IPPROTO_ICMP) {
++ const struct icmphdr *icmph;
+
++ if (!pskb_network_may_pull(skb, iph->ihl * 4 +
++ offsetofend(struct icmphdr, type)))
++ return 0;
++ iph = ip_hdr(skb);
++ icmph = (void *)iph + iph->ihl * 4;
++ if (icmp_is_err(icmph->type))
++ return 0;
++ }
+ return iptunnel_pmtud_build_icmp(skb, mtu);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 104f0ec2a40c4cb7e2488e0b61727ba290002e30 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:13:35 +0000
+Subject: tunnels: load network headers after skb_cow() in
+ iptunnel_pmtud_build_icmp[v6]()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b4bc94353050b1fa7b702bd4c6600710dd926cff ]
+
+Sashiko found that iptunnel_pmtud_build_icmp() and
+iptunnel_pmtud_build_icmpv6() were caching ip_hdr() and ipv6_hdr()
+before an skb_cow() call which can reallocate skb->head.
+
+Fix this possible UAF by initializing the local variables
+after the skb_cow() call.
+
+Remove skb_reset_network_header() calls which were not needed.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525201335.2361845-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 3cdb546dbc8d71..05c7bb78fe96f0 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -194,7 +194,7 @@ EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
+ */
+ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct iphdr *iph = ip_hdr(skb);
++ const struct iphdr *iph;
+ struct icmphdr *icmph;
+ struct iphdr *niph;
+ struct ethhdr eh;
+@@ -208,7 +208,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, 576 - sizeof(*niph) - sizeof(*icmph));
+ if (err)
+@@ -218,7 +217,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ err = skb_cow(skb, sizeof(*niph) + sizeof(*icmph) + ETH_HLEN);
+ if (err)
+ return err;
+-
++ iph = ip_hdr(skb);
+ icmph = skb_push(skb, sizeof(*icmph));
+ *icmph = (struct icmphdr) {
+ .type = ICMP_DEST_UNREACH,
+@@ -290,7 +289,7 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ {
+- const struct ipv6hdr *ip6h = ipv6_hdr(skb);
++ const struct ipv6hdr *ip6h;
+ struct icmp6hdr *icmp6h;
+ struct ipv6hdr *nip6h;
+ struct ethhdr eh;
+@@ -305,7 +304,6 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, IPV6_MIN_MTU - sizeof(*nip6h) - sizeof(*icmp6h));
+ if (err)
+@@ -316,6 +314,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ if (err)
+ return err;
+
++ ip6h = ipv6_hdr(skb);
+ icmp6h = skb_push(skb, sizeof(*icmp6h));
+ *icmp6h = (struct icmp6hdr) {
+ .icmp6_type = ICMPV6_PKT_TOOBIG,
+--
+2.53.0
+
--- /dev/null
+From 5d7a85504c75a4d224003957fc78eea9483778e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:36:42 +0000
+Subject: vxlan: do not reuse cached ip_hdr() value after
+ skb_tunnel_check_pmtu()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 7d9ef0cb271555d8cf39fefe6c981e1493b25ecf ]
+
+skb_tunnel_check_pmtu() can change skb->head.
+
+Reusing old_iph afer skb_tunnel_check_pmtu() can cause an UAF.
+
+Use instead ip_hdr(skb) as done in drivers/net/bareudp.c
+and drivers/net/geneve.c.
+
+Found by Sashiko.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525203642.2389723-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index 5e5dfa9579d3aa..053cc74bd904f8 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -2752,7 +2752,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
+ vni, md, flags, udp_sum);
+@@ -2815,7 +2815,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip6_dst_hoplimit(ndst);
+ skb_scrub_packet(skb, xnet);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
+--
+2.53.0
+
--- /dev/null
+From 6ca4502d79e333e839a77e9c00308b99bf3d9ba3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:49:14 -0600
+Subject: xfrm: Check for underflow in xfrm_state_mtu
+
+From: David Ahern <dahern@nvidia.com>
+
+[ Upstream commit 742b04d0550b0ec89dcbc99537ec88653bd1ad90 ]
+
+Leo Lin reported OOB write issue in esp component:
+
+ xfrm_state_mtu() returns u32 but performs its arithmetic in unsigned
+ modulo-2^32 space using an attacker-influenced "header_len + authsize +
+ net_adj" subtracted from a small "mtu" argument. A nobody user can
+ install an IPv4 ESP tunnel SA with a large authentication key
+ (XFRMA_ALG_AUTH_TRUNC, e.g. hmac(sha512), 64-byte key, 64-byte trunc),
+ configure a small interface MTU (68 bytes), and set XFRMA_TFCPAD to a
+ large value. When a single UDP datagram is then sent through the
+ tunnel, xfrm_state_mtu() underflows to a near-2^32 value, and
+ esp_output() consumes it as a signed int via:
+
+ padto = min(x->tfcpad, xfrm_state_mtu(x, mtu_cached))
+ esp.tfclen = padto - skb->len (assigned to int)
+
+ esp.tfclen ends up negative (e.g. -207). It is sign-extended to size_t
+ when passed to memset() inside esp_output_fill_trailer(), producing a
+ ~16 EB write of zeroes at skb_tail_pointer(skb). KASAN logs it as
+ "Write of size 18446744073709551537 at addr ffff888...".
+
+Check for underflow and return 1. This causes the sendmsg attempt to
+fail with ENETUNREACH.
+
+Fixes: c5c252389374 ("[XFRM]: Optimize MTU calculation")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Assisted-by: Codex:26.506.31004
+Signed-off-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 02d1d8d1fdea40..5f407f4f8eee7a 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -2549,10 +2549,14 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ const struct xfrm_type *type = READ_ONCE(x->type);
+ struct crypto_aead *aead;
+ u32 blksize, net_adj = 0;
++ u32 overhead, payload_mtu;
+
+ if (x->km.state != XFRM_STATE_VALID ||
+- !type || type->proto != IPPROTO_ESP)
++ !type || type->proto != IPPROTO_ESP) {
++ if (mtu <= x->props.header_len)
++ return 1;
+ return mtu - x->props.header_len;
++ }
+
+ aead = x->data;
+ blksize = ALIGN(crypto_aead_blocksize(aead), 4);
+@@ -2572,8 +2576,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ break;
+ }
+
+- return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
+- net_adj) & ~(blksize - 1)) + net_adj - 2;
++ overhead = x->props.header_len + crypto_aead_authsize(aead) + net_adj;
++ if (mtu <= overhead)
++ return 1;
++
++ payload_mtu = mtu - overhead;
++ payload_mtu &= ~(blksize - 1);
++ if (payload_mtu <= 2)
++ return 1;
++
++ return payload_mtu + net_adj - 2;
++
+ }
+ EXPORT_SYMBOL_GPL(xfrm_state_mtu);
+
+--
+2.53.0
+
--- /dev/null
+From 5215ae9a41b85629ca1fa2761ed7d70b5ffd1247 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 09:24:00 -0300
+Subject: ASoC: codecs: simple-mux: Fix enum control bounds check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit f63ad68e18d774a5d15cd7e405ead63f6b322679 ]
+
+simple_mux_control_put() rejects values greater than e->items, but
+enum control values are zero based. For the two-entry mux used by this
+driver, valid values are 0 and 1, so value 2 must be rejected as well.
+
+Accepting e->items can store an invalid mux state, pass it to the GPIO
+setter, and pass it on to the DAPM mux update path where it is used as
+an index into the enum text array.
+
+Use the same >= e->items check used by the ASoC enum helpers.
+
+Fixes: 342fbb7578d1 ("ASoC: add simple-mux")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260527-asoc-simple-mux-enum-bounds-v1-1-3f805b9fc671@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/simple-mux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/simple-mux.c b/sound/soc/codecs/simple-mux.c
+index e0a09dadfa7cf0..344bc61b9dc26a 100644
+--- a/sound/soc/codecs/simple-mux.c
++++ b/sound/soc/codecs/simple-mux.c
+@@ -40,7 +40,7 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
+ struct simple_mux *priv = snd_soc_component_get_drvdata(c);
+
+- if (ucontrol->value.enumerated.item[0] > e->items)
++ if (ucontrol->value.enumerated.item[0] >= e->items)
+ return -EINVAL;
+
+ if (priv->mux == ucontrol->value.enumerated.item[0])
+--
+2.53.0
+
--- /dev/null
+From ca7ba65fe7ca81e0707eebe2bbc9c70d09349e9a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 13:51:47 -0300
+Subject: ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit afb2a3a9d8369d18122a0d7cd294eba9a98259c6 ]
+
+byt_cht_es8316_init() enables MCLK before configuring the codec sysclk
+and creating the headset jack. If either of those later steps fails, the
+function returns without disabling MCLK, leaving the clock enabled after
+card registration fails.
+
+Track whether this driver enabled MCLK and disable it on the init error
+paths. Add the matching DAI link exit callback so the same clock enable
+is also balanced when ASoC cleans up a successfully initialized link.
+
+Fixes: a03bdaa565cb ("ASoC: Intel: add machine driver for BYT/CHT + ES8316")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260519-asoc-bytcht-es8316-mclk-leak-v1-1-b4a11cdc2afd@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/bytcht_es8316.c | 29 ++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
+index 923e69c7695c29..d54bc667175f50 100644
+--- a/sound/soc/intel/boards/bytcht_es8316.c
++++ b/sound/soc/intel/boards/bytcht_es8316.c
+@@ -39,6 +39,7 @@ struct byt_cht_es8316_private {
+ struct gpio_desc *speaker_en_gpio;
+ struct device *codec_dev;
+ bool speaker_en;
++ bool mclk_enabled;
+ };
+
+ enum {
+@@ -169,6 +170,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
+ },
+ };
+
++static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
++{
++ if (!priv->mclk_enabled)
++ return;
++
++ clk_disable_unprepare(priv->mclk);
++ priv->mclk_enabled = false;
++}
++
+ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ {
+ struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
+@@ -225,12 +235,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret)
+ dev_err(card->dev, "unable to enable MCLK\n");
++ else
++ priv->mclk_enabled = true;
+
+ ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(runtime, 0), 0, 19200000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set codec clock %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ ret = snd_soc_card_jack_new(card, "Headset",
+@@ -239,13 +251,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ARRAY_SIZE(byt_cht_es8316_jack_pins));
+ if (ret) {
+ dev_err(card->dev, "jack creation failed %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_soc_component_set_jack(codec, &priv->jack, NULL);
+
+ return 0;
++
++err_disable_mclk:
++ byt_cht_es8316_disable_mclk(priv);
++ return ret;
++}
++
++static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
++{
++ struct snd_soc_card *card = runtime->card;
++ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
++
++ byt_cht_es8316_disable_mclk(priv);
+ }
+
+ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+@@ -355,6 +379,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .init = byt_cht_es8316_init,
++ .exit = byt_cht_es8316_exit,
+ SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
+ },
+ };
+--
+2.53.0
+
--- /dev/null
+From dcf2ae8fc417a0f33b793bdc44d2146907b40e58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 11:21:39 +0800
+Subject: Bluetooth: 6lowpan: check skb_clone() return value in
+ send_mcast_pkt()
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+[ Upstream commit 3c40d381ce04f9575a5d8b542898183c3b4b38dc ]
+
+The skb_clone() function can return NULL if memory allocation fails.
+send_mcast_pkt() calls skb_clone() without checking the return value, which
+can lead to a NULL pointer dereference in send_pkt() when it dereferences
+skb->data.
+Add a NULL check after skb_clone() and skip the peer if the clone fails.
+
+Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/6lowpan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
+index b70d3a38fdedc1..26bc594182ea08 100644
+--- a/net/bluetooth/6lowpan.c
++++ b/net/bluetooth/6lowpan.c
+@@ -485,6 +485,8 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
+ int ret;
+
+ local_skb = skb_clone(skb, GFP_ATOMIC);
++ if (!local_skb)
++ continue;
+
+ BT_DBG("xmit %s to %pMR type %u IP %pI6c chan %p",
+ netdev->name,
+--
+2.53.0
+
--- /dev/null
+From 88b80890252e34db534c76091b0327a9044aa673 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 18:51:52 +0800
+Subject: Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit 00e1950716c6ed67d74777b2db286b0fa23b4be9 ]
+
+l2cap_ecred_reconf_rsp() returns early on success without clearing
+chan->ident. Every other L2CAP response handler (l2cap_ecred_conn_rsp,
+l2cap_le_connect_rsp, l2cap_config_rsp) clears chan->ident after a
+successful transaction to prevent the channel from matching subsequent
+responses with the recycled ident value.
+
+A remote attacker that completed a reconfiguration as the peer can
+replay a failure response with the stale ident, causing the kernel to
+match and destroy the already-established channel via
+l2cap_chan_del(chan, ECONNRESET).
+
+Clear chan->ident for all matching channels on success, and harden the
+failure path by using l2cap_chan_hold_unless_zero() consistent with
+other L2CAP handlers (l2cap_le_command_rej, __l2cap_get_chan_by_ident).
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index a5db427c13de20..7e3825c1b10b95 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6422,14 +6422,20 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("result 0x%4.4x", result);
+
+- if (!result)
++ if (!result) {
++ list_for_each_entry(chan, &conn->chan_l, list) {
++ if (chan->ident == cmd->ident)
++ chan->ident = 0;
++ }
+ return 0;
++ }
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
+ if (chan->ident != cmd->ident)
+ continue;
+
+- l2cap_chan_hold(chan);
++ if (!l2cap_chan_hold_unless_zero(chan))
++ continue;
+ l2cap_chan_lock(chan);
+
+ l2cap_chan_del(chan, ECONNRESET);
+--
+2.53.0
+
--- /dev/null
+From 393ffffe6c1927eb8f839bcd3400df8ec5d105fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 May 2026 12:09:42 -0400
+Subject: Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 41c2713b204e6cb6a94587bc6bf6935107df5479 ]
+
+If dcid is received for an already-assigned destination CID the spec
+requires that both channels to be discarded, but calling l2cap_chan_del
+may invalidate the tmp cursor created by list_for_each_entry_safe and
+in fact it is the wrong procedure as the chan->dcid may be assigned
+previously it really needs to be disconnected.
+
+Calling l2cap_chan_clone directly may still lead to l2cap_chan_del so
+instead schedule l2cap_chan_timeout with delay 0 to close the channel
+asynchronously.
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 7e3825c1b10b95..38ac75f85144be 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6222,6 +6222,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ cmd_len -= sizeof(*rsp);
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
++ struct l2cap_chan *orig;
+ u16 dcid;
+
+ if (chan->ident != cmd->ident ||
+@@ -6243,8 +6244,10 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
+
++ orig = __l2cap_get_chan_by_dcid(conn, dcid);
++
+ /* Check if dcid is already in use */
+- if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
++ if (dcid && orig) {
+ /* If a device receives a
+ * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
+ * already-assigned Destination CID, then both the
+@@ -6253,10 +6256,24 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ */
+ l2cap_chan_del(chan, ECONNREFUSED);
+ l2cap_chan_unlock(chan);
+- chan = __l2cap_get_chan_by_dcid(conn, dcid);
+- l2cap_chan_lock(chan);
+- l2cap_chan_del(chan, ECONNRESET);
+- l2cap_chan_unlock(chan);
++
++ /* Check that the dcid channel mode is
++ * L2CAP_MODE_EXT_FLOWCTL since this procedure is only
++ * valid for that mode and shouldn't disconnect a dcid
++ * in other modes.
++ */
++ if (orig->mode == L2CAP_MODE_EXT_FLOWCTL) {
++ l2cap_chan_lock(orig);
++ /* Disconnect the original channel as it may be
++ * considered connected since dcid has already
++ * been assigned; don't call l2cap_chan_close
++ * directly since that could lead to
++ * l2cap_chan_del and then removing the channel
++ * from the list while we're iterating over it.
++ */
++ __set_chan_timer(orig, 0);
++ l2cap_chan_unlock(orig);
++ }
+ continue;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 8f9b352ebc74f13c003ce2ca2a71bc360c4453eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:33:19 +0200
+Subject: bonding: refuse to enslave CAN devices
+
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+
+[ Upstream commit 8ba68464e4787b6a7ec938826e16124df20fd23d ]
+
+syzbot reported a kernel paging request crash in
+can_rx_unregister() inside net/can/af_can.c. The crash occurs
+because a virtual CAN device (vxcan) is being enslaved to a
+bonding master.
+
+During the enslavement process, the bonding driver mutates
+and modifies the network device states to fit an Ethernet-like
+aggregation model. However, CAN devices operate on a completely
+different Layer 2 architecture, relying on the CAN mid-layer
+private data structure (can_ml_priv) instead of standard
+Ethernet structures. Since bonding does not initialize or
+maintain these CAN structures, subsequent operations on the
+half-enslaved interface (such as closing associated sockets
+via isotp_release) lead to a null-pointer dereference when
+accessing the CAN receiver lists.
+
+Bonding CAN interfaces is architecturally invalid as CAN lacks
+MAC addresses, ARP capabilities, and standard Ethernet
+link-layer mechanisms. While generic loopback devices are
+blocked globally in net/core/dev.c, virtual CAN devices
+bypass this check because they do not carry the IFF_LOOPBACK
+flag, despite acting as local software-loopbacks.
+
+Fix this by explicitly blocking network devices of type
+ARPHRD_CAN from being enslaved at the very beginning of
+bond_enslave(). This prevents illegal state mutations,
+eliminates the resulting KASAN crashes, and avoids potential
+memory leaks from incomplete socket cleanups.
+
+As the CAN support has been added a long time after bonding
+the Fixes-tag points to the introduction of ARPHRD_CAN that
+would have needed a specific handling in bonding_main.c.
+
+Fixes: cd05acfe65ed ("[CAN]: Allocate protocol numbers for PF_CAN")
+Reported-by: syzbot+8ed98cbd0161632bce95@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=8ed98cbd0161632bce95
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260526-bonding-candev-v1-1-ba1df400918a@hartkopp.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 5321d9dca698a9..42ad34b308b924 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1776,6 +1776,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
+ int link_reporting;
+ int res = 0, i;
+
++ if (slave_dev->type == ARPHRD_CAN) {
++ BOND_NL_ERR(bond_dev, extack,
++ "CAN devices cannot be enslaved");
++ return -EPERM;
++ }
++
+ if (slave_dev->flags & IFF_MASTER &&
+ !netif_is_bond_master(slave_dev)) {
+ BOND_NL_ERR(bond_dev, extack,
+--
+2.53.0
+
--- /dev/null
+From c6f88ca06d9276170efdf68cdf9eba8377a9fbb0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:33 -0700
+Subject: ethtool: eeprom: add more safeties to EEPROM Netlink fallback
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 67cfdd9210b99f260b3e0afeb9525e0acc7be31e ]
+
+The Netlink fallback path for reading module EEPROM
+(fallback_set_params()) validates that offset < eeprom_len,
+but does not check that offset + length stays within eeprom_len.
+The ioctl equivalent (ethtool_get_any_eeprom() in ioctl.c) has
+always enforced both bounds:
+
+ if (eeprom.offset + eeprom.len > total_len)
+ return -EINVAL;
+
+This could lead to surprises in both drivers and device FW.
+Add the missing offset + length validation to fallback_set_params(),
+mirroring the ioctl.
+
+Similarly - ethtool core in general, and ethtool_get_any_eeprom()
+in particular tries to zero-init all buffers passed to the drivers
+to avoid any extra work of zeroing things out. eeprom_fallback()
+uses a plain kmalloc(), change it to zalloc.
+
+Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-11-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/eeprom.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c
+index 49c0a2a77f02de..6ce40f95d8aba5 100644
+--- a/net/ethtool/eeprom.c
++++ b/net/ethtool/eeprom.c
+@@ -43,6 +43,9 @@ static int fallback_set_params(struct eeprom_req_info *request,
+ if (offset >= modinfo->eeprom_len)
+ return -EINVAL;
+
++ if (length > modinfo->eeprom_len - offset)
++ return -EINVAL;
++
+ eeprom->cmd = ETHTOOL_GMODULEEEPROM;
+ eeprom->len = length;
+ eeprom->offset = offset;
+@@ -69,7 +72,7 @@ static int eeprom_fallback(struct eeprom_req_info *request,
+ if (err < 0)
+ return err;
+
+- data = kmalloc(eeprom.len, GFP_KERNEL);
++ data = kzalloc(eeprom.len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ err = ethtool_get_module_eeprom_call(dev, &eeprom, data);
+--
+2.53.0
+
--- /dev/null
+From 12476c61f034d6d453c15c5ba72225947eb33f30 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:02:45 +0200
+Subject: gpio: rockchip: convert bank->clk to devm_clk_get_enabled()
+
+From: Marco Scardovi <scardracs@disroot.org>
+
+[ Upstream commit 3e46c18d5d87f063a93ae0fe7662fbf6660459d5 ]
+
+The bank->clk was previously obtained via of_clk_get() and manually
+prepared/enabled. However, it was missing a corresponding clk_put() in
+both the error paths and the remove function, leading to a reference leak.
+
+Convert the allocation to devm_clk_get_enabled(), which also properly
+propagates failures from clk_prepare_enable() that were previously ignored.
+
+The GPIO bank device uses the same OF node as the previous of_clk_get()
+call, so devm_clk_get_enabled(dev, NULL) correctly resolves the same
+clock provider entry.
+
+Fix the reference leak and simplify the code by removing the manual
+clk_disable_unprepare() calls in the probe error paths and in the
+remove function.
+
+Fixes: 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio")
+Assisted-by: Antigravity:gemini-3.5-flash
+Signed-off-by: Marco Scardovi <scardracs@disroot.org>
+Link: https://patch.msgid.link/20260526171050.12785-2-scardracs@disroot.org
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-rockchip.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
+index d331745da1a3a8..df2eefc1554a01 100644
+--- a/drivers/gpio/gpio-rockchip.c
++++ b/drivers/gpio/gpio-rockchip.c
+@@ -649,11 +649,10 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ if (!bank->irq)
+ return -EINVAL;
+
+- bank->clk = of_clk_get(bank->of_node, 0);
++ bank->clk = devm_clk_get_enabled(bank->dev, NULL);
+ if (IS_ERR(bank->clk))
+ return PTR_ERR(bank->clk);
+
+- clk_prepare_enable(bank->clk);
+ id = readl(bank->reg_base + gpio_regs_v2.version_id);
+
+ /* If not gpio v2, that is default to v1. */
+@@ -663,7 +662,6 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ bank->db_clk = of_clk_get(bank->of_node, 1);
+ if (IS_ERR(bank->db_clk)) {
+ dev_err(bank->dev, "cannot find debounce clk\n");
+- clk_disable_unprepare(bank->clk);
+ return -EINVAL;
+ }
+ } else {
+@@ -737,7 +735,6 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
+
+ ret = rockchip_gpiolib_register(bank);
+ if (ret) {
+- clk_disable_unprepare(bank->clk);
+ mutex_unlock(&bank->deferred_lock);
+ return ret;
+ }
+@@ -773,7 +770,6 @@ static int rockchip_gpio_remove(struct platform_device *pdev)
+ {
+ struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
+
+- clk_disable_unprepare(bank->clk);
+ gpiochip_remove(&bank->gpio_chip);
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 31fe5d6f53e55b29e3de2edf56e7154850a00b43 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 12:21:47 +0000
+Subject: ipv4: free net->ipv4.sysctl_local_reserved_ports after
+ unregister_net_sysctl_table()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 87a1e0fe7776da7ab411be332b4be58ac8840d10 ]
+
+ipv4_sysctl_exit_net() is currently freeing net->ipv4.sysctl_local_reserved_ports
+too soon.
+
+Only after unregister_net_sysctl_table() we can be sure no threads can possibly
+use the sysctls, including /proc/sys/net/ipv4/ip_local_reserved_ports.
+
+Fixes: 122ff243f5f1 ("ipv4: make ip_local_reserved_ports per netns")
+Reported-by: Ji'an Zhou <eilaimemedsnaimel@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260521122147.3584624-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/sysctl_net_ipv4.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 1f22e72074fdca..a7d335ab000403 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -1415,10 +1415,10 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net)
+ {
+ struct ctl_table *table;
+
+- kfree(net->ipv4.sysctl_local_reserved_ports);
+ table = net->ipv4.ipv4_hdr->ctl_table_arg;
+ unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
+ kfree(table);
++ kfree(net->ipv4.sysctl_local_reserved_ports);
+ }
+
+ static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
+--
+2.53.0
+
--- /dev/null
+From 6ccd6c9272c29323b347031d382d5abaff1371b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 21:10:31 +0530
+Subject: ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress()
+
+From: Rahul Chandelkar <rc@rexion.ai>
+
+[ Upstream commit 9d5e7a46a9f6d8f503b41bfefef70659845f1679 ]
+
+ipv6_rpl_srh_decompress() computes:
+
+ outhdr->hdrlen = (((n + 1) * sizeof(struct in6_addr)) >> 3);
+
+hdrlen is __u8. For n >= 127 the result exceeds 255 and silently
+truncates. With n=127 (cmpri=15, cmpre=15, pad=0, hdrlen=16):
+
+ (128 * 16) >> 3 = 256, truncated to 0 as __u8
+
+The caller in ipv6_rpl_srh_rcv() then places the compressed header
+at buf + ((ohdr->hdrlen + 1) << 3). With hdrlen=0 this is buf + 8,
+but the decompressed region occupies buf[0..2055] (8-byte header
+plus 128 full addresses). The compressed header overlaps the
+decompressed data, and ipv6_rpl_srh_compress() writes into this
+overlap, corrupting the routing header of the forwarded packet.
+
+The existing guard at exthdrs.c:546 checks (n + 1) > 255, which
+prevents n+1 from overflowing unsigned char (the segments_left
+field), but does not prevent the computed hdrlen from overflowing
+__u8. n=127 passes because 128 <= 255, yet hdrlen=256 does not
+fit.
+
+Tighten the bound to (n + 1) > 127. This caps n at 126, giving
+hdrlen = (127 * 16) >> 3 = 254, which fits in __u8. The compressed
+header then lands at buf + ((254 + 1) << 3) = buf + 2040, exactly
+past the decompressed region (buf[0..2039]). No overlap. 127
+segments is well beyond any realistic RPL deployment.
+
+Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
+Signed-off-by: Rahul Chandelkar <rc@rexion.ai>
+Link: https://patch.msgid.link/20260525154031.2290876-1-rc@rexion.ai
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/exthdrs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
+index 343b957e6337ab..a25dfa59ca2196 100644
+--- a/net/ipv6/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -557,7 +557,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
+ * unsigned char which is segments_left field. Should not be
+ * higher than that.
+ */
+- if (r || (n + 1) > 255) {
++ if (r || (n + 1) > 127) {
+ kfree_skb(skb);
+ return -1;
+ }
+--
+2.53.0
+
--- /dev/null
+From a672b7dc40692524e3cd2127ccf43f1bb8109361 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 20:49:56 +0530
+Subject: kernel/fork: validate exit_signal in kernel_clone()
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit 09e7827e785729f391c8d46dc71becce70d296ab ]
+
+When a child process exits, it sends exit_signal to its parent via
+do_notify_parent(). The clone() syscall constructs exit_signal as:
+
+(lower_32_bits(clone_flags) & CSIGNAL)
+
+CSIGNAL is 0xff, so values in the range 65-255 are possible. However,
+valid_signal() only accepts signals up to _NSIG (64 on x86_64). A
+non-zero non-valid exit_signal acts the same as exit_signal == 0: the
+parent process is not signaled when the child terminates.
+
+The syzkaller reproducer triggers this by calling clone() with flags=0x80,
+resulting in exit_signal = (0x80 & CSIGNAL) = 128, which exceeds _NSIG and
+is not a valid signal.
+
+The v1 of this patch added the check only in the clone() syscall handler,
+which is incomplete. kernel_clone() has other callers such as
+sys_ia32_clone() which would remain unprotected. Move the check to
+kernel_clone() to cover all callers.
+
+Since the valid_signal() check is now in kernel_clone() and covers all
+callers including clone3(), the same check in copy_clone_args_from_user()
+becomes redundant and is removed. The higher 32bits check for clone3() is
+kept as it is clone3() specific.
+
+Note that this is a user-visible change: previously, passing an invalid
+exit_signal to clone() was silently accepted. The man page for clone()
+does not document any defined behavior for invalid exit_signal values, so
+rejecting them with -EINVAL is the correct behavior. It is unlikely that
+any sane application relies on passing an invalid exit_signal.
+
+[oleg@redhat.com: the comment above kernel_clone() should be updated]
+ Link: https://lore.kernel.org/abwvgU17W8wuW2-J@redhat.com
+Link: https://lore.kernel.org/20260316151956.563558-1-kartikey406@gmail.com
+Fixes: 3f2c788a1314 ("fork: prevent accidental access to clone3 features")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Reported-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=bbe6b99feefc3a0842de
+Tested-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/all/20260307064202.353405-1-kartikey406@gmail.com/T/ [v1]
+Link: https://lore.kernel.org/all/20260316104536.558108-1-kartikey406@gmail.com/T/ [v2]
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Ben Segall <bsegall@google.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Juri Lelli <juri.lelli@redhat.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: Liam Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
+Cc: Mel Gorman <mgorman@suse.de>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Valentin Schneider <vschneid@redhat.com>
+Cc: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/fork.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index eb772b1e819f2f..faf9d68fae3029 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -2632,8 +2632,6 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
+ *
+ * It copies the process, and if successful kick-starts
+ * it and waits for it to finish using the VM if required.
+- *
+- * args->exit_signal is expected to be checked for sanity by the caller.
+ */
+ pid_t kernel_clone(struct kernel_clone_args *args)
+ {
+@@ -2658,6 +2656,9 @@ pid_t kernel_clone(struct kernel_clone_args *args)
+ (args->pidfd == args->parent_tid))
+ return -EINVAL;
+
++ if (!valid_signal(args->exit_signal))
++ return -EINVAL;
++
+ /*
+ * Determine whether and which event to report to ptracer. When
+ * called from kernel_thread or CLONE_UNTRACED is explicitly
+@@ -2834,11 +2835,9 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
+ return -EINVAL;
+
+ /*
+- * Verify that higher 32bits of exit_signal are unset and that
+- * it is a valid signal
++ * Verify that higher 32bits of exit_signal are unset
+ */
+- if (unlikely((args.exit_signal & ~((u64)CSIGNAL)) ||
+- !valid_signal(args.exit_signal)))
++ if (unlikely(args.exit_signal & ~((u64)CSIGNAL)))
+ return -EINVAL;
+
+ if ((args.flags & CLONE_INTO_CGROUP) &&
+--
+2.53.0
+
--- /dev/null
+From b1ae81f8dddb681b2eddf3193864b1b66a2997ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 07:11:45 -0700
+Subject: net/iucv: fix locking in .getsockopt
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 3589d20a666caf30ad100c960a2de7de390fce88 ]
+
+Mirror iucv_sock_setsockopt() and wrap the whole switch in
+lock_sock()/release_sock(). The pre-existing SO_MSGLIMIT-only lock
+becomes redundant and is removed.
+
+Any AF_IUCV HIPER user can potentially crash the kernel by racing
+recvmsg() with getsockopt(SO_MSGSIZE): the SO_MSGSIZE arm dereferences
+iucv->hs_dev->mtu after iucv_sock_close() (called from the racing
+recvmsg()) has set hs_dev to NULL, producing a NULL pointer dereference
+oops.
+
+Suggested-by: Stanislav Fomichev <sdf.kernel@gmail.com>
+Fixes: 51363b8751a6 ("af_iucv: allow retrieval of maximum message size")
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
+Tested-by: Alexandra Winter <wintera@linux.ibm.com>
+Link: https://patch.msgid.link/20260521-af_iucv_fix2-v1-1-f16b1c510aa9@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/iucv/af_iucv.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index e6cb3e1cbbf9b8..3188d719a2e42d 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -1533,7 +1533,7 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+ struct sock *sk = sock->sk;
+ struct iucv_sock *iucv = iucv_sk(sk);
+ unsigned int val;
+- int len;
++ int len, rc;
+
+ if (level != SOL_IUCV)
+ return -ENOPROTOOPT;
+@@ -1546,26 +1546,34 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+
+ len = min_t(unsigned int, len, sizeof(int));
+
++ rc = 0;
++
++ lock_sock(sk);
+ switch (optname) {
+ case SO_IPRMDATA_MSG:
+ val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0;
+ break;
+ case SO_MSGLIMIT:
+- lock_sock(sk);
+ val = (iucv->path != NULL) ? iucv->path->msglim /* connected */
+ : iucv->msglimit; /* default */
+- release_sock(sk);
+ break;
+ case SO_MSGSIZE:
+- if (sk->sk_state == IUCV_OPEN)
+- return -EBADFD;
++ if (sk->sk_state == IUCV_OPEN) {
++ rc = -EBADFD;
++ break;
++ }
+ val = (iucv->hs_dev) ? iucv->hs_dev->mtu -
+ sizeof(struct af_iucv_trans_hdr) - ETH_HLEN :
+ 0x7fffffff;
+ break;
+ default:
+- return -ENOPROTOOPT;
++ rc = -ENOPROTOOPT;
++ break;
+ }
++ release_sock(sk);
++
++ if (rc)
++ return rc;
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+--
+2.53.0
+
--- /dev/null
+From 8e997f36f06cd4000c395ddafafad1bf52c0ae8b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:36 +0200
+Subject: net: netlink: don't set nsid on local notifications
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 88b126b39f9757e9debc322d4679239e9af089c7 ]
+
+In most cases, notifications on sockets with NETLINK_LISTEN_ALL_NSID
+do not contain NSID in their ancillary data in case the event is local
+to the listener.
+
+However, when a self-referential NSID is allocated for a namespace,
+every local notification starts sending this ID to the user space.
+
+This is problematic, because the listener cannot tell if those
+notifications are local or not anymore without making extra requests
+to figure out if the provided NSID is local or not. The listener
+can also not figure out the local NSID beforehand as it can be
+allocated at any point in time by other processes, changing the
+structure of the future notifications for everyone.
+
+The value is practically not useful, since it's the namespace's own
+ID that the application has to obtain from other sources in order to
+figure out if it's the same or not. So, for the application it's
+just an extra busy work with no benefits. Moreover, applications
+that do not know about this quirk may be mishandling notifications
+with NSID set as notifications from remote namespaces. This is the
+case for ovs-vswitchd and the iproute2's 'ip monitor' that stops
+printing 'current' and starts printing the nsid number mid-session.
+
+Lack of clear documentation for this behavior is also not helping.
+
+A search though open-source projects doesn't reveal any projects
+that use NETNSA_NSID_NOT_ASSIGNED and rely on metadata to contain
+self-referential NSIDs (expected, since the value is not useful).
+Quite the opposite, as already mentioned, there are few applications
+that rely on NSID to not be present in local events.
+
+Since the value is not useful and actively harmful in some cases,
+let's not report it for local events, making the notifications more
+consistent.
+
+Also adding some blank lines for readability.
+
+Fixes: 59324cf35aba ("netlink: allow to listen "all" netns")
+Reported-by: Matteo Perin <matteo.perin@canonical.com>
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-3-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 12e765fcbd747d..731c53178eb559 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1482,10 +1482,14 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++
+ NETLINK_CB(p->skb2).nsid_is_set = false;
+- NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+- if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+- NETLINK_CB(p->skb2).nsid_is_set = true;
++ if (!net_eq(sock_net(sk), p->net)) {
++ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
++ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
++ NETLINK_CB(p->skb2).nsid_is_set = true;
++ }
++
+ val = netlink_broadcast_deliver(sk, p->skb2);
+ if (val < 0) {
+ netlink_overrun(sk);
+--
+2.53.0
+
--- /dev/null
+From 1c2e8ff9678997ab9d9e9fafcda4a7065d1b13b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:35 +0200
+Subject: net: netlink: fix sending unassigned nsid after assigned one
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 70f8592ee90585272018a725054b6eb2ab7e99ca ]
+
+If the current skb is not shared, it is re-used directly for all the
+sockets subscribed to the notification. If we have remote all-nsid
+socket receiving a message first, then the 'nsid_is_set' will be
+set to 'true'. If the nsid is NOT_ASSIGNED for the next socket in
+the list, the 'nsid_is_set' will remain 'true' and the negative value
+is be delivered to the user space. All subsequent nsid values will be
+delivered as well, since there is no code path that sets the flag
+back to 'false'.
+
+Fix that by always dropping the flag to 'false' first.
+
+Fixes: 7212462fa6fd ("netlink: don't send unknown nsid")
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-2-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 65eb164d00c40d..12e765fcbd747d 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1482,6 +1482,7 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++ NETLINK_CB(p->skb2).nsid_is_set = false;
+ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+ NETLINK_CB(p->skb2).nsid_is_set = true;
+--
+2.53.0
+
--- /dev/null
+From 15fbd43e1439577d25c3a1604fdc2ef8e46d0a66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:49 -0400
+Subject: net/sched: Revert "net/sched: Restrict conditions for adding
+ duplicating netems to qdisc tree"
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit eda0b7f203bb166c98d1418b204135bd566ac83b ]
+
+This reverts commit ec8e0e3d7adef940cdf9475e2352c0680189d14e.
+
+The original patch rejects any tree containing two netems when
+either has duplication set, even when they sit on unrelated classes
+of the same classful parent. That broke configurations that have
+worked since netem was introduced.
+
+The re-entrancy problem the original commit was trying to solve is
+handled by later patch using tc_depth flag.
+
+Doing this revert will (re)expose the original bug with multiple
+netem duplication. When this patch is backported make sure
+and get the full series.
+
+Fixes: ec8e0e3d7ade ("net/sched: Restrict conditions for adding duplicating netems to qdisc tree")
+Reported-by: Ji-Soo Chung <jschung2@proton.me>
+Reported-by: Gerlinde <lrGerlinde@mailfence.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220774
+Reported-by: zyc zyc <zyc199902@zohomail.cn>
+Closes: https://lore.kernel.org/all/19adda5a1e2.12410b78222774.9191120410578703463@zohomail.cn/
+Reported-by: Manas Ghandat <ghandatmanas@gmail.com>
+Closes: https://lore.kernel.org/netdev/f69b2c8f-8325-4c2e-a011-6dbc089f30e4@gmail.com/
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-3-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_netem.c | 40 ----------------------------------------
+ 1 file changed, 40 deletions(-)
+
+diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
+index 3e3bced82c564d..3dc6411b0a33c7 100644
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -985,41 +985,6 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+ return 0;
+ }
+
+-static const struct Qdisc_class_ops netem_class_ops;
+-
+-static int check_netem_in_tree(struct Qdisc *sch, bool duplicates,
+- struct netlink_ext_ack *extack)
+-{
+- struct Qdisc *root, *q;
+- unsigned int i;
+-
+- root = qdisc_root_sleeping(sch);
+-
+- if (sch != root && root->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(root))->duplicate)
+- goto err;
+- }
+-
+- if (!qdisc_dev(root))
+- return 0;
+-
+- hash_for_each(qdisc_dev(root)->qdisc_hash, i, q, hash) {
+- if (sch != q && q->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(q))->duplicate)
+- goto err;
+- }
+- }
+-
+- return 0;
+-
+-err:
+- NL_SET_ERR_MSG(extack,
+- "netem: cannot mix duplicating netems with other netems in tree");
+- return -EINVAL;
+-}
+-
+ /* Parse netlink message to set options */
+ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
+@@ -1087,11 +1052,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ q->gap = qopt->gap;
+ q->counter = 0;
+ q->loss = qopt->loss;
+-
+- ret = check_netem_in_tree(sch, qopt->duplicate, extack);
+- if (ret)
+- goto unlock;
+-
+ q->duplicate = qopt->duplicate;
+
+ /* for compatibility with earlier versions.
+--
+2.53.0
+
--- /dev/null
+From ad78b70f116d7974dfa0ebc4c03c6b86f8a79984 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 16:56:39 +0200
+Subject: net/smc: Do not re-initialize smc hashtables
+
+From: Alexandra Winter <wintera@linux.ibm.com>
+
+[ Upstream commit 9e4389b0038781f19f97895186ed941ff8ac1678 ]
+
+INIT_HLIST_HEAD(&smc_v*_hashinfo.ht) are called after smc_nl_init(),
+proto_register() and sock_register(). This can lead to smc_v*_hashinfo.ht
+being reset even though hash entries already exist and are being used,
+possibly resulting in a corrupted list.
+
+Remove unnecessary and dangerous re-initialisation of smc_v*_hashinfo.ht in
+smc_init(); it is implicitly initialised to zero anyhow. Add
+HLIST_HEAD_INIT to the definitions for clarity.
+
+Fixes: f16a7dd5cf27 ("smc: netlink interface for SMC sockets")
+Suggested-by: Halil Pasic <pasic@linux.ibm.com>
+Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
+Acked-by: Halil Pasic <pasic@linux.ibm.com>
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Link: https://patch.msgid.link/20260521145639.10317-1-wintera@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index 5425c46a2e7c71..6b60a5dd240dd1 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -123,10 +123,12 @@ static struct sock *smc_tcp_syn_recv_sock(const struct sock *sk,
+
+ static struct smc_hashinfo smc_v4_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v4_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ static struct smc_hashinfo smc_v6_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v6_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ int smc_hash_sk(struct sock *sk)
+@@ -2938,8 +2940,6 @@ static int __init smc_init(void)
+ pr_err("%s: sock_register fails with %d\n", __func__, rc);
+ goto out_proto6;
+ }
+- INIT_HLIST_HEAD(&smc_v4_hashinfo.ht);
+- INIT_HLIST_HEAD(&smc_v6_hashinfo.ht);
+
+ rc = smc_ib_register_client();
+ if (rc) {
+--
+2.53.0
+
--- /dev/null
+From 2a0697060f2a0682a13e9dbc26b0cc2b9dd12ddc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 22:52:07 +0200
+Subject: netfilter: ebtables: fix OOB read in compat_mtw_from_user
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit f438d1786d657d57790c5d138d6db3fc9fdac392 ]
+
+Luxiao Xu says:
+
+ The function compat_mtw_from_user() converts ebtables extensions from
+ 32-bit user structures to kernel native structures. However, it lacks
+ proper validation of the user-supplied match_size/target_size.
+
+ When certain extensions are processed, the kernel-side translation
+ logic may perform memory accesses based on the extension's expected
+ size. If the user provides a size smaller than what the extension
+ requires, it results in an out-of-bounds read as reported by KASAN.
+
+ This fix introduces a check to ensure match_size is at least as large
+ as the extension's required compatsize. This covers matches, watchers,
+ and targets, while maintaining compatibility with standard targets.
+
+AFAIU this is relevant for matches that need to go though
+match->compat_from_user() call. Those that use plain memcpy with the
+user-provided size are ok because the caller checks that size vs the
+start of the next rule entry offset (which itself is checked vs. total
+size copied from userspace).
+
+The ->compat_from_user() callbacks assume they can read compatsize bytes,
+so they need this extra check.
+
+Based on an earlier patch from Luxiao Xu.
+
+Fixes: 81e675c227ec ("netfilter: ebtables: add CONFIG_COMPAT support")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/netfilter/ebtables.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index c74efcc2b4996d..2083facfc87d9b 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -1951,6 +1951,25 @@ enum compat_mwt {
+ EBT_COMPAT_TARGET,
+ };
+
++static bool match_size_ok(const struct xt_match *match, unsigned int match_size)
++{
++ u16 csize;
++
++ if (match->matchsize == -1) /* cannot validate ebt_among */
++ return true;
++
++ csize = match->compatsize ? : match->matchsize;
++
++ return match_size >= csize;
++}
++
++static bool tgt_size_ok(const struct xt_target *tgt, unsigned int tgt_size)
++{
++ u16 csize = tgt->compatsize ? : tgt->targetsize;
++
++ return tgt_size >= csize;
++}
++
+ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ enum compat_mwt compat_mwt,
+ struct ebt_entries_buf_state *state,
+@@ -1976,6 +1995,11 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+
++ if (!match_size_ok(match, match_size)) {
++ module_put(match->me);
++ return -EINVAL;
++ }
++
+ off = ebt_compat_match_offset(match, match_size);
+ if (dst) {
+ if (match->compat_from_user)
+@@ -1995,6 +2019,12 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ mwt->u.revision);
+ if (IS_ERR(wt))
+ return PTR_ERR(wt);
++
++ if (!tgt_size_ok(wt, match_size)) {
++ module_put(wt->me);
++ return -EINVAL;
++ }
++
+ off = xt_compat_target_offset(wt);
+
+ if (dst) {
+--
+2.53.0
+
--- /dev/null
+From 0899af06dcf89b63877fa69450af6847b0c75547 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 12:36:14 -0700
+Subject: netfilter: synproxy: refresh tcphdr after skb_ensure_writable
+
+From: Chris Mason <clm@meta.com>
+
+[ Upstream commit 92170e6afe927ab2792a3f71902845789c8e31b1 ]
+
+synproxy_tstamp_adjust() rewrites the TCP timestamp option in place
+and then patches the TCP checksum via inet_proto_csum_replace4() on
+the caller-supplied tcphdr pointer. Both ipv4_synproxy_hook() and
+ipv6_synproxy_hook() obtain that pointer with skb_header_pointer()
+before calling in, so it may either alias skb->head directly or
+point at the caller's on-stack _tcph buffer.
+
+Between obtaining the pointer and using it, the function calls
+skb_ensure_writable(skb, optend), which on a cloned or non-linear
+skb invokes pskb_expand_head() and frees the old skb->head. After
+that point the cached th is stale:
+
+ caller (ipv[46]_synproxy_hook)
+ th = skb_header_pointer(skb, ..., &_tcph)
+ synproxy_tstamp_adjust(skb, protoff, th, ...)
+ skb_ensure_writable(skb, optend)
+ pskb_expand_head() /* kfree(old skb->head) */
+ ...
+ inet_proto_csum_replace4(&th->check, ...)
+ /* writes into freed head, or
+ into the caller's stack copy
+ leaving the on-wire checksum
+ stale */
+
+The option bytes are written through skb->data and are fine; only
+the checksum update goes through th and so lands in the wrong
+place. The result is either a write into freed slab memory or a
+packet leaving with a checksum that does not match its payload.
+
+Fix by re-deriving th from skb->data + protoff immediately after
+skb_ensure_writable() succeeds, so the subsequent checksum update
+targets the linear, writable header.
+
+Fixes: 48b1de4c110a ("netfilter: add SYNPROXY core/target")
+Assisted-by: kres (claude-opus-4-7)
+Signed-off-by: Chris Mason <clm@meta.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_synproxy_core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 049a88f0380117..cdb2c3e23af7ee 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -199,6 +199,8 @@ synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,
+ if (skb_ensure_writable(skb, optend))
+ return 0;
+
++ th = (struct tcphdr *)(skb->data + protoff);
++
+ while (optoff < optend) {
+ unsigned char *op = skb->data + optoff;
+
+--
+2.53.0
+
--- /dev/null
+From 2f7ee612f3843e6f212e651de546b55665281a55 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 20:10:08 +0200
+Subject: netfilter: xt_cpu: prefer raw_smp_processor_id
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit c376f07e16c02239ed44cabb97145d03f65b4d15 ]
+
+With PREEMPT_RCU we get splat:
+
+BUG: using smp_processor_id() in preemptible [..]
+caller is cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+CPU: 1 .. Comm: syz.3.1377 #0 PREEMPT(full)
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
+ check_preemption_disabled+0xd3/0xe0 lib/smp_processor_id.c:47
+ cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+ [..]
+
+Just use raw version instead.
+This is similar to 14d14a5d2957 ("netfilter: nft_meta: use raw_smp_processor_id()").
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Reported-by: syzbot+690d3e3ffa7335ac10eb@syzkaller.appspotmail.com
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/xt_cpu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_cpu.c b/net/netfilter/xt_cpu.c
+index 3bdc302a0f9137..9cb259902a586b 100644
+--- a/net/netfilter/xt_cpu.c
++++ b/net/netfilter/xt_cpu.c
+@@ -34,7 +34,7 @@ static bool cpu_mt(const struct sk_buff *skb, struct xt_action_param *par)
+ {
+ const struct xt_cpu_info *info = par->matchinfo;
+
+- return (info->cpu == smp_processor_id()) ^ info->invert;
++ return (info->cpu == raw_smp_processor_id()) ^ info->invert;
+ }
+
+ static struct xt_match cpu_mt_reg __read_mostly = {
+--
+2.53.0
+
--- /dev/null
+From 1da7769db462443217ed66ce6646363125c03e5b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:41 +0000
+Subject: nfc: llcp: Fix use-after-free in llcp_sock_release()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit f4268b466190dae95a7585f69b4f1f8ad097632c ]
+
+llcp_sock_release() unconditionally unlinks the socket from the local
+sockets list. However, if the socket is still in connecting state, it
+is on the connecting list.
+
+Fix this by checking the socket state and unlinking from the correct list.
+
+Fixes: b4011239a08e ("NFC: llcp: Fix non blocking sockets connections")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-1-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_sock.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index 6e1fba2084930e..54af85d939c6b9 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -640,6 +640,8 @@ static int llcp_sock_release(struct socket *sock)
+
+ if (sock->type == SOCK_RAW)
+ nfc_llcp_sock_unlink(&local->raw_sockets, sk);
++ else if (sk->sk_state == LLCP_CONNECTING)
++ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ else
+ nfc_llcp_sock_unlink(&local->sockets, sk);
+
+--
+2.53.0
+
--- /dev/null
+From 652fe46e2b45d2433a29cb76584eea98e082c2f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:42 +0000
+Subject: nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit b493ea2765cc17cb8aa7e7544a4b6dcb05b6ed77 ]
+
+A race condition exists in the NFC LLCP connection state machine where
+the connection acceptance packet (CC) can be processed concurrently with
+socket release. This can lead to a use-after-free of the socket object.
+
+When nfc_llcp_recv_cc() moves the socket from the connecting_sockets
+list to the sockets list, it does so without holding the socket lock.
+If llcp_sock_release() is executing concurrently, it might have already
+unlinked the socket and dropped its references, which can result in
+nfc_llcp_recv_cc() linking a freed socket into the live list.
+
+Fix this by holding lock_sock() during the state transition and list
+movement in nfc_llcp_recv_cc(). After acquiring the lock, check if
+the socket is still hashed to ensure it hasn't already been unlinked
+and marked for destruction by the release path. This aligns the locking
+pattern with recv_hdlc() and recv_disc().
+
+Fixes: a69f32af86e3 ("NFC: Socket linked list")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-2-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_core.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
+index e04634f22b49f4..c7de44637e0187 100644
+--- a/net/nfc/llcp_core.c
++++ b/net/nfc/llcp_core.c
+@@ -1225,6 +1225,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+
+ sk = &llcp_sock->sk;
+
++ lock_sock(sk);
++
++ /* Check if socket was destroyed whilst waiting for the lock */
++ if (!sk_hashed(sk)) {
++ release_sock(sk);
++ nfc_llcp_sock_put(llcp_sock);
++ return;
++ }
++
+ /* Unlink from connecting and link to the client array */
+ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ nfc_llcp_sock_link(&local->sockets, sk);
+@@ -1236,6 +1245,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+ sk->sk_state = LLCP_CONNECTED;
+ sk->sk_state_change(sk);
+
++ release_sock(sk);
++
+ nfc_llcp_sock_put(llcp_sock);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 7ce95e17969c2ef6813c3c45d94a553315dce89b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 May 2026 19:55:18 +0800
+Subject: nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems
+
+From: Carl Lee <carl.lee@amd.com>
+
+[ Upstream commit f23bf992d65a42007c517b060ca35cebdea3525a ]
+
+Some ACPI-based platforms report incorrect IRQ trigger types (e.g.
+IRQF_TRIGGER_HIGH), which can lead to interrupt storms.
+
+Use the historically working rising-edge trigger on ACPI systems to
+avoid this regression.
+
+Device Tree-based systems continue to use the firmware-provided
+trigger type.
+
+Fixes: 57be33f85e36 ("nfc: nxp-nci: remove interrupt trigger type")
+Signed-off-by: Carl Lee <carl.lee@amd.com>
+Tested-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Luca Stefani <luca.stefani.ge1@gmail.com>
+Link: https://patch.msgid.link/20260516-nfc-nxp-nci-i2c-restore-irq-trigger-fallback-v3-1-37ba4b6e9086@amd.com
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/nxp-nci/i2c.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
+index 22c498860c03d5..a0e665f958c4d5 100644
+--- a/drivers/nfc/nxp-nci/i2c.c
++++ b/drivers/nfc/nxp-nci/i2c.c
+@@ -16,6 +16,7 @@
+ #include <linux/delay.h>
+ #include <linux/i2c.h>
+ #include <linux/interrupt.h>
++#include <linux/irq.h>
+ #include <linux/module.h>
+ #include <linux/nfc.h>
+ #include <linux/gpio/consumer.h>
+@@ -268,6 +269,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
+ {
+ struct device *dev = &client->dev;
+ struct nxp_nci_i2c_phy *phy;
++ unsigned long irqflags;
+ int r;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+@@ -304,9 +306,26 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
+ if (r < 0)
+ return r;
+
++ /*
++ * ACPI platforms may report incorrect IRQ trigger types
++ * (e.g. level-high), which can lead to interrupt storms.
++ *
++ * Use the historically stable rising-edge trigger for ACPI devices.
++ *
++ * On non-ACPI systems (e.g. Device Tree), prefer the firmware-
++ * provided trigger type, falling back to rising-edge if not set.
++ */
++ if (ACPI_COMPANION(dev)) {
++ irqflags = IRQF_TRIGGER_RISING;
++ } else {
++ irqflags = irq_get_trigger_type(client->irq);
++ if (!irqflags)
++ irqflags = IRQF_TRIGGER_RISING;
++ }
++
+ r = request_threaded_irq(client->irq, NULL,
+ nxp_nci_i2c_irq_thread_fn,
+- IRQF_ONESHOT,
++ irqflags | IRQF_ONESHOT,
+ NXP_NCI_I2C_DRIVER_NAME, phy);
+ if (r < 0)
+ nfc_err(&client->dev, "Unable to register IRQ handler\n");
+--
+2.53.0
+
--- /dev/null
+From a27b84367bd322f2b53cd168f454ab479cb9e934 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 11:24:11 +0800
+Subject: sctp: fix race between sctp_wait_for_connect and peeloff
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit f14fe6395a8b3d961a61e138ad7b36ba3626dd4e ]
+
+sctp_wait_for_connect() drops and re-acquires the socket lock while
+waiting for the association to reach ESTABLISHED state. During this
+window, another thread can peeloff the association to a new socket via
+getsockopt(SCTP_SOCKOPT_PEELOFF), changing asoc->base.sk. After
+re-acquiring the old socket lock, sctp_wait_for_connect() returns
+success without noticing the migration — the caller then accesses
+the association under the wrong lock in sctp_datamsg_from_user().
+
+Add the same sk != asoc->base.sk check that sctp_wait_for_sndbuf()
+already has, returning an error if the association was migrated while
+we slept.
+
+Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260527032411.60959-1-kipreyyy@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/socket.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 11040232ee937b..136b122d87c5a6 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -9369,6 +9369,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
+ release_sock(sk);
+ current_timeo = schedule_timeout(current_timeo);
+ lock_sock(sk);
++ if (sk != asoc->base.sk)
++ goto do_error;
+
+ *timeo_p = current_timeo;
+ }
+--
+2.53.0
+
drm-remove-plane-hsub-vsub-alignment-requirement-for.patch
dmaengine-idxd-fix-not-releasing-workqueue-on-.relea.patch
net-cpsw_new-fix-potential-unregister-of-netdev-that.patch
+nfc-llcp-fix-use-after-free-in-llcp_sock_release.patch
+nfc-llcp-fix-use-after-free-race-in-nfc_llcp_recv_cc.patch
+xfrm-check-for-underflow-in-xfrm_state_mtu.patch
+nfc-nxp-nci-i2c-use-rising-edge-irq-on-acpi-systems.patch
+kernel-fork-validate-exit_signal-in-kernel_clone.patch
+netfilter-synproxy-refresh-tcphdr-after-skb_ensure_w.patch
+netfilter-xt_cpu-prefer-raw_smp_processor_id.patch
+netfilter-ebtables-fix-oob-read-in-compat_mtw_from_u.patch
+tun-free-page-on-short-frame-rejection-in-tun_xdp_on.patch
+net-netlink-fix-sending-unassigned-nsid-after-assign.patch
+net-netlink-don-t-set-nsid-on-local-notifications.patch
+net-smc-do-not-re-initialize-smc-hashtables.patch
+net-iucv-fix-locking-in-.getsockopt.patch
+ipv4-free-net-ipv4.sysctl_local_reserved_ports-after.patch
+asoc-intel-bytcht_es8316-fix-mclk-leak-on-init-error.patch
+tunnels-load-network-headers-after-skb_cow-in-iptunn.patch
+vxlan-do-not-reuse-cached-ip_hdr-value-after-skb_tun.patch
+tunnels-do-not-assume-transport-header-in-iptunnel_p.patch
+asoc-codecs-simple-mux-fix-enum-control-bounds-check.patch
+bluetooth-6lowpan-check-skb_clone-return-value-in-se.patch
+bonding-refuse-to-enslave-can-devices.patch
+ethtool-eeprom-add-more-safeties-to-eeprom-netlink-f.patch
+ipv6-rpl-fix-hdrlen-overflow-in-ipv6_rpl_srh_decompr.patch
+net-sched-revert-net-sched-restrict-conditions-for-a.patch
+bluetooth-l2cap-clear-chan-ident-on-ecred-reconfigur.patch
+bluetooth-l2cap-fix-possible-crash-on-l2cap_ecred_co.patch
+gpio-rockchip-convert-bank-clk-to-devm_clk_get_enabl.patch
+sctp-fix-race-between-sctp_wait_for_connect-and-peel.patch
--- /dev/null
+From 5429844329f1004c49595dabfd07861f21710708 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 09:00:21 -0700
+Subject: tun: free page on short-frame rejection in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f4feb1e20058e407cb00f45aff47f5b7e19a6bbf ]
+
+tun_xdp_one() returns -EINVAL on a frame shorter than ETH_HLEN without
+freeing the page that vhost_net_build_xdp() allocated for it.
+tun_sendmsg() discards that -EINVAL and still returns total_len, so
+vhost_tx_batch() takes the success path and never frees the page; each
+short frame in a batch leaks one page-frag chunk.
+
+A local process that can open /dev/net/tun and /dev/vhost-net can hit
+this path: it attaches a tun/tap device as the vhost-net backend and
+feeds TX descriptors whose length minus the virtio-net header is below
+ETH_HLEN. Each kick leaks the page-frag chunks for that batch, and a
+tight submission loop exhausts host memory and triggers an OOM panic.
+Free the page before returning -EINVAL, matching the XDP-program error
+path in the same function.
+
+Fixes: 049584807f1d ("tun: add missing verification for short frame")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260520160020.375349-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 5c9e7d0beffa26..803cb4722dbf4a 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2422,8 +2422,10 @@ static int tun_xdp_one(struct tun_struct *tun,
+ bool skb_xdp = false;
+ struct page *page;
+
+- if (unlikely(datasize < ETH_HLEN))
++ if (unlikely(datasize < ETH_HLEN)) {
++ put_page(virt_to_head_page(xdp->data));
+ return -EINVAL;
++ }
+
+ xdp_prog = rcu_dereference(tun->xdp_prog);
+ if (xdp_prog) {
+--
+2.53.0
+
--- /dev/null
+From 8249b8fe86dec818a6318d68f03ebe8f26e89ef6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 11:55:12 +0000
+Subject: tunnels: do not assume transport header in
+ iptunnel_pmtud_check_icmp()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 509323077ef79a26ba0c60bb556e45c12c398b2d ]
+
+In some cases, iptunnel_pmtud_check_icmp() can be called while
+skb transport header is not set.
+
+This triggers an out-of-bound access, because
+(typeof(skb->transport_header))~0U is 65535.
+
+Access the icmp header based on IPv4 network header,
+after making sure icmp->type is present in skb linear part.
+
+Note that iptunnel_pmtud_check_icmpv6()) is fine.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Reported-by: Damiano Melotti <melotti@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260522115512.1519110-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 4d80bbcd15d5a4..f535b875a02b88 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -262,7 +262,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct icmphdr *icmph = icmp_hdr(skb);
+ const struct iphdr *iph = ip_hdr(skb);
+
+ if (mtu < 576 || iph->frag_off != htons(IP_DF))
+@@ -273,9 +272,17 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ ipv4_is_lbcast(iph->saddr) || ipv4_is_multicast(iph->saddr))
+ return 0;
+
+- if (iph->protocol == IPPROTO_ICMP && icmp_is_err(icmph->type))
+- return 0;
++ if (iph->protocol == IPPROTO_ICMP) {
++ const struct icmphdr *icmph;
+
++ if (!pskb_network_may_pull(skb, iph->ihl * 4 +
++ offsetofend(struct icmphdr, type)))
++ return 0;
++ iph = ip_hdr(skb);
++ icmph = (void *)iph + iph->ihl * 4;
++ if (icmp_is_err(icmph->type))
++ return 0;
++ }
+ return iptunnel_pmtud_build_icmp(skb, mtu);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From ee4436d0931a8ff123078311a8193abd52e3cd76 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:13:35 +0000
+Subject: tunnels: load network headers after skb_cow() in
+ iptunnel_pmtud_build_icmp[v6]()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b4bc94353050b1fa7b702bd4c6600710dd926cff ]
+
+Sashiko found that iptunnel_pmtud_build_icmp() and
+iptunnel_pmtud_build_icmpv6() were caching ip_hdr() and ipv6_hdr()
+before an skb_cow() call which can reallocate skb->head.
+
+Fix this possible UAF by initializing the local variables
+after the skb_cow() call.
+
+Remove skb_reset_network_header() calls which were not needed.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525201335.2361845-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 3737188ba4e1e5..4d80bbcd15d5a4 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -194,7 +194,7 @@ EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
+ */
+ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct iphdr *iph = ip_hdr(skb);
++ const struct iphdr *iph;
+ struct icmphdr *icmph;
+ struct iphdr *niph;
+ struct ethhdr eh;
+@@ -208,7 +208,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, 576 - sizeof(*niph) - sizeof(*icmph));
+ if (err)
+@@ -218,7 +217,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ err = skb_cow(skb, sizeof(*niph) + sizeof(*icmph) + ETH_HLEN);
+ if (err)
+ return err;
+-
++ iph = ip_hdr(skb);
+ icmph = skb_push(skb, sizeof(*icmph));
+ *icmph = (struct icmphdr) {
+ .type = ICMP_DEST_UNREACH,
+@@ -290,7 +289,7 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ {
+- const struct ipv6hdr *ip6h = ipv6_hdr(skb);
++ const struct ipv6hdr *ip6h;
+ struct icmp6hdr *icmp6h;
+ struct ipv6hdr *nip6h;
+ struct ethhdr eh;
+@@ -305,7 +304,6 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, IPV6_MIN_MTU - sizeof(*nip6h) - sizeof(*icmp6h));
+ if (err)
+@@ -316,6 +314,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ if (err)
+ return err;
+
++ ip6h = ipv6_hdr(skb);
+ icmp6h = skb_push(skb, sizeof(*icmp6h));
+ *icmp6h = (struct icmp6hdr) {
+ .icmp6_type = ICMPV6_PKT_TOOBIG,
+--
+2.53.0
+
--- /dev/null
+From cd0e8f185705b7c38723c084e49eebd54f644098 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:36:42 +0000
+Subject: vxlan: do not reuse cached ip_hdr() value after
+ skb_tunnel_check_pmtu()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 7d9ef0cb271555d8cf39fefe6c981e1493b25ecf ]
+
+skb_tunnel_check_pmtu() can change skb->head.
+
+Reusing old_iph afer skb_tunnel_check_pmtu() can cause an UAF.
+
+Use instead ip_hdr(skb) as done in drivers/net/bareudp.c
+and drivers/net/geneve.c.
+
+Found by Sashiko.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525203642.2389723-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index bd2b44071781ca..7967b429dfcf5f 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -2753,7 +2753,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
+ vni, md, flags, udp_sum);
+@@ -2816,7 +2816,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip6_dst_hoplimit(ndst);
+ skb_scrub_packet(skb, xnet);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
+--
+2.53.0
+
--- /dev/null
+From 1c7e2d114626b6cb876e8e6707895c38d83bdaa8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:49:14 -0600
+Subject: xfrm: Check for underflow in xfrm_state_mtu
+
+From: David Ahern <dahern@nvidia.com>
+
+[ Upstream commit 742b04d0550b0ec89dcbc99537ec88653bd1ad90 ]
+
+Leo Lin reported OOB write issue in esp component:
+
+ xfrm_state_mtu() returns u32 but performs its arithmetic in unsigned
+ modulo-2^32 space using an attacker-influenced "header_len + authsize +
+ net_adj" subtracted from a small "mtu" argument. A nobody user can
+ install an IPv4 ESP tunnel SA with a large authentication key
+ (XFRMA_ALG_AUTH_TRUNC, e.g. hmac(sha512), 64-byte key, 64-byte trunc),
+ configure a small interface MTU (68 bytes), and set XFRMA_TFCPAD to a
+ large value. When a single UDP datagram is then sent through the
+ tunnel, xfrm_state_mtu() underflows to a near-2^32 value, and
+ esp_output() consumes it as a signed int via:
+
+ padto = min(x->tfcpad, xfrm_state_mtu(x, mtu_cached))
+ esp.tfclen = padto - skb->len (assigned to int)
+
+ esp.tfclen ends up negative (e.g. -207). It is sign-extended to size_t
+ when passed to memset() inside esp_output_fill_trailer(), producing a
+ ~16 EB write of zeroes at skb_tail_pointer(skb). KASAN logs it as
+ "Write of size 18446744073709551537 at addr ffff888...".
+
+Check for underflow and return 1. This causes the sendmsg attempt to
+fail with ENETUNREACH.
+
+Fixes: c5c252389374 ("[XFRM]: Optimize MTU calculation")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Assisted-by: Codex:26.506.31004
+Signed-off-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index f7f568bfb93a80..9593fcc7508c94 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -2581,10 +2581,14 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ const struct xfrm_type *type = READ_ONCE(x->type);
+ struct crypto_aead *aead;
+ u32 blksize, net_adj = 0;
++ u32 overhead, payload_mtu;
+
+ if (x->km.state != XFRM_STATE_VALID ||
+- !type || type->proto != IPPROTO_ESP)
++ !type || type->proto != IPPROTO_ESP) {
++ if (mtu <= x->props.header_len)
++ return 1;
+ return mtu - x->props.header_len;
++ }
+
+ aead = x->data;
+ blksize = ALIGN(crypto_aead_blocksize(aead), 4);
+@@ -2604,8 +2608,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ break;
+ }
+
+- return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
+- net_adj) & ~(blksize - 1)) + net_adj - 2;
++ overhead = x->props.header_len + crypto_aead_authsize(aead) + net_adj;
++ if (mtu <= overhead)
++ return 1;
++
++ payload_mtu = mtu - overhead;
++ payload_mtu &= ~(blksize - 1);
++ if (payload_mtu <= 2)
++ return 1;
++
++ return payload_mtu + net_adj - 2;
++
+ }
+ EXPORT_SYMBOL_GPL(xfrm_state_mtu);
+
+--
+2.53.0
+
--- /dev/null
+From 86f15fb7b3bcaa9307a6962b5201b5f93ea6b5b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 09:24:00 -0300
+Subject: ASoC: codecs: simple-mux: Fix enum control bounds check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit f63ad68e18d774a5d15cd7e405ead63f6b322679 ]
+
+simple_mux_control_put() rejects values greater than e->items, but
+enum control values are zero based. For the two-entry mux used by this
+driver, valid values are 0 and 1, so value 2 must be rejected as well.
+
+Accepting e->items can store an invalid mux state, pass it to the GPIO
+setter, and pass it on to the DAPM mux update path where it is used as
+an index into the enum text array.
+
+Use the same >= e->items check used by the ASoC enum helpers.
+
+Fixes: 342fbb7578d1 ("ASoC: add simple-mux")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260527-asoc-simple-mux-enum-bounds-v1-1-3f805b9fc671@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/simple-mux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/simple-mux.c b/sound/soc/codecs/simple-mux.c
+index d30c0d24d90a65..c5aa58c6e7bae6 100644
+--- a/sound/soc/codecs/simple-mux.c
++++ b/sound/soc/codecs/simple-mux.c
+@@ -40,7 +40,7 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
+ struct simple_mux *priv = snd_soc_component_get_drvdata(c);
+
+- if (ucontrol->value.enumerated.item[0] > e->items)
++ if (ucontrol->value.enumerated.item[0] >= e->items)
+ return -EINVAL;
+
+ if (priv->mux == ucontrol->value.enumerated.item[0])
+--
+2.53.0
+
--- /dev/null
+From 6676b3b2d8abbdf90a58f3d3e887db52017ed1ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 13:51:47 -0300
+Subject: ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit afb2a3a9d8369d18122a0d7cd294eba9a98259c6 ]
+
+byt_cht_es8316_init() enables MCLK before configuring the codec sysclk
+and creating the headset jack. If either of those later steps fails, the
+function returns without disabling MCLK, leaving the clock enabled after
+card registration fails.
+
+Track whether this driver enabled MCLK and disable it on the init error
+paths. Add the matching DAI link exit callback so the same clock enable
+is also balanced when ASoC cleans up a successfully initialized link.
+
+Fixes: a03bdaa565cb ("ASoC: Intel: add machine driver for BYT/CHT + ES8316")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260519-asoc-bytcht-es8316-mclk-leak-v1-1-b4a11cdc2afd@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/bytcht_es8316.c | 29 ++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
+index fa2c3981dacac9..ff3642e8c132f8 100644
+--- a/sound/soc/intel/boards/bytcht_es8316.c
++++ b/sound/soc/intel/boards/bytcht_es8316.c
+@@ -39,6 +39,7 @@ struct byt_cht_es8316_private {
+ struct gpio_desc *speaker_en_gpio;
+ struct device *codec_dev;
+ bool speaker_en;
++ bool mclk_enabled;
+ };
+
+ enum {
+@@ -169,6 +170,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
+ },
+ };
+
++static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
++{
++ if (!priv->mclk_enabled)
++ return;
++
++ clk_disable_unprepare(priv->mclk);
++ priv->mclk_enabled = false;
++}
++
+ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ {
+ struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
+@@ -225,12 +235,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret)
+ dev_err(card->dev, "unable to enable MCLK\n");
++ else
++ priv->mclk_enabled = true;
+
+ ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(runtime, 0), 0, 19200000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set codec clock %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ ret = snd_soc_card_jack_new_pins(card, "Headset",
+@@ -239,13 +251,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ARRAY_SIZE(byt_cht_es8316_jack_pins));
+ if (ret) {
+ dev_err(card->dev, "jack creation failed %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_soc_component_set_jack(codec, &priv->jack, NULL);
+
+ return 0;
++
++err_disable_mclk:
++ byt_cht_es8316_disable_mclk(priv);
++ return ret;
++}
++
++static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
++{
++ struct snd_soc_card *card = runtime->card;
++ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
++
++ byt_cht_es8316_disable_mclk(priv);
+ }
+
+ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+@@ -355,6 +379,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .init = byt_cht_es8316_init,
++ .exit = byt_cht_es8316_exit,
+ SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
+ },
+ };
+--
+2.53.0
+
--- /dev/null
+From d4fd1b935a27d91a39dec9c29069b4f02909647d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 11:21:39 +0800
+Subject: Bluetooth: 6lowpan: check skb_clone() return value in
+ send_mcast_pkt()
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+[ Upstream commit 3c40d381ce04f9575a5d8b542898183c3b4b38dc ]
+
+The skb_clone() function can return NULL if memory allocation fails.
+send_mcast_pkt() calls skb_clone() without checking the return value, which
+can lead to a NULL pointer dereference in send_pkt() when it dereferences
+skb->data.
+Add a NULL check after skb_clone() and skip the peer if the clone fails.
+
+Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/6lowpan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
+index 347361ff0cc878..dc3d1d5326e96a 100644
+--- a/net/bluetooth/6lowpan.c
++++ b/net/bluetooth/6lowpan.c
+@@ -485,6 +485,8 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
+ int ret;
+
+ local_skb = skb_clone(skb, GFP_ATOMIC);
++ if (!local_skb)
++ continue;
+
+ BT_DBG("xmit %s to %pMR type %u IP %pI6c chan %p",
+ netdev->name,
+--
+2.53.0
+
--- /dev/null
+From 04075e492b5bd67fee72be4528f851b3ead2a771 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 18:51:52 +0800
+Subject: Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit 00e1950716c6ed67d74777b2db286b0fa23b4be9 ]
+
+l2cap_ecred_reconf_rsp() returns early on success without clearing
+chan->ident. Every other L2CAP response handler (l2cap_ecred_conn_rsp,
+l2cap_le_connect_rsp, l2cap_config_rsp) clears chan->ident after a
+successful transaction to prevent the channel from matching subsequent
+responses with the recycled ident value.
+
+A remote attacker that completed a reconfiguration as the peer can
+replay a failure response with the stale ident, causing the kernel to
+match and destroy the already-established channel via
+l2cap_chan_del(chan, ECONNRESET).
+
+Clear chan->ident for all matching channels on success, and harden the
+failure path by using l2cap_chan_hold_unless_zero() consistent with
+other L2CAP handlers (l2cap_le_command_rej, __l2cap_get_chan_by_ident).
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 21f63ca434e3fd..a3ee31f2fa2880 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6454,14 +6454,20 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("result 0x%4.4x", result);
+
+- if (!result)
++ if (!result) {
++ list_for_each_entry(chan, &conn->chan_l, list) {
++ if (chan->ident == cmd->ident)
++ chan->ident = 0;
++ }
+ return 0;
++ }
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
+ if (chan->ident != cmd->ident)
+ continue;
+
+- l2cap_chan_hold(chan);
++ if (!l2cap_chan_hold_unless_zero(chan))
++ continue;
+ l2cap_chan_lock(chan);
+
+ l2cap_chan_del(chan, ECONNRESET);
+--
+2.53.0
+
--- /dev/null
+From 093c62d66dd253d45c07ce26aa6ad7e6dfea7a2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 May 2026 12:09:42 -0400
+Subject: Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 41c2713b204e6cb6a94587bc6bf6935107df5479 ]
+
+If dcid is received for an already-assigned destination CID the spec
+requires that both channels to be discarded, but calling l2cap_chan_del
+may invalidate the tmp cursor created by list_for_each_entry_safe and
+in fact it is the wrong procedure as the chan->dcid may be assigned
+previously it really needs to be disconnected.
+
+Calling l2cap_chan_clone directly may still lead to l2cap_chan_del so
+instead schedule l2cap_chan_timeout with delay 0 to close the channel
+asynchronously.
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index a3ee31f2fa2880..8031f83b10832e 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -6254,6 +6254,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ cmd_len -= sizeof(*rsp);
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
++ struct l2cap_chan *orig;
+ u16 dcid;
+
+ if (chan->ident != cmd->ident ||
+@@ -6275,8 +6276,10 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
+
++ orig = __l2cap_get_chan_by_dcid(conn, dcid);
++
+ /* Check if dcid is already in use */
+- if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
++ if (dcid && orig) {
+ /* If a device receives a
+ * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
+ * already-assigned Destination CID, then both the
+@@ -6285,10 +6288,24 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ */
+ l2cap_chan_del(chan, ECONNREFUSED);
+ l2cap_chan_unlock(chan);
+- chan = __l2cap_get_chan_by_dcid(conn, dcid);
+- l2cap_chan_lock(chan);
+- l2cap_chan_del(chan, ECONNRESET);
+- l2cap_chan_unlock(chan);
++
++ /* Check that the dcid channel mode is
++ * L2CAP_MODE_EXT_FLOWCTL since this procedure is only
++ * valid for that mode and shouldn't disconnect a dcid
++ * in other modes.
++ */
++ if (orig->mode == L2CAP_MODE_EXT_FLOWCTL) {
++ l2cap_chan_lock(orig);
++ /* Disconnect the original channel as it may be
++ * considered connected since dcid has already
++ * been assigned; don't call l2cap_chan_close
++ * directly since that could lead to
++ * l2cap_chan_del and then removing the channel
++ * from the list while we're iterating over it.
++ */
++ __set_chan_timer(orig, 0);
++ l2cap_chan_unlock(orig);
++ }
+ continue;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 569e72048542af72775f2bb22a0a150fe87e678f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:33:19 +0200
+Subject: bonding: refuse to enslave CAN devices
+
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+
+[ Upstream commit 8ba68464e4787b6a7ec938826e16124df20fd23d ]
+
+syzbot reported a kernel paging request crash in
+can_rx_unregister() inside net/can/af_can.c. The crash occurs
+because a virtual CAN device (vxcan) is being enslaved to a
+bonding master.
+
+During the enslavement process, the bonding driver mutates
+and modifies the network device states to fit an Ethernet-like
+aggregation model. However, CAN devices operate on a completely
+different Layer 2 architecture, relying on the CAN mid-layer
+private data structure (can_ml_priv) instead of standard
+Ethernet structures. Since bonding does not initialize or
+maintain these CAN structures, subsequent operations on the
+half-enslaved interface (such as closing associated sockets
+via isotp_release) lead to a null-pointer dereference when
+accessing the CAN receiver lists.
+
+Bonding CAN interfaces is architecturally invalid as CAN lacks
+MAC addresses, ARP capabilities, and standard Ethernet
+link-layer mechanisms. While generic loopback devices are
+blocked globally in net/core/dev.c, virtual CAN devices
+bypass this check because they do not carry the IFF_LOOPBACK
+flag, despite acting as local software-loopbacks.
+
+Fix this by explicitly blocking network devices of type
+ARPHRD_CAN from being enslaved at the very beginning of
+bond_enslave(). This prevents illegal state mutations,
+eliminates the resulting KASAN crashes, and avoids potential
+memory leaks from incomplete socket cleanups.
+
+As the CAN support has been added a long time after bonding
+the Fixes-tag points to the introduction of ARPHRD_CAN that
+would have needed a specific handling in bonding_main.c.
+
+Fixes: cd05acfe65ed ("[CAN]: Allocate protocol numbers for PF_CAN")
+Reported-by: syzbot+8ed98cbd0161632bce95@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=8ed98cbd0161632bce95
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260526-bonding-candev-v1-1-ba1df400918a@hartkopp.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index e9e2dec1dcb131..0e078252b52a98 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1848,6 +1848,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
+ int link_reporting;
+ int res = 0, i;
+
++ if (slave_dev->type == ARPHRD_CAN) {
++ BOND_NL_ERR(bond_dev, extack,
++ "CAN devices cannot be enslaved");
++ return -EPERM;
++ }
++
+ if (slave_dev->flags & IFF_MASTER &&
+ !netif_is_bond_master(slave_dev)) {
+ BOND_NL_ERR(bond_dev, extack,
+--
+2.53.0
+
--- /dev/null
+From 0390598b033bcf7f29952077b262ac1327599c47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:33 -0700
+Subject: ethtool: eeprom: add more safeties to EEPROM Netlink fallback
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 67cfdd9210b99f260b3e0afeb9525e0acc7be31e ]
+
+The Netlink fallback path for reading module EEPROM
+(fallback_set_params()) validates that offset < eeprom_len,
+but does not check that offset + length stays within eeprom_len.
+The ioctl equivalent (ethtool_get_any_eeprom() in ioctl.c) has
+always enforced both bounds:
+
+ if (eeprom.offset + eeprom.len > total_len)
+ return -EINVAL;
+
+This could lead to surprises in both drivers and device FW.
+Add the missing offset + length validation to fallback_set_params(),
+mirroring the ioctl.
+
+Similarly - ethtool core in general, and ethtool_get_any_eeprom()
+in particular tries to zero-init all buffers passed to the drivers
+to avoid any extra work of zeroing things out. eeprom_fallback()
+uses a plain kmalloc(), change it to zalloc.
+
+Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-11-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/eeprom.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c
+index 49c0a2a77f02de..6ce40f95d8aba5 100644
+--- a/net/ethtool/eeprom.c
++++ b/net/ethtool/eeprom.c
+@@ -43,6 +43,9 @@ static int fallback_set_params(struct eeprom_req_info *request,
+ if (offset >= modinfo->eeprom_len)
+ return -EINVAL;
+
++ if (length > modinfo->eeprom_len - offset)
++ return -EINVAL;
++
+ eeprom->cmd = ETHTOOL_GMODULEEEPROM;
+ eeprom->len = length;
+ eeprom->offset = offset;
+@@ -69,7 +72,7 @@ static int eeprom_fallback(struct eeprom_req_info *request,
+ if (err < 0)
+ return err;
+
+- data = kmalloc(eeprom.len, GFP_KERNEL);
++ data = kzalloc(eeprom.len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ err = ethtool_get_module_eeprom_call(dev, &eeprom, data);
+--
+2.53.0
+
--- /dev/null
+From 1ffd821641663944469346fbac362cf6b6e8116f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:02:45 +0200
+Subject: gpio: rockchip: convert bank->clk to devm_clk_get_enabled()
+
+From: Marco Scardovi <scardracs@disroot.org>
+
+[ Upstream commit 3e46c18d5d87f063a93ae0fe7662fbf6660459d5 ]
+
+The bank->clk was previously obtained via of_clk_get() and manually
+prepared/enabled. However, it was missing a corresponding clk_put() in
+both the error paths and the remove function, leading to a reference leak.
+
+Convert the allocation to devm_clk_get_enabled(), which also properly
+propagates failures from clk_prepare_enable() that were previously ignored.
+
+The GPIO bank device uses the same OF node as the previous of_clk_get()
+call, so devm_clk_get_enabled(dev, NULL) correctly resolves the same
+clock provider entry.
+
+Fix the reference leak and simplify the code by removing the manual
+clk_disable_unprepare() calls in the probe error paths and in the
+remove function.
+
+Fixes: 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio")
+Assisted-by: Antigravity:gemini-3.5-flash
+Signed-off-by: Marco Scardovi <scardracs@disroot.org>
+Link: https://patch.msgid.link/20260526171050.12785-2-scardracs@disroot.org
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-rockchip.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
+index bf301b2d18b8f1..147d2fda4fe120 100644
+--- a/drivers/gpio/gpio-rockchip.c
++++ b/drivers/gpio/gpio-rockchip.c
+@@ -647,11 +647,10 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ if (!bank->irq)
+ return -EINVAL;
+
+- bank->clk = of_clk_get(bank->of_node, 0);
++ bank->clk = devm_clk_get_enabled(bank->dev, NULL);
+ if (IS_ERR(bank->clk))
+ return PTR_ERR(bank->clk);
+
+- clk_prepare_enable(bank->clk);
+ id = readl(bank->reg_base + gpio_regs_v2.version_id);
+
+ /* If not gpio v2, that is default to v1. */
+@@ -661,7 +660,6 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ bank->db_clk = of_clk_get(bank->of_node, 1);
+ if (IS_ERR(bank->db_clk)) {
+ dev_err(bank->dev, "cannot find debounce clk\n");
+- clk_disable_unprepare(bank->clk);
+ return -EINVAL;
+ }
+ } else {
+@@ -735,7 +733,6 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
+
+ ret = rockchip_gpiolib_register(bank);
+ if (ret) {
+- clk_disable_unprepare(bank->clk);
+ mutex_unlock(&bank->deferred_lock);
+ return ret;
+ }
+@@ -776,7 +773,6 @@ static int rockchip_gpio_remove(struct platform_device *pdev)
+ {
+ struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
+
+- clk_disable_unprepare(bank->clk);
+ gpiochip_remove(&bank->gpio_chip);
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 63fafc9c26c6336ea6bc00bdb6ad06f7f2f371b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 12:21:47 +0000
+Subject: ipv4: free net->ipv4.sysctl_local_reserved_ports after
+ unregister_net_sysctl_table()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 87a1e0fe7776da7ab411be332b4be58ac8840d10 ]
+
+ipv4_sysctl_exit_net() is currently freeing net->ipv4.sysctl_local_reserved_ports
+too soon.
+
+Only after unregister_net_sysctl_table() we can be sure no threads can possibly
+use the sysctls, including /proc/sys/net/ipv4/ip_local_reserved_ports.
+
+Fixes: 122ff243f5f1 ("ipv4: make ip_local_reserved_ports per netns")
+Reported-by: Ji'an Zhou <eilaimemedsnaimel@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260521122147.3584624-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/sysctl_net_ipv4.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 6b4c9b0fc9abb7..ef17d0f95a9da5 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -1449,10 +1449,10 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net)
+ {
+ struct ctl_table *table;
+
+- kfree(net->ipv4.sysctl_local_reserved_ports);
+ table = net->ipv4.ipv4_hdr->ctl_table_arg;
+ unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
+ kfree(table);
++ kfree(net->ipv4.sysctl_local_reserved_ports);
+ }
+
+ static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
+--
+2.53.0
+
--- /dev/null
+From 14cd9def271cd39d43881ac55b6ef3bb8988eb82 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:31:31 +0800
+Subject: ipv6: fix possible infinite loop in fib6_select_path()
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 9c7da87c2dc860bb17ca1ece942495d28b1ce3b9 ]
+
+Found while auditing the same pattern Sashiko reported in
+rt6_fill_node() [1]. Apply the same fix as
+commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").
+
+Writers holding tb6_lock can list_del_rcu(&first->fib6_siblings)
+without waiting for RCU readers; first->fib6_siblings.next then
+still points into the old ring and this softirq-side walker never
+reaches &first->fib6_siblings as its terminator. fib6_purge_rt()
+always WRITE_ONCE()s first->fib6_nsiblings to 0 before
+list_del_rcu(), so an inside-loop check is a reliable detach signal.
+
+[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev
+
+Fixes: d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260527053133.180695-2-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index 0e96f7cb21a297..2b861eacee30e4 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -486,6 +486,9 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
+ const struct fib6_nh *nh = sibling->fib6_nh;
+ int nh_upper_bound;
+
++ if (!READ_ONCE(first->fib6_nsiblings))
++ break;
++
+ nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
+ if (hash > nh_upper_bound)
+ continue;
+--
+2.53.0
+
--- /dev/null
+From bc635bfda0f2d9086fd4fcf9c9fd736a9f92a20c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:31:30 +0800
+Subject: ipv6: fix possible infinite loop in rt6_fill_node()
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 9f72412bcf60144f252b0d6205106abf14344abc ]
+
+Sashiko reported this issue [1]. Apply the same fix as
+commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").
+
+Writers holding tb6_lock can list_del_rcu(&rt->fib6_siblings)
+without waiting for RCU readers; rt->fib6_siblings.next then still
+points into the old ring and this softirq-side walker never reaches
+&rt->fib6_siblings, causing a CPU stall. fib6_del_route() always
+WRITE_ONCE()s rt->fib6_nsiblings to 0 before list_del_rcu(), so an
+inside-loop check is a reliable detach signal.
+
+[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev
+
+Fixes: d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260527053133.180695-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index 987ef0954e2ea2..0e96f7cb21a297 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -5790,6 +5790,8 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
+
+ goto nla_put_failure;
+ }
++ if (!READ_ONCE(rt->fib6_nsiblings))
++ break;
+ }
+
+ rcu_read_unlock();
+--
+2.53.0
+
--- /dev/null
+From fc08ca2f450c85073a0bdb2150bf886682099420 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 21:10:31 +0530
+Subject: ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress()
+
+From: Rahul Chandelkar <rc@rexion.ai>
+
+[ Upstream commit 9d5e7a46a9f6d8f503b41bfefef70659845f1679 ]
+
+ipv6_rpl_srh_decompress() computes:
+
+ outhdr->hdrlen = (((n + 1) * sizeof(struct in6_addr)) >> 3);
+
+hdrlen is __u8. For n >= 127 the result exceeds 255 and silently
+truncates. With n=127 (cmpri=15, cmpre=15, pad=0, hdrlen=16):
+
+ (128 * 16) >> 3 = 256, truncated to 0 as __u8
+
+The caller in ipv6_rpl_srh_rcv() then places the compressed header
+at buf + ((ohdr->hdrlen + 1) << 3). With hdrlen=0 this is buf + 8,
+but the decompressed region occupies buf[0..2055] (8-byte header
+plus 128 full addresses). The compressed header overlaps the
+decompressed data, and ipv6_rpl_srh_compress() writes into this
+overlap, corrupting the routing header of the forwarded packet.
+
+The existing guard at exthdrs.c:546 checks (n + 1) > 255, which
+prevents n+1 from overflowing unsigned char (the segments_left
+field), but does not prevent the computed hdrlen from overflowing
+__u8. n=127 passes because 128 <= 255, yet hdrlen=256 does not
+fit.
+
+Tighten the bound to (n + 1) > 127. This caps n at 126, giving
+hdrlen = (127 * 16) >> 3 = 254, which fits in __u8. The compressed
+header then lands at buf + ((254 + 1) << 3) = buf + 2040, exactly
+past the decompressed region (buf[0..2039]). No overlap. 127
+segments is well beyond any realistic RPL deployment.
+
+Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
+Signed-off-by: Rahul Chandelkar <rc@rexion.ai>
+Link: https://patch.msgid.link/20260525154031.2290876-1-rc@rexion.ai
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/exthdrs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
+index 826ef36aa2bcc0..13e57e3f7d7981 100644
+--- a/net/ipv6/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -564,7 +564,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
+ * unsigned char which is segments_left field. Should not be
+ * higher than that.
+ */
+- if (r || (n + 1) > 255) {
++ if (r || (n + 1) > 127) {
+ kfree_skb(skb);
+ return -1;
+ }
+--
+2.53.0
+
--- /dev/null
+From b8ed18def3adb8737a3547e5363196f58fd7c05e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 20:49:56 +0530
+Subject: kernel/fork: validate exit_signal in kernel_clone()
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit 09e7827e785729f391c8d46dc71becce70d296ab ]
+
+When a child process exits, it sends exit_signal to its parent via
+do_notify_parent(). The clone() syscall constructs exit_signal as:
+
+(lower_32_bits(clone_flags) & CSIGNAL)
+
+CSIGNAL is 0xff, so values in the range 65-255 are possible. However,
+valid_signal() only accepts signals up to _NSIG (64 on x86_64). A
+non-zero non-valid exit_signal acts the same as exit_signal == 0: the
+parent process is not signaled when the child terminates.
+
+The syzkaller reproducer triggers this by calling clone() with flags=0x80,
+resulting in exit_signal = (0x80 & CSIGNAL) = 128, which exceeds _NSIG and
+is not a valid signal.
+
+The v1 of this patch added the check only in the clone() syscall handler,
+which is incomplete. kernel_clone() has other callers such as
+sys_ia32_clone() which would remain unprotected. Move the check to
+kernel_clone() to cover all callers.
+
+Since the valid_signal() check is now in kernel_clone() and covers all
+callers including clone3(), the same check in copy_clone_args_from_user()
+becomes redundant and is removed. The higher 32bits check for clone3() is
+kept as it is clone3() specific.
+
+Note that this is a user-visible change: previously, passing an invalid
+exit_signal to clone() was silently accepted. The man page for clone()
+does not document any defined behavior for invalid exit_signal values, so
+rejecting them with -EINVAL is the correct behavior. It is unlikely that
+any sane application relies on passing an invalid exit_signal.
+
+[oleg@redhat.com: the comment above kernel_clone() should be updated]
+ Link: https://lore.kernel.org/abwvgU17W8wuW2-J@redhat.com
+Link: https://lore.kernel.org/20260316151956.563558-1-kartikey406@gmail.com
+Fixes: 3f2c788a1314 ("fork: prevent accidental access to clone3 features")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Reported-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=bbe6b99feefc3a0842de
+Tested-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/all/20260307064202.353405-1-kartikey406@gmail.com/T/ [v1]
+Link: https://lore.kernel.org/all/20260316104536.558108-1-kartikey406@gmail.com/T/ [v2]
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Ben Segall <bsegall@google.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Juri Lelli <juri.lelli@redhat.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: Liam Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
+Cc: Mel Gorman <mgorman@suse.de>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Valentin Schneider <vschneid@redhat.com>
+Cc: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/fork.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index db2a9016f636f4..9931ee7e1dfa4a 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -2717,8 +2717,6 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
+ *
+ * It copies the process, and if successful kick-starts
+ * it and waits for it to finish using the VM if required.
+- *
+- * args->exit_signal is expected to be checked for sanity by the caller.
+ */
+ pid_t kernel_clone(struct kernel_clone_args *args)
+ {
+@@ -2743,6 +2741,9 @@ pid_t kernel_clone(struct kernel_clone_args *args)
+ (args->pidfd == args->parent_tid))
+ return -EINVAL;
+
++ if (!valid_signal(args->exit_signal))
++ return -EINVAL;
++
+ /*
+ * Determine whether and which event to report to ptracer. When
+ * called from kernel_thread or CLONE_UNTRACED is explicitly
+@@ -2943,11 +2944,9 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
+ return -EINVAL;
+
+ /*
+- * Verify that higher 32bits of exit_signal are unset and that
+- * it is a valid signal
++ * Verify that higher 32bits of exit_signal are unset
+ */
+- if (unlikely((args.exit_signal & ~((u64)CSIGNAL)) ||
+- !valid_signal(args.exit_signal)))
++ if (unlikely(args.exit_signal & ~((u64)CSIGNAL)))
+ return -EINVAL;
+
+ if ((args.flags & CLONE_INTO_CGROUP) &&
+--
+2.53.0
+
--- /dev/null
+From 0b29ab076e6420d94cdf71344843273ac24c035c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 15:03:30 +0200
+Subject: net: hsr: fix potential OOB access in supervision frame handling
+
+From: Luka Gejak <luka.gejak@linux.dev>
+
+[ Upstream commit f229426072fc865654a60978bb7fda790a051ff3 ]
+
+Ensure the entire TLV header is linearized before access by adding
+sizeof(struct hsr_sup_tlv) to the pskb_may_pull() calls. Without this,
+a truncated frame could cause an out-of-bounds access.
+
+Fixes: eafaa88b3eb7 ("net: hsr: Add support for redbox supervision frames")
+Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Link: https://patch.msgid.link/20260523130330.61880-1-luka.gejak@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_forward.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
+index 3852fd99509f04..7a596c4f603e2d 100644
+--- a/net/hsr/hsr_forward.c
++++ b/net/hsr/hsr_forward.c
+@@ -84,7 +84,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
+
+ /* Get next tlv */
+ total_length += hsr_sup_tag->tlv.HSR_TLV_length;
+- if (!pskb_may_pull(skb, total_length))
++ if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
+ return false;
+ skb_pull(skb, total_length);
+ hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data;
+@@ -100,7 +100,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
+
+ /* make sure another tlv follows */
+ total_length += sizeof(struct hsr_sup_tlv) + hsr_sup_tlv->HSR_TLV_length;
+- if (!pskb_may_pull(skb, total_length))
++ if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
+ return false;
+
+ /* get next tlv */
+--
+2.53.0
+
--- /dev/null
+From 277a6dc2ceb871eeb57e47f85f1a96b4074d627f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 07:11:45 -0700
+Subject: net/iucv: fix locking in .getsockopt
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 3589d20a666caf30ad100c960a2de7de390fce88 ]
+
+Mirror iucv_sock_setsockopt() and wrap the whole switch in
+lock_sock()/release_sock(). The pre-existing SO_MSGLIMIT-only lock
+becomes redundant and is removed.
+
+Any AF_IUCV HIPER user can potentially crash the kernel by racing
+recvmsg() with getsockopt(SO_MSGSIZE): the SO_MSGSIZE arm dereferences
+iucv->hs_dev->mtu after iucv_sock_close() (called from the racing
+recvmsg()) has set hs_dev to NULL, producing a NULL pointer dereference
+oops.
+
+Suggested-by: Stanislav Fomichev <sdf.kernel@gmail.com>
+Fixes: 51363b8751a6 ("af_iucv: allow retrieval of maximum message size")
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
+Tested-by: Alexandra Winter <wintera@linux.ibm.com>
+Link: https://patch.msgid.link/20260521-af_iucv_fix2-v1-1-f16b1c510aa9@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/iucv/af_iucv.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index 0f660b1d3bd51c..e9a9bb0dee065a 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -1539,7 +1539,7 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+ struct sock *sk = sock->sk;
+ struct iucv_sock *iucv = iucv_sk(sk);
+ unsigned int val;
+- int len;
++ int len, rc;
+
+ if (level != SOL_IUCV)
+ return -ENOPROTOOPT;
+@@ -1552,26 +1552,34 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+
+ len = min_t(unsigned int, len, sizeof(int));
+
++ rc = 0;
++
++ lock_sock(sk);
+ switch (optname) {
+ case SO_IPRMDATA_MSG:
+ val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0;
+ break;
+ case SO_MSGLIMIT:
+- lock_sock(sk);
+ val = (iucv->path != NULL) ? iucv->path->msglim /* connected */
+ : iucv->msglimit; /* default */
+- release_sock(sk);
+ break;
+ case SO_MSGSIZE:
+- if (sk->sk_state == IUCV_OPEN)
+- return -EBADFD;
++ if (sk->sk_state == IUCV_OPEN) {
++ rc = -EBADFD;
++ break;
++ }
+ val = (iucv->hs_dev) ? iucv->hs_dev->mtu -
+ sizeof(struct af_iucv_trans_hdr) - ETH_HLEN :
+ 0x7fffffff;
+ break;
+ default:
+- return -ENOPROTOOPT;
++ rc = -ENOPROTOOPT;
++ break;
+ }
++ release_sock(sk);
++
++ if (rc)
++ return rc;
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+--
+2.53.0
+
--- /dev/null
+From 887318a634db628011b9fada12068b88c78a2c19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 01:08:24 -0700
+Subject: net: mana: Add NULL guards in teardown path to prevent panic on
+ attach failure
+
+From: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+
+[ Upstream commit 17bfe0a8c014ee1d542ad352cd6a0a505361664a ]
+
+When queue allocation fails partway through, the error cleanup frees
+and NULLs apc->tx_qp and apc->rxqs. Multiple teardown paths such as
+mana_remove(), mana_change_mtu() recovery, and internal error handling
+in mana_alloc_queues() can subsequently call into functions that
+dereference these pointers without NULL checks:
+
+- mana_chn_setxdp() dereferences apc->rxqs[0], causing a NULL pointer
+ dereference panic (CR2: 0000000000000000 at mana_chn_setxdp+0x26).
+- mana_destroy_vport() iterates apc->rxqs without a NULL check.
+- mana_fence_rqs() iterates apc->rxqs without a NULL check.
+- mana_dealloc_queues() iterates apc->tx_qp without a NULL check.
+
+Add NULL guards for apc->rxqs in mana_fence_rqs(),
+mana_destroy_vport(), and before the mana_chn_setxdp() call. Add a
+NULL guard for apc->tx_qp in mana_dealloc_queues() to skip TX queue
+draining when TX queues were never allocated or already freed.
+
+Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+Link: https://patch.msgid.link/20260525081129.1230035-2-dipayanroy@linux.microsoft.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 70 +++++++++++--------
+ 1 file changed, 41 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 3f46a6edcee521..0f84cc4586f02e 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -914,6 +914,9 @@ static void mana_fence_rqs(struct mana_port_context *apc)
+ struct mana_rxq *rxq;
+ int err;
+
++ if (!apc->rxqs)
++ return;
++
+ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+ rxq = apc->rxqs[rxq_idx];
+ err = mana_fence_rq(apc, rxq);
+@@ -1815,13 +1818,16 @@ static void mana_destroy_vport(struct mana_port_context *apc)
+ struct mana_rxq *rxq;
+ u32 rxq_idx;
+
+- for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+- rxq = apc->rxqs[rxq_idx];
+- if (!rxq)
+- continue;
++ if (apc->rxqs) {
+
+- mana_destroy_rxq(apc, rxq, true);
+- apc->rxqs[rxq_idx] = NULL;
++ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
++ rxq = apc->rxqs[rxq_idx];
++ if (!rxq)
++ continue;
++
++ mana_destroy_rxq(apc, rxq, true);
++ apc->rxqs[rxq_idx] = NULL;
++ }
+ }
+
+ mana_destroy_txq(apc);
+@@ -2010,7 +2016,8 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ if (apc->port_is_up)
+ return -EINVAL;
+
+- mana_chn_setxdp(apc, NULL);
++ if (apc->rxqs)
++ mana_chn_setxdp(apc, NULL);
+
+ if (gd->gdma_context->is_pf)
+ mana_pf_deregister_filter(apc);
+@@ -2028,33 +2035,38 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ * number of queues.
+ */
+
+- for (i = 0; i < apc->num_queues; i++) {
+- txq = &apc->tx_qp[i].txq;
+- tsleep = 1000;
+- while (atomic_read(&txq->pending_sends) > 0 &&
+- time_before(jiffies, timeout)) {
+- usleep_range(tsleep, tsleep + 1000);
+- tsleep <<= 1;
+- }
+- if (atomic_read(&txq->pending_sends)) {
+- err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
+- if (err) {
+- netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+- err, atomic_read(&txq->pending_sends),
+- txq->gdma_txq_id);
++ if (apc->tx_qp) {
++ for (i = 0; i < apc->num_queues; i++) {
++ txq = &apc->tx_qp[i].txq;
++ tsleep = 1000;
++ while (atomic_read(&txq->pending_sends) > 0 &&
++ time_before(jiffies, timeout)) {
++ usleep_range(tsleep, tsleep + 1000);
++ tsleep <<= 1;
++ }
++ if (atomic_read(&txq->pending_sends)) {
++ err =
++ pcie_flr(to_pci_dev(gd->gdma_context->dev));
++ if (err) {
++ netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
++ err,
++ atomic_read(&txq->pending_sends),
++ txq->gdma_txq_id);
++ }
++ break;
+ }
+- break;
+ }
+- }
+
+- for (i = 0; i < apc->num_queues; i++) {
+- txq = &apc->tx_qp[i].txq;
+- while ((skb = skb_dequeue(&txq->pending_skbs))) {
+- mana_unmap_skb(skb, apc);
+- dev_kfree_skb_any(skb);
++ for (i = 0; i < apc->num_queues; i++) {
++ txq = &apc->tx_qp[i].txq;
++ while ((skb = skb_dequeue(&txq->pending_skbs))) {
++ mana_unmap_skb(skb, apc);
++ dev_kfree_skb_any(skb);
++ }
++ atomic_set(&txq->pending_sends, 0);
+ }
+- atomic_set(&txq->pending_sends, 0);
+ }
++
+ /* We're 100% sure the queues can no longer be woken up, because
+ * we're sure now mana_poll_tx_cq() can't be running.
+ */
+--
+2.53.0
+
--- /dev/null
+From 87583f214a963aadfd305bd6e219b3164ca2a4f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:36 +0200
+Subject: net: netlink: don't set nsid on local notifications
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 88b126b39f9757e9debc322d4679239e9af089c7 ]
+
+In most cases, notifications on sockets with NETLINK_LISTEN_ALL_NSID
+do not contain NSID in their ancillary data in case the event is local
+to the listener.
+
+However, when a self-referential NSID is allocated for a namespace,
+every local notification starts sending this ID to the user space.
+
+This is problematic, because the listener cannot tell if those
+notifications are local or not anymore without making extra requests
+to figure out if the provided NSID is local or not. The listener
+can also not figure out the local NSID beforehand as it can be
+allocated at any point in time by other processes, changing the
+structure of the future notifications for everyone.
+
+The value is practically not useful, since it's the namespace's own
+ID that the application has to obtain from other sources in order to
+figure out if it's the same or not. So, for the application it's
+just an extra busy work with no benefits. Moreover, applications
+that do not know about this quirk may be mishandling notifications
+with NSID set as notifications from remote namespaces. This is the
+case for ovs-vswitchd and the iproute2's 'ip monitor' that stops
+printing 'current' and starts printing the nsid number mid-session.
+
+Lack of clear documentation for this behavior is also not helping.
+
+A search though open-source projects doesn't reveal any projects
+that use NETNSA_NSID_NOT_ASSIGNED and rely on metadata to contain
+self-referential NSIDs (expected, since the value is not useful).
+Quite the opposite, as already mentioned, there are few applications
+that rely on NSID to not be present in local events.
+
+Since the value is not useful and actively harmful in some cases,
+let's not report it for local events, making the notifications more
+consistent.
+
+Also adding some blank lines for readability.
+
+Fixes: 59324cf35aba ("netlink: allow to listen "all" netns")
+Reported-by: Matteo Perin <matteo.perin@canonical.com>
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-3-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index f502a57ad5470e..f5d4eba785d03c 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1473,10 +1473,14 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++
+ NETLINK_CB(p->skb2).nsid_is_set = false;
+- NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+- if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+- NETLINK_CB(p->skb2).nsid_is_set = true;
++ if (!net_eq(sock_net(sk), p->net)) {
++ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
++ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
++ NETLINK_CB(p->skb2).nsid_is_set = true;
++ }
++
+ val = netlink_broadcast_deliver(sk, p->skb2);
+ if (val < 0) {
+ netlink_overrun(sk);
+--
+2.53.0
+
--- /dev/null
+From 7b8fa930fb47141bf44e3402249e442349265a97 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:35 +0200
+Subject: net: netlink: fix sending unassigned nsid after assigned one
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 70f8592ee90585272018a725054b6eb2ab7e99ca ]
+
+If the current skb is not shared, it is re-used directly for all the
+sockets subscribed to the notification. If we have remote all-nsid
+socket receiving a message first, then the 'nsid_is_set' will be
+set to 'true'. If the nsid is NOT_ASSIGNED for the next socket in
+the list, the 'nsid_is_set' will remain 'true' and the negative value
+is be delivered to the user space. All subsequent nsid values will be
+delivered as well, since there is no code path that sets the flag
+back to 'false'.
+
+Fix that by always dropping the flag to 'false' first.
+
+Fixes: 7212462fa6fd ("netlink: don't send unknown nsid")
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-2-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 8c441c98ba5630..f502a57ad5470e 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1473,6 +1473,7 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++ NETLINK_CB(p->skb2).nsid_is_set = false;
+ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+ NETLINK_CB(p->skb2).nsid_is_set = true;
+--
+2.53.0
+
--- /dev/null
+From f0782e00e36a05e61adcdd37cb84129da8466d7a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:49 -0400
+Subject: net/sched: Revert "net/sched: Restrict conditions for adding
+ duplicating netems to qdisc tree"
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit eda0b7f203bb166c98d1418b204135bd566ac83b ]
+
+This reverts commit ec8e0e3d7adef940cdf9475e2352c0680189d14e.
+
+The original patch rejects any tree containing two netems when
+either has duplication set, even when they sit on unrelated classes
+of the same classful parent. That broke configurations that have
+worked since netem was introduced.
+
+The re-entrancy problem the original commit was trying to solve is
+handled by later patch using tc_depth flag.
+
+Doing this revert will (re)expose the original bug with multiple
+netem duplication. When this patch is backported make sure
+and get the full series.
+
+Fixes: ec8e0e3d7ade ("net/sched: Restrict conditions for adding duplicating netems to qdisc tree")
+Reported-by: Ji-Soo Chung <jschung2@proton.me>
+Reported-by: Gerlinde <lrGerlinde@mailfence.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220774
+Reported-by: zyc zyc <zyc199902@zohomail.cn>
+Closes: https://lore.kernel.org/all/19adda5a1e2.12410b78222774.9191120410578703463@zohomail.cn/
+Reported-by: Manas Ghandat <ghandatmanas@gmail.com>
+Closes: https://lore.kernel.org/netdev/f69b2c8f-8325-4c2e-a011-6dbc089f30e4@gmail.com/
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-3-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_netem.c | 40 ----------------------------------------
+ 1 file changed, 40 deletions(-)
+
+diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
+index 2c47bd8dba6478..3bebe8043cfaf5 100644
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -984,41 +984,6 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+ return 0;
+ }
+
+-static const struct Qdisc_class_ops netem_class_ops;
+-
+-static int check_netem_in_tree(struct Qdisc *sch, bool duplicates,
+- struct netlink_ext_ack *extack)
+-{
+- struct Qdisc *root, *q;
+- unsigned int i;
+-
+- root = qdisc_root_sleeping(sch);
+-
+- if (sch != root && root->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(root))->duplicate)
+- goto err;
+- }
+-
+- if (!qdisc_dev(root))
+- return 0;
+-
+- hash_for_each(qdisc_dev(root)->qdisc_hash, i, q, hash) {
+- if (sch != q && q->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(q))->duplicate)
+- goto err;
+- }
+- }
+-
+- return 0;
+-
+-err:
+- NL_SET_ERR_MSG(extack,
+- "netem: cannot mix duplicating netems with other netems in tree");
+- return -EINVAL;
+-}
+-
+ /* Parse netlink message to set options */
+ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
+@@ -1083,11 +1048,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ q->gap = qopt->gap;
+ q->counter = 0;
+ q->loss = qopt->loss;
+-
+- ret = check_netem_in_tree(sch, qopt->duplicate, extack);
+- if (ret)
+- goto unlock;
+-
+ q->duplicate = qopt->duplicate;
+
+ /* for compatibility with earlier versions.
+--
+2.53.0
+
--- /dev/null
+From 38bf0156ae6705225351535aa395c6dd24a7f70c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 19:43:53 +0100
+Subject: net: skbuff: fix pskb_carve leaking zcopy pages
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit ff6e798c2eac3ebd0501ad7e796f583fab928de8 ]
+
+When SKBFL_MANAGED_FRAG_REFS is set, frag pages are not refcounted but
+their lifetime is controlled by the attached ubuf_info. To make a copy
+of the skb_shared_info, we either should clear the flag and reference
+the frags, or keep the flag and have frags unreferenced.
+
+pskb_carve_inside_header() and pskb_carve_inside_nonlinear() don't
+follow the rule and thus can leak page references. Let's clear
+SKBFL_MANAGED_FRAG_REFS from the original skb to fix it. It's the
+simplest way to address it, but there are more performant ways to do
+that if it ever becomes a problem.
+
+Link: https://lore.kernel.org/all/20260523085809.26331-1-nvminh232@clc.fitus.edu.vn/
+Fixes: 753f1ca4e1e50 ("net: introduce managed frags infrastructure")
+Reported-by: Minh Nguyen <minhnguyen.080505@gmail.com>
+Reported-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/1e2086aa69217d7f9c8da3d38f5be7160f1b4cd1.1779993185.git.asml.silence@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/skbuff.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 8bc4b26de5e538..41b2aaed7a14aa 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -6232,6 +6232,11 @@ static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off,
+ skb_copy_from_linear_data_offset(skb, off, data, new_hlen);
+ skb->len -= off;
+
++ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
++ * while refcounting frags below.
++ */
++ skb_zcopy_downgrade_managed(skb);
++
+ memcpy((struct skb_shared_info *)(data + size),
+ skb_shinfo(skb),
+ offsetof(struct skb_shared_info,
+@@ -6344,6 +6349,11 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,
+ return -ENOMEM;
+ size = SKB_WITH_OVERHEAD(size);
+
++ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
++ * while refcounting frags below.
++ */
++ skb_zcopy_downgrade_managed(skb);
++
+ memcpy((struct skb_shared_info *)(data + size),
+ skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0]));
+ if (skb_orphan_frags(skb, gfp_mask)) {
+--
+2.53.0
+
--- /dev/null
+From 2a6427b72ba9dcb901fec45dc4de27ea66c17565 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 16:56:39 +0200
+Subject: net/smc: Do not re-initialize smc hashtables
+
+From: Alexandra Winter <wintera@linux.ibm.com>
+
+[ Upstream commit 9e4389b0038781f19f97895186ed941ff8ac1678 ]
+
+INIT_HLIST_HEAD(&smc_v*_hashinfo.ht) are called after smc_nl_init(),
+proto_register() and sock_register(). This can lead to smc_v*_hashinfo.ht
+being reset even though hash entries already exist and are being used,
+possibly resulting in a corrupted list.
+
+Remove unnecessary and dangerous re-initialisation of smc_v*_hashinfo.ht in
+smc_init(); it is implicitly initialised to zero anyhow. Add
+HLIST_HEAD_INIT to the definitions for clarity.
+
+Fixes: f16a7dd5cf27 ("smc: netlink interface for SMC sockets")
+Suggested-by: Halil Pasic <pasic@linux.ibm.com>
+Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
+Acked-by: Halil Pasic <pasic@linux.ibm.com>
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Link: https://patch.msgid.link/20260521145639.10317-1-wintera@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index b0f8eca077b893..012a7da967441d 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -180,10 +180,12 @@ static bool smc_hs_congested(const struct sock *sk)
+
+ static struct smc_hashinfo smc_v4_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v4_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ static struct smc_hashinfo smc_v6_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v6_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ int smc_hash_sk(struct sock *sk)
+@@ -3495,8 +3497,6 @@ static int __init smc_init(void)
+ pr_err("%s: sock_register fails with %d\n", __func__, rc);
+ goto out_proto6;
+ }
+- INIT_HLIST_HEAD(&smc_v4_hashinfo.ht);
+- INIT_HLIST_HEAD(&smc_v6_hashinfo.ht);
+
+ rc = smc_ib_register_client();
+ if (rc) {
+--
+2.53.0
+
--- /dev/null
+From 3dfaa74871b35bb24db1992f864ad737da52a802 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 22:52:07 +0200
+Subject: netfilter: ebtables: fix OOB read in compat_mtw_from_user
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit f438d1786d657d57790c5d138d6db3fc9fdac392 ]
+
+Luxiao Xu says:
+
+ The function compat_mtw_from_user() converts ebtables extensions from
+ 32-bit user structures to kernel native structures. However, it lacks
+ proper validation of the user-supplied match_size/target_size.
+
+ When certain extensions are processed, the kernel-side translation
+ logic may perform memory accesses based on the extension's expected
+ size. If the user provides a size smaller than what the extension
+ requires, it results in an out-of-bounds read as reported by KASAN.
+
+ This fix introduces a check to ensure match_size is at least as large
+ as the extension's required compatsize. This covers matches, watchers,
+ and targets, while maintaining compatibility with standard targets.
+
+AFAIU this is relevant for matches that need to go though
+match->compat_from_user() call. Those that use plain memcpy with the
+user-provided size are ok because the caller checks that size vs the
+start of the next rule entry offset (which itself is checked vs. total
+size copied from userspace).
+
+The ->compat_from_user() callbacks assume they can read compatsize bytes,
+so they need this extra check.
+
+Based on an earlier patch from Luxiao Xu.
+
+Fixes: 81e675c227ec ("netfilter: ebtables: add CONFIG_COMPAT support")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/netfilter/ebtables.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index f99e348c8f37fa..bc69406d103df6 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -1952,6 +1952,25 @@ enum compat_mwt {
+ EBT_COMPAT_TARGET,
+ };
+
++static bool match_size_ok(const struct xt_match *match, unsigned int match_size)
++{
++ u16 csize;
++
++ if (match->matchsize == -1) /* cannot validate ebt_among */
++ return true;
++
++ csize = match->compatsize ? : match->matchsize;
++
++ return match_size >= csize;
++}
++
++static bool tgt_size_ok(const struct xt_target *tgt, unsigned int tgt_size)
++{
++ u16 csize = tgt->compatsize ? : tgt->targetsize;
++
++ return tgt_size >= csize;
++}
++
+ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ enum compat_mwt compat_mwt,
+ struct ebt_entries_buf_state *state,
+@@ -1977,6 +1996,11 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+
++ if (!match_size_ok(match, match_size)) {
++ module_put(match->me);
++ return -EINVAL;
++ }
++
+ off = ebt_compat_match_offset(match, match_size);
+ if (dst) {
+ if (match->compat_from_user)
+@@ -1996,6 +2020,12 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ mwt->u.revision);
+ if (IS_ERR(wt))
+ return PTR_ERR(wt);
++
++ if (!tgt_size_ok(wt, match_size)) {
++ module_put(wt->me);
++ return -EINVAL;
++ }
++
+ off = xt_compat_target_offset(wt);
+
+ if (dst) {
+--
+2.53.0
+
--- /dev/null
+From ab8e73dd82db0bae81cac0f2b54f4cb37bc6849d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 12:36:14 -0700
+Subject: netfilter: synproxy: refresh tcphdr after skb_ensure_writable
+
+From: Chris Mason <clm@meta.com>
+
+[ Upstream commit 92170e6afe927ab2792a3f71902845789c8e31b1 ]
+
+synproxy_tstamp_adjust() rewrites the TCP timestamp option in place
+and then patches the TCP checksum via inet_proto_csum_replace4() on
+the caller-supplied tcphdr pointer. Both ipv4_synproxy_hook() and
+ipv6_synproxy_hook() obtain that pointer with skb_header_pointer()
+before calling in, so it may either alias skb->head directly or
+point at the caller's on-stack _tcph buffer.
+
+Between obtaining the pointer and using it, the function calls
+skb_ensure_writable(skb, optend), which on a cloned or non-linear
+skb invokes pskb_expand_head() and frees the old skb->head. After
+that point the cached th is stale:
+
+ caller (ipv[46]_synproxy_hook)
+ th = skb_header_pointer(skb, ..., &_tcph)
+ synproxy_tstamp_adjust(skb, protoff, th, ...)
+ skb_ensure_writable(skb, optend)
+ pskb_expand_head() /* kfree(old skb->head) */
+ ...
+ inet_proto_csum_replace4(&th->check, ...)
+ /* writes into freed head, or
+ into the caller's stack copy
+ leaving the on-wire checksum
+ stale */
+
+The option bytes are written through skb->data and are fine; only
+the checksum update goes through th and so lands in the wrong
+place. The result is either a write into freed slab memory or a
+packet leaving with a checksum that does not match its payload.
+
+Fix by re-deriving th from skb->data + protoff immediately after
+skb_ensure_writable() succeeds, so the subsequent checksum update
+targets the linear, writable header.
+
+Fixes: 48b1de4c110a ("netfilter: add SYNPROXY core/target")
+Assisted-by: kres (claude-opus-4-7)
+Signed-off-by: Chris Mason <clm@meta.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_synproxy_core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 16915f8eef2b16..f5a52075691faa 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -199,6 +199,8 @@ synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,
+ if (skb_ensure_writable(skb, optend))
+ return 0;
+
++ th = (struct tcphdr *)(skb->data + protoff);
++
+ while (optoff < optend) {
+ unsigned char *op = skb->data + optoff;
+
+--
+2.53.0
+
--- /dev/null
+From ac92733db8b1e88939556d09b9dc735b73ae25eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 20:10:08 +0200
+Subject: netfilter: xt_cpu: prefer raw_smp_processor_id
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit c376f07e16c02239ed44cabb97145d03f65b4d15 ]
+
+With PREEMPT_RCU we get splat:
+
+BUG: using smp_processor_id() in preemptible [..]
+caller is cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+CPU: 1 .. Comm: syz.3.1377 #0 PREEMPT(full)
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
+ check_preemption_disabled+0xd3/0xe0 lib/smp_processor_id.c:47
+ cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+ [..]
+
+Just use raw version instead.
+This is similar to 14d14a5d2957 ("netfilter: nft_meta: use raw_smp_processor_id()").
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Reported-by: syzbot+690d3e3ffa7335ac10eb@syzkaller.appspotmail.com
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/xt_cpu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_cpu.c b/net/netfilter/xt_cpu.c
+index 3bdc302a0f9137..9cb259902a586b 100644
+--- a/net/netfilter/xt_cpu.c
++++ b/net/netfilter/xt_cpu.c
+@@ -34,7 +34,7 @@ static bool cpu_mt(const struct sk_buff *skb, struct xt_action_param *par)
+ {
+ const struct xt_cpu_info *info = par->matchinfo;
+
+- return (info->cpu == smp_processor_id()) ^ info->invert;
++ return (info->cpu == raw_smp_processor_id()) ^ info->invert;
+ }
+
+ static struct xt_match cpu_mt_reg __read_mostly = {
+--
+2.53.0
+
--- /dev/null
+From c32c38996dfd259ee827a46098b263a72fd3261c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:41 +0000
+Subject: nfc: llcp: Fix use-after-free in llcp_sock_release()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit f4268b466190dae95a7585f69b4f1f8ad097632c ]
+
+llcp_sock_release() unconditionally unlinks the socket from the local
+sockets list. However, if the socket is still in connecting state, it
+is on the connecting list.
+
+Fix this by checking the socket state and unlinking from the correct list.
+
+Fixes: b4011239a08e ("NFC: llcp: Fix non blocking sockets connections")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-1-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_sock.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index cd0fd26196b8b6..6cdcc49a58bcd5 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -633,6 +633,8 @@ static int llcp_sock_release(struct socket *sock)
+
+ if (sock->type == SOCK_RAW)
+ nfc_llcp_sock_unlink(&local->raw_sockets, sk);
++ else if (sk->sk_state == LLCP_CONNECTING)
++ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ else
+ nfc_llcp_sock_unlink(&local->sockets, sk);
+
+--
+2.53.0
+
--- /dev/null
+From d4e4ff599f7d61e66989494fc457d98a740ca2cb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:42 +0000
+Subject: nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit b493ea2765cc17cb8aa7e7544a4b6dcb05b6ed77 ]
+
+A race condition exists in the NFC LLCP connection state machine where
+the connection acceptance packet (CC) can be processed concurrently with
+socket release. This can lead to a use-after-free of the socket object.
+
+When nfc_llcp_recv_cc() moves the socket from the connecting_sockets
+list to the sockets list, it does so without holding the socket lock.
+If llcp_sock_release() is executing concurrently, it might have already
+unlinked the socket and dropped its references, which can result in
+nfc_llcp_recv_cc() linking a freed socket into the live list.
+
+Fix this by holding lock_sock() during the state transition and list
+movement in nfc_llcp_recv_cc(). After acquiring the lock, check if
+the socket is still hashed to ensure it hasn't already been unlinked
+and marked for destruction by the release path. This aligns the locking
+pattern with recv_hdlc() and recv_disc().
+
+Fixes: a69f32af86e3 ("NFC: Socket linked list")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-2-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_core.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
+index d9562840fa180b..62b0f2d6686eb8 100644
+--- a/net/nfc/llcp_core.c
++++ b/net/nfc/llcp_core.c
+@@ -1216,6 +1216,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+
+ sk = &llcp_sock->sk;
+
++ lock_sock(sk);
++
++ /* Check if socket was destroyed whilst waiting for the lock */
++ if (!sk_hashed(sk)) {
++ release_sock(sk);
++ nfc_llcp_sock_put(llcp_sock);
++ return;
++ }
++
+ /* Unlink from connecting and link to the client array */
+ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ nfc_llcp_sock_link(&local->sockets, sk);
+@@ -1227,6 +1236,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+ sk->sk_state = LLCP_CONNECTED;
+ sk->sk_state_change(sk);
+
++ release_sock(sk);
++
+ nfc_llcp_sock_put(llcp_sock);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From f0d02dec96b3c85b336ad9ff6d259d0688281009 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 May 2026 19:55:18 +0800
+Subject: nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems
+
+From: Carl Lee <carl.lee@amd.com>
+
+[ Upstream commit f23bf992d65a42007c517b060ca35cebdea3525a ]
+
+Some ACPI-based platforms report incorrect IRQ trigger types (e.g.
+IRQF_TRIGGER_HIGH), which can lead to interrupt storms.
+
+Use the historically working rising-edge trigger on ACPI systems to
+avoid this regression.
+
+Device Tree-based systems continue to use the firmware-provided
+trigger type.
+
+Fixes: 57be33f85e36 ("nfc: nxp-nci: remove interrupt trigger type")
+Signed-off-by: Carl Lee <carl.lee@amd.com>
+Tested-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Luca Stefani <luca.stefani.ge1@gmail.com>
+Link: https://patch.msgid.link/20260516-nfc-nxp-nci-i2c-restore-irq-trigger-fallback-v3-1-37ba4b6e9086@amd.com
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/nxp-nci/i2c.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
+index f256c85888229a..9b9ca3ced856b4 100644
+--- a/drivers/nfc/nxp-nci/i2c.c
++++ b/drivers/nfc/nxp-nci/i2c.c
+@@ -16,6 +16,7 @@
+ #include <linux/delay.h>
+ #include <linux/i2c.h>
+ #include <linux/interrupt.h>
++#include <linux/irq.h>
+ #include <linux/module.h>
+ #include <linux/nfc.h>
+ #include <linux/gpio/consumer.h>
+@@ -268,6 +269,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
+ {
+ struct device *dev = &client->dev;
+ struct nxp_nci_i2c_phy *phy;
++ unsigned long irqflags;
+ int r;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+@@ -304,9 +306,26 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
+ if (r < 0)
+ return r;
+
++ /*
++ * ACPI platforms may report incorrect IRQ trigger types
++ * (e.g. level-high), which can lead to interrupt storms.
++ *
++ * Use the historically stable rising-edge trigger for ACPI devices.
++ *
++ * On non-ACPI systems (e.g. Device Tree), prefer the firmware-
++ * provided trigger type, falling back to rising-edge if not set.
++ */
++ if (ACPI_COMPANION(dev)) {
++ irqflags = IRQF_TRIGGER_RISING;
++ } else {
++ irqflags = irq_get_trigger_type(client->irq);
++ if (!irqflags)
++ irqflags = IRQF_TRIGGER_RISING;
++ }
++
+ r = request_threaded_irq(client->irq, NULL,
+ nxp_nci_i2c_irq_thread_fn,
+- IRQF_ONESHOT,
++ irqflags | IRQF_ONESHOT,
+ NXP_NCI_I2C_DRIVER_NAME, phy);
+ if (r < 0)
+ nfc_err(&client->dev, "Unable to register IRQ handler\n");
+--
+2.53.0
+
--- /dev/null
+From 87a75459a2341fcf236e5a31f9cddef2f14f909f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 11:24:11 +0800
+Subject: sctp: fix race between sctp_wait_for_connect and peeloff
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit f14fe6395a8b3d961a61e138ad7b36ba3626dd4e ]
+
+sctp_wait_for_connect() drops and re-acquires the socket lock while
+waiting for the association to reach ESTABLISHED state. During this
+window, another thread can peeloff the association to a new socket via
+getsockopt(SCTP_SOCKOPT_PEELOFF), changing asoc->base.sk. After
+re-acquiring the old socket lock, sctp_wait_for_connect() returns
+success without noticing the migration — the caller then accesses
+the association under the wrong lock in sctp_datamsg_from_user().
+
+Add the same sk != asoc->base.sk check that sctp_wait_for_sndbuf()
+already has, returning an error if the association was migrated while
+we slept.
+
+Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260527032411.60959-1-kipreyyy@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/socket.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index b544f403f7ca8f..867a426867a7d1 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -9364,6 +9364,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
+ release_sock(sk);
+ current_timeo = schedule_timeout(current_timeo);
+ lock_sock(sk);
++ if (sk != asoc->base.sk)
++ goto do_error;
+
+ *timeo_p = current_timeo;
+ }
+--
+2.53.0
+
net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
drm-remove-plane-hsub-vsub-alignment-requirement-for.patch
net-cpsw_new-fix-potential-unregister-of-netdev-that.patch
+nfc-llcp-fix-use-after-free-in-llcp_sock_release.patch
+nfc-llcp-fix-use-after-free-race-in-nfc_llcp_recv_cc.patch
+xfrm-check-for-underflow-in-xfrm_state_mtu.patch
+nfc-nxp-nci-i2c-use-rising-edge-irq-on-acpi-systems.patch
+tools-bootconfig-cleanup-bootconfig-footer-size-calc.patch
+tools-bootconfig-fix-buf-leaks-in-apply_xbc.patch
+kernel-fork-validate-exit_signal-in-kernel_clone.patch
+netfilter-synproxy-refresh-tcphdr-after-skb_ensure_w.patch
+netfilter-xt_cpu-prefer-raw_smp_processor_id.patch
+netfilter-ebtables-fix-oob-read-in-compat_mtw_from_u.patch
+tun-free-page-on-short-frame-rejection-in-tun_xdp_on.patch
+tun-free-page-on-build_skb-failure-in-tun_xdp_one.patch
+net-netlink-fix-sending-unassigned-nsid-after-assign.patch
+net-netlink-don-t-set-nsid-on-local-notifications.patch
+net-smc-do-not-re-initialize-smc-hashtables.patch
+net-iucv-fix-locking-in-.getsockopt.patch
+ipv4-free-net-ipv4.sysctl_local_reserved_ports-after.patch
+asoc-intel-bytcht_es8316-fix-mclk-leak-on-init-error.patch
+net-hsr-fix-potential-oob-access-in-supervision-fram.patch
+tunnels-load-network-headers-after-skb_cow-in-iptunn.patch
+vxlan-do-not-reuse-cached-ip_hdr-value-after-skb_tun.patch
+tunnels-do-not-assume-transport-header-in-iptunnel_p.patch
+asoc-codecs-simple-mux-fix-enum-control-bounds-check.patch
+bluetooth-6lowpan-check-skb_clone-return-value-in-se.patch
+bonding-refuse-to-enslave-can-devices.patch
+ethtool-eeprom-add-more-safeties-to-eeprom-netlink-f.patch
+ipv6-rpl-fix-hdrlen-overflow-in-ipv6_rpl_srh_decompr.patch
+net-sched-revert-net-sched-restrict-conditions-for-a.patch
+bluetooth-l2cap-clear-chan-ident-on-ecred-reconfigur.patch
+bluetooth-l2cap-fix-possible-crash-on-l2cap_ecred_co.patch
+gpio-rockchip-convert-bank-clk-to-devm_clk_get_enabl.patch
+net-mana-add-null-guards-in-teardown-path-to-prevent.patch
+sctp-fix-race-between-sctp_wait_for_connect-and-peel.patch
+ipv6-fix-possible-infinite-loop-in-rt6_fill_node.patch
+ipv6-fix-possible-infinite-loop-in-fib6_select_path.patch
+net-skbuff-fix-pskb_carve-leaking-zcopy-pages.patch
--- /dev/null
+From ac0eebf10a72887064f430ccaeb21d016f6fefb4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Jul 2025 11:24:17 +0900
+Subject: tools/bootconfig: Cleanup bootconfig footer size calculations
+
+From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+
+[ Upstream commit 26dda57695090e05c1a99c3e8f802f862d1ac474 ]
+
+There are many same pattern of 8 + BOOTCONFIG_MAGIC_LEN for calculating
+the size of bootconfig footer. Use BOOTCONFIG_FOOTER_SIZE macro to
+clean up those magic numbers.
+
+Link: https://lore.kernel.org/all/175211425693.2591046.16029516706923643510.stgit@mhiramat.tok.corp.google.com/
+
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Stable-dep-of: f42d01aadced ("tools/bootconfig: Fix buf leaks in apply_xbc")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/bootconfig/main.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c
+index 32cf48f2da9a1d..d302235f6b9743 100644
+--- a/tools/bootconfig/main.c
++++ b/tools/bootconfig/main.c
+@@ -16,6 +16,10 @@
+
+ #define pr_err(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
+
++/* Bootconfig footer is [size][csum][BOOTCONFIG_MAGIC]. */
++#define BOOTCONFIG_FOOTER_SIZE \
++ (sizeof(uint32_t) * 2 + BOOTCONFIG_MAGIC_LEN)
++
+ static int xbc_show_value(struct xbc_node *node, bool semicolon)
+ {
+ const char *val, *eol;
+@@ -188,7 +192,7 @@ static int load_xbc_from_initrd(int fd, char **buf)
+ if (ret < 0)
+ return -errno;
+
+- if (stat.st_size < 8 + BOOTCONFIG_MAGIC_LEN)
++ if (stat.st_size < BOOTCONFIG_FOOTER_SIZE)
+ return 0;
+
+ if (lseek(fd, -BOOTCONFIG_MAGIC_LEN, SEEK_END) < 0)
+@@ -201,7 +205,7 @@ static int load_xbc_from_initrd(int fd, char **buf)
+ if (memcmp(magic, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN) != 0)
+ return 0;
+
+- if (lseek(fd, -(8 + BOOTCONFIG_MAGIC_LEN), SEEK_END) < 0)
++ if (lseek(fd, -BOOTCONFIG_FOOTER_SIZE, SEEK_END) < 0)
+ return pr_errno("Failed to lseek for size", -errno);
+
+ if (read(fd, &size, sizeof(uint32_t)) < 0)
+@@ -213,12 +217,12 @@ static int load_xbc_from_initrd(int fd, char **buf)
+ csum = le32toh(csum);
+
+ /* Wrong size error */
+- if (stat.st_size < size + 8 + BOOTCONFIG_MAGIC_LEN) {
++ if (stat.st_size < size + BOOTCONFIG_FOOTER_SIZE) {
+ pr_err("bootconfig size is too big\n");
+ return -E2BIG;
+ }
+
+- if (lseek(fd, stat.st_size - (size + 8 + BOOTCONFIG_MAGIC_LEN),
++ if (lseek(fd, stat.st_size - (size + BOOTCONFIG_FOOTER_SIZE),
+ SEEK_SET) < 0)
+ return pr_errno("Failed to lseek", -errno);
+
+@@ -349,7 +353,7 @@ static int delete_xbc(const char *path)
+ ret = fstat(fd, &stat);
+ if (!ret)
+ ret = ftruncate(fd, stat.st_size
+- - size - 8 - BOOTCONFIG_MAGIC_LEN);
++ - size - BOOTCONFIG_FOOTER_SIZE);
+ if (ret)
+ ret = -errno;
+ } /* Ignore if there is no boot config in initrd */
+@@ -379,8 +383,7 @@ static int apply_xbc(const char *path, const char *xbc_path)
+ csum = xbc_calc_checksum(buf, size);
+
+ /* Backup the bootconfig data */
+- data = calloc(size + BOOTCONFIG_ALIGN +
+- sizeof(uint32_t) + sizeof(uint32_t) + BOOTCONFIG_MAGIC_LEN, 1);
++ data = calloc(size + BOOTCONFIG_ALIGN + BOOTCONFIG_FOOTER_SIZE, 1);
+ if (!data)
+ return -ENOMEM;
+ memcpy(data, buf, size);
+@@ -428,7 +431,7 @@ static int apply_xbc(const char *path, const char *xbc_path)
+ }
+
+ /* To align up the total size to BOOTCONFIG_ALIGN, get padding size */
+- total_size = stat.st_size + size + sizeof(uint32_t) * 2 + BOOTCONFIG_MAGIC_LEN;
++ total_size = stat.st_size + size + BOOTCONFIG_FOOTER_SIZE;
+ pad = ((total_size + BOOTCONFIG_ALIGN - 1) & (~BOOTCONFIG_ALIGN_MASK)) - total_size;
+ size += pad;
+
+--
+2.53.0
+
--- /dev/null
+From 5d57c3fbd9d27d7268cda74dca1bc7cf324a97b2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 11:01:26 +0800
+Subject: tools/bootconfig: Fix buf leaks in apply_xbc
+
+From: Hongtao Lee <lihongtao@kylinos.cn>
+
+[ Upstream commit f42d01aadcedd7bbf4f9a466cabe25c1781dedad ]
+
+If data calloc failed, free the buf before return.
+
+Link: https://lore.kernel.org/all/20260520030126.147782-1-lihongtao@kylinos.cn/
+
+Fixes: 950313ebf79c ("tools: bootconfig: Add bootconfig command")
+Signed-off-by: Hongtao Lee <lihongtao@kylinos.cn>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/bootconfig/main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c
+index d302235f6b9743..49573044e93a58 100644
+--- a/tools/bootconfig/main.c
++++ b/tools/bootconfig/main.c
+@@ -384,8 +384,10 @@ static int apply_xbc(const char *path, const char *xbc_path)
+
+ /* Backup the bootconfig data */
+ data = calloc(size + BOOTCONFIG_ALIGN + BOOTCONFIG_FOOTER_SIZE, 1);
+- if (!data)
++ if (!data) {
++ free(buf);
+ return -ENOMEM;
++ }
+ memcpy(data, buf, size);
+
+ /* Check the data format */
+--
+2.53.0
+
--- /dev/null
+From bb188f576f0edabc4130f514c78a24e7688ab500 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 09:33:13 -0700
+Subject: tun: free page on build_skb failure in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit aa8963fdce667a42fb7f0bdd2909fadcab02f9a8 ]
+
+When build_skb() fails in tun_xdp_one(), the function sets ret to
+-ENOMEM and jumps to the out label, which returns without freeing the
+page that vhost_net_build_xdp() allocated for the frame. As with the
+short-frame rejection path, tun_sendmsg() discards the per-buffer error
+and still returns total_len, so vhost_tx_batch() takes the success path
+and never frees the page. Each build_skb() failure in a batch leaks one
+page-frag chunk.
+
+Free the page before taking the error path, matching the put_page() the
+other error exits of tun_xdp_one() already perform.
+
+Fixes: 043d222f93ab ("tuntap: accept an array of XDP buffs through sendmsg()")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260521163312.1479805-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 1ad6af74de7c3f..e8f8c7d5df29ec 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2494,6 +2494,7 @@ static int tun_xdp_one(struct tun_struct *tun,
+ build:
+ skb = build_skb(xdp->data_hard_start, buflen);
+ if (!skb) {
++ put_page(virt_to_head_page(xdp->data));
+ ret = -ENOMEM;
+ goto out;
+ }
+--
+2.53.0
+
--- /dev/null
+From 5c440911e85062918a527b28e9134ebfe175ca0d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 09:00:21 -0700
+Subject: tun: free page on short-frame rejection in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f4feb1e20058e407cb00f45aff47f5b7e19a6bbf ]
+
+tun_xdp_one() returns -EINVAL on a frame shorter than ETH_HLEN without
+freeing the page that vhost_net_build_xdp() allocated for it.
+tun_sendmsg() discards that -EINVAL and still returns total_len, so
+vhost_tx_batch() takes the success path and never frees the page; each
+short frame in a batch leaks one page-frag chunk.
+
+A local process that can open /dev/net/tun and /dev/vhost-net can hit
+this path: it attaches a tun/tap device as the vhost-net backend and
+feeds TX descriptors whose length minus the virtio-net header is below
+ETH_HLEN. Each kick leaks the page-frag chunks for that batch, and a
+tight submission loop exhausts host memory and triggers an OOM panic.
+Free the page before returning -EINVAL, matching the XDP-program error
+path in the same function.
+
+Fixes: 049584807f1d ("tun: add missing verification for short frame")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260520160020.375349-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 03478ae3ff2448..1ad6af74de7c3f 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2448,8 +2448,10 @@ static int tun_xdp_one(struct tun_struct *tun,
+ bool skb_xdp = false;
+ struct page *page;
+
+- if (unlikely(datasize < ETH_HLEN))
++ if (unlikely(datasize < ETH_HLEN)) {
++ put_page(virt_to_head_page(xdp->data));
+ return -EINVAL;
++ }
+
+ xdp_prog = rcu_dereference(tun->xdp_prog);
+ if (xdp_prog) {
+--
+2.53.0
+
--- /dev/null
+From c2d1652243c2106030b888d049b0723b0595a461 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 11:55:12 +0000
+Subject: tunnels: do not assume transport header in
+ iptunnel_pmtud_check_icmp()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 509323077ef79a26ba0c60bb556e45c12c398b2d ]
+
+In some cases, iptunnel_pmtud_check_icmp() can be called while
+skb transport header is not set.
+
+This triggers an out-of-bound access, because
+(typeof(skb->transport_header))~0U is 65535.
+
+Access the icmp header based on IPv4 network header,
+after making sure icmp->type is present in skb linear part.
+
+Note that iptunnel_pmtud_check_icmpv6()) is fine.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Reported-by: Damiano Melotti <melotti@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260522115512.1519110-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 5fb437f040ace7..9f6f1b435d8d72 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -262,7 +262,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct icmphdr *icmph = icmp_hdr(skb);
+ const struct iphdr *iph = ip_hdr(skb);
+
+ if (mtu < 576 || iph->frag_off != htons(IP_DF))
+@@ -273,9 +272,17 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ ipv4_is_lbcast(iph->saddr) || ipv4_is_multicast(iph->saddr))
+ return 0;
+
+- if (iph->protocol == IPPROTO_ICMP && icmp_is_err(icmph->type))
+- return 0;
++ if (iph->protocol == IPPROTO_ICMP) {
++ const struct icmphdr *icmph;
+
++ if (!pskb_network_may_pull(skb, iph->ihl * 4 +
++ offsetofend(struct icmphdr, type)))
++ return 0;
++ iph = ip_hdr(skb);
++ icmph = (void *)iph + iph->ihl * 4;
++ if (icmp_is_err(icmph->type))
++ return 0;
++ }
+ return iptunnel_pmtud_build_icmp(skb, mtu);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 631f31b7f9b3d6112d874c23a3166f4d820f43d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:13:35 +0000
+Subject: tunnels: load network headers after skb_cow() in
+ iptunnel_pmtud_build_icmp[v6]()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b4bc94353050b1fa7b702bd4c6600710dd926cff ]
+
+Sashiko found that iptunnel_pmtud_build_icmp() and
+iptunnel_pmtud_build_icmpv6() were caching ip_hdr() and ipv6_hdr()
+before an skb_cow() call which can reallocate skb->head.
+
+Fix this possible UAF by initializing the local variables
+after the skb_cow() call.
+
+Remove skb_reset_network_header() calls which were not needed.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525201335.2361845-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 75e3d7501752df..5fb437f040ace7 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -194,7 +194,7 @@ EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
+ */
+ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct iphdr *iph = ip_hdr(skb);
++ const struct iphdr *iph;
+ struct icmphdr *icmph;
+ struct iphdr *niph;
+ struct ethhdr eh;
+@@ -208,7 +208,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, 576 - sizeof(*niph) - sizeof(*icmph));
+ if (err)
+@@ -218,7 +217,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ err = skb_cow(skb, sizeof(*niph) + sizeof(*icmph) + ETH_HLEN);
+ if (err)
+ return err;
+-
++ iph = ip_hdr(skb);
+ icmph = skb_push(skb, sizeof(*icmph));
+ *icmph = (struct icmphdr) {
+ .type = ICMP_DEST_UNREACH,
+@@ -290,7 +289,7 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ {
+- const struct ipv6hdr *ip6h = ipv6_hdr(skb);
++ const struct ipv6hdr *ip6h;
+ struct icmp6hdr *icmp6h;
+ struct ipv6hdr *nip6h;
+ struct ethhdr eh;
+@@ -305,7 +304,6 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, IPV6_MIN_MTU - sizeof(*nip6h) - sizeof(*icmp6h));
+ if (err)
+@@ -316,6 +314,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ if (err)
+ return err;
+
++ ip6h = ipv6_hdr(skb);
+ icmp6h = skb_push(skb, sizeof(*icmp6h));
+ *icmp6h = (struct icmp6hdr) {
+ .icmp6_type = ICMPV6_PKT_TOOBIG,
+--
+2.53.0
+
--- /dev/null
+From a7a6e641fe6fc96f9df30d1a1d9f9746487e304d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:36:42 +0000
+Subject: vxlan: do not reuse cached ip_hdr() value after
+ skb_tunnel_check_pmtu()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 7d9ef0cb271555d8cf39fefe6c981e1493b25ecf ]
+
+skb_tunnel_check_pmtu() can change skb->head.
+
+Reusing old_iph afer skb_tunnel_check_pmtu() can cause an UAF.
+
+Use instead ip_hdr(skb) as done in drivers/net/bareudp.c
+and drivers/net/geneve.c.
+
+Found by Sashiko.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525203642.2389723-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index 6ad59c8afdcfc1..9d7ebf8aa79f66 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -2682,7 +2682,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
+ vni, md, flags, udp_sum);
+@@ -2745,7 +2745,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip6_dst_hoplimit(ndst);
+ skb_scrub_packet(skb, xnet);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
+--
+2.53.0
+
--- /dev/null
+From 79e34564ad0557d657a7f43b3bf7be9cf7ee3c9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:49:14 -0600
+Subject: xfrm: Check for underflow in xfrm_state_mtu
+
+From: David Ahern <dahern@nvidia.com>
+
+[ Upstream commit 742b04d0550b0ec89dcbc99537ec88653bd1ad90 ]
+
+Leo Lin reported OOB write issue in esp component:
+
+ xfrm_state_mtu() returns u32 but performs its arithmetic in unsigned
+ modulo-2^32 space using an attacker-influenced "header_len + authsize +
+ net_adj" subtracted from a small "mtu" argument. A nobody user can
+ install an IPv4 ESP tunnel SA with a large authentication key
+ (XFRMA_ALG_AUTH_TRUNC, e.g. hmac(sha512), 64-byte key, 64-byte trunc),
+ configure a small interface MTU (68 bytes), and set XFRMA_TFCPAD to a
+ large value. When a single UDP datagram is then sent through the
+ tunnel, xfrm_state_mtu() underflows to a near-2^32 value, and
+ esp_output() consumes it as a signed int via:
+
+ padto = min(x->tfcpad, xfrm_state_mtu(x, mtu_cached))
+ esp.tfclen = padto - skb->len (assigned to int)
+
+ esp.tfclen ends up negative (e.g. -207). It is sign-extended to size_t
+ when passed to memset() inside esp_output_fill_trailer(), producing a
+ ~16 EB write of zeroes at skb_tail_pointer(skb). KASAN logs it as
+ "Write of size 18446744073709551537 at addr ffff888...".
+
+Check for underflow and return 1. This causes the sendmsg attempt to
+fail with ENETUNREACH.
+
+Fixes: c5c252389374 ("[XFRM]: Optimize MTU calculation")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Assisted-by: Codex:26.506.31004
+Signed-off-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 7dd536d5f43f3a..f3661d2946e6ef 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -2577,10 +2577,14 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ const struct xfrm_type *type = READ_ONCE(x->type);
+ struct crypto_aead *aead;
+ u32 blksize, net_adj = 0;
++ u32 overhead, payload_mtu;
+
+ if (x->km.state != XFRM_STATE_VALID ||
+- !type || type->proto != IPPROTO_ESP)
++ !type || type->proto != IPPROTO_ESP) {
++ if (mtu <= x->props.header_len)
++ return 1;
+ return mtu - x->props.header_len;
++ }
+
+ aead = x->data;
+ blksize = ALIGN(crypto_aead_blocksize(aead), 4);
+@@ -2600,8 +2604,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ break;
+ }
+
+- return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
+- net_adj) & ~(blksize - 1)) + net_adj - 2;
++ overhead = x->props.header_len + crypto_aead_authsize(aead) + net_adj;
++ if (mtu <= overhead)
++ return 1;
++
++ payload_mtu = mtu - overhead;
++ payload_mtu &= ~(blksize - 1);
++ if (payload_mtu <= 2)
++ return 1;
++
++ return payload_mtu + net_adj - 2;
++
+ }
+ EXPORT_SYMBOL_GPL(xfrm_state_mtu);
+
+--
+2.53.0
+
--- /dev/null
+From 4c9ad76d387005dffad998dac23b2459ec145dc3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 10:14:42 +0300
+Subject: accel/ivpu: prevent uninitialized data bug in debugfs
+
+From: Dan Carpenter <error27@gmail.com>
+
+[ Upstream commit 44e151be23deb788d9f6124de93823faf6e04e99 ]
+
+The simple_write_to_buffer() will only initialize data starting from
+the *pos offset so if it's non-zero then the first part of the buffer
+uninitialized. Really, if *pos is non-zero then this code won't work
+so just check for that at the start of the function.
+
+Fixes: 320323d2e545 ("accel/ivpu: Add debugfs interface for setting HWS priority bands")
+Signed-off-by: Dan Carpenter <error27@gmail.com>
+Reviewed-by: Karol Wachowski <karol.wachowski@linux.intel.com>
+Signed-off-by: Karol Wachowski <karol.wachowski@linux.intel.com>
+Link: https://patch.msgid.link/ahP24m6Mii9EDL7Q@stanley.mountain
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/accel/ivpu/ivpu_debugfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c
+index df89c1c0da6dd7..1da4ce6a99cd9b 100644
+--- a/drivers/accel/ivpu/ivpu_debugfs.c
++++ b/drivers/accel/ivpu/ivpu_debugfs.c
+@@ -447,7 +447,7 @@ priority_bands_fops_write(struct file *file, const char __user *user_buf, size_t
+ u32 band;
+ int ret;
+
+- if (size >= sizeof(buf))
++ if (*pos != 0 || size >= sizeof(buf))
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, pos, user_buf, size);
+--
+2.53.0
+
--- /dev/null
+From e2bfb6d6bb3939d07c524c14d0bbbacb36dc8c36 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 22:09:40 -0300
+Subject: ALSA: pcm: oss: Fix setup list UAF on proc write error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit 4cc54bdd54b337e77115be5b55577d1c58608eae ]
+
+snd_pcm_oss_proc_write() links a newly allocated setup entry into the
+OSS setup list before duplicating the task name. If the task-name
+allocation fails, the error path frees the already linked entry and
+leaves setup_list pointing at freed memory.
+
+A later OSS device open can then walk the stale list entry in
+snd_pcm_oss_look_for_setup() and dereference freed memory.
+
+Allocate the task name and initialize the setup entry before publishing
+the entry on setup_list. Also fetch the initial proc read iterator only
+after taking setup_mutex, so all setup_list traversal follows the same
+list lifetime rules.
+
+Reported-by: syzbot+8e498074a794999eb41c@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/6a1062b7.170a0220.35b2b7.0003.GAE@google.com
+Closes: https://syzkaller.appspot.com/bug?extid=8e498074a794999eb41c
+Fixes: 060d77b9c04a ("[ALSA] Fix / clean up PCM-OSS setup hooks")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260522-alsa-pcm-oss-setup-uaf-v1-1-40bdcc4d17e8@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/core/oss/pcm_oss.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index daa7cda98ae6f6..a65a3b8d04b8cb 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -2966,8 +2966,10 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+ {
+ struct snd_pcm_str *pstr = entry->private_data;
+- struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
++ struct snd_pcm_oss_setup *setup;
++
+ guard(mutex)(&pstr->oss.setup_mutex);
++ setup = pstr->oss.setup_list;
+ while (setup) {
+ snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
+ setup->task_name,
+@@ -3052,6 +3054,13 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
+ buffer->error = -ENOMEM;
+ return;
+ }
++ template.task_name = kstrdup(task_name, GFP_KERNEL);
++ if (!template.task_name) {
++ kfree(setup);
++ buffer->error = -ENOMEM;
++ return;
++ }
++ *setup = template;
+ if (pstr->oss.setup_list == NULL)
+ pstr->oss.setup_list = setup;
+ else {
+@@ -3059,12 +3068,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
+ setup1->next; setup1 = setup1->next);
+ setup1->next = setup;
+ }
+- template.task_name = kstrdup(task_name, GFP_KERNEL);
+- if (! template.task_name) {
+- kfree(setup);
+- buffer->error = -ENOMEM;
+- return;
+- }
++ continue;
+ }
+ *setup = template;
+ }
+--
+2.53.0
+
--- /dev/null
+From 9722d73d4801f84157614d8954bec2c2b9bdc203 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 09:24:00 -0300
+Subject: ASoC: codecs: simple-mux: Fix enum control bounds check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit f63ad68e18d774a5d15cd7e405ead63f6b322679 ]
+
+simple_mux_control_put() rejects values greater than e->items, but
+enum control values are zero based. For the two-entry mux used by this
+driver, valid values are 0 and 1, so value 2 must be rejected as well.
+
+Accepting e->items can store an invalid mux state, pass it to the GPIO
+setter, and pass it on to the DAPM mux update path where it is used as
+an index into the enum text array.
+
+Use the same >= e->items check used by the ASoC enum helpers.
+
+Fixes: 342fbb7578d1 ("ASoC: add simple-mux")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260527-asoc-simple-mux-enum-bounds-v1-1-3f805b9fc671@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/simple-mux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/simple-mux.c b/sound/soc/codecs/simple-mux.c
+index 240af0563283e5..4c94087a246e16 100644
+--- a/sound/soc/codecs/simple-mux.c
++++ b/sound/soc/codecs/simple-mux.c
+@@ -49,7 +49,7 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
+ struct simple_mux *priv = snd_soc_component_get_drvdata(c);
+
+- if (ucontrol->value.enumerated.item[0] > e->items)
++ if (ucontrol->value.enumerated.item[0] >= e->items)
+ return -EINVAL;
+
+ if (priv->mux == ucontrol->value.enumerated.item[0])
+--
+2.53.0
+
--- /dev/null
+From 5e5c472d24ad493061f66fe89eb7267232ccc545 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 13:51:47 -0300
+Subject: ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit afb2a3a9d8369d18122a0d7cd294eba9a98259c6 ]
+
+byt_cht_es8316_init() enables MCLK before configuring the codec sysclk
+and creating the headset jack. If either of those later steps fails, the
+function returns without disabling MCLK, leaving the clock enabled after
+card registration fails.
+
+Track whether this driver enabled MCLK and disable it on the init error
+paths. Add the matching DAI link exit callback so the same clock enable
+is also balanced when ASoC cleans up a successfully initialized link.
+
+Fixes: a03bdaa565cb ("ASoC: Intel: add machine driver for BYT/CHT + ES8316")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260519-asoc-bytcht-es8316-mclk-leak-v1-1-b4a11cdc2afd@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/bytcht_es8316.c | 29 ++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
+index 7975dc0ceb3518..676c08247cfcb9 100644
+--- a/sound/soc/intel/boards/bytcht_es8316.c
++++ b/sound/soc/intel/boards/bytcht_es8316.c
+@@ -40,6 +40,7 @@ struct byt_cht_es8316_private {
+ struct gpio_desc *speaker_en_gpio;
+ struct device *codec_dev;
+ bool speaker_en;
++ bool mclk_enabled;
+ };
+
+ enum {
+@@ -170,6 +171,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
+ },
+ };
+
++static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
++{
++ if (!priv->mclk_enabled)
++ return;
++
++ clk_disable_unprepare(priv->mclk);
++ priv->mclk_enabled = false;
++}
++
+ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ {
+ struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component;
+@@ -226,12 +236,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret)
+ dev_err(card->dev, "unable to enable MCLK\n");
++ else
++ priv->mclk_enabled = true;
+
+ ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(runtime, 0), 0, 19200000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set codec clock %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ ret = snd_soc_card_jack_new_pins(card, "Headset",
+@@ -240,13 +252,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ARRAY_SIZE(byt_cht_es8316_jack_pins));
+ if (ret) {
+ dev_err(card->dev, "jack creation failed %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_soc_component_set_jack(codec, &priv->jack, NULL);
+
+ return 0;
++
++err_disable_mclk:
++ byt_cht_es8316_disable_mclk(priv);
++ return ret;
++}
++
++static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
++{
++ struct snd_soc_card *card = runtime->card;
++ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
++
++ byt_cht_es8316_disable_mclk(priv);
+ }
+
+ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+@@ -356,6 +380,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .init = byt_cht_es8316_init,
++ .exit = byt_cht_es8316_exit,
+ SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
+ },
+ };
+--
+2.53.0
+
--- /dev/null
+From 847aa47b30c596764ef8708a2a20ce10ca5f3f42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 11:21:39 +0800
+Subject: Bluetooth: 6lowpan: check skb_clone() return value in
+ send_mcast_pkt()
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+[ Upstream commit 3c40d381ce04f9575a5d8b542898183c3b4b38dc ]
+
+The skb_clone() function can return NULL if memory allocation fails.
+send_mcast_pkt() calls skb_clone() without checking the return value, which
+can lead to a NULL pointer dereference in send_pkt() when it dereferences
+skb->data.
+Add a NULL check after skb_clone() and skip the peer if the clone fails.
+
+Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/6lowpan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
+index e5186a438290ae..03f0b5d27b60d3 100644
+--- a/net/bluetooth/6lowpan.c
++++ b/net/bluetooth/6lowpan.c
+@@ -485,6 +485,8 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
+ int ret;
+
+ local_skb = skb_clone(skb, GFP_ATOMIC);
++ if (!local_skb)
++ continue;
+
+ BT_DBG("xmit %s to %pMR type %u IP %pI6c chan %p",
+ netdev->name,
+--
+2.53.0
+
--- /dev/null
+From c03e703dbdffb14ce5981c3217312da176b23f7e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 10:50:58 -0300
+Subject: Bluetooth: hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close
+
+From: Heitor Alves de Siqueira <halves@igalia.com>
+
+[ Upstream commit 525daaea459fc215f432de1b8debbd9144bf97b0 ]
+
+Since hci_dev_close_sync() can now be called during the reset path, we
+should also set HCI_CMD_DRAIN_WORKQUEUE. This avoids queuing timeouts
+while the hdev workqueue is being drained.
+
+Fixes: 877afadad2dc ("Bluetooth: When HCI work queue is drained, only queue chained work")
+Signed-off-by: Heitor Alves de Siqueira <halves@igalia.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sync.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index fbcb3bbfef4fde..f6e133756bd9ba 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -5223,6 +5223,12 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+
+ bt_dev_dbg(hdev, "");
+
++ /* Set HCI_DRAIN_WORKQUEUE flag to prevent queuing work during
++ * reset/close. See hci_cmd_work() and handle_cmd_cnt_and_timer().
++ */
++ hci_dev_set_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
++ synchronize_rcu();
++
+ if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+ disable_delayed_work(&hdev->power_off);
+ disable_delayed_work(&hdev->ncmd_timer);
+@@ -5246,6 +5252,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+
+ if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
+ cancel_delayed_work_sync(&hdev->cmd_timer);
++ hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
+ return err;
+ }
+
+@@ -5345,6 +5352,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+ /* Clear flags */
+ hdev->flags &= BIT(HCI_RAW);
+ hci_dev_clear_volatile_flags(hdev);
++ hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
+
+ memset(hdev->eir, 0, sizeof(hdev->eir));
+ memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
+--
+2.53.0
+
--- /dev/null
+From 02ad67cbd0668dcb120eee25ed7f55b3e99520a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 18:51:52 +0800
+Subject: Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit 00e1950716c6ed67d74777b2db286b0fa23b4be9 ]
+
+l2cap_ecred_reconf_rsp() returns early on success without clearing
+chan->ident. Every other L2CAP response handler (l2cap_ecred_conn_rsp,
+l2cap_le_connect_rsp, l2cap_config_rsp) clears chan->ident after a
+successful transaction to prevent the channel from matching subsequent
+responses with the recycled ident value.
+
+A remote attacker that completed a reconfiguration as the peer can
+replay a failure response with the stale ident, causing the kernel to
+match and destroy the already-established channel via
+l2cap_chan_del(chan, ECONNRESET).
+
+Clear chan->ident for all matching channels on success, and harden the
+failure path by using l2cap_chan_hold_unless_zero() consistent with
+other L2CAP handlers (l2cap_le_command_rej, __l2cap_get_chan_by_ident).
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index b24e4d8130ddb1..9de5d545966d60 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -5392,14 +5392,20 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("result 0x%4.4x", result);
+
+- if (!result)
++ if (!result) {
++ list_for_each_entry(chan, &conn->chan_l, list) {
++ if (chan->ident == cmd->ident)
++ chan->ident = 0;
++ }
+ return 0;
++ }
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
+ if (chan->ident != cmd->ident)
+ continue;
+
+- l2cap_chan_hold(chan);
++ if (!l2cap_chan_hold_unless_zero(chan))
++ continue;
+ l2cap_chan_lock(chan);
+
+ l2cap_chan_del(chan, ECONNRESET);
+--
+2.53.0
+
--- /dev/null
+From c1acc8473ff9e3ae3fd224360f8981462a6a97c3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 May 2026 12:09:42 -0400
+Subject: Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 41c2713b204e6cb6a94587bc6bf6935107df5479 ]
+
+If dcid is received for an already-assigned destination CID the spec
+requires that both channels to be discarded, but calling l2cap_chan_del
+may invalidate the tmp cursor created by list_for_each_entry_safe and
+in fact it is the wrong procedure as the chan->dcid may be assigned
+previously it really needs to be disconnected.
+
+Calling l2cap_chan_clone directly may still lead to l2cap_chan_del so
+instead schedule l2cap_chan_timeout with delay 0 to close the channel
+asynchronously.
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 9de5d545966d60..f0b0f347ebc10a 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -5194,6 +5194,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ cmd_len -= sizeof(*rsp);
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
++ struct l2cap_chan *orig;
+ u16 dcid;
+
+ if (chan->ident != cmd->ident ||
+@@ -5215,8 +5216,10 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
+
++ orig = __l2cap_get_chan_by_dcid(conn, dcid);
++
+ /* Check if dcid is already in use */
+- if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
++ if (dcid && orig) {
+ /* If a device receives a
+ * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
+ * already-assigned Destination CID, then both the
+@@ -5225,10 +5228,24 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ */
+ l2cap_chan_del(chan, ECONNREFUSED);
+ l2cap_chan_unlock(chan);
+- chan = __l2cap_get_chan_by_dcid(conn, dcid);
+- l2cap_chan_lock(chan);
+- l2cap_chan_del(chan, ECONNRESET);
+- l2cap_chan_unlock(chan);
++
++ /* Check that the dcid channel mode is
++ * L2CAP_MODE_EXT_FLOWCTL since this procedure is only
++ * valid for that mode and shouldn't disconnect a dcid
++ * in other modes.
++ */
++ if (orig->mode == L2CAP_MODE_EXT_FLOWCTL) {
++ l2cap_chan_lock(orig);
++ /* Disconnect the original channel as it may be
++ * considered connected since dcid has already
++ * been assigned; don't call l2cap_chan_close
++ * directly since that could lead to
++ * l2cap_chan_del and then removing the channel
++ * from the list while we're iterating over it.
++ */
++ __set_chan_timer(orig, 0);
++ l2cap_chan_unlock(orig);
++ }
+ continue;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From b54fbe3c1b9b0b52f9b4cee559d51a479d4e18e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:33:19 +0200
+Subject: bonding: refuse to enslave CAN devices
+
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+
+[ Upstream commit 8ba68464e4787b6a7ec938826e16124df20fd23d ]
+
+syzbot reported a kernel paging request crash in
+can_rx_unregister() inside net/can/af_can.c. The crash occurs
+because a virtual CAN device (vxcan) is being enslaved to a
+bonding master.
+
+During the enslavement process, the bonding driver mutates
+and modifies the network device states to fit an Ethernet-like
+aggregation model. However, CAN devices operate on a completely
+different Layer 2 architecture, relying on the CAN mid-layer
+private data structure (can_ml_priv) instead of standard
+Ethernet structures. Since bonding does not initialize or
+maintain these CAN structures, subsequent operations on the
+half-enslaved interface (such as closing associated sockets
+via isotp_release) lead to a null-pointer dereference when
+accessing the CAN receiver lists.
+
+Bonding CAN interfaces is architecturally invalid as CAN lacks
+MAC addresses, ARP capabilities, and standard Ethernet
+link-layer mechanisms. While generic loopback devices are
+blocked globally in net/core/dev.c, virtual CAN devices
+bypass this check because they do not carry the IFF_LOOPBACK
+flag, despite acting as local software-loopbacks.
+
+Fix this by explicitly blocking network devices of type
+ARPHRD_CAN from being enslaved at the very beginning of
+bond_enslave(). This prevents illegal state mutations,
+eliminates the resulting KASAN crashes, and avoids potential
+memory leaks from incomplete socket cleanups.
+
+As the CAN support has been added a long time after bonding
+the Fixes-tag points to the introduction of ARPHRD_CAN that
+would have needed a specific handling in bonding_main.c.
+
+Fixes: cd05acfe65ed ("[CAN]: Allocate protocol numbers for PF_CAN")
+Reported-by: syzbot+8ed98cbd0161632bce95@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=8ed98cbd0161632bce95
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260526-bonding-candev-v1-1-ba1df400918a@hartkopp.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 1b2cd7f870353c..c6b114946d9a5a 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1927,6 +1927,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
+ int link_reporting;
+ int res = 0, i;
+
++ if (slave_dev->type == ARPHRD_CAN) {
++ BOND_NL_ERR(bond_dev, extack,
++ "CAN devices cannot be enslaved");
++ return -EPERM;
++ }
++
+ if (slave_dev->flags & IFF_MASTER &&
+ !netif_is_bond_master(slave_dev)) {
+ BOND_NL_ERR(bond_dev, extack,
+--
+2.53.0
+
--- /dev/null
+From acdb4ee2828f711306d28baa05e6e3605db0dc70 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 20:14:57 +0800
+Subject: cxl/test: Update mock dev array before calling platform_device_add()
+
+From: Li Ming <ming.li@zohomail.com>
+
+[ Upstream commit d90f236f8b9e354848bd226f581db27755ab901d ]
+
+CXL test environment hits the following error sometimes.
+
+ cxl_mem mem9: endpoint7 failed probe
+
+All mock memdevs are platform firmware devices added by cxl_test module,
+and cxl_test module also provides a platform device driver for them to
+create a memdev device to CXL subsystem. cxl_test module uses
+cxl_rcd/mem_single/mem arrays to store different types of mock memdevs.
+CXL drivers calls registered mock functions for a mock memdev by
+checking if a given memdev is in these arrays.
+
+When cxl_test module adds these mock memdevs, it always calls
+platform_device_add() before adding them to a suitable mock memdev
+array. However, there is a small window where CXL drivers calls mock
+function for a added memdev before it added to a mock memdev array. In
+above case, cxl endpoint driver considers a added memdev was not a mock
+memdev, then calling devm_cxl_endpoint_decoders_setup() for it rather
+than mock_endpoint_decoders_setup().
+
+An appropriate solution is that adding a new mock device to a mock
+device array before calling platform_device_add() for it. It can
+guarantee the new mock device is visible to CXL subsystem.
+
+This patch introduces a new helped called cxl_mock_platform_device_add()
+to handle the issue, and uses the function for all mock devices addition.
+
+Fixes: 3a2b97b3210b ("cxl/test: Improve init-order fidelity relative to real-world systems")
+Signed-off-by: Li Ming <ming.li@zohomail.com>
+Tested-by: Alison Schofield <alison.schofield@intel.com>
+Reviewed-by: Alison Schofield <alison.schofield@intel.com>
+Link: https://patch.msgid.link/20260520121457.234404-1-ming.li@zohomail.com
+Signed-off-by: Dave Jiang <dave.jiang@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/cxl/test/cxl.c | 105 ++++++++++++++---------------------
+ 1 file changed, 43 insertions(+), 62 deletions(-)
+
+diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
+index 050725afa45d16..0d0c434426e7bf 100644
+--- a/tools/testing/cxl/test/cxl.c
++++ b/tools/testing/cxl/test/cxl.c
+@@ -1058,6 +1058,23 @@ static void mock_companion(struct acpi_device *adev, struct device *dev)
+ #define SZ_64G (SZ_32G * 2)
+ #endif
+
++static int cxl_mock_platform_device_add(struct platform_device *pdev,
++ struct platform_device **ppdev)
++{
++ int rc;
++
++ if (ppdev)
++ *ppdev = pdev;
++ rc = platform_device_add(pdev);
++ if (rc) {
++ platform_device_put(pdev);
++ if (ppdev)
++ *ppdev = NULL;
++ }
++
++ return rc;
++}
++
+ static __init int cxl_rch_topo_init(void)
+ {
+ int rc, i;
+@@ -1072,13 +1089,10 @@ static __init int cxl_rch_topo_init(void)
+ goto err_bridge;
+
+ mock_companion(adev, &pdev->dev);
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_rch[i]);
++ if (rc)
+ goto err_bridge;
+- }
+
+- cxl_rch[i] = pdev;
+ mock_pci_bus[idx].bridge = &pdev->dev;
+ rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
+ "firmware_node");
+@@ -1130,13 +1144,10 @@ static __init int cxl_single_topo_init(void)
+ goto err_bridge;
+
+ mock_companion(adev, &pdev->dev);
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_hb_single[i]);
++ if (rc)
+ goto err_bridge;
+- }
+
+- cxl_hb_single[i] = pdev;
+ mock_pci_bus[i + NR_CXL_HOST_BRIDGES].bridge = &pdev->dev;
+ rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
+ "physical_node");
+@@ -1155,12 +1166,9 @@ static __init int cxl_single_topo_init(void)
+ goto err_port;
+ pdev->dev.parent = &bridge->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_root_single[i]);
++ if (rc)
+ goto err_port;
+- }
+- cxl_root_single[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_swu_single); i++) {
+@@ -1173,12 +1181,9 @@ static __init int cxl_single_topo_init(void)
+ goto err_uport;
+ pdev->dev.parent = &root_port->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_swu_single[i]);
++ if (rc)
+ goto err_uport;
+- }
+- cxl_swu_single[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_swd_single); i++) {
+@@ -1192,12 +1197,9 @@ static __init int cxl_single_topo_init(void)
+ goto err_dport;
+ pdev->dev.parent = &uport->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_swd_single[i]);
++ if (rc)
+ goto err_dport;
+- }
+- cxl_swd_single[i] = pdev;
+ }
+
+ return 0;
+@@ -1270,12 +1272,9 @@ static int cxl_mem_init(void)
+ pdev->dev.parent = &dport->dev;
+ set_dev_node(&pdev->dev, i % 2);
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_mem[i]);
++ if (rc)
+ goto err_mem;
+- }
+- cxl_mem[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++) {
+@@ -1288,12 +1287,9 @@ static int cxl_mem_init(void)
+ pdev->dev.parent = &dport->dev;
+ set_dev_node(&pdev->dev, i % 2);
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_mem_single[i]);
++ if (rc)
+ goto err_single;
+- }
+- cxl_mem_single[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++) {
+@@ -1307,12 +1303,9 @@ static int cxl_mem_init(void)
+ pdev->dev.parent = &rch->dev;
+ set_dev_node(&pdev->dev, i % 2);
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_rcd[i]);
++ if (rc)
+ goto err_rcd;
+- }
+- cxl_rcd[i] = pdev;
+ }
+
+ return 0;
+@@ -1373,13 +1366,10 @@ static __init int cxl_test_init(void)
+ goto err_bridge;
+
+ mock_companion(adev, &pdev->dev);
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_host_bridge[i]);
++ if (rc)
+ goto err_bridge;
+- }
+
+- cxl_host_bridge[i] = pdev;
+ mock_pci_bus[i].bridge = &pdev->dev;
+ rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
+ "physical_node");
+@@ -1397,12 +1387,9 @@ static __init int cxl_test_init(void)
+ goto err_port;
+ pdev->dev.parent = &bridge->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_root_port[i]);
++ if (rc)
+ goto err_port;
+- }
+- cxl_root_port[i] = pdev;
+ }
+
+ BUILD_BUG_ON(ARRAY_SIZE(cxl_switch_uport) != ARRAY_SIZE(cxl_root_port));
+@@ -1415,12 +1402,9 @@ static __init int cxl_test_init(void)
+ goto err_uport;
+ pdev->dev.parent = &root_port->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_switch_uport[i]);
++ if (rc)
+ goto err_uport;
+- }
+- cxl_switch_uport[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++) {
+@@ -1433,12 +1417,9 @@ static __init int cxl_test_init(void)
+ goto err_dport;
+ pdev->dev.parent = &uport->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_switch_dport[i]);
++ if (rc)
+ goto err_dport;
+- }
+- cxl_switch_dport[i] = pdev;
+ }
+
+ rc = cxl_single_topo_init();
+@@ -1456,9 +1437,9 @@ static __init int cxl_test_init(void)
+ mock_companion(&acpi0017_mock, &cxl_acpi->dev);
+ acpi0017_mock.dev.bus = &platform_bus_type;
+
+- rc = platform_device_add(cxl_acpi);
++ rc = cxl_mock_platform_device_add(cxl_acpi, NULL);
+ if (rc)
+- goto err_root;
++ goto err_rch;
+
+ rc = cxl_mem_init();
+ if (rc)
+--
+2.53.0
+
--- /dev/null
+From 648671bc8093e3ce79abced8f849bce032120898 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:10 -0700
+Subject: ethtool: cmis: fix u16-to-u8 truncation of msleep_pre_rpl
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 3e8c3d464c36bb342fe377b026577c7ec27fdbb4 ]
+
+ethtool_cmis_cdb_compose_args() accepts msleep_pre_rpl as u16 but stores
+it into the u8 field ethtool_cmis_cdb_cmd_args::msleep_pre_rpl, silently
+truncating values >= 256. Seven of the nine call sites pass 1000 ms
+(it's the third argument from the end).
+
+Fixes: a39c84d79625 ("ethtool: cmis_cdb: Add a layer for supporting CDB commands")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-8-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/cmis.h b/net/ethtool/cmis.h
+index 3e7c293af78c4d..aa32a675b8f8d2 100644
+--- a/net/ethtool/cmis.h
++++ b/net/ethtool/cmis.h
+@@ -59,9 +59,9 @@ struct ethtool_cmis_cdb_request {
+ * struct ethtool_cmis_cdb_cmd_args - CDB commands execution arguments
+ * @req: CDB command fields as described in the CMIS standard.
+ * @max_duration: Maximum duration time for command completion in msec.
++ * @msleep_pre_rpl: Waiting time before checking reply in msec.
+ * @read_write_len_ext: Allowable additional number of byte octets to the LPL
+ * in a READ or a WRITE commands.
+- * @msleep_pre_rpl: Waiting time before checking reply in msec.
+ * @rpl_exp_len: Expected reply length in bytes.
+ * @flags: Validation flags for CDB commands.
+ * @err_msg: Error message to be sent to user space.
+@@ -69,8 +69,8 @@ struct ethtool_cmis_cdb_request {
+ struct ethtool_cmis_cdb_cmd_args {
+ struct ethtool_cmis_cdb_request req;
+ u16 max_duration;
++ u16 msleep_pre_rpl;
+ u8 read_write_len_ext;
+- u8 msleep_pre_rpl;
+ u8 rpl_exp_len;
+ u8 flags;
+ char *err_msg;
+--
+2.53.0
+
--- /dev/null
+From 3a4007ec8ec1e03a9ff89f57f73ee84e04c25d89 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:09 -0700
+Subject: ethtool: cmis: require exact CDB reply length
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 6c3f999a9d1338c6c89a9ff4549eafe72bc2e7b1 ]
+
+Malicious SFP module could respond with rpl_len longer than
+what cmis_cdb_process_reply() expected, leading to OOB writes.
+Malicious HW is a bit theoretical but some modules may just
+be buggy and/or the reads may occasionally get corrupted,
+so let's protect the kernel.
+
+The existing check protects from short replies. We need to
+protect from long ones, too. All callers that pass a non-zero
+rpl_exp_len cast the reply payload to a fixed-layout struct
+and read fields at fixed offsets, with no version negotiation
+or short-reply handling:
+
+ - cmis_cdb_validate_password()
+ - cmis_cdb_module_features_get()
+ - cmis_fw_update_fw_mng_features_get()
+
+so let's assume that responses longer than expected do not
+have to be handled gracefully here. Add a warning message
+to make the debug easier in case my understanding is wrong...
+
+Note that page_data->length (argument of kmalloc) comes from
+last arg to ethtool_cmis_page_init() which is rpl_exp_len.
+
+Note2 that AIs also like to point out overflows in args->req.payload
+itself (which is a fixed-size 120 B buffer, on the stack),
+but callers should be reading structs defined by the standard,
+so protecting from requests for more data than max seem like
+defensive programming.
+
+Fixes: a39c84d79625 ("ethtool: cmis_cdb: Add a layer for supporting CDB commands")
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-7-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis_cdb.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/cmis_cdb.c b/net/ethtool/cmis_cdb.c
+index 8bf99295bfbe96..690002366d965a 100644
+--- a/net/ethtool/cmis_cdb.c
++++ b/net/ethtool/cmis_cdb.c
+@@ -508,8 +508,13 @@ static int cmis_cdb_process_reply(struct net_device *dev,
+ }
+
+ rpl = (struct ethtool_cmis_cdb_rpl *)page_data->data;
+- if ((args->rpl_exp_len > rpl->hdr.rpl_len + rpl_hdr_len) ||
+- !rpl->hdr.rpl_chk_code) {
++ if (rpl->hdr.rpl_len != args->rpl_exp_len) {
++ netdev_warn(dev, "CDB reply length mismatch, expected %u got %u\n",
++ args->rpl_exp_len, rpl->hdr.rpl_len);
++ err = -EIO;
++ goto out;
++ }
++ if (!rpl->hdr.rpl_chk_code) {
+ err = -EIO;
+ goto out;
+ }
+--
+2.53.0
+
--- /dev/null
+From fcc4acaaba061fd1a5f467a29e8275b8fa2e553d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:12 -0700
+Subject: ethtool: cmis: validate fw->size against start_cmd_payload_size
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit d5551f4c1800dc714cec86647bdd651ae0de923e ]
+
+cmis_fw_update_start_download() copies start_cmd_payload_size bytes
+from the firmware blob into the CDB LPL vendor_data[] payload without
+validating that the FW has enough data.
+
+Since the start_cmd_payload_size can only be ~120B an image too short
+is most likely corrupted, so reject it.
+
+Fixes: c4f78134d45c ("ethtool: cmis_fw_update: add a layer for supporting firmware update using CDB")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-10-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis_fw_update.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/net/ethtool/cmis_fw_update.c b/net/ethtool/cmis_fw_update.c
+index 560bafd4d16864..9c6d9571cf24db 100644
+--- a/net/ethtool/cmis_fw_update.c
++++ b/net/ethtool/cmis_fw_update.c
+@@ -129,6 +129,14 @@ cmis_fw_update_start_download(struct ethtool_cmis_cdb *cdb,
+ u8 lpl_len;
+ int err;
+
++ if (fw_update->fw->size < vendor_data_size) {
++ ethnl_module_fw_flash_ntf_err(fw_update->dev,
++ &fw_update->ntf_params,
++ "Firmware image too small for module's start payload",
++ NULL);
++ return -EINVAL;
++ }
++
+ pl.image_size = cpu_to_be32(fw_update->fw->size);
+ memcpy(pl.vendor_data, fw_update->fw->data, vendor_data_size);
+
+--
+2.53.0
+
--- /dev/null
+From d367668456b5ef08aa2d63a9210126855a598733 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:11 -0700
+Subject: ethtool: cmis: validate start_cmd_payload_size from module
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 12c2496a71f82f63617971ca9b730dffa05cf58b ]
+
+The CMIS firmware update code reads start_cmd_payload_size from
+the module's FW Management Features CDB reply and uses it directly
+as the byte count for memcpy. The destination buffer is 112 bytes
+(ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH - 8). So a malicious
+module (or corrupted response) can cause a OOB write later on in
+cmis_fw_update_start_download().
+
+Let's error out. If modules that expect longer LPL writes actually
+exist we should revisit.
+
+struct cmis_cdb_start_fw_download_pl's definition has to move,
+no change there.
+
+Fixes: c4f78134d45c ("ethtool: cmis_fw_update: add a layer for supporting firmware update using CDB")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-9-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis_fw_update.c | 36 ++++++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 14 deletions(-)
+
+diff --git a/net/ethtool/cmis_fw_update.c b/net/ethtool/cmis_fw_update.c
+index 48aef6220f0094..560bafd4d16864 100644
+--- a/net/ethtool/cmis_fw_update.c
++++ b/net/ethtool/cmis_fw_update.c
+@@ -43,6 +43,20 @@ enum cmis_cdb_fw_write_mechanism {
+ CMIS_CDB_FW_WRITE_MECHANISM_BOTH = 0x11,
+ };
+
++/* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
++ * revision 5.2.
++ * struct cmis_cdb_start_fw_download_pl is a structured layout of the
++ * flat array, ethtool_cmis_cdb_request::payload.
++ */
++struct cmis_cdb_start_fw_download_pl {
++ __struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */,
++ __be32 image_size;
++ __be32 resv1;
++ );
++ u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH -
++ sizeof(struct cmis_cdb_start_fw_download_pl_h)];
++};
++
+ static int
+ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ struct net_device *dev,
+@@ -85,6 +99,14 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ */
+ cdb->read_write_len_ext = rpl->read_write_len_ext;
+ fw_mng->start_cmd_payload_size = rpl->start_cmd_payload_size;
++ if (fw_mng->start_cmd_payload_size >
++ sizeof_field(struct cmis_cdb_start_fw_download_pl, vendor_data)) {
++ ethnl_module_fw_flash_ntf_err(dev, ntf_params,
++ "Start cmd payload size exceeds max LPL payload",
++ NULL);
++ return -EINVAL;
++ }
++
+ fw_mng->write_mechanism =
+ rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL ?
+ CMIS_CDB_FW_WRITE_MECHANISM_LPL :
+@@ -96,20 +118,6 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ return 0;
+ }
+
+-/* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
+- * revision 5.2.
+- * struct cmis_cdb_start_fw_download_pl is a structured layout of the
+- * flat array, ethtool_cmis_cdb_request::payload.
+- */
+-struct cmis_cdb_start_fw_download_pl {
+- __struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */,
+- __be32 image_size;
+- __be32 resv1;
+- );
+- u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH -
+- sizeof(struct cmis_cdb_start_fw_download_pl_h)];
+-};
+-
+ static int
+ cmis_fw_update_start_download(struct ethtool_cmis_cdb *cdb,
+ struct ethtool_cmis_fw_update_params *fw_update,
+--
+2.53.0
+
--- /dev/null
+From 6ebe6f5cd207f3de29da77f0f70dc68965c22876 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:24 -0700
+Subject: ethtool: coalesce: cap profile updates at NET_DIM_PARAMS_NUM_PROFILES
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 7281b096b072f6c6e30420e3467d738f2e4c4b57 ]
+
+ethnl_update_profile() walks the ETHTOOL_A_PROFILE_IRQ_MODERATION
+nest list with an index 'i' and writes new_profile[i++] without
+bounding i. The destination is kmemdup()'d at NET_DIM_PARAMS_NUM_PROFILES
+entries (5), but the Netlink nest count is entirely user-controlled.
+Netlink policies do not have support for constraining the number
+of nested entries (or number of multi-attr entries).
+
+Fixes: f750dfe825b9 ("ethtool: provide customized dim profile management")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-2-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/coalesce.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/net/ethtool/coalesce.c b/net/ethtool/coalesce.c
+index 3e18ca1ccc5ef6..cace02d964cb21 100644
+--- a/net/ethtool/coalesce.c
++++ b/net/ethtool/coalesce.c
+@@ -463,6 +463,12 @@ static int ethnl_update_profile(struct net_device *dev,
+
+ nla_for_each_nested_type(nest, ETHTOOL_A_PROFILE_IRQ_MODERATION,
+ nests, rem) {
++ if (i >= NET_DIM_PARAMS_NUM_PROFILES) {
++ NL_SET_BAD_ATTR(extack, nest);
++ ret = -E2BIG;
++ goto err_out;
++ }
++
+ ret = nla_parse_nested(tb, len_irq_moder - 1, nest,
+ coalesce_irq_moderation_policy,
+ extack);
+--
+2.53.0
+
--- /dev/null
+From a13b6bf690bfd0087cc339710797feaef6f6d5b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:32 -0700
+Subject: ethtool: eeprom: add missing ethnl_ops_begin() / _complete() during
+ fallback
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 2376586f85f972fefe701f095bb37dcfe7405d21 ]
+
+All ethtool driver op calls should be sandwiched between
+ethnl_ops_begin() / ethnl_ops_complete(). In Netlink eeprom code,
+if the paged access failed we fall back to old API, but we
+first call _complete() and the fallback never does its own
+ethnl_ops_begin(). Move the fallback into the _begin() / _complete()
+section.
+
+Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-10-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/eeprom.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c
+index 3b8209e930fd3a..03cb418a15823b 100644
+--- a/net/ethtool/eeprom.c
++++ b/net/ethtool/eeprom.c
+@@ -140,12 +140,11 @@ static int eeprom_prepare_data(const struct ethnl_req_info *req_base,
+ return 0;
+
+ err_ops:
++ if (ret == -EOPNOTSUPP)
++ ret = eeprom_fallback(request, reply);
+ ethnl_ops_complete(dev);
+ err_free:
+ kfree(page_data.data);
+-
+- if (ret == -EOPNOTSUPP)
+- return eeprom_fallback(request, reply);
+ return ret;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From eace429d42bbff2aa2557fa49842b196eb23a680 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:33 -0700
+Subject: ethtool: eeprom: add more safeties to EEPROM Netlink fallback
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 67cfdd9210b99f260b3e0afeb9525e0acc7be31e ]
+
+The Netlink fallback path for reading module EEPROM
+(fallback_set_params()) validates that offset < eeprom_len,
+but does not check that offset + length stays within eeprom_len.
+The ioctl equivalent (ethtool_get_any_eeprom() in ioctl.c) has
+always enforced both bounds:
+
+ if (eeprom.offset + eeprom.len > total_len)
+ return -EINVAL;
+
+This could lead to surprises in both drivers and device FW.
+Add the missing offset + length validation to fallback_set_params(),
+mirroring the ioctl.
+
+Similarly - ethtool core in general, and ethtool_get_any_eeprom()
+in particular tries to zero-init all buffers passed to the drivers
+to avoid any extra work of zeroing things out. eeprom_fallback()
+uses a plain kmalloc(), change it to zalloc.
+
+Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-11-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/eeprom.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c
+index 03cb418a15823b..80af38a6c76acf 100644
+--- a/net/ethtool/eeprom.c
++++ b/net/ethtool/eeprom.c
+@@ -43,6 +43,9 @@ static int fallback_set_params(struct eeprom_req_info *request,
+ if (offset >= modinfo->eeprom_len)
+ return -EINVAL;
+
++ if (length > modinfo->eeprom_len - offset)
++ return -EINVAL;
++
+ eeprom->cmd = ETHTOOL_GMODULEEEPROM;
+ eeprom->len = length;
+ eeprom->offset = offset;
+@@ -68,7 +71,7 @@ static int eeprom_fallback(struct eeprom_req_info *request,
+ if (err < 0)
+ return err;
+
+- data = kmalloc(eeprom.len, GFP_KERNEL);
++ data = kzalloc(eeprom.len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ err = ethtool_get_module_eeprom_call(dev, &eeprom, data);
+--
+2.53.0
+
--- /dev/null
+From c9c55cdbc9d68d28c4942b316acd0c34051b286f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:26 -0700
+Subject: ethtool: linkstate: fix unbalanced ethnl_ops_complete() on PHY lookup
+ error
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 596c51ed9e125b12c4d85b4530dfd4c7847634b7 ]
+
+linkstate_prepare_data() calls ethnl_req_get_phydev() before
+ethnl_ops_begin(), but routes its error path through "goto out"
+which calls ethnl_ops_complete().
+
+Fixes: fe55b1d401c6 ("ethtool: linkstate: migrate linkstate functions to support multi-PHY setups")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-4-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/linkstate.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c
+index 05a5f72c99fab1..3dc52a39d34525 100644
+--- a/net/ethtool/linkstate.c
++++ b/net/ethtool/linkstate.c
+@@ -105,10 +105,8 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
+
+ phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_LINKSTATE_HEADER,
+ info->extack);
+- if (IS_ERR(phydev)) {
+- ret = PTR_ERR(phydev);
+- goto out;
+- }
++ if (IS_ERR(phydev))
++ return PTR_ERR(phydev);
+
+ ret = ethnl_ops_begin(dev);
+ if (ret < 0)
+--
+2.53.0
+
--- /dev/null
+From ecce56fee8e68bba693ca2a51c13cb0a8d90ae9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:05 -0700
+Subject: ethtool: module: avoid leaking a netdev ref on module flash errors
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit fb7f511d62692661846c47f199e0afe25c2982db ]
+
+module_flash_fw_schedule() is missing undo for setting
+the "in_progress" flag and taking the netdev reference.
+Delay taking these, the device can't disappear while
+we are holding rtnl_lock.
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-3-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index 6988e07bdcd6d4..76d13ef4ba0427 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -318,8 +318,6 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
+ if (err < 0)
+ goto err_release_firmware;
+
+- dev->ethtool->module_fw_flash_in_progress = true;
+- netdev_hold(dev, &module_fw->dev_tracker, GFP_KERNEL);
+ fw_update->dev = dev;
+ fw_update->ntf_params.portid = info->snd_portid;
+ fw_update->ntf_params.seq = info->snd_seq;
+@@ -334,6 +332,9 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
+ if (err < 0)
+ goto err_release_firmware;
+
++ dev->ethtool->module_fw_flash_in_progress = true;
++ netdev_hold(dev, &module_fw->dev_tracker, GFP_KERNEL);
++
+ schedule_work(&module_fw->work);
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 97b374a40553467f255faf43f38484155f16857f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:07 -0700
+Subject: ethtool: module: check fw_flash_in_progress under rtnl_lock
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 504eaefa44c8dec50f7499edcb36d24f3aefab2a ]
+
+ethnl_set_module_validate() inspects module_fw_flash_in_progress
+but validate is meant for _input_ validation, not state validation.
+rtnl_lock is not held, yet. Move the check into ethnl_set_module().
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-5-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index 76d13ef4ba0427..ab1e8a83acd0b1 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -119,12 +119,6 @@ ethnl_set_module_validate(struct ethnl_req_info *req_info,
+ if (!tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY])
+ return 0;
+
+- if (req_info->dev->ethtool->module_fw_flash_in_progress) {
+- NL_SET_ERR_MSG(info->extack,
+- "Module firmware flashing is in progress");
+- return -EBUSY;
+- }
+-
+ if (!ops->get_module_power_mode || !ops->set_module_power_mode) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY],
+@@ -147,6 +141,12 @@ ethnl_set_module(struct ethnl_req_info *req_info, struct genl_info *info)
+
+ ops = dev->ethtool_ops;
+
++ if (dev->ethtool->module_fw_flash_in_progress) {
++ NL_SET_ERR_MSG(info->extack,
++ "Module firmware flashing is in progress");
++ return -EBUSY;
++ }
++
+ power_new.policy = nla_get_u8(tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]);
+ ret = ops->get_module_power_mode(dev, &power, info->extack);
+ if (ret < 0)
+--
+2.53.0
+
--- /dev/null
+From e1fa51ed09dcfa83fcecf69b928831a72149f740 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:08 -0700
+Subject: ethtool: module: fix cleanup if socket used for flashing multiple
+ devices
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 760d04ebad5c4304f22c0d2251c9623b87a117c8 ]
+
+When a single Netlink socket issues MODULE_FW_FLASH_ACT against multiple
+devices, ethnl_sock_priv_set() overwrites sk_priv->dev on each call,
+retaining only the last one. The socket priv is used on socket close,
+to walk the global work list and mark the uncompleted flashing work
+as "orphaned". Otherwise if another socket reuses the PID it will
+unexpectedly receive the flashing notifications.
+
+Don't record the device, record net pointer instead. The purpose of
+the dev is to scope the work to a netns, anyway. If we store netns
+the overrides are safe/a nop since all flashed devices must be in
+the same netns as the socket.
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-6-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 9 ++++-----
+ net/ethtool/netlink.c | 4 ++--
+ net/ethtool/netlink.h | 4 ++--
+ 3 files changed, 8 insertions(+), 9 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index ab1e8a83acd0b1..5a08c320b4660d 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -282,11 +282,9 @@ void ethnl_module_fw_flash_sock_destroy(struct ethnl_sock_priv *sk_priv)
+
+ spin_lock(&module_fw_flash_work_list_lock);
+ list_for_each_entry(work, &module_fw_flash_work_list, list) {
+- if (work->fw_update.dev == sk_priv->dev &&
+- work->fw_update.ntf_params.portid == sk_priv->portid) {
++ if (work->fw_update.ntf_params.portid == sk_priv->portid &&
++ dev_net(work->fw_update.dev) == sk_priv->net)
+ work->fw_update.ntf_params.closed_sock = true;
+- break;
+- }
+ }
+ spin_unlock(&module_fw_flash_work_list_lock);
+ }
+@@ -323,7 +321,8 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
+ fw_update->ntf_params.seq = info->snd_seq;
+ fw_update->ntf_params.closed_sock = false;
+
+- err = ethnl_sock_priv_set(skb, dev, fw_update->ntf_params.portid,
++ err = ethnl_sock_priv_set(skb, dev_net(dev),
++ fw_update->ntf_params.portid,
+ ETHTOOL_SOCK_TYPE_MODULE_FW_FLASH);
+ if (err < 0)
+ goto err_release_firmware;
+diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
+index a52be67139d0ac..409b4109940b7c 100644
+--- a/net/ethtool/netlink.c
++++ b/net/ethtool/netlink.c
+@@ -50,7 +50,7 @@ const struct nla_policy ethnl_header_policy_phy_stats[] = {
+ [ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1),
+ };
+
+-int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
++int ethnl_sock_priv_set(struct sk_buff *skb, struct net *net, u32 portid,
+ enum ethnl_sock_type type)
+ {
+ struct ethnl_sock_priv *sk_priv;
+@@ -59,7 +59,7 @@ int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
+ if (IS_ERR(sk_priv))
+ return PTR_ERR(sk_priv);
+
+- sk_priv->dev = dev;
++ sk_priv->net = net;
+ sk_priv->portid = portid;
+ sk_priv->type = type;
+
+diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
+index 5e176938d6d228..11843bd10bcade 100644
+--- a/net/ethtool/netlink.h
++++ b/net/ethtool/netlink.h
+@@ -315,12 +315,12 @@ enum ethnl_sock_type {
+ };
+
+ struct ethnl_sock_priv {
+- struct net_device *dev;
++ struct net *net;
+ u32 portid;
+ enum ethnl_sock_type type;
+ };
+
+-int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
++int ethnl_sock_priv_set(struct sk_buff *skb, struct net *net, u32 portid,
+ enum ethnl_sock_type type);
+
+ /**
+--
+2.53.0
+
--- /dev/null
+From d87e38cb504e75d198e622156e79c9804c30b718 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:27 -0700
+Subject: ethtool: pse-pd: fix missing ethnl_ops_complete()
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit ab5bf428fb6bd361163c7247b92750d1d24ca2ed ]
+
+pse_prepare_data() is missing ethnl_ops_complete() if
+ethnl_req_get_phydev() returned an error. Move getting
+phydev up so that we don't have to worry about this
+(similar order to linkstate_prepare_data()).
+
+Note that phydev may still be NULL (this is checked in
+pse_get_pse_attributes()), the goal isn't really to avoid
+the _begin() / _complete() calls, only to simplify the error
+handling.
+
+While at it propagate the original error. Why this code
+overrides the error with -ENODEV but !phydev generates
+-EOPNOTSUPP is unclear to me...
+
+Fixes: 31748765bed3 ("net: ethtool: pse-pd: Target the command to the requested PHY")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-5-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/pse-pd.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c
+index 71843de832cca7..01517c53113def 100644
+--- a/net/ethtool/pse-pd.c
++++ b/net/ethtool/pse-pd.c
+@@ -60,14 +60,14 @@ static int pse_prepare_data(const struct ethnl_req_info *req_base,
+ struct phy_device *phydev;
+ int ret;
+
+- ret = ethnl_ops_begin(dev);
+- if (ret < 0)
+- return ret;
+-
+ phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PSE_HEADER,
+ info->extack);
+ if (IS_ERR(phydev))
+- return -ENODEV;
++ return PTR_ERR(phydev);
++
++ ret = ethnl_ops_begin(dev);
++ if (ret < 0)
++ return ret;
+
+ ret = pse_get_pse_attributes(phydev, info->extack, data);
+
+--
+2.53.0
+
--- /dev/null
+From cc79b6df73ae96027b1531931f0e6aa6c979ca41 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:46 -0700
+Subject: ethtool: rss: fix hkey leak when indir_size is 0
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 78ccf1a70c6378e1f5073a8c2209b5129067b925 ]
+
+rss_get_data_alloc() allocates a single buffer that backs both the
+indirection table and the hash key, but only assigned data->indir_table
+when indir_size was nonzero. The expectation was that no driver
+implements RSS without supporting indirection table but apparently
+enic does just that (it's the only such in-tree driver).
+enic has get_rxfh_key_size but no get_rxfh_indir_size.
+data->indir_table stays as NULL, hkey gets set but rss_get_data_free()
+kfree(data->indir_table) is a nop and the allocation leaks.
+
+Always store the allocation base in data->indir_table so the free path
+is unambiguous. No caller treats indir_table as a sentinel; everything
+keys off indir_size.
+
+Fixes: 7112a04664bf ("ethtool: add netlink based get rss support")
+Link: https://patch.msgid.link/20260522230647.1705600-6-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index 8aa45f3fdfdf08..3570d58c5cca6d 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -78,8 +78,7 @@ rss_prepare_get(const struct rss_req_info *request, struct net_device *dev,
+ goto out_ops;
+ }
+
+- if (data->indir_size)
+- data->indir_table = (u32 *)rss_config;
++ data->indir_table = (u32 *)rss_config;
+ if (data->hkey_size)
+ data->hkey = rss_config + indir_bytes;
+
+--
+2.53.0
+
--- /dev/null
+From 2f5ec54271a0eada7e7c8c5e819d0923c0b17ce8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:31 -0700
+Subject: ethtool: strset: fix header attribute index in ethnl_req_get_phydev()
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit a8d8bef6b45bf7cc0b1f6110c5cd8d0160a9bad7 ]
+
+strset_prepare_data() passes ETHTOOL_A_HEADER_FLAGS (3) as the header
+attribute to ethnl_req_get_phydev(). This is incorrect, in the main
+attr space 3 is ETHTOOL_A_STRSET_COUNTS_ONLY, not the request
+header attr. The correct constant is ETHTOOL_A_STRSET_HEADER (1).
+
+ethnl_req_get_phydev() only uses this value for the extack,
+so this is not a "functionally visible"(?) bug.
+
+Fixes: e96c93aa4be9 ("net: ethtool: strset: Allow querying phy stats by index")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-9-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/strset.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c
+index b9400d18f01d58..73597f0bc923a3 100644
+--- a/net/ethtool/strset.c
++++ b/net/ethtool/strset.c
+@@ -299,7 +299,7 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base,
+ return 0;
+ }
+
+- phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_HEADER_FLAGS,
++ phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_STRSET_HEADER,
+ info->extack);
+
+ /* phydev can be NULL, check for errors only */
+--
+2.53.0
+
--- /dev/null
+From d06b6fb2d6a16285e12b133c9a3e2efd9f1e060f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:01 +0200
+Subject: gpio: mxc: fix irq_high handling
+
+From: Alexander Stein <alexander.stein@ew.tq-group.com>
+
+[ Upstream commit dac917ed5aead741004db8d0d5151dd577802df8 ]
+
+If port->irq_high is -1 (fsl,imx21-gpio compatible) and gpio_idx is >= 16
+enable_irq_wake() is called with -1 which is wrong.
+
+Fixes: 5f6d1998adeb ("gpio: mxc: release the parent IRQ in runtime suspend")
+Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://patch.msgid.link/20260526063504.25916-1-alexander.stein@ew.tq-group.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-mxc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
+index 3cdc2b218a86af..a8ab78ae7fa30c 100644
+--- a/drivers/gpio/gpio-mxc.c
++++ b/drivers/gpio/gpio-mxc.c
+@@ -473,7 +473,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
+ * the handler is needed only once, but doing it for every port
+ * is more robust and easier.
+ */
+- port->irq_high = -1;
++ port->irq_high = 0;
+ port->mx_irq_handler = mx2_gpio_irq_handler;
+ } else
+ port->mx_irq_handler = mx3_gpio_irq_handler;
+--
+2.53.0
+
--- /dev/null
+From d1aae623768e071f3095ecc7b4a0b90aa914e851 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:02:45 +0200
+Subject: gpio: rockchip: convert bank->clk to devm_clk_get_enabled()
+
+From: Marco Scardovi <scardracs@disroot.org>
+
+[ Upstream commit 3e46c18d5d87f063a93ae0fe7662fbf6660459d5 ]
+
+The bank->clk was previously obtained via of_clk_get() and manually
+prepared/enabled. However, it was missing a corresponding clk_put() in
+both the error paths and the remove function, leading to a reference leak.
+
+Convert the allocation to devm_clk_get_enabled(), which also properly
+propagates failures from clk_prepare_enable() that were previously ignored.
+
+The GPIO bank device uses the same OF node as the previous of_clk_get()
+call, so devm_clk_get_enabled(dev, NULL) correctly resolves the same
+clock provider entry.
+
+Fix the reference leak and simplify the code by removing the manual
+clk_disable_unprepare() calls in the probe error paths and in the
+remove function.
+
+Fixes: 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio")
+Assisted-by: Antigravity:gemini-3.5-flash
+Signed-off-by: Marco Scardovi <scardracs@disroot.org>
+Link: https://patch.msgid.link/20260526171050.12785-2-scardracs@disroot.org
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-rockchip.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
+index 4e2132c80be32a..052713bd8d07a9 100644
+--- a/drivers/gpio/gpio-rockchip.c
++++ b/drivers/gpio/gpio-rockchip.c
+@@ -647,11 +647,10 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ if (!bank->irq)
+ return -EINVAL;
+
+- bank->clk = of_clk_get(bank->of_node, 0);
++ bank->clk = devm_clk_get_enabled(bank->dev, NULL);
+ if (IS_ERR(bank->clk))
+ return PTR_ERR(bank->clk);
+
+- clk_prepare_enable(bank->clk);
+ id = readl(bank->reg_base + gpio_regs_v2.version_id);
+
+ /* If not gpio v2, that is default to v1. */
+@@ -661,7 +660,6 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ bank->db_clk = of_clk_get(bank->of_node, 1);
+ if (IS_ERR(bank->db_clk)) {
+ dev_err(bank->dev, "cannot find debounce clk\n");
+- clk_disable_unprepare(bank->clk);
+ return -EINVAL;
+ }
+ } else {
+@@ -735,7 +733,6 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
+
+ ret = rockchip_gpiolib_register(bank);
+ if (ret) {
+- clk_disable_unprepare(bank->clk);
+ mutex_unlock(&bank->deferred_lock);
+ return ret;
+ }
+@@ -776,7 +773,6 @@ static void rockchip_gpio_remove(struct platform_device *pdev)
+ {
+ struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
+
+- clk_disable_unprepare(bank->clk);
+ gpiochip_remove(&bank->gpio_chip);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From e8a0ef3e4d01ecf7c6b89f1ef4a52b96e3fc1fc3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 10:15:16 +0300
+Subject: gpio: virtuser: Fix uninitialized data bug in
+ gpio_virtuser_direction_do_write()
+
+From: Dan Carpenter <error27@gmail.com>
+
+[ Upstream commit 8a122b5e72cc0043705f0d524bcd15f0c0b3ec15 ]
+
+If *ppos is non-zero (user-space write split over multiple calls to
+write()) then simple_write_to_buffer() won't initialize the start of the
+buffer. Really, non-zero values for *ppos aren't going to work at all.
+Check for that and return -EINVAL at the start of the function.
+
+Fixes: 91581c4b3f29 ("gpio: virtuser: new virtual testing driver for the GPIO API")
+Signed-off-by: Dan Carpenter <error27@gmail.com>
+Link: https://patch.msgid.link/ahP3BJWWy-m_qI0X@stanley.mountain
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-virtuser.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpio/gpio-virtuser.c b/drivers/gpio/gpio-virtuser.c
+index 8a313dd624c26e..ff1977b2699144 100644
+--- a/drivers/gpio/gpio-virtuser.c
++++ b/drivers/gpio/gpio-virtuser.c
+@@ -400,7 +400,7 @@ static ssize_t gpio_virtuser_direction_do_write(struct file *file,
+ char buf[32], *trimmed;
+ int ret, dir, val = 0;
+
+- if (count >= sizeof(buf))
++ if (*ppos != 0 || count >= sizeof(buf))
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+@@ -627,7 +627,7 @@ static ssize_t gpio_virtuser_consumer_write(struct file *file,
+ char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2];
+ int ret;
+
+- if (count >= sizeof(buf))
++ if (*ppos != 0 || count >= sizeof(buf))
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos,
+--
+2.53.0
+
--- /dev/null
+From b85bcdd734c195cd86e91ea415c8cb2b48d20683 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 12:21:47 +0000
+Subject: ipv4: free net->ipv4.sysctl_local_reserved_ports after
+ unregister_net_sysctl_table()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 87a1e0fe7776da7ab411be332b4be58ac8840d10 ]
+
+ipv4_sysctl_exit_net() is currently freeing net->ipv4.sysctl_local_reserved_ports
+too soon.
+
+Only after unregister_net_sysctl_table() we can be sure no threads can possibly
+use the sysctls, including /proc/sys/net/ipv4/ip_local_reserved_ports.
+
+Fixes: 122ff243f5f1 ("ipv4: make ip_local_reserved_ports per netns")
+Reported-by: Ji'an Zhou <eilaimemedsnaimel@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260521122147.3584624-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/sysctl_net_ipv4.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 8d411cce0aedc1..35a6e7d8f52f7e 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -1630,10 +1630,10 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net)
+ {
+ const struct ctl_table *table;
+
+- kfree(net->ipv4.sysctl_local_reserved_ports);
+ table = net->ipv4.ipv4_hdr->ctl_table_arg;
+ unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
+ kfree(table);
++ kfree(net->ipv4.sysctl_local_reserved_ports);
+ }
+
+ static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
+--
+2.53.0
+
--- /dev/null
+From 0c667bf1831d8bd1afb0b20048bae0657bc19b0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:31:31 +0800
+Subject: ipv6: fix possible infinite loop in fib6_select_path()
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 9c7da87c2dc860bb17ca1ece942495d28b1ce3b9 ]
+
+Found while auditing the same pattern Sashiko reported in
+rt6_fill_node() [1]. Apply the same fix as
+commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").
+
+Writers holding tb6_lock can list_del_rcu(&first->fib6_siblings)
+without waiting for RCU readers; first->fib6_siblings.next then
+still points into the old ring and this softirq-side walker never
+reaches &first->fib6_siblings as its terminator. fib6_purge_rt()
+always WRITE_ONCE()s first->fib6_nsiblings to 0 before
+list_del_rcu(), so an inside-loop check is a reliable detach signal.
+
+[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev
+
+Fixes: d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260527053133.180695-2-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index c73218fd82c615..9e7470e8154429 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -482,6 +482,9 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
+ const struct fib6_nh *nh = sibling->fib6_nh;
+ int nh_upper_bound;
+
++ if (!READ_ONCE(first->fib6_nsiblings))
++ break;
++
+ nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
+ if (hash > nh_upper_bound)
+ continue;
+--
+2.53.0
+
--- /dev/null
+From eadfc481d6f6a107bce2837ee1f4423d95b0730a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:31:30 +0800
+Subject: ipv6: fix possible infinite loop in rt6_fill_node()
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 9f72412bcf60144f252b0d6205106abf14344abc ]
+
+Sashiko reported this issue [1]. Apply the same fix as
+commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").
+
+Writers holding tb6_lock can list_del_rcu(&rt->fib6_siblings)
+without waiting for RCU readers; rt->fib6_siblings.next then still
+points into the old ring and this softirq-side walker never reaches
+&rt->fib6_siblings, causing a CPU stall. fib6_del_route() always
+WRITE_ONCE()s rt->fib6_nsiblings to 0 before list_del_rcu(), so an
+inside-loop check is a reliable detach signal.
+
+[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev
+
+Fixes: d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260527053133.180695-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index 31c9e3b73f2da1..c73218fd82c615 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -5812,6 +5812,8 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
+
+ goto nla_put_failure;
+ }
++ if (!READ_ONCE(rt->fib6_nsiblings))
++ break;
+ }
+
+ rcu_read_unlock();
+--
+2.53.0
+
--- /dev/null
+From 5fe5a7749f8348b1f29eecadcf936692b1efc613 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 21:10:31 +0530
+Subject: ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress()
+
+From: Rahul Chandelkar <rc@rexion.ai>
+
+[ Upstream commit 9d5e7a46a9f6d8f503b41bfefef70659845f1679 ]
+
+ipv6_rpl_srh_decompress() computes:
+
+ outhdr->hdrlen = (((n + 1) * sizeof(struct in6_addr)) >> 3);
+
+hdrlen is __u8. For n >= 127 the result exceeds 255 and silently
+truncates. With n=127 (cmpri=15, cmpre=15, pad=0, hdrlen=16):
+
+ (128 * 16) >> 3 = 256, truncated to 0 as __u8
+
+The caller in ipv6_rpl_srh_rcv() then places the compressed header
+at buf + ((ohdr->hdrlen + 1) << 3). With hdrlen=0 this is buf + 8,
+but the decompressed region occupies buf[0..2055] (8-byte header
+plus 128 full addresses). The compressed header overlaps the
+decompressed data, and ipv6_rpl_srh_compress() writes into this
+overlap, corrupting the routing header of the forwarded packet.
+
+The existing guard at exthdrs.c:546 checks (n + 1) > 255, which
+prevents n+1 from overflowing unsigned char (the segments_left
+field), but does not prevent the computed hdrlen from overflowing
+__u8. n=127 passes because 128 <= 255, yet hdrlen=256 does not
+fit.
+
+Tighten the bound to (n + 1) > 127. This caps n at 126, giving
+hdrlen = (127 * 16) >> 3 = 254, which fits in __u8. The compressed
+header then lands at buf + ((254 + 1) << 3) = buf + 2040, exactly
+past the decompressed region (buf[0..2039]). No overlap. 127
+segments is well beyond any realistic RPL deployment.
+
+Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
+Signed-off-by: Rahul Chandelkar <rc@rexion.ai>
+Link: https://patch.msgid.link/20260525154031.2290876-1-rc@rexion.ai
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/exthdrs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
+index 5ef6fbc66beb11..43e34fe448ffe5 100644
+--- a/net/ipv6/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -546,7 +546,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
+ * unsigned char which is segments_left field. Should not be
+ * higher than that.
+ */
+- if (r || (n + 1) > 255) {
++ if (r || (n + 1) > 127) {
+ kfree_skb(skb);
+ return -1;
+ }
+--
+2.53.0
+
--- /dev/null
+From a82d548757479b3ca17d9a83621823a9b630a9c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 20:49:56 +0530
+Subject: kernel/fork: validate exit_signal in kernel_clone()
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit 09e7827e785729f391c8d46dc71becce70d296ab ]
+
+When a child process exits, it sends exit_signal to its parent via
+do_notify_parent(). The clone() syscall constructs exit_signal as:
+
+(lower_32_bits(clone_flags) & CSIGNAL)
+
+CSIGNAL is 0xff, so values in the range 65-255 are possible. However,
+valid_signal() only accepts signals up to _NSIG (64 on x86_64). A
+non-zero non-valid exit_signal acts the same as exit_signal == 0: the
+parent process is not signaled when the child terminates.
+
+The syzkaller reproducer triggers this by calling clone() with flags=0x80,
+resulting in exit_signal = (0x80 & CSIGNAL) = 128, which exceeds _NSIG and
+is not a valid signal.
+
+The v1 of this patch added the check only in the clone() syscall handler,
+which is incomplete. kernel_clone() has other callers such as
+sys_ia32_clone() which would remain unprotected. Move the check to
+kernel_clone() to cover all callers.
+
+Since the valid_signal() check is now in kernel_clone() and covers all
+callers including clone3(), the same check in copy_clone_args_from_user()
+becomes redundant and is removed. The higher 32bits check for clone3() is
+kept as it is clone3() specific.
+
+Note that this is a user-visible change: previously, passing an invalid
+exit_signal to clone() was silently accepted. The man page for clone()
+does not document any defined behavior for invalid exit_signal values, so
+rejecting them with -EINVAL is the correct behavior. It is unlikely that
+any sane application relies on passing an invalid exit_signal.
+
+[oleg@redhat.com: the comment above kernel_clone() should be updated]
+ Link: https://lore.kernel.org/abwvgU17W8wuW2-J@redhat.com
+Link: https://lore.kernel.org/20260316151956.563558-1-kartikey406@gmail.com
+Fixes: 3f2c788a1314 ("fork: prevent accidental access to clone3 features")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Reported-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=bbe6b99feefc3a0842de
+Tested-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/all/20260307064202.353405-1-kartikey406@gmail.com/T/ [v1]
+Link: https://lore.kernel.org/all/20260316104536.558108-1-kartikey406@gmail.com/T/ [v2]
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Ben Segall <bsegall@google.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Juri Lelli <juri.lelli@redhat.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: Liam Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
+Cc: Mel Gorman <mgorman@suse.de>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Valentin Schneider <vschneid@redhat.com>
+Cc: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/fork.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index c4955cffcb6f4e..1f306743832b3e 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -2773,8 +2773,6 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
+ *
+ * It copies the process, and if successful kick-starts
+ * it and waits for it to finish using the VM if required.
+- *
+- * args->exit_signal is expected to be checked for sanity by the caller.
+ */
+ pid_t kernel_clone(struct kernel_clone_args *args)
+ {
+@@ -2799,6 +2797,9 @@ pid_t kernel_clone(struct kernel_clone_args *args)
+ (args->pidfd == args->parent_tid))
+ return -EINVAL;
+
++ if (!valid_signal(args->exit_signal))
++ return -EINVAL;
++
+ /*
+ * Determine whether and which event to report to ptracer. When
+ * called from kernel_thread or CLONE_UNTRACED is explicitly
+@@ -2999,11 +3000,9 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
+ return -EINVAL;
+
+ /*
+- * Verify that higher 32bits of exit_signal are unset and that
+- * it is a valid signal
++ * Verify that higher 32bits of exit_signal are unset
+ */
+- if (unlikely((args.exit_signal & ~((u64)CSIGNAL)) ||
+- !valid_signal(args.exit_signal)))
++ if (unlikely(args.exit_signal & ~((u64)CSIGNAL)))
+ return -EINVAL;
+
+ if ((args.flags & CLONE_INTO_CGROUP) &&
+--
+2.53.0
+
--- /dev/null
+From da3f684ae417a67b4727c5f4f7fd96d3860085bd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 May 2026 10:48:54 +0200
+Subject: kunit: fix use-after-free in debugfs when using kunit.filter
+
+From: Florian Schmaus <florian.schmaus@codasip.com>
+
+[ Upstream commit fb6988b83b4cafe8db63999c1ddff1b7c66d2ff5 ]
+
+When the kernel is booted with a kunit filter (e.g.,
+kunit.filter="speed!=slow"), the kunit executor dynamically allocates
+copies of the filtered test suites using kmalloc/kmemdup.
+
+During the initial boot execution, kunit_debugfs_create_suite() creates
+debugfs files (such as /sys/kernel/debug/kunit/<suite>/run) and
+permanently stores a pointer to the dynamically allocated suite in the
+inode's i_private field.
+
+Previously, the executor freed this dynamically allocated suite_set
+immediately after executing the boot-time tests. Because the debugfs
+nodes were not destroyed, any subsequent interaction with the debugfs
+`run` file from userspace triggered a use-after-free (UAF). On systems
+with architectural capabilities, like CHERI RISC-V, this resulted in
+an immediate fatal hardware exception due to the invalidation of the
+capability tags on the reclaimed memory. On other architectures, it
+resulted in silent memory corruption.
+
+Fix this UAF by properly coupling the lifetime of the filtered suite
+memory allocation to the lifetime of the kunit subsystem and its
+associated VFS nodes. Ownership of the boot-time suite_set is now
+transferred to a global tracker ('kunit_boot_suites'), and the memory
+is cleanly released in kunit_exit() during module teardown.
+
+Link: https://lore.kernel.org/r/20260507084854.233984-1-florian.schmaus@codasip.com
+Fixes: e2219db280e3 ("kunit: add debugfs /sys/kernel/debug/kunit/<suite>/results display")
+Signed-off-by: Florian Schmaus <florian.schmaus@codasip.com>
+Reviewed-by: Martin Kaiser <martin@kaiser.cx>
+Reviewed-by: David Gow <david@davidgow.net>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/kunit/test.h | 1 +
+ lib/kunit/executor.c | 19 ++++++++++++++++---
+ lib/kunit/test.c | 1 +
+ 3 files changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/include/kunit/test.h b/include/kunit/test.h
+index 34b71e42fb107c..6132faa314fcb8 100644
+--- a/include/kunit/test.h
++++ b/include/kunit/test.h
+@@ -547,6 +547,7 @@ unsigned long kunit_vm_mmap(struct kunit *test, struct file *file,
+ unsigned long offset);
+
+ void kunit_cleanup(struct kunit *test);
++void kunit_free_boot_suites(void);
+
+ void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt, ...);
+
+diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
+index 34b7b6833df3d5..7cd1c87eb2edfb 100644
+--- a/lib/kunit/executor.c
++++ b/lib/kunit/executor.c
+@@ -15,6 +15,16 @@ extern struct kunit_suite * const __kunit_suites_end[];
+ extern struct kunit_suite * const __kunit_init_suites_start[];
+ extern struct kunit_suite * const __kunit_init_suites_end[];
+
++static struct kunit_suite_set kunit_boot_suites;
++
++void kunit_free_boot_suites(void)
++{
++ if (kunit_boot_suites.start) {
++ kunit_free_suite_set(kunit_boot_suites);
++ kunit_boot_suites = (struct kunit_suite_set){ NULL, NULL };
++ }
++}
++
+ static char *action_param;
+
+ module_param_named(action, action_param, charp, 0400);
+@@ -392,9 +402,12 @@ int kunit_run_all_tests(void)
+ pr_err("kunit executor: unknown action '%s'\n", action_param);
+
+ free_out:
+- if (filter_glob_param || filter_param)
+- kunit_free_suite_set(suite_set);
+- else if (init_num_suites > 0)
++ if (filter_glob_param || filter_param) {
++ if (err)
++ kunit_free_suite_set(suite_set);
++ else
++ kunit_boot_suites = suite_set;
++ } else if (init_num_suites > 0)
+ /* Don't use kunit_free_suite_set because suites aren't individually allocated */
+ kfree(suite_set.start);
+
+diff --git a/lib/kunit/test.c b/lib/kunit/test.c
+index 089c832e3cdbd5..b808826e6de2cf 100644
+--- a/lib/kunit/test.c
++++ b/lib/kunit/test.c
+@@ -954,6 +954,7 @@ static void __exit kunit_exit(void)
+ kunit_bus_shutdown();
+
+ kunit_debugfs_cleanup();
++ kunit_free_boot_suites();
+ }
+ module_exit(kunit_exit);
+
+--
+2.53.0
+
--- /dev/null
+From 4f491a1ffae73fe0d638ea5ee51e151c69b23ab5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 14:06:40 +0200
+Subject: net: Avoid checksumming unreadable skb tail on trim
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Björn Töpel <bjorn@kernel.org>
+
+[ Upstream commit 2e357f002c61fd76fd8f12468744a06a5ec48eaa ]
+
+pskb_trim_rcsum_slow() keeps CHECKSUM_COMPLETE valid by subtracting
+the checksum of the bytes removed from the skb tail. That assumes the
+removed bytes can be read.
+
+io_uring zcrx skbs may contain unreadable net_iov frags. With fbnic
+header/data split, small TCP/IPv4 packets can carry Ethernet padding
+in such a frag. ip_rcv_core() trims the skb to iph->tot_len before TCP
+sees it, and the CHECKSUM_COMPLETE adjustment then calls
+skb_checksum() on the padding.
+
+This is exposed by IPv4 because small TCP/IPv4 frames can be shorter
+than the Ethernet minimum payload. TCP/IPv6 frames are large enough in
+the normal zcrx path, so they do not hit the same padding trim.
+
+Keep the existing checksum adjustment for readable skbs. If the
+remaining packet is fully linear, drop CHECKSUM_COMPLETE and let the
+stack validate the packet after trimming. If unreadable payload would
+remain, fail the trim; the checksum cannot be adjusted without reading
+the trimmed tail.
+
+Also clear skb->unreadable when trimming removes all frags.
+
+Fixes: 65249feb6b3d ("net: add support for skbs with unreadable frags")
+Signed-off-by: Björn Töpel <bjorn@kernel.org>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Link: https://patch.msgid.link/20260522120643.242974-1-bjorn@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/skbuff.c | 31 +++++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index aa9e9148847363..8c9f026182a6f0 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -2765,6 +2765,8 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
+ skb->data_len = 0;
+ skb_set_tail_pointer(skb, len);
+ }
++ if (!skb_shinfo(skb)->nr_frags && !skb_has_frag_list(skb))
++ skb->unreadable = 0;
+
+ if (!skb->sk || skb->destructor == sock_edemux)
+ skb_condense(skb);
+@@ -2772,16 +2774,37 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
+ }
+ EXPORT_SYMBOL(___pskb_trim);
+
++static int pskb_trim_rcsum_complete(struct sk_buff *skb, unsigned int len)
++{
++ int delta = skb->len - len;
++
++ if (skb_frags_readable(skb)) {
++ skb->csum = csum_block_sub(skb->csum,
++ skb_checksum(skb, len, delta, 0),
++ len);
++ return 0;
++ }
++
++ if (len > skb_headlen(skb))
++ return -EFAULT;
++
++ /* The trimmed bytes are unreadable, but the remaining packet can be
++ * checksummed by software after trimming.
++ */
++ skb->ip_summed = CHECKSUM_NONE;
++ return 0;
++}
++
+ /* Note : use pskb_trim_rcsum() instead of calling this directly
+ */
+ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len)
+ {
+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
+- int delta = skb->len - len;
++ int err;
+
+- skb->csum = csum_block_sub(skb->csum,
+- skb_checksum(skb, len, delta, 0),
+- len);
++ err = pskb_trim_rcsum_complete(skb, len);
++ if (err)
++ return err;
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ int hdlen = (len > skb_headlen(skb)) ? skb_headlen(skb) : len;
+ int offset = skb_checksum_start_offset(skb) + skb->csum_offset;
+--
+2.53.0
+
--- /dev/null
+From ef3d0abad78355d2c1d9a1832b2540b666451d9a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Oct 2024 13:53:46 +0300
+Subject: net: ethtool: Add new parameters and a function to support EPL
+
+From: Danielle Ratson <danieller@nvidia.com>
+
+[ Upstream commit edc344568922eb9588e77ba49de1ef0cb9a2ff1c ]
+
+In the CMIS specification for pluggable modules, LPL (Local Payload) and
+EPL (Extended Payload) are two types of data payloads used for managing
+various functions and features of the module.
+
+EPL payloads are used for more complex and extensive management
+functions that require a larger amount of data, so writing firmware
+blocks using EPL is much more efficient.
+
+Currently, only LPL payload is supported for writing firmware blocks to
+the module.
+
+Add EPL related parameters to the function ethtool_cmis_cdb_compose_args()
+and add a specific function for calculating the maximum allowable length
+extension for EPL. Both will be used in the next patch to add support for
+writing firmware blocks using EPL.
+
+Signed-off-by: Danielle Ratson <danieller@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 12c2496a71f8 ("ethtool: cmis: validate start_cmd_payload_size from module")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis.h | 12 +++++++-----
+ net/ethtool/cmis_cdb.c | 32 +++++++++++++++++++++-----------
+ net/ethtool/cmis_fw_update.c | 17 ++++++++++-------
+ 3 files changed, 38 insertions(+), 23 deletions(-)
+
+diff --git a/net/ethtool/cmis.h b/net/ethtool/cmis.h
+index aa32a675b8f8d2..e11e47b3f2fc8f 100644
+--- a/net/ethtool/cmis.h
++++ b/net/ethtool/cmis.h
+@@ -96,13 +96,15 @@ struct ethtool_cmis_cdb_rpl {
+ u8 payload[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH];
+ };
+
+-u32 ethtool_cmis_get_max_payload_size(u8 num_of_byte_octs);
++u32 ethtool_cmis_get_max_lpl_size(u8 num_of_byte_octs);
++u32 ethtool_cmis_get_max_epl_size(u8 num_of_byte_octs);
+
+ void ethtool_cmis_cdb_compose_args(struct ethtool_cmis_cdb_cmd_args *args,
+- enum ethtool_cmis_cdb_cmd_id cmd, u8 *pl,
+- u8 lpl_len, u16 max_duration,
+- u8 read_write_len_ext, u16 msleep_pre_rpl,
+- u8 rpl_exp_len, u8 flags);
++ enum ethtool_cmis_cdb_cmd_id cmd, u8 *lpl,
++ u8 lpl_len, u8 *epl, u16 epl_len,
++ u16 max_duration, u8 read_write_len_ext,
++ u16 msleep_pre_rpl, u8 rpl_exp_len,
++ u8 flags);
+
+ void ethtool_cmis_cdb_check_completion_flag(u8 cmis_rev, u8 *flags);
+
+diff --git a/net/ethtool/cmis_cdb.c b/net/ethtool/cmis_cdb.c
+index 690002366d965a..31142e239cf6b2 100644
+--- a/net/ethtool/cmis_cdb.c
++++ b/net/ethtool/cmis_cdb.c
+@@ -11,25 +11,34 @@
+ * min(i, 15) byte octets where i specifies the allowable additional number of
+ * byte octets in a READ or a WRITE.
+ */
+-u32 ethtool_cmis_get_max_payload_size(u8 num_of_byte_octs)
++u32 ethtool_cmis_get_max_lpl_size(u8 num_of_byte_octs)
+ {
+ return 8 * (1 + min_t(u8, num_of_byte_octs, 15));
+ }
+
++/* For accessing the EPL field on page 9Fh, the allowable length extension is
++ * min(i, 255) byte octets where i specifies the allowable additional number of
++ * byte octets in a READ or a WRITE.
++ */
++u32 ethtool_cmis_get_max_epl_size(u8 num_of_byte_octs)
++{
++ return 8 * (1 + min_t(u8, num_of_byte_octs, 255));
++}
++
+ void ethtool_cmis_cdb_compose_args(struct ethtool_cmis_cdb_cmd_args *args,
+- enum ethtool_cmis_cdb_cmd_id cmd, u8 *pl,
+- u8 lpl_len, u16 max_duration,
+- u8 read_write_len_ext, u16 msleep_pre_rpl,
+- u8 rpl_exp_len, u8 flags)
++ enum ethtool_cmis_cdb_cmd_id cmd, u8 *lpl,
++ u8 lpl_len, u8 *epl, u16 epl_len,
++ u16 max_duration, u8 read_write_len_ext,
++ u16 msleep_pre_rpl, u8 rpl_exp_len, u8 flags)
+ {
+ args->req.id = cpu_to_be16(cmd);
+ args->req.lpl_len = lpl_len;
+- if (pl)
+- memcpy(args->req.payload, pl, args->req.lpl_len);
++ if (lpl)
++ memcpy(args->req.payload, lpl, args->req.lpl_len);
+
+ args->max_duration = max_duration;
+ args->read_write_len_ext =
+- ethtool_cmis_get_max_payload_size(read_write_len_ext);
++ ethtool_cmis_get_max_lpl_size(read_write_len_ext);
+ args->msleep_pre_rpl = msleep_pre_rpl;
+ args->rpl_exp_len = rpl_exp_len;
+ args->flags = flags;
+@@ -183,7 +192,7 @@ cmis_cdb_validate_password(struct ethtool_cmis_cdb *cdb,
+ }
+
+ ethtool_cmis_cdb_compose_args(&args, ETHTOOL_CMIS_CDB_CMD_QUERY_STATUS,
+- (u8 *)&qs_pl, sizeof(qs_pl), 0,
++ (u8 *)&qs_pl, sizeof(qs_pl), NULL, 0, 0,
+ cdb->read_write_len_ext, 1000,
+ sizeof(*rpl),
+ CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
+@@ -245,8 +254,9 @@ static int cmis_cdb_module_features_get(struct ethtool_cmis_cdb *cdb,
+ ethtool_cmis_cdb_check_completion_flag(cdb->cmis_rev, &flags);
+ ethtool_cmis_cdb_compose_args(&args,
+ ETHTOOL_CMIS_CDB_CMD_MODULE_FEATURES,
+- NULL, 0, 0, cdb->read_write_len_ext,
+- 1000, sizeof(*rpl), flags);
++ NULL, 0, NULL, 0, 0,
++ cdb->read_write_len_ext, 1000,
++ sizeof(*rpl), flags);
+
+ err = ethtool_cmis_cdb_execute_cmd(dev, &args);
+ if (err < 0) {
+diff --git a/net/ethtool/cmis_fw_update.c b/net/ethtool/cmis_fw_update.c
+index 655ff5224ffa30..a514127985d44e 100644
+--- a/net/ethtool/cmis_fw_update.c
++++ b/net/ethtool/cmis_fw_update.c
+@@ -54,7 +54,8 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ ethtool_cmis_cdb_check_completion_flag(cdb->cmis_rev, &flags);
+ ethtool_cmis_cdb_compose_args(&args,
+ ETHTOOL_CMIS_CDB_CMD_FW_MANAGMENT_FEATURES,
+- NULL, 0, cdb->max_completion_time,
++ NULL, 0, NULL, 0,
++ cdb->max_completion_time,
+ cdb->read_write_len_ext, 1000,
+ sizeof(*rpl), flags);
+
+@@ -122,7 +123,7 @@ cmis_fw_update_start_download(struct ethtool_cmis_cdb *cdb,
+
+ ethtool_cmis_cdb_compose_args(&args,
+ ETHTOOL_CMIS_CDB_CMD_START_FW_DOWNLOAD,
+- (u8 *)&pl, lpl_len,
++ (u8 *)&pl, lpl_len, NULL, 0,
+ fw_mng->max_duration_start,
+ cdb->read_write_len_ext, 1000, 0,
+ CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
+@@ -158,7 +159,7 @@ cmis_fw_update_write_image(struct ethtool_cmis_cdb *cdb,
+ int err;
+
+ max_lpl_len = min_t(u32,
+- ethtool_cmis_get_max_payload_size(cdb->read_write_len_ext),
++ ethtool_cmis_get_max_lpl_size(cdb->read_write_len_ext),
+ ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH);
+ max_block_size =
+ max_lpl_len - sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl,
+@@ -183,7 +184,7 @@ cmis_fw_update_write_image(struct ethtool_cmis_cdb *cdb,
+
+ ethtool_cmis_cdb_compose_args(&args,
+ ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_LPL,
+- (u8 *)&pl, lpl_len,
++ (u8 *)&pl, lpl_len, NULL, 0,
+ fw_mng->max_duration_write,
+ cdb->read_write_len_ext, 1, 0,
+ CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
+@@ -212,7 +213,8 @@ cmis_fw_update_complete_download(struct ethtool_cmis_cdb *cdb,
+
+ ethtool_cmis_cdb_compose_args(&args,
+ ETHTOOL_CMIS_CDB_CMD_COMPLETE_FW_DOWNLOAD,
+- NULL, 0, fw_mng->max_duration_complete,
++ NULL, 0, NULL, 0,
++ fw_mng->max_duration_complete,
+ cdb->read_write_len_ext, 1000, 0,
+ CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
+
+@@ -294,7 +296,7 @@ cmis_fw_update_run_image(struct ethtool_cmis_cdb *cdb, struct net_device *dev,
+ int err;
+
+ ethtool_cmis_cdb_compose_args(&args, ETHTOOL_CMIS_CDB_CMD_RUN_FW_IMAGE,
+- (u8 *)&pl, sizeof(pl),
++ (u8 *)&pl, sizeof(pl), NULL, 0,
+ cdb->max_completion_time,
+ cdb->read_write_len_ext, 1000, 0,
+ CDB_F_MODULE_STATE_VALID);
+@@ -326,7 +328,8 @@ cmis_fw_update_commit_image(struct ethtool_cmis_cdb *cdb,
+
+ ethtool_cmis_cdb_compose_args(&args,
+ ETHTOOL_CMIS_CDB_CMD_COMMIT_FW_IMAGE,
+- NULL, 0, cdb->max_completion_time,
++ NULL, 0, NULL, 0,
++ cdb->max_completion_time,
+ cdb->read_write_len_ext, 1000, 0,
+ CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
+
+--
+2.53.0
+
--- /dev/null
+From 72b43e32aa56e2172e3d7423bf34884e809aea85 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Oct 2024 13:53:47 +0300
+Subject: net: ethtool: Add support for writing firmware blocks using EPL
+ payload
+
+From: Danielle Ratson <danieller@nvidia.com>
+
+[ Upstream commit 9a3b0d078bd825613c0821bf7bf5a2e1d8d60057 ]
+
+In the CMIS specification for pluggable modules, LPL (Local Payload) and
+EPL (Extended Payload) are two types of data payloads used for managing
+various functions and features of the module.
+
+EPL payloads are used for more complex and extensive management
+functions that require a larger amount of data, so writing firmware
+blocks using EPL is much more efficient.
+
+Currently, only LPL payload is supported for writing firmware blocks to
+the module.
+
+Add support for writing firmware block using EPL payload, both to
+support modules that supports only EPL write mechanism, and to optimize
+the flashing process of modules that support LPL and EPL.
+
+Signed-off-by: Danielle Ratson <danieller@nvidia.com>
+Reviewed-by: Petr Machata <petrm@nvidia.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 12c2496a71f8 ("ethtool: cmis: validate start_cmd_payload_size from module")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis.h | 4 ++
+ net/ethtool/cmis_cdb.c | 66 ++++++++++++++++++++++++--
+ net/ethtool/cmis_fw_update.c | 91 ++++++++++++++++++++++++++++++++----
+ 3 files changed, 148 insertions(+), 13 deletions(-)
+
+diff --git a/net/ethtool/cmis.h b/net/ethtool/cmis.h
+index e11e47b3f2fc8f..1ab96bdd2c6f92 100644
+--- a/net/ethtool/cmis.h
++++ b/net/ethtool/cmis.h
+@@ -1,6 +1,7 @@
+ /* SPDX-License-Identifier: GPL-2.0-only */
+
+ #define ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH 120
++#define ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH 2048
+ #define ETHTOOL_CMIS_CDB_CMD_PAGE 0x9F
+ #define ETHTOOL_CMIS_CDB_PAGE_I2C_ADDR 0x50
+
+@@ -23,6 +24,7 @@ enum ethtool_cmis_cdb_cmd_id {
+ ETHTOOL_CMIS_CDB_CMD_FW_MANAGMENT_FEATURES = 0x0041,
+ ETHTOOL_CMIS_CDB_CMD_START_FW_DOWNLOAD = 0x0101,
+ ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_LPL = 0x0103,
++ ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_EPL = 0x0104,
+ ETHTOOL_CMIS_CDB_CMD_COMPLETE_FW_DOWNLOAD = 0x0107,
+ ETHTOOL_CMIS_CDB_CMD_RUN_FW_IMAGE = 0x0109,
+ ETHTOOL_CMIS_CDB_CMD_COMMIT_FW_IMAGE = 0x010A,
+@@ -38,6 +40,7 @@ enum ethtool_cmis_cdb_cmd_id {
+ * @resv1: Added to match the CMIS standard request continuity.
+ * @resv2: Added to match the CMIS standard request continuity.
+ * @payload: Payload for the CDB commands.
++ * @epl: Extended payload for the CDB commands.
+ */
+ struct ethtool_cmis_cdb_request {
+ __be16 id;
+@@ -49,6 +52,7 @@ struct ethtool_cmis_cdb_request {
+ u8 resv2;
+ u8 payload[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH];
+ );
++ u8 *epl; /* Everything above this field checksummed. */
+ };
+
+ #define CDB_F_COMPLETION_VALID BIT(0)
+diff --git a/net/ethtool/cmis_cdb.c b/net/ethtool/cmis_cdb.c
+index 31142e239cf6b2..606d88df31f235 100644
+--- a/net/ethtool/cmis_cdb.c
++++ b/net/ethtool/cmis_cdb.c
+@@ -33,12 +33,19 @@ void ethtool_cmis_cdb_compose_args(struct ethtool_cmis_cdb_cmd_args *args,
+ {
+ args->req.id = cpu_to_be16(cmd);
+ args->req.lpl_len = lpl_len;
+- if (lpl)
++ if (lpl) {
+ memcpy(args->req.payload, lpl, args->req.lpl_len);
++ args->read_write_len_ext =
++ ethtool_cmis_get_max_lpl_size(read_write_len_ext);
++ }
++ if (epl) {
++ args->req.epl_len = cpu_to_be16(epl_len);
++ args->req.epl = epl;
++ args->read_write_len_ext =
++ ethtool_cmis_get_max_epl_size(read_write_len_ext);
++ }
+
+ args->max_duration = max_duration;
+- args->read_write_len_ext =
+- ethtool_cmis_get_max_lpl_size(read_write_len_ext);
+ args->msleep_pre_rpl = msleep_pre_rpl;
+ args->rpl_exp_len = rpl_exp_len;
+ args->flags = flags;
+@@ -561,6 +568,49 @@ __ethtool_cmis_cdb_execute_cmd(struct net_device *dev,
+ return err;
+ }
+
++#define CMIS_CDB_EPL_PAGE_START 0xA0
++#define CMIS_CDB_EPL_PAGE_END 0xAF
++#define CMIS_CDB_EPL_FW_BLOCK_OFFSET_START 128
++#define CMIS_CDB_EPL_FW_BLOCK_OFFSET_END 255
++
++static int
++ethtool_cmis_cdb_execute_epl_cmd(struct net_device *dev,
++ struct ethtool_cmis_cdb_cmd_args *args,
++ struct ethtool_module_eeprom *page_data)
++{
++ u16 epl_len = be16_to_cpu(args->req.epl_len);
++ u32 bytes_written = 0;
++ u8 page;
++ int err;
++
++ for (page = CMIS_CDB_EPL_PAGE_START;
++ page <= CMIS_CDB_EPL_PAGE_END && bytes_written < epl_len; page++) {
++ u16 offset = CMIS_CDB_EPL_FW_BLOCK_OFFSET_START;
++
++ while (offset <= CMIS_CDB_EPL_FW_BLOCK_OFFSET_END &&
++ bytes_written < epl_len) {
++ u32 bytes_left = epl_len - bytes_written;
++ u16 space_left, bytes_to_write;
++
++ space_left = CMIS_CDB_EPL_FW_BLOCK_OFFSET_END - offset + 1;
++ bytes_to_write = min_t(u16, bytes_left,
++ min_t(u16, space_left,
++ args->read_write_len_ext));
++
++ err = __ethtool_cmis_cdb_execute_cmd(dev, page_data,
++ page, offset,
++ bytes_to_write,
++ args->req.epl + bytes_written);
++ if (err < 0)
++ return err;
++
++ offset += bytes_to_write;
++ bytes_written += bytes_to_write;
++ }
++ }
++ return 0;
++}
++
+ static u8 cmis_cdb_calc_checksum(const void *data, size_t size)
+ {
+ const u8 *bytes = (const u8 *)data;
+@@ -582,7 +632,9 @@ int ethtool_cmis_cdb_execute_cmd(struct net_device *dev,
+ int err;
+
+ args->req.chk_code =
+- cmis_cdb_calc_checksum(&args->req, sizeof(args->req));
++ cmis_cdb_calc_checksum(&args->req,
++ offsetof(struct ethtool_cmis_cdb_request,
++ epl));
+
+ if (args->req.lpl_len > args->read_write_len_ext) {
+ args->err_msg = "LPL length is longer than CDB read write length extension allows";
+@@ -604,6 +656,12 @@ int ethtool_cmis_cdb_execute_cmd(struct net_device *dev,
+ if (err < 0)
+ return err;
+
++ if (args->req.epl_len) {
++ err = ethtool_cmis_cdb_execute_epl_cmd(dev, args, &page_data);
++ if (err < 0)
++ return err;
++ }
++
+ offset = CMIS_CDB_CMD_ID_OFFSET +
+ offsetof(struct ethtool_cmis_cdb_request, id);
+ err = __ethtool_cmis_cdb_execute_cmd(dev, &page_data,
+diff --git a/net/ethtool/cmis_fw_update.c b/net/ethtool/cmis_fw_update.c
+index a514127985d44e..48aef6220f0094 100644
+--- a/net/ethtool/cmis_fw_update.c
++++ b/net/ethtool/cmis_fw_update.c
+@@ -9,6 +9,7 @@
+
+ struct cmis_fw_update_fw_mng_features {
+ u8 start_cmd_payload_size;
++ u8 write_mechanism;
+ u16 max_duration_start;
+ u16 max_duration_write;
+ u16 max_duration_complete;
+@@ -36,7 +37,9 @@ struct cmis_cdb_fw_mng_features_rpl {
+ };
+
+ enum cmis_cdb_fw_write_mechanism {
++ CMIS_CDB_FW_WRITE_MECHANISM_NONE = 0x00,
+ CMIS_CDB_FW_WRITE_MECHANISM_LPL = 0x01,
++ CMIS_CDB_FW_WRITE_MECHANISM_EPL = 0x10,
+ CMIS_CDB_FW_WRITE_MECHANISM_BOTH = 0x11,
+ };
+
+@@ -68,10 +71,9 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ }
+
+ rpl = (struct cmis_cdb_fw_mng_features_rpl *)args.req.payload;
+- if (!(rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL ||
+- rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_BOTH)) {
++ if (rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_NONE) {
+ ethnl_module_fw_flash_ntf_err(dev, ntf_params,
+- "Write LPL is not supported",
++ "CDB write mechanism is not supported",
+ NULL);
+ return -EOPNOTSUPP;
+ }
+@@ -83,6 +85,10 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ */
+ cdb->read_write_len_ext = rpl->read_write_len_ext;
+ fw_mng->start_cmd_payload_size = rpl->start_cmd_payload_size;
++ fw_mng->write_mechanism =
++ rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL ?
++ CMIS_CDB_FW_WRITE_MECHANISM_LPL :
++ CMIS_CDB_FW_WRITE_MECHANISM_EPL;
+ fw_mng->max_duration_start = be16_to_cpu(rpl->max_duration_start);
+ fw_mng->max_duration_write = be16_to_cpu(rpl->max_duration_write);
+ fw_mng->max_duration_complete = be16_to_cpu(rpl->max_duration_complete);
+@@ -149,9 +155,9 @@ struct cmis_cdb_write_fw_block_lpl_pl {
+ };
+
+ static int
+-cmis_fw_update_write_image(struct ethtool_cmis_cdb *cdb,
+- struct ethtool_cmis_fw_update_params *fw_update,
+- struct cmis_fw_update_fw_mng_features *fw_mng)
++cmis_fw_update_write_image_lpl(struct ethtool_cmis_cdb *cdb,
++ struct ethtool_cmis_fw_update_params *fw_update,
++ struct cmis_fw_update_fw_mng_features *fw_mng)
+ {
+ u8 start = fw_mng->start_cmd_payload_size;
+ u32 offset, max_block_size, max_lpl_len;
+@@ -202,6 +208,67 @@ cmis_fw_update_write_image(struct ethtool_cmis_cdb *cdb,
+ return 0;
+ }
+
++struct cmis_cdb_write_fw_block_epl_pl {
++ u8 fw_block[ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH];
++};
++
++static int
++cmis_fw_update_write_image_epl(struct ethtool_cmis_cdb *cdb,
++ struct ethtool_cmis_fw_update_params *fw_update,
++ struct cmis_fw_update_fw_mng_features *fw_mng)
++{
++ u8 start = fw_mng->start_cmd_payload_size;
++ u32 image_size = fw_update->fw->size;
++ u32 offset, lpl_len;
++ int err;
++
++ lpl_len = sizeof_field(struct cmis_cdb_write_fw_block_lpl_pl,
++ block_address);
++
++ for (offset = start; offset < image_size;
++ offset += ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH) {
++ struct cmis_cdb_write_fw_block_lpl_pl lpl = {
++ .block_address = cpu_to_be32(offset - start),
++ };
++ struct cmis_cdb_write_fw_block_epl_pl *epl;
++ struct ethtool_cmis_cdb_cmd_args args = {};
++ u32 epl_len;
++
++ ethnl_module_fw_flash_ntf_in_progress(fw_update->dev,
++ &fw_update->ntf_params,
++ offset - start,
++ image_size);
++
++ epl_len = min_t(u32, ETHTOOL_CMIS_CDB_EPL_MAX_PL_LENGTH,
++ image_size - offset);
++ epl = kmalloc_array(epl_len, sizeof(u8), GFP_KERNEL);
++ if (!epl)
++ return -ENOMEM;
++
++ memcpy(epl->fw_block, &fw_update->fw->data[offset], epl_len);
++
++ ethtool_cmis_cdb_compose_args(&args,
++ ETHTOOL_CMIS_CDB_CMD_WRITE_FW_BLOCK_EPL,
++ (u8 *)&lpl, lpl_len, (u8 *)epl,
++ epl_len,
++ fw_mng->max_duration_write,
++ cdb->read_write_len_ext, 1, 0,
++ CDB_F_COMPLETION_VALID | CDB_F_STATUS_VALID);
++
++ err = ethtool_cmis_cdb_execute_cmd(fw_update->dev, &args);
++ kfree(epl);
++ if (err < 0) {
++ ethnl_module_fw_flash_ntf_err(fw_update->dev,
++ &fw_update->ntf_params,
++ "Write FW block EPL command failed",
++ args.err_msg);
++ return err;
++ }
++ }
++
++ return 0;
++}
++
+ static int
+ cmis_fw_update_complete_download(struct ethtool_cmis_cdb *cdb,
+ struct net_device *dev,
+@@ -238,9 +305,15 @@ cmis_fw_update_download_image(struct ethtool_cmis_cdb *cdb,
+ if (err < 0)
+ return err;
+
+- err = cmis_fw_update_write_image(cdb, fw_update, fw_mng);
+- if (err < 0)
+- return err;
++ if (fw_mng->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL) {
++ err = cmis_fw_update_write_image_lpl(cdb, fw_update, fw_mng);
++ if (err < 0)
++ return err;
++ } else {
++ err = cmis_fw_update_write_image_epl(cdb, fw_update, fw_mng);
++ if (err < 0)
++ return err;
++ }
+
+ err = cmis_fw_update_complete_download(cdb, fw_update->dev, fw_mng,
+ &fw_update->ntf_params);
+--
+2.53.0
+
--- /dev/null
+From b31d1fc4e428f49c68f4bf59c55cd6c35c252205 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:22 -0400
+Subject: net/handshake: Drain pending requests at net namespace exit
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit ea5fe6a73ca57e5150b8a38b341aef2636eb72f0 ]
+
+The arguments to list_splice_init() in handshake_net_exit() are
+reversed. The call moves the local empty "requests" list onto
+hn->hn_requests, leaving the local list empty, so the subsequent
+drain loop runs zero iterations. Pending handshake requests that
+had not yet been accepted are not torn down when the net namespace
+is destroyed; each one keeps a reference on a socket file and on
+the handshake_req allocation.
+
+Pass the source and destination in the documented order
+(list_splice_init(list, head) moves list onto head) so the pending
+list is transferred to the local scratch list and drained through
+handshake_complete().
+
+Fixing the splice direction exposes a list-corruption race. After
+the splice each req->hr_list still has non-empty link pointers,
+threading the stack-local scratch list rather than hn_requests.
+A concurrent handshake_req_cancel() -- for example, from sunrpc's
+TLS timeout on a kernel socket whose netns reference was not
+taken -- finds the request through the rhashtable, calls
+remove_pending(), and sees !list_empty(&req->hr_list).
+__remove_pending_locked() then list_del_init()s an entry off the
+scratch list while the drain iterates, corrupting it. The same
+call arriving after the drain loop has run list_del() on an
+entry hits LIST_POISON instead.
+
+Have remove_pending() check HANDSHAKE_F_NET_DRAINING under
+hn_lock and report not-found when drain is in progress. The
+drain has already taken ownership; handshake_complete()'s existing
+test_and_set on HANDSHAKE_F_REQ_COMPLETED still arbitrates
+between drain and cancel for who calls the consumer's hp_done. Use
+list_del_init() rather than list_del() in the drain so req->hr_list
+does not carry LIST_POISON after drain releases the entry.
+
+The DRAINING guard in remove_pending() makes cancel return false,
+but cancel still falls through to test_and_set_bit on
+HANDSHAKE_F_REQ_COMPLETED and drops the request's hr_file reference.
+Without another pin, if that is the last reference, sk_destruct frees
+the request while it is still linked on the drain loop's local list.
+Pin each request's hr_file under hn_lock before releasing the list,
+and drop that drain pin after the loop finishes with the request.
+
+Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-8-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/handshake/netlink.c | 10 ++++++++--
+ net/handshake/request.c | 5 ++++-
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index 86a12c9125d403..e49041cc0f9d70 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -205,13 +205,19 @@ static void __net_exit handshake_net_exit(struct net *net)
+ */
+ spin_lock_bh(&hn->hn_lock);
+ set_bit(HANDSHAKE_F_NET_DRAINING, &hn->hn_flags);
+- list_splice_init(&requests, &hn->hn_requests);
++ list_splice_init(&hn->hn_requests, &requests);
++ list_for_each_entry(req, &requests, hr_list)
++ get_file(req->hr_file);
+ spin_unlock_bh(&hn->hn_lock);
+
+ while (!list_empty(&requests)) {
++ struct file *file;
++
+ req = list_first_entry(&requests, struct handshake_req, hr_list);
+- list_del(&req->hr_list);
++ file = req->hr_file;
++ list_del_init(&req->hr_list);
+ handshake_complete(req, -ETIMEDOUT, NULL);
++ fput(file);
+ }
+ }
+
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 35bc6290e12033..96f80e0df67b50 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -163,13 +163,16 @@ static void __remove_pending_locked(struct handshake_net *hn,
+ * otherwise %false.
+ *
+ * If @req was on a pending list, it has not yet been accepted.
++ * Returns %false when the net namespace is draining; the drain
++ * loop has taken ownership of the pending list.
+ */
+ static bool remove_pending(struct handshake_net *hn, struct handshake_req *req)
+ {
+ bool ret = false;
+
+ spin_lock_bh(&hn->hn_lock);
+- if (!list_empty(&req->hr_list)) {
++ if (!test_bit(HANDSHAKE_F_NET_DRAINING, &hn->hn_flags) &&
++ !list_empty(&req->hr_list)) {
+ __remove_pending_locked(hn, req);
+ ret = true;
+ }
+--
+2.53.0
+
--- /dev/null
+From 1616ec410d95511eda4e449b2797c511fb5f7bf1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:17 -0400
+Subject: net/handshake: Pass negative errno through handshake_complete()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 6b22d433aa13f68e3cd9534ca9a5f4277bfa01c2 ]
+
+handshake_complete() declares status as unsigned int and
+tls_handshake_done() negates that value (-status) before handing
+it to the TLS consumer. Consumers match on negative errno
+constants -- xs_tls_handshake_done() has
+
+ switch (status) {
+ case 0:
+ case -EACCES:
+ case -ETIMEDOUT:
+ lower_transport->xprt_err = status;
+ break;
+ default:
+ lower_transport->xprt_err = -EACCES;
+ }
+
+so the API as designed expects callers to pass positive errno
+values that the tlshd shim then negates.
+
+Three internal callers in handshake_nl_accept_doit(), the
+net-exit drain, and a kunit test follow kernel convention and
+pass negative errnos -- -EIO, -ETIMEDOUT, -ETIMEDOUT. The
+implicit conversion to unsigned int turns -ETIMEDOUT into
+0xFFFFFF92; the subsequent -status in tls_handshake_done()
+wraps back to 110, the consumer's switch falls through, and
+the xprt reports -EACCES on what should be -ETIMEDOUT or -EIO.
+
+Fix the API rather than the call sites. The natural kernel
+convention is negative errno in, negative errno out. Change
+handshake_complete() and hp_done to take int status, drop the
+negation in tls_handshake_done(), and negate once in
+handshake_nl_done_doit() where status arrives from the wire
+as an unsigned netlink attribute. The three internal callers
+were already correct under that convention and need no change.
+
+At the same wire boundary, declare MAX_ERRNO as the netlink
+policy upper bound for HANDSHAKE_A_DONE_STATUS. Attribute
+validation rejects out-of-range values before
+handshake_nl_done_doit() runs, and negating a bounded u32 there
+stays within int range -- closing the UBSAN-visible signed-
+integer overflow that an unconstrained u32 would invoke.
+
+Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-3-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/netlink/specs/handshake.yaml | 8 ++++++++
+ net/handshake/genl.c | 3 ++-
+ net/handshake/genl.h | 1 +
+ net/handshake/handshake-test.c | 2 +-
+ net/handshake/handshake.h | 4 ++--
+ net/handshake/netlink.c | 2 +-
+ net/handshake/request.c | 2 +-
+ net/handshake/tlshd.c | 4 ++--
+ 8 files changed, 18 insertions(+), 8 deletions(-)
+
+diff --git a/Documentation/netlink/specs/handshake.yaml b/Documentation/netlink/specs/handshake.yaml
+index b934cc513e3d6f..090fc11da4604a 100644
+--- a/Documentation/netlink/specs/handshake.yaml
++++ b/Documentation/netlink/specs/handshake.yaml
+@@ -12,6 +12,12 @@ protocol: genetlink
+ doc: Netlink protocol to request a transport layer security handshake.
+
+ definitions:
++ -
++ type: const
++ name: max-errno
++ value: 4095
++ header: linux/err.h
++ scope: kernel
+ -
+ type: enum
+ name: handler-class
+@@ -77,6 +83,8 @@ attribute-sets:
+ -
+ name: status
+ type: u32
++ checks:
++ max: max-errno
+ -
+ name: sockfd
+ type: s32
+diff --git a/net/handshake/genl.c b/net/handshake/genl.c
+index f55d14d7b7269d..a5fa8b27f22423 100644
+--- a/net/handshake/genl.c
++++ b/net/handshake/genl.c
+@@ -9,6 +9,7 @@
+ #include "genl.h"
+
+ #include <uapi/linux/handshake.h>
++#include <linux/err.h>
+
+ /* HANDSHAKE_CMD_ACCEPT - do */
+ static const struct nla_policy handshake_accept_nl_policy[HANDSHAKE_A_ACCEPT_HANDLER_CLASS + 1] = {
+@@ -17,7 +18,7 @@ static const struct nla_policy handshake_accept_nl_policy[HANDSHAKE_A_ACCEPT_HAN
+
+ /* HANDSHAKE_CMD_DONE - do */
+ static const struct nla_policy handshake_done_nl_policy[HANDSHAKE_A_DONE_REMOTE_AUTH + 1] = {
+- [HANDSHAKE_A_DONE_STATUS] = { .type = NLA_U32, },
++ [HANDSHAKE_A_DONE_STATUS] = NLA_POLICY_MAX(NLA_U32, MAX_ERRNO),
+ [HANDSHAKE_A_DONE_SOCKFD] = { .type = NLA_S32, },
+ [HANDSHAKE_A_DONE_REMOTE_AUTH] = { .type = NLA_U32, },
+ };
+diff --git a/net/handshake/genl.h b/net/handshake/genl.h
+index ae72a596f6cc3e..684e5fd684481b 100644
+--- a/net/handshake/genl.h
++++ b/net/handshake/genl.h
+@@ -10,6 +10,7 @@
+ #include <net/genetlink.h>
+
+ #include <uapi/linux/handshake.h>
++#include <linux/err.h>
+
+ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info);
+ int handshake_nl_done_doit(struct sk_buff *skb, struct genl_info *info);
+diff --git a/net/handshake/handshake-test.c b/net/handshake/handshake-test.c
+index 34fd1d9b2db861..a331b308aaa240 100644
+--- a/net/handshake/handshake-test.c
++++ b/net/handshake/handshake-test.c
+@@ -25,7 +25,7 @@ static int test_accept_func(struct handshake_req *req, struct genl_info *info,
+ return 0;
+ }
+
+-static void test_done_func(struct handshake_req *req, unsigned int status,
++static void test_done_func(struct handshake_req *req, int status,
+ struct genl_info *info)
+ {
+ }
+diff --git a/net/handshake/handshake.h b/net/handshake/handshake.h
+index a48163765a7a1d..2289b0e274f40a 100644
+--- a/net/handshake/handshake.h
++++ b/net/handshake/handshake.h
+@@ -57,7 +57,7 @@ struct handshake_proto {
+ int (*hp_accept)(struct handshake_req *req,
+ struct genl_info *info, int fd);
+ void (*hp_done)(struct handshake_req *req,
+- unsigned int status,
++ int status,
+ struct genl_info *info);
+ void (*hp_destroy)(struct handshake_req *req);
+ };
+@@ -86,7 +86,7 @@ struct handshake_req *handshake_req_hash_lookup(struct sock *sk);
+ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class);
+ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ gfp_t flags);
+-void handshake_complete(struct handshake_req *req, unsigned int status,
++void handshake_complete(struct handshake_req *req, int status,
+ struct genl_info *info);
+ bool handshake_req_cancel(struct sock *sk);
+
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index 394e270cc505cb..d8211e0ba75c69 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -161,7 +161,7 @@ int handshake_nl_done_doit(struct sk_buff *skb, struct genl_info *info)
+
+ status = -EIO;
+ if (info->attrs[HANDSHAKE_A_DONE_STATUS])
+- status = nla_get_u32(info->attrs[HANDSHAKE_A_DONE_STATUS]);
++ status = -(int)nla_get_u32(info->attrs[HANDSHAKE_A_DONE_STATUS]);
+
+ handshake_complete(req, status, info);
+ sockfd_put(sock);
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 75562f6629e050..2f58d74f16554b 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -285,7 +285,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ }
+ EXPORT_SYMBOL(handshake_req_submit);
+
+-void handshake_complete(struct handshake_req *req, unsigned int status,
++void handshake_complete(struct handshake_req *req, int status,
+ struct genl_info *info)
+ {
+ struct sock *sk = req->hr_sk;
+diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c
+index fd71ef2d18ceb2..5464e57c347b9c 100644
+--- a/net/handshake/tlshd.c
++++ b/net/handshake/tlshd.c
+@@ -93,7 +93,7 @@ static void tls_handshake_remote_peerids(struct tls_handshake_req *treq,
+ *
+ */
+ static void tls_handshake_done(struct handshake_req *req,
+- unsigned int status, struct genl_info *info)
++ int status, struct genl_info *info)
+ {
+ struct tls_handshake_req *treq = handshake_req_private(req);
+
+@@ -104,7 +104,7 @@ static void tls_handshake_done(struct handshake_req *req,
+ if (!status)
+ set_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags);
+
+- treq->th_consumer_done(treq->th_consumer_data, -status,
++ treq->th_consumer_done(treq->th_consumer_data, status,
+ treq->th_peerid[0]);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 3285d576d858e0fd808c19cd043f6dc5649577fd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:18 -0400
+Subject: net/handshake: Take a long-lived file reference at submit
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 09dba37eee70d0596e26645015f1aa95a9848e9d ]
+
+handshake_nl_accept_doit() needs the file pointer backing
+req->hr_sk->sk_socket to survive the window between
+handshake_req_next() and the subsequent FD_PREPARE() and get_file().
+The submit-side sock_hold() does not provide that. sk_refcnt keeps
+struct sock alive, but struct socket is owned by sock->file: when
+the consumer fputs the last file reference, sock_release() tears
+the socket down regardless of any sock_hold.
+
+Add an hr_file pointer to struct handshake_req and acquire an
+explicit reference on sock->file during handshake_req_submit().
+handshake_complete() and handshake_req_cancel() release the
+reference on the completion-bit-winning path.
+
+The submit error path must also release the file reference, but
+after rhashtable insertion a concurrent handshake_req_cancel() can
+discover the request and race the error path. Gate the error-path
+cleanup -- sk_destruct restoration, fput, and request destruction
+-- with test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED), the same
+serialization handshake_complete() and handshake_req_cancel()
+already use. When cancel has already claimed ownership, the submit
+error path returns without touching the request; socket teardown
+handles final destruction.
+
+The accept-side dereferences are not yet retargeted; that change
+comes in the next patch.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-4-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: ea5fe6a73ca5 ("net/handshake: Drain pending requests at net namespace exit")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/handshake/handshake.h | 2 ++
+ net/handshake/netlink.c | 6 ------
+ net/handshake/request.c | 42 ++++++++++++++++++++++++++++++++-------
+ 3 files changed, 37 insertions(+), 13 deletions(-)
+
+diff --git a/net/handshake/handshake.h b/net/handshake/handshake.h
+index 2289b0e274f40a..da61cadd1ad3e7 100644
+--- a/net/handshake/handshake.h
++++ b/net/handshake/handshake.h
+@@ -24,6 +24,7 @@ enum hn_flags_bits {
+ HANDSHAKE_F_NET_DRAINING,
+ };
+
++struct file;
+ struct handshake_proto;
+
+ /* One handshake request */
+@@ -32,6 +33,7 @@ struct handshake_req {
+ struct rhash_head hr_rhash;
+ unsigned long hr_flags;
+ const struct handshake_proto *hr_proto;
++ struct file *hr_file;
+ struct sock *hr_sk;
+ void (*hr_odestruct)(struct sock *sk);
+
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index d8211e0ba75c69..86a12c9125d403 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -211,12 +211,6 @@ static void __net_exit handshake_net_exit(struct net *net)
+ while (!list_empty(&requests)) {
+ req = list_first_entry(&requests, struct handshake_req, hr_list);
+ list_del(&req->hr_list);
+-
+- /*
+- * Requests on this list have not yet been
+- * accepted, so they do not have an fd to put.
+- */
+-
+ handshake_complete(req, -ETIMEDOUT, NULL);
+ }
+ }
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 62efb7e32730ea..35bc6290e12033 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -13,6 +13,7 @@
+ #include <linux/module.h>
+ #include <linux/skbuff.h>
+ #include <linux/inet.h>
++#include <linux/file.h>
+ #include <linux/rhashtable.h>
+
+ #include <net/sock.h>
+@@ -215,9 +216,16 @@ EXPORT_SYMBOL_IF_KUNIT(handshake_req_next);
+ * A zero return value from handshake_req_submit() means that
+ * exactly one subsequent completion callback is guaranteed.
+ *
+- * A negative return value from handshake_req_submit() means that
+- * no completion callback will be done and that @req has been
+- * destroyed.
++ * A negative return value from handshake_req_submit() guarantees that
++ * no completion callback will occur and that @req is no longer owned by
++ * the caller. If cancellation wins the completion race after the request
++ * has been published, final destruction is deferred until socket teardown.
++ *
++ * The caller must hold a reference on @sock->file for the duration
++ * of this call. Once the request is published to the accept side, a
++ * concurrent completion or cancellation may release the request's pin on
++ * @sock->file; the caller's reference is what keeps @sock->sk valid until
++ * handshake_req_submit() returns.
+ */
+ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ gfp_t flags)
+@@ -236,6 +244,14 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ kfree(req);
+ return -EINVAL;
+ }
++
++ /*
++ * Pin sock->file for the lifetime of the request so the
++ * accept side does not race a consumer that releases the
++ * socket while a handshake is pending.
++ */
++ req->hr_file = get_file(sock->file);
++
+ req->hr_odestruct = req->hr_sk->sk_destruct;
+ req->hr_sk->sk_destruct = handshake_sk_destruct;
+
+@@ -267,7 +283,11 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ goto out_err;
+ }
+
+- /* Prevent socket release while a handshake request is pending */
++ /*
++ * Pin struct sock so sk_destruct does not run until the
++ * handshake completion path releases it; struct socket is
++ * held separately via hr_file above.
++ */
+ sock_hold(req->hr_sk);
+
+ trace_handshake_submit(net, req, req->hr_sk);
+@@ -276,10 +296,13 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ out_unlock:
+ spin_unlock_bh(&hn->hn_lock);
+ out_err:
+- /* Restore original destructor so socket teardown still runs on failure */
+- req->hr_sk->sk_destruct = req->hr_odestruct;
+ trace_handshake_submit_err(net, req, req->hr_sk, ret);
+- handshake_req_destroy(req);
++ if (!test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) {
++ /* Restore original destructor so socket teardown still runs. */
++ req->hr_sk->sk_destruct = req->hr_odestruct;
++ fput(req->hr_file);
++ handshake_req_destroy(req);
++ }
+ return ret;
+ }
+ EXPORT_SYMBOL(handshake_req_submit);
+@@ -291,11 +314,15 @@ void handshake_complete(struct handshake_req *req, int status,
+ struct net *net = sock_net(sk);
+
+ if (!test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) {
++ struct file *file = req->hr_file;
++
+ trace_handshake_complete(net, req, sk, status);
+ req->hr_proto->hp_done(req, status, info);
+
+ /* Handshake request is no longer pending */
+ sock_put(sk);
++
++ fput(file);
+ }
+ }
+ EXPORT_SYMBOL_IF_KUNIT(handshake_complete);
+@@ -344,6 +371,7 @@ bool handshake_req_cancel(struct sock *sk)
+
+ /* Handshake request is no longer pending */
+ sock_put(sk);
++ fput(req->hr_file);
+ return true;
+ }
+ EXPORT_SYMBOL(handshake_req_cancel);
+--
+2.53.0
+
--- /dev/null
+From 5c0599665b076e2fc881cd31a2fcefc2561a6b45 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:15 -0400
+Subject: net/handshake: Use spin_lock_bh for hn_lock
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit cc993e0927ec8bd98ea33377ada03295fcda0f24 ]
+
+nvmet_tcp_state_change(), a socket callback that runs in BH context,
+can reach handshake_req_cancel() via nvmet_tcp_schedule_release_queue()
+and tls_handshake_cancel(). handshake_req_cancel() acquires
+hn->hn_lock with plain spin_lock(). If a process-context thread on
+the same CPU holds hn->hn_lock when a softirq invokes the cancel path,
+the lock attempt deadlocks. This is the only caller that invokes
+tls_handshake_cancel() from BH context; every other consumer calls it
+from process context.
+
+Deferring the cancel to process context in the NVMe target is not
+straightforward: nvmet_tcp_schedule_release_queue() must call
+tls_handshake_cancel() atomically with its state transition to
+DISCONNECTING. If the cancel were deferred, the handshake completion
+callback could fire in the window before the cancel runs, observe the
+unexpected state, and return without dropping its kref on the queue.
+Reworking that interlock is considerably more invasive than hardening
+the handshake lock. Convert all hn->hn_lock acquisitions from
+spin_lock/spin_unlock to spin_lock_bh/spin_unlock_bh so the lock is
+never taken with softirqs enabled.
+
+Fixes: 675b453e0241 ("nvmet-tcp: enable TLS handshake upcall")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-1-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/handshake/netlink.c | 4 ++--
+ net/handshake/request.c | 14 +++++++-------
+ net/handshake/tlshd.c | 2 ++
+ 3 files changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index 7e46d130dce2cd..394e270cc505cb 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -203,10 +203,10 @@ static void __net_exit handshake_net_exit(struct net *net)
+ * accepted and are in progress will be destroyed when
+ * the socket is closed.
+ */
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ set_bit(HANDSHAKE_F_NET_DRAINING, &hn->hn_flags);
+ list_splice_init(&requests, &hn->hn_requests);
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ while (!list_empty(&requests)) {
+ req = list_first_entry(&requests, struct handshake_req, hr_list);
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 5df102534a596f..75562f6629e050 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -168,12 +168,12 @@ static bool remove_pending(struct handshake_net *hn, struct handshake_req *req)
+ {
+ bool ret = false;
+
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ if (!list_empty(&req->hr_list)) {
+ __remove_pending_locked(hn, req);
+ ret = true;
+ }
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ return ret;
+ }
+@@ -183,7 +183,7 @@ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class)
+ struct handshake_req *req, *pos;
+
+ req = NULL;
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ list_for_each_entry(pos, &hn->hn_requests, hr_list) {
+ if (pos->hr_proto->hp_handler_class != class)
+ continue;
+@@ -191,7 +191,7 @@ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class)
+ req = pos;
+ break;
+ }
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ return req;
+ }
+@@ -250,7 +250,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ if (READ_ONCE(hn->hn_pending) >= hn->hn_pending_max)
+ goto out_err;
+
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ ret = -EOPNOTSUPP;
+ if (test_bit(HANDSHAKE_F_NET_DRAINING, &hn->hn_flags))
+ goto out_unlock;
+@@ -259,7 +259,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ goto out_unlock;
+ if (!__add_pending_locked(hn, req))
+ goto out_unlock;
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ ret = handshake_genl_notify(net, req->hr_proto, flags);
+ if (ret) {
+@@ -275,7 +275,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ return 0;
+
+ out_unlock:
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+ out_err:
+ /* Restore original destructor so socket teardown still runs on failure */
+ req->hr_sk->sk_destruct = req->hr_odestruct;
+diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c
+index 822507b87447c0..fd71ef2d18ceb2 100644
+--- a/net/handshake/tlshd.c
++++ b/net/handshake/tlshd.c
+@@ -419,6 +419,8 @@ EXPORT_SYMBOL(tls_server_hello_psk);
+ * Request cancellation races with request completion. To determine
+ * who won, callers examine the return value from this function.
+ *
++ * Context: May be called from process or softirq context.
++ *
+ * Return values:
+ * %true - Uncompleted handshake request was canceled
+ * %false - Handshake request already completed or not found
+--
+2.53.0
+
--- /dev/null
+From 4453632aeb4955287c7963dcadf7e21ab15260db Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 15:03:30 +0200
+Subject: net: hsr: fix potential OOB access in supervision frame handling
+
+From: Luka Gejak <luka.gejak@linux.dev>
+
+[ Upstream commit f229426072fc865654a60978bb7fda790a051ff3 ]
+
+Ensure the entire TLV header is linearized before access by adding
+sizeof(struct hsr_sup_tlv) to the pskb_may_pull() calls. Without this,
+a truncated frame could cause an out-of-bounds access.
+
+Fixes: eafaa88b3eb7 ("net: hsr: Add support for redbox supervision frames")
+Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Link: https://patch.msgid.link/20260523130330.61880-1-luka.gejak@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_forward.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
+index fa97405c517c70..e3037741a74895 100644
+--- a/net/hsr/hsr_forward.c
++++ b/net/hsr/hsr_forward.c
+@@ -84,7 +84,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
+
+ /* Get next tlv */
+ total_length += hsr_sup_tag->tlv.HSR_TLV_length;
+- if (!pskb_may_pull(skb, total_length))
++ if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
+ return false;
+ skb_pull(skb, total_length);
+ hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data;
+@@ -100,7 +100,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
+
+ /* make sure another tlv follows */
+ total_length += sizeof(struct hsr_sup_tlv) + hsr_sup_tlv->HSR_TLV_length;
+- if (!pskb_may_pull(skb, total_length))
++ if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
+ return false;
+
+ /* get next tlv */
+--
+2.53.0
+
--- /dev/null
+From 90e38873af8af2d4ba92f811b83ad66bc4b1a203 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:48 -0400
+Subject: net: Introduce skb tc depth field to track packet loops
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 98b34f3e8c3492cfc89ff943c9d92b4d52863d1d ]
+
+Add a 2-bit per-skb tc depth field to track packet loops across the stack.
+
+The previous per-CPU loop counters like MIRRED_NEST_LIMIT
+assume a single call stack and lose state in two cases:
+1) When a packet is queued and reprocessed later (e.g., egress->ingress
+ via backlog), the per-cpu state is gone by the time it is dequeued.
+2) With XPS/RPS a packet may arrive on one CPU and be processed on
+ another.
+
+A per-skb field solves both by travelling with the packet itself.
+
+The field fits in existing padding, using 2 bits that were previously a
+hole:
+
+pahole before(-) and after (+) diff looks like:
+ __u8 slow_gro:1; /* 132: 3 1 */
+ __u8 csum_not_inet:1; /* 132: 4 1 */
+ __u8 unreadable:1; /* 132: 5 1 */
+ + __u8 tc_depth:2; /* 132: 6 1 */
+
+ - /* XXX 2 bits hole, try to pack */
+ /* XXX 1 byte hole, try to pack */
+
+ __u16 tc_index; /* 134 2 */
+
+There used to be a ttl field which was removed as part of tc_verd in commit
+aec745e2c520 ("net-tc: remove unused tc_verd fields"). It was already
+unused by that time, due to remove earlier in commit c19ae86a510c ("tc: remove
+unused redirect ttl").
+
+The first user of this field is netem, which increments tc_depth on
+duplicated packets before re-enqueueing them at the root qdisc. On
+re-entry, netem skips duplication for any skb with tc_depth already set,
+bounding recursion to a single level regardless of tree topology.
+
+The other user is mirred which increments it on each pass
+and limits to depth to MIRRED_DEFER_LIMIT (3).
+
+The new field was called ttl in earlier versions of this patch
+but renamed to tc_depth to avoid confusion with IP ttl.
+
+Note (looking at you Sashiko! Dont ignore me and continue bringing this up):
+1. Since both mirred and netem utilize the same 2-bit tc_depth field it is
+ possible when netem and mirred are used together that netem qdisc to skip
+ the duplication step. This is a known trade-off, as a 2-bit field cannot
+ independently track both features' recursion depths and it is not considered
+ sane to have a setup that addresses both features on at the same time.
+
+2. skb_scrub_packet does not clear tc_depth. This means a packet's loop history
+ is preserved even across namespaces. While this might be restrictive for
+ some topologies, it is also design intent to provide robustness against loops
+ across namespaces.
+
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-2-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: e80ad525fc7e ("net/sched: act_mirred: Fix return code in early mirred redirect error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/skbuff.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 4344724a978212..107a8c3ff07fa2 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -802,6 +802,7 @@ enum skb_tstamp_type {
+ * @_sk_redir: socket redirection information for skmsg
+ * @_nfct: Associated connection, if any (with nfctinfo bits)
+ * @skb_iif: ifindex of device we arrived on
++ * @tc_depth: counter for packet duplication
+ * @tc_index: Traffic control index
+ * @hash: the packet hash
+ * @queue_mapping: Queue mapping for multiqueue devices
+@@ -1011,6 +1012,7 @@ struct sk_buff {
+ __u8 csum_not_inet:1;
+ #endif
+ __u8 unreadable:1;
++ __u8 tc_depth:2;
+ #if defined(CONFIG_NET_SCHED) || defined(CONFIG_NET_XGRESS)
+ __u16 tc_index; /* traffic control index */
+ #endif
+--
+2.53.0
+
--- /dev/null
+From e2a2f772df0da114de96941796e67fd0b4ad4059 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 07:11:45 -0700
+Subject: net/iucv: fix locking in .getsockopt
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 3589d20a666caf30ad100c960a2de7de390fce88 ]
+
+Mirror iucv_sock_setsockopt() and wrap the whole switch in
+lock_sock()/release_sock(). The pre-existing SO_MSGLIMIT-only lock
+becomes redundant and is removed.
+
+Any AF_IUCV HIPER user can potentially crash the kernel by racing
+recvmsg() with getsockopt(SO_MSGSIZE): the SO_MSGSIZE arm dereferences
+iucv->hs_dev->mtu after iucv_sock_close() (called from the racing
+recvmsg()) has set hs_dev to NULL, producing a NULL pointer dereference
+oops.
+
+Suggested-by: Stanislav Fomichev <sdf.kernel@gmail.com>
+Fixes: 51363b8751a6 ("af_iucv: allow retrieval of maximum message size")
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
+Tested-by: Alexandra Winter <wintera@linux.ibm.com>
+Link: https://patch.msgid.link/20260521-af_iucv_fix2-v1-1-f16b1c510aa9@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/iucv/af_iucv.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index 7929df08d4e023..1a0b41fcea8131 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -1537,7 +1537,7 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+ struct sock *sk = sock->sk;
+ struct iucv_sock *iucv = iucv_sk(sk);
+ unsigned int val;
+- int len;
++ int len, rc;
+
+ if (level != SOL_IUCV)
+ return -ENOPROTOOPT;
+@@ -1550,26 +1550,34 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+
+ len = min_t(unsigned int, len, sizeof(int));
+
++ rc = 0;
++
++ lock_sock(sk);
+ switch (optname) {
+ case SO_IPRMDATA_MSG:
+ val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0;
+ break;
+ case SO_MSGLIMIT:
+- lock_sock(sk);
+ val = (iucv->path != NULL) ? iucv->path->msglim /* connected */
+ : iucv->msglimit; /* default */
+- release_sock(sk);
+ break;
+ case SO_MSGSIZE:
+- if (sk->sk_state == IUCV_OPEN)
+- return -EBADFD;
++ if (sk->sk_state == IUCV_OPEN) {
++ rc = -EBADFD;
++ break;
++ }
+ val = (iucv->hs_dev) ? iucv->hs_dev->mtu -
+ sizeof(struct af_iucv_trans_hdr) - ETH_HLEN :
+ 0x7fffffff;
+ break;
+ default:
+- return -ENOPROTOOPT;
++ rc = -ENOPROTOOPT;
++ break;
+ }
++ release_sock(sk);
++
++ if (rc)
++ return rc;
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+--
+2.53.0
+
--- /dev/null
+From 2b3bd98e4234b3cfbc959a8502ffa7f5525f648b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 01:08:24 -0700
+Subject: net: mana: Add NULL guards in teardown path to prevent panic on
+ attach failure
+
+From: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+
+[ Upstream commit 17bfe0a8c014ee1d542ad352cd6a0a505361664a ]
+
+When queue allocation fails partway through, the error cleanup frees
+and NULLs apc->tx_qp and apc->rxqs. Multiple teardown paths such as
+mana_remove(), mana_change_mtu() recovery, and internal error handling
+in mana_alloc_queues() can subsequently call into functions that
+dereference these pointers without NULL checks:
+
+- mana_chn_setxdp() dereferences apc->rxqs[0], causing a NULL pointer
+ dereference panic (CR2: 0000000000000000 at mana_chn_setxdp+0x26).
+- mana_destroy_vport() iterates apc->rxqs without a NULL check.
+- mana_fence_rqs() iterates apc->rxqs without a NULL check.
+- mana_dealloc_queues() iterates apc->tx_qp without a NULL check.
+
+Add NULL guards for apc->rxqs in mana_fence_rqs(),
+mana_destroy_vport(), and before the mana_chn_setxdp() call. Add a
+NULL guard for apc->tx_qp in mana_dealloc_queues() to skip TX queue
+draining when TX queues were never allocated or already freed.
+
+Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+Link: https://patch.msgid.link/20260525081129.1230035-2-dipayanroy@linux.microsoft.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 70 +++++++++++--------
+ 1 file changed, 41 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index e527139936dee4..0e4b0ac4acf86b 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -1304,6 +1304,9 @@ static void mana_fence_rqs(struct mana_port_context *apc)
+ struct mana_rxq *rxq;
+ int err;
+
++ if (!apc->rxqs)
++ return;
++
+ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+ rxq = apc->rxqs[rxq_idx];
+ err = mana_fence_rq(apc, rxq);
+@@ -2324,13 +2327,16 @@ static void mana_destroy_vport(struct mana_port_context *apc)
+ struct mana_rxq *rxq;
+ u32 rxq_idx;
+
+- for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+- rxq = apc->rxqs[rxq_idx];
+- if (!rxq)
+- continue;
++ if (apc->rxqs) {
+
+- mana_destroy_rxq(apc, rxq, true);
+- apc->rxqs[rxq_idx] = NULL;
++ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
++ rxq = apc->rxqs[rxq_idx];
++ if (!rxq)
++ continue;
++
++ mana_destroy_rxq(apc, rxq, true);
++ apc->rxqs[rxq_idx] = NULL;
++ }
+ }
+
+ mana_destroy_txq(apc);
+@@ -2633,7 +2639,8 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ if (apc->port_is_up)
+ return -EINVAL;
+
+- mana_chn_setxdp(apc, NULL);
++ if (apc->rxqs)
++ mana_chn_setxdp(apc, NULL);
+
+ if (gd->gdma_context->is_pf)
+ mana_pf_deregister_filter(apc);
+@@ -2651,33 +2658,38 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ * number of queues.
+ */
+
+- for (i = 0; i < apc->num_queues; i++) {
+- txq = &apc->tx_qp[i].txq;
+- tsleep = 1000;
+- while (atomic_read(&txq->pending_sends) > 0 &&
+- time_before(jiffies, timeout)) {
+- usleep_range(tsleep, tsleep + 1000);
+- tsleep <<= 1;
+- }
+- if (atomic_read(&txq->pending_sends)) {
+- err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
+- if (err) {
+- netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+- err, atomic_read(&txq->pending_sends),
+- txq->gdma_txq_id);
++ if (apc->tx_qp) {
++ for (i = 0; i < apc->num_queues; i++) {
++ txq = &apc->tx_qp[i].txq;
++ tsleep = 1000;
++ while (atomic_read(&txq->pending_sends) > 0 &&
++ time_before(jiffies, timeout)) {
++ usleep_range(tsleep, tsleep + 1000);
++ tsleep <<= 1;
++ }
++ if (atomic_read(&txq->pending_sends)) {
++ err =
++ pcie_flr(to_pci_dev(gd->gdma_context->dev));
++ if (err) {
++ netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
++ err,
++ atomic_read(&txq->pending_sends),
++ txq->gdma_txq_id);
++ }
++ break;
+ }
+- break;
+ }
+- }
+
+- for (i = 0; i < apc->num_queues; i++) {
+- txq = &apc->tx_qp[i].txq;
+- while ((skb = skb_dequeue(&txq->pending_skbs))) {
+- mana_unmap_skb(skb, apc);
+- dev_kfree_skb_any(skb);
++ for (i = 0; i < apc->num_queues; i++) {
++ txq = &apc->tx_qp[i].txq;
++ while ((skb = skb_dequeue(&txq->pending_skbs))) {
++ mana_unmap_skb(skb, apc);
++ dev_kfree_skb_any(skb);
++ }
++ atomic_set(&txq->pending_sends, 0);
+ }
+- atomic_set(&txq->pending_sends, 0);
+ }
++
+ /* We're 100% sure the queues can no longer be woken up, because
+ * we're sure now mana_poll_tx_cq() can't be running.
+ */
+--
+2.53.0
+
--- /dev/null
+From 840c55ccee1c046b863d71aec99dbb4728047aed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:36 +0200
+Subject: net: netlink: don't set nsid on local notifications
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 88b126b39f9757e9debc322d4679239e9af089c7 ]
+
+In most cases, notifications on sockets with NETLINK_LISTEN_ALL_NSID
+do not contain NSID in their ancillary data in case the event is local
+to the listener.
+
+However, when a self-referential NSID is allocated for a namespace,
+every local notification starts sending this ID to the user space.
+
+This is problematic, because the listener cannot tell if those
+notifications are local or not anymore without making extra requests
+to figure out if the provided NSID is local or not. The listener
+can also not figure out the local NSID beforehand as it can be
+allocated at any point in time by other processes, changing the
+structure of the future notifications for everyone.
+
+The value is practically not useful, since it's the namespace's own
+ID that the application has to obtain from other sources in order to
+figure out if it's the same or not. So, for the application it's
+just an extra busy work with no benefits. Moreover, applications
+that do not know about this quirk may be mishandling notifications
+with NSID set as notifications from remote namespaces. This is the
+case for ovs-vswitchd and the iproute2's 'ip monitor' that stops
+printing 'current' and starts printing the nsid number mid-session.
+
+Lack of clear documentation for this behavior is also not helping.
+
+A search though open-source projects doesn't reveal any projects
+that use NETNSA_NSID_NOT_ASSIGNED and rely on metadata to contain
+self-referential NSIDs (expected, since the value is not useful).
+Quite the opposite, as already mentioned, there are few applications
+that rely on NSID to not be present in local events.
+
+Since the value is not useful and actively harmful in some cases,
+let's not report it for local events, making the notifications more
+consistent.
+
+Also adding some blank lines for readability.
+
+Fixes: 59324cf35aba ("netlink: allow to listen "all" netns")
+Reported-by: Matteo Perin <matteo.perin@canonical.com>
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-3-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 287b4f921c607e..e250d4a3d03097 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1477,10 +1477,14 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++
+ NETLINK_CB(p->skb2).nsid_is_set = false;
+- NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+- if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+- NETLINK_CB(p->skb2).nsid_is_set = true;
++ if (!net_eq(sock_net(sk), p->net)) {
++ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
++ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
++ NETLINK_CB(p->skb2).nsid_is_set = true;
++ }
++
+ val = netlink_broadcast_deliver(sk, p->skb2);
+ if (val < 0) {
+ netlink_overrun(sk);
+--
+2.53.0
+
--- /dev/null
+From 87ccc21623c7194078b291a9a5397cb505f4703d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:35 +0200
+Subject: net: netlink: fix sending unassigned nsid after assigned one
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 70f8592ee90585272018a725054b6eb2ab7e99ca ]
+
+If the current skb is not shared, it is re-used directly for all the
+sockets subscribed to the notification. If we have remote all-nsid
+socket receiving a message first, then the 'nsid_is_set' will be
+set to 'true'. If the nsid is NOT_ASSIGNED for the next socket in
+the list, the 'nsid_is_set' will remain 'true' and the negative value
+is be delivered to the user space. All subsequent nsid values will be
+delivered as well, since there is no code path that sets the flag
+back to 'false'.
+
+Fix that by always dropping the flag to 'false' first.
+
+Fixes: 7212462fa6fd ("netlink: don't send unknown nsid")
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-2-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 8b060465a2be1a..287b4f921c607e 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1477,6 +1477,7 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++ NETLINK_CB(p->skb2).nsid_is_set = false;
+ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+ NETLINK_CB(p->skb2).nsid_is_set = true;
+--
+2.53.0
+
--- /dev/null
+From 05b0fe4883ca44e8dae070151229f3ada6ff0ba6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Oct 2025 17:19:04 +0000
+Subject: net/sched: act_mirred: add loop detection
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit fe946a751d9b52b7c45ca34899723b314b79b249 ]
+
+Commit 0f022d32c3ec ("net/sched: Fix mirred deadlock on device recursion")
+added code in the fast path, even when act_mirred is not used.
+
+Prepare its revert by implementing loop detection in act_mirred.
+
+Adds an array of device pointers in struct netdev_xmit.
+
+tcf_mirred_is_act_redirect() can detect if the array
+already contains the target device.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Tested-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20251014171907.3554413-4-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: e80ad525fc7e ("net/sched: act_mirred: Fix return code in early mirred redirect error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/netdevice_xmit.h | 9 ++++-
+ net/sched/act_mirred.c | 62 +++++++++++++---------------------
+ 2 files changed, 31 insertions(+), 40 deletions(-)
+
+diff --git a/include/linux/netdevice_xmit.h b/include/linux/netdevice_xmit.h
+index 848735b3a7c02d..59726e6cd2cc67 100644
+--- a/include/linux/netdevice_xmit.h
++++ b/include/linux/netdevice_xmit.h
+@@ -2,6 +2,12 @@
+ #ifndef _LINUX_NETDEVICE_XMIT_H
+ #define _LINUX_NETDEVICE_XMIT_H
+
++#if IS_ENABLED(CONFIG_NET_ACT_MIRRED)
++#define MIRRED_NEST_LIMIT 4
++#endif
++
++struct net_device;
++
+ struct netdev_xmit {
+ u16 recursion;
+ u8 more;
+@@ -9,7 +15,8 @@ struct netdev_xmit {
+ u8 skip_txqueue;
+ #endif
+ #if IS_ENABLED(CONFIG_NET_ACT_MIRRED)
+- u8 sched_mirred_nest;
++ u8 sched_mirred_nest;
++ struct net_device *sched_mirred_dev[MIRRED_NEST_LIMIT];
+ #endif
+ };
+
+diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
+index 18d9378a9c1134..35812b6808e0a8 100644
+--- a/net/sched/act_mirred.c
++++ b/net/sched/act_mirred.c
+@@ -29,31 +29,6 @@
+ static LIST_HEAD(mirred_list);
+ static DEFINE_SPINLOCK(mirred_list_lock);
+
+-#define MIRRED_NEST_LIMIT 4
+-
+-#ifndef CONFIG_PREEMPT_RT
+-static u8 tcf_mirred_nest_level_inc_return(void)
+-{
+- return __this_cpu_inc_return(softnet_data.xmit.sched_mirred_nest);
+-}
+-
+-static void tcf_mirred_nest_level_dec(void)
+-{
+- __this_cpu_dec(softnet_data.xmit.sched_mirred_nest);
+-}
+-
+-#else
+-static u8 tcf_mirred_nest_level_inc_return(void)
+-{
+- return current->net_xmit.sched_mirred_nest++;
+-}
+-
+-static void tcf_mirred_nest_level_dec(void)
+-{
+- current->net_xmit.sched_mirred_nest--;
+-}
+-#endif
+-
+ static bool tcf_mirred_is_act_redirect(int action)
+ {
+ return action == TCA_EGRESS_REDIR || action == TCA_INGRESS_REDIR;
+@@ -439,44 +414,53 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ {
+ struct tcf_mirred *m = to_mirred(a);
+ int retval = READ_ONCE(m->tcf_action);
+- unsigned int nest_level;
++ struct netdev_xmit *xmit;
+ bool m_mac_header_xmit;
+ struct net_device *dev;
+- int m_eaction;
++ int i, m_eaction;
+ u32 blockid;
+
+- nest_level = tcf_mirred_nest_level_inc_return();
+- if (unlikely(nest_level > MIRRED_NEST_LIMIT)) {
++#ifdef CONFIG_PREEMPT_RT
++ xmit = ¤t->net_xmit;
++#else
++ xmit = this_cpu_ptr(&softnet_data.xmit);
++#endif
++ if (unlikely(xmit->sched_mirred_nest >= MIRRED_NEST_LIMIT)) {
+ net_warn_ratelimited("Packet exceeded mirred recursion limit on dev %s\n",
+ netdev_name(skb->dev));
+- retval = TC_ACT_SHOT;
+- goto dec_nest_level;
++ return TC_ACT_SHOT;
+ }
+
+ tcf_lastuse_update(&m->tcf_tm);
+ tcf_action_update_bstats(&m->common, skb);
+
+ blockid = READ_ONCE(m->tcfm_blockid);
+- if (blockid) {
+- retval = tcf_blockcast(skb, m, blockid, res, retval);
+- goto dec_nest_level;
+- }
++ if (blockid)
++ return tcf_blockcast(skb, m, blockid, res, retval);
+
+ dev = rcu_dereference_bh(m->tcfm_dev);
+ if (unlikely(!dev)) {
+ pr_notice_once("tc mirred: target device is gone\n");
+ tcf_action_inc_overlimit_qstats(&m->common);
+- goto dec_nest_level;
++ return retval;
+ }
++ for (i = 0; i < xmit->sched_mirred_nest; i++) {
++ if (xmit->sched_mirred_dev[i] != dev)
++ continue;
++ pr_notice_once("tc mirred: loop on device %s\n",
++ netdev_name(dev));
++ tcf_action_inc_overlimit_qstats(&m->common);
++ return retval;
++ }
++
++ xmit->sched_mirred_dev[xmit->sched_mirred_nest++] = dev;
+
+ m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
+ m_eaction = READ_ONCE(m->tcfm_eaction);
+
+ retval = tcf_mirred_to_dev(skb, m, dev, m_mac_header_xmit, m_eaction,
+ retval);
+-
+-dec_nest_level:
+- tcf_mirred_nest_level_dec();
++ xmit->sched_mirred_nest--;
+
+ return retval;
+ }
+--
+2.53.0
+
--- /dev/null
+From 0dbbbc2ab2ba3d6976cc0d0913a7e17b77f2ec3b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:54 -0400
+Subject: net/sched: act_mirred: Fix return code in early mirred redirect error
+ paths
+
+From: Victor Nogueira <victor@mojatatu.com>
+
+[ Upstream commit e80ad525fc7e8c933ad78478c5dda286cfd55c60 ]
+
+Since retval is set as TC_ACT_STOLEN in the mirred redirect case, returning
+retval in cases where redirect failed will make the callers not register
+the skb as being dropped.
+
+Fix this by returning TC_ACT_SHOT instead in such scenarios.
+
+Fixes: 16085e48cb48 ("net/sched: act_mirred: Create function tcf_mirred_to_dev and improve readability")
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260413082027.2244884-1-hxzene%40gmail.com
+Signed-off-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-8-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_mirred.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
+index ae9b307ad66e0d..41b731176dfe77 100644
+--- a/net/sched/act_mirred.c
++++ b/net/sched/act_mirred.c
+@@ -363,7 +363,8 @@ static int tcf_blockcast_redir(struct sk_buff *skb, struct tcf_mirred *m,
+ dev_is_mac_header_xmit(dev_prev),
+ m_eaction, retval);
+
+- return retval;
++ /* If the packet wasn't redirected, we have to register as a drop */
++ return TC_ACT_SHOT;
+ }
+
+ static int tcf_blockcast_mirror(struct sk_buff *skb, struct tcf_mirred *m,
+@@ -403,7 +404,7 @@ static int tcf_blockcast(struct sk_buff *skb, struct tcf_mirred *m,
+ block = tcf_block_lookup(dev_net(skb->dev), blockid);
+ if (!block || xa_empty(&block->ports)) {
+ tcf_action_inc_overlimit_qstats(&m->common);
+- return retval;
++ return is_redirect ? TC_ACT_SHOT : retval;
+ }
+
+ if (is_redirect)
+@@ -421,8 +422,8 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ {
+ struct tcf_mirred *m = to_mirred(a);
+ int retval = READ_ONCE(m->tcf_action);
++ bool m_mac_header_xmit, is_redirect;
+ struct netdev_xmit *xmit;
+- bool m_mac_header_xmit;
+ struct net_device *dev;
+ bool want_ingress;
+ int i, m_eaction;
+@@ -447,11 +448,13 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ if (blockid)
+ return tcf_blockcast(skb, m, blockid, res, retval);
+
++ is_redirect = tcf_mirred_is_act_redirect(m_eaction);
++
+ dev = rcu_dereference_bh(m->tcfm_dev);
+ if (unlikely(!dev)) {
+ pr_notice_once("tc mirred: target device is gone\n");
+ tcf_action_inc_overlimit_qstats(&m->common);
+- return retval;
++ goto err_out;
+ }
+
+ m_eaction = READ_ONCE(m->tcfm_eaction);
+@@ -463,7 +466,7 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ pr_notice_once("tc mirred: loop on device %s\n",
+ netdev_name(dev));
+ tcf_action_inc_overlimit_qstats(&m->common);
+- return retval;
++ goto err_out;
+ }
+ xmit->sched_mirred_dev[xmit->sched_mirred_nest++] = dev;
+ }
+@@ -476,6 +479,11 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ xmit->sched_mirred_nest--;
+
+ return retval;
++
++err_out:
++ if (is_redirect)
++ retval = TC_ACT_SHOT;
++ return retval;
+ }
+
+ static void tcf_stats_update(struct tc_action *a, u64 bytes, u64 packets,
+--
+2.53.0
+
--- /dev/null
+From e1bd679da06931529a67c291b565cee93887021a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 12 May 2025 11:27:31 +0200
+Subject: net/sched: act_mirred: Move the recursion counter struct netdev_xmit
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 7fe70c06a182a140be9996b02256d907e114479a ]
+
+mirred_nest_level is a per-CPU variable and relies on disabled BH for its
+locking. Without per-CPU locking in local_bh_disable() on PREEMPT_RT
+this data structure requires explicit locking.
+
+Move mirred_nest_level to struct netdev_xmit as u8, provide wrappers.
+
+Cc: Jamal Hadi Salim <jhs@mojatatu.com>
+Cc: Cong Wang <xiyou.wangcong@gmail.com>
+Cc: Jiri Pirko <jiri@resnulli.us>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Reviewed-by: Juri Lelli <juri.lelli@redhat.com>
+Link: https://patch.msgid.link/20250512092736.229935-11-bigeasy@linutronix.de
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: e80ad525fc7e ("net/sched: act_mirred: Fix return code in early mirred redirect error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/netdevice_xmit.h | 3 +++
+ net/sched/act_mirred.c | 28 +++++++++++++++++++++++++---
+ 2 files changed, 28 insertions(+), 3 deletions(-)
+
+diff --git a/include/linux/netdevice_xmit.h b/include/linux/netdevice_xmit.h
+index 38325e07029685..848735b3a7c02d 100644
+--- a/include/linux/netdevice_xmit.h
++++ b/include/linux/netdevice_xmit.h
+@@ -8,6 +8,9 @@ struct netdev_xmit {
+ #ifdef CONFIG_NET_EGRESS
+ u8 skip_txqueue;
+ #endif
++#if IS_ENABLED(CONFIG_NET_ACT_MIRRED)
++ u8 sched_mirred_nest;
++#endif
+ };
+
+ #endif
+diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
+index b1b0049d7a0e9d..18d9378a9c1134 100644
+--- a/net/sched/act_mirred.c
++++ b/net/sched/act_mirred.c
+@@ -30,7 +30,29 @@ static LIST_HEAD(mirred_list);
+ static DEFINE_SPINLOCK(mirred_list_lock);
+
+ #define MIRRED_NEST_LIMIT 4
+-static DEFINE_PER_CPU(unsigned int, mirred_nest_level);
++
++#ifndef CONFIG_PREEMPT_RT
++static u8 tcf_mirred_nest_level_inc_return(void)
++{
++ return __this_cpu_inc_return(softnet_data.xmit.sched_mirred_nest);
++}
++
++static void tcf_mirred_nest_level_dec(void)
++{
++ __this_cpu_dec(softnet_data.xmit.sched_mirred_nest);
++}
++
++#else
++static u8 tcf_mirred_nest_level_inc_return(void)
++{
++ return current->net_xmit.sched_mirred_nest++;
++}
++
++static void tcf_mirred_nest_level_dec(void)
++{
++ current->net_xmit.sched_mirred_nest--;
++}
++#endif
+
+ static bool tcf_mirred_is_act_redirect(int action)
+ {
+@@ -423,7 +445,7 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ int m_eaction;
+ u32 blockid;
+
+- nest_level = __this_cpu_inc_return(mirred_nest_level);
++ nest_level = tcf_mirred_nest_level_inc_return();
+ if (unlikely(nest_level > MIRRED_NEST_LIMIT)) {
+ net_warn_ratelimited("Packet exceeded mirred recursion limit on dev %s\n",
+ netdev_name(skb->dev));
+@@ -454,7 +476,7 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ retval);
+
+ dec_nest_level:
+- __this_cpu_dec(mirred_nest_level);
++ tcf_mirred_nest_level_dec();
+
+ return retval;
+ }
+--
+2.53.0
+
--- /dev/null
+From 3baa1fb4063a7688344267fcbce344fced937bc5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:52 -0400
+Subject: net/sched: Fix ethx:ingress -> ethy:egress -> ethx:ingress mirred
+ loop
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit db875221ab08d213a83bf30196ae8b64d55a3403 ]
+
+When mirred redirects to ingress (from either ingress or egress) the loop
+state from sched_mirred_dev array dev is lost because of 1) the packet
+deferral into the backlog and 2) the fact the sched_mirred_dev array is
+cleared. In such cases, if there was a loop we won't discover it.
+
+Here's a simple test to reproduce:
+ip a add dev port0 10.10.10.11/24
+
+tc qdisc add dev port0 clsact
+tc filter add dev port0 egress protocol ip \
+ prio 10 matchall action mirred ingress redirect dev port1
+
+tc qdisc add dev port1 clsact
+tc filter add dev port1 ingress protocol ip \
+ prio 10 matchall action mirred egress redirect dev port0
+
+ping -c 1 -W0.01 10.10.10.10
+
+Fixes: fe946a751d9b ("net/sched: act_mirred: add loop detection")
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-6-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: e80ad525fc7e ("net/sched: act_mirred: Fix return code in early mirred redirect error paths")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_mirred.c | 47 +++++++++++++++++++++++++++---------------
+ 1 file changed, 30 insertions(+), 17 deletions(-)
+
+diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
+index 35812b6808e0a8..ae9b307ad66e0d 100644
+--- a/net/sched/act_mirred.c
++++ b/net/sched/act_mirred.c
+@@ -26,6 +26,10 @@
+ #include <net/tc_act/tc_mirred.h>
+ #include <net/tc_wrapper.h>
+
++#define MIRRED_DEFER_LIMIT 3
++_Static_assert(MIRRED_DEFER_LIMIT <= 3,
++ "MIRRED_DEFER_LIMIT exceeds tc_depth bitfield width");
++
+ static LIST_HEAD(mirred_list);
+ static DEFINE_SPINLOCK(mirred_list_lock);
+
+@@ -234,12 +238,15 @@ tcf_mirred_forward(bool at_ingress, bool want_ingress, struct sk_buff *skb)
+ {
+ int err;
+
+- if (!want_ingress)
++ if (!want_ingress) {
+ err = tcf_dev_queue_xmit(skb, dev_queue_xmit);
+- else if (!at_ingress)
+- err = netif_rx(skb);
+- else
+- err = netif_receive_skb(skb);
++ } else {
++ skb->tc_depth++;
++ if (!at_ingress)
++ err = netif_rx(skb);
++ else
++ err = netif_receive_skb(skb);
++ }
+
+ return err;
+ }
+@@ -417,6 +424,7 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ struct netdev_xmit *xmit;
+ bool m_mac_header_xmit;
+ struct net_device *dev;
++ bool want_ingress;
+ int i, m_eaction;
+ u32 blockid;
+
+@@ -425,7 +433,8 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ #else
+ xmit = this_cpu_ptr(&softnet_data.xmit);
+ #endif
+- if (unlikely(xmit->sched_mirred_nest >= MIRRED_NEST_LIMIT)) {
++ if (unlikely(xmit->sched_mirred_nest >= MIRRED_NEST_LIMIT ||
++ skb->tc_depth >= MIRRED_DEFER_LIMIT)) {
+ net_warn_ratelimited("Packet exceeded mirred recursion limit on dev %s\n",
+ netdev_name(skb->dev));
+ return TC_ACT_SHOT;
+@@ -444,23 +453,27 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ tcf_action_inc_overlimit_qstats(&m->common);
+ return retval;
+ }
+- for (i = 0; i < xmit->sched_mirred_nest; i++) {
+- if (xmit->sched_mirred_dev[i] != dev)
+- continue;
+- pr_notice_once("tc mirred: loop on device %s\n",
+- netdev_name(dev));
+- tcf_action_inc_overlimit_qstats(&m->common);
+- return retval;
+- }
+
+- xmit->sched_mirred_dev[xmit->sched_mirred_nest++] = dev;
++ m_eaction = READ_ONCE(m->tcfm_eaction);
++ want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
++ if (!want_ingress) {
++ for (i = 0; i < xmit->sched_mirred_nest; i++) {
++ if (xmit->sched_mirred_dev[i] != dev)
++ continue;
++ pr_notice_once("tc mirred: loop on device %s\n",
++ netdev_name(dev));
++ tcf_action_inc_overlimit_qstats(&m->common);
++ return retval;
++ }
++ xmit->sched_mirred_dev[xmit->sched_mirred_nest++] = dev;
++ }
+
+ m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
+- m_eaction = READ_ONCE(m->tcfm_eaction);
+
+ retval = tcf_mirred_to_dev(skb, m, dev, m_mac_header_xmit, m_eaction,
+ retval);
+- xmit->sched_mirred_nest--;
++ if (!want_ingress)
++ xmit->sched_mirred_nest--;
+
+ return retval;
+ }
+--
+2.53.0
+
--- /dev/null
+From 17b4e7dc1eb95443953d4bd2d4fea853e48dc36a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:51 -0400
+Subject: net/sched: fix packet loop on netem when duplicate is on
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 9552b11e3edabc97cfcd9f29103d5afbce7ae183 ]
+
+When netem duplicates a packet it re-enqueues the copy at the root qdisc.
+If another netem sits in the tree the copy can be duplicated
+again, recursing until the stack or memory is exhausted.
+
+The original duplication guard temporarily zeroed q->duplicate around
+the re-enqueue, but that does not cover all cases because it is
+per-qdisc state shared across all concurrent enqueue paths
+and is not safe without additional locking.
+
+Use the skb tc_depth field introduced in an earlier patch:
+ - increment it on the duplicate before re-enqueue
+ - skip duplication for any skb whose tc_depth is already non-zero.
+
+This marks the packet itself rather than mutating qdisc state,
+therefore it is safe regardless of tree topology or concurrency.
+
+Fixes: 0afb51e72855 ("[PKT_SCHED]: netem: reinsert for duplication")
+Reported-by: William Liu <will@willsroot.io>
+Reported-by: Savino Dicanosa <savy@syst3mfailure.io>
+Closes: https://lore.kernel.org/netdev/8DuRWwfqjoRDLDmBMlIfbrsZg9Gx50DHJc1ilxsEBNe2D6NMoigR_eIRIG0LOjMc3r10nUUZtArXx4oZBIdUfZQrwjcQhdinnMis_0G7VEk=@willsroot.io/
+Co-developed-by: Victor Nogueira <victor@mojatatu.com>
+Signed-off-by: Victor Nogueira <victor@mojatatu.com>
+Reviewed-by: William Liu <will@willsroot.io>
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-5-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_netem.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
+index 1fdebf2ab7ee46..136b7d81296eff 100644
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -459,7 +459,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+ skb->prev = NULL;
+
+ /* Random duplication */
+- if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor, &q->prng))
++ if (q->duplicate && skb->tc_depth == 0 &&
++ q->duplicate >= get_crandom(&q->dup_cor, &q->prng))
+ ++count;
+
+ /* Drop packet? */
+@@ -538,11 +539,9 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+ */
+ if (skb2) {
+ struct Qdisc *rootq = qdisc_root_bh(sch);
+- u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
+
+- q->duplicate = 0;
++ skb2->tc_depth++; /* prevent duplicating a dup... */
+ rootq->enqueue(skb2, rootq, to_free);
+- q->duplicate = dupsave;
+ skb2 = NULL;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 73f565fe71ea2136ff92eb2bac6514e173d7debc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:49 -0400
+Subject: net/sched: Revert "net/sched: Restrict conditions for adding
+ duplicating netems to qdisc tree"
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit eda0b7f203bb166c98d1418b204135bd566ac83b ]
+
+This reverts commit ec8e0e3d7adef940cdf9475e2352c0680189d14e.
+
+The original patch rejects any tree containing two netems when
+either has duplication set, even when they sit on unrelated classes
+of the same classful parent. That broke configurations that have
+worked since netem was introduced.
+
+The re-entrancy problem the original commit was trying to solve is
+handled by later patch using tc_depth flag.
+
+Doing this revert will (re)expose the original bug with multiple
+netem duplication. When this patch is backported make sure
+and get the full series.
+
+Fixes: ec8e0e3d7ade ("net/sched: Restrict conditions for adding duplicating netems to qdisc tree")
+Reported-by: Ji-Soo Chung <jschung2@proton.me>
+Reported-by: Gerlinde <lrGerlinde@mailfence.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220774
+Reported-by: zyc zyc <zyc199902@zohomail.cn>
+Closes: https://lore.kernel.org/all/19adda5a1e2.12410b78222774.9191120410578703463@zohomail.cn/
+Reported-by: Manas Ghandat <ghandatmanas@gmail.com>
+Closes: https://lore.kernel.org/netdev/f69b2c8f-8325-4c2e-a011-6dbc089f30e4@gmail.com/
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-3-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_netem.c | 40 ----------------------------------------
+ 1 file changed, 40 deletions(-)
+
+diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
+index 498c18d7d9c39b..1fdebf2ab7ee46 100644
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -1005,41 +1005,6 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+ return 0;
+ }
+
+-static const struct Qdisc_class_ops netem_class_ops;
+-
+-static int check_netem_in_tree(struct Qdisc *sch, bool duplicates,
+- struct netlink_ext_ack *extack)
+-{
+- struct Qdisc *root, *q;
+- unsigned int i;
+-
+- root = qdisc_root_sleeping(sch);
+-
+- if (sch != root && root->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(root))->duplicate)
+- goto err;
+- }
+-
+- if (!qdisc_dev(root))
+- return 0;
+-
+- hash_for_each(qdisc_dev(root)->qdisc_hash, i, q, hash) {
+- if (sch != q && q->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(q))->duplicate)
+- goto err;
+- }
+- }
+-
+- return 0;
+-
+-err:
+- NL_SET_ERR_MSG(extack,
+- "netem: cannot mix duplicating netems with other netems in tree");
+- return -EINVAL;
+-}
+-
+ /* Parse netlink message to set options */
+ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
+@@ -1116,11 +1081,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ q->gap = qopt->gap;
+ q->counter = 0;
+ q->loss = qopt->loss;
+-
+- ret = check_netem_in_tree(sch, qopt->duplicate, extack);
+- if (ret)
+- goto unlock;
+-
+ q->duplicate = qopt->duplicate;
+
+ /* for compatibility with earlier versions.
+--
+2.53.0
+
--- /dev/null
+From bd33ff9a6462c8f47edb5a624bede3a0f5cab6dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 19:43:53 +0100
+Subject: net: skbuff: fix pskb_carve leaking zcopy pages
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit ff6e798c2eac3ebd0501ad7e796f583fab928de8 ]
+
+When SKBFL_MANAGED_FRAG_REFS is set, frag pages are not refcounted but
+their lifetime is controlled by the attached ubuf_info. To make a copy
+of the skb_shared_info, we either should clear the flag and reference
+the frags, or keep the flag and have frags unreferenced.
+
+pskb_carve_inside_header() and pskb_carve_inside_nonlinear() don't
+follow the rule and thus can leak page references. Let's clear
+SKBFL_MANAGED_FRAG_REFS from the original skb to fix it. It's the
+simplest way to address it, but there are more performant ways to do
+that if it ever becomes a problem.
+
+Link: https://lore.kernel.org/all/20260523085809.26331-1-nvminh232@clc.fitus.edu.vn/
+Fixes: 753f1ca4e1e50 ("net: introduce managed frags infrastructure")
+Reported-by: Minh Nguyen <minhnguyen.080505@gmail.com>
+Reported-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/1e2086aa69217d7f9c8da3d38f5be7160f1b4cd1.1779993185.git.asml.silence@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/skbuff.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 8c9f026182a6f0..c8653ed1991ae0 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -6689,6 +6689,11 @@ static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off,
+ skb_copy_from_linear_data_offset(skb, off, data, new_hlen);
+ skb->len -= off;
+
++ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
++ * while refcounting frags below.
++ */
++ skb_zcopy_downgrade_managed(skb);
++
+ memcpy((struct skb_shared_info *)(data + size),
+ skb_shinfo(skb),
+ offsetof(struct skb_shared_info,
+@@ -6801,6 +6806,11 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,
+ return -ENOMEM;
+ size = SKB_WITH_OVERHEAD(size);
+
++ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
++ * while refcounting frags below.
++ */
++ skb_zcopy_downgrade_managed(skb);
++
+ memcpy((struct skb_shared_info *)(data + size),
+ skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0]));
+ if (skb_orphan_frags(skb, gfp_mask)) {
+--
+2.53.0
+
--- /dev/null
+From 6f8d315da8edbeca5a96360e65f25bbe546c3bde Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 16:56:39 +0200
+Subject: net/smc: Do not re-initialize smc hashtables
+
+From: Alexandra Winter <wintera@linux.ibm.com>
+
+[ Upstream commit 9e4389b0038781f19f97895186ed941ff8ac1678 ]
+
+INIT_HLIST_HEAD(&smc_v*_hashinfo.ht) are called after smc_nl_init(),
+proto_register() and sock_register(). This can lead to smc_v*_hashinfo.ht
+being reset even though hash entries already exist and are being used,
+possibly resulting in a corrupted list.
+
+Remove unnecessary and dangerous re-initialisation of smc_v*_hashinfo.ht in
+smc_init(); it is implicitly initialised to zero anyhow. Add
+HLIST_HEAD_INIT to the definitions for clarity.
+
+Fixes: f16a7dd5cf27 ("smc: netlink interface for SMC sockets")
+Suggested-by: Halil Pasic <pasic@linux.ibm.com>
+Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
+Acked-by: Halil Pasic <pasic@linux.ibm.com>
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Link: https://patch.msgid.link/20260521145639.10317-1-wintera@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index c96abb1386be4b..6f3469ad54a165 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -187,10 +187,12 @@ static bool smc_hs_congested(const struct sock *sk)
+
+ struct smc_hashinfo smc_v4_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v4_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ struct smc_hashinfo smc_v6_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v6_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ int smc_hash_sk(struct sock *sk)
+@@ -3594,8 +3596,6 @@ static int __init smc_init(void)
+ pr_err("%s: sock_register fails with %d\n", __func__, rc);
+ goto out_proto6;
+ }
+- INIT_HLIST_HEAD(&smc_v4_hashinfo.ht);
+- INIT_HLIST_HEAD(&smc_v6_hashinfo.ht);
+
+ rc = smc_ib_register_client();
+ if (rc) {
+--
+2.53.0
+
--- /dev/null
+From 93d5aa2ceb11b27e7ae2c6ea1e0f2865c1cb4667 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 22:52:07 +0200
+Subject: netfilter: ebtables: fix OOB read in compat_mtw_from_user
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit f438d1786d657d57790c5d138d6db3fc9fdac392 ]
+
+Luxiao Xu says:
+
+ The function compat_mtw_from_user() converts ebtables extensions from
+ 32-bit user structures to kernel native structures. However, it lacks
+ proper validation of the user-supplied match_size/target_size.
+
+ When certain extensions are processed, the kernel-side translation
+ logic may perform memory accesses based on the extension's expected
+ size. If the user provides a size smaller than what the extension
+ requires, it results in an out-of-bounds read as reported by KASAN.
+
+ This fix introduces a check to ensure match_size is at least as large
+ as the extension's required compatsize. This covers matches, watchers,
+ and targets, while maintaining compatibility with standard targets.
+
+AFAIU this is relevant for matches that need to go though
+match->compat_from_user() call. Those that use plain memcpy with the
+user-provided size are ok because the caller checks that size vs the
+start of the next rule entry offset (which itself is checked vs. total
+size copied from userspace).
+
+The ->compat_from_user() callbacks assume they can read compatsize bytes,
+so they need this extra check.
+
+Based on an earlier patch from Luxiao Xu.
+
+Fixes: 81e675c227ec ("netfilter: ebtables: add CONFIG_COMPAT support")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/netfilter/ebtables.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index a461c59ad28595..1bc7b5d8f76d7a 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -1952,6 +1952,25 @@ enum compat_mwt {
+ EBT_COMPAT_TARGET,
+ };
+
++static bool match_size_ok(const struct xt_match *match, unsigned int match_size)
++{
++ u16 csize;
++
++ if (match->matchsize == -1) /* cannot validate ebt_among */
++ return true;
++
++ csize = match->compatsize ? : match->matchsize;
++
++ return match_size >= csize;
++}
++
++static bool tgt_size_ok(const struct xt_target *tgt, unsigned int tgt_size)
++{
++ u16 csize = tgt->compatsize ? : tgt->targetsize;
++
++ return tgt_size >= csize;
++}
++
+ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ enum compat_mwt compat_mwt,
+ struct ebt_entries_buf_state *state,
+@@ -1977,6 +1996,11 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+
++ if (!match_size_ok(match, match_size)) {
++ module_put(match->me);
++ return -EINVAL;
++ }
++
+ off = ebt_compat_match_offset(match, match_size);
+ if (dst) {
+ if (match->compat_from_user)
+@@ -1996,6 +2020,12 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ mwt->u.revision);
+ if (IS_ERR(wt))
+ return PTR_ERR(wt);
++
++ if (!tgt_size_ok(wt, match_size)) {
++ module_put(wt->me);
++ return -EINVAL;
++ }
++
+ off = xt_compat_target_offset(wt);
+
+ if (dst) {
+--
+2.53.0
+
--- /dev/null
+From a3f3f69a35f27105f687f284f50ac318b03783e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 12:36:14 -0700
+Subject: netfilter: synproxy: refresh tcphdr after skb_ensure_writable
+
+From: Chris Mason <clm@meta.com>
+
+[ Upstream commit 92170e6afe927ab2792a3f71902845789c8e31b1 ]
+
+synproxy_tstamp_adjust() rewrites the TCP timestamp option in place
+and then patches the TCP checksum via inet_proto_csum_replace4() on
+the caller-supplied tcphdr pointer. Both ipv4_synproxy_hook() and
+ipv6_synproxy_hook() obtain that pointer with skb_header_pointer()
+before calling in, so it may either alias skb->head directly or
+point at the caller's on-stack _tcph buffer.
+
+Between obtaining the pointer and using it, the function calls
+skb_ensure_writable(skb, optend), which on a cloned or non-linear
+skb invokes pskb_expand_head() and frees the old skb->head. After
+that point the cached th is stale:
+
+ caller (ipv[46]_synproxy_hook)
+ th = skb_header_pointer(skb, ..., &_tcph)
+ synproxy_tstamp_adjust(skb, protoff, th, ...)
+ skb_ensure_writable(skb, optend)
+ pskb_expand_head() /* kfree(old skb->head) */
+ ...
+ inet_proto_csum_replace4(&th->check, ...)
+ /* writes into freed head, or
+ into the caller's stack copy
+ leaving the on-wire checksum
+ stale */
+
+The option bytes are written through skb->data and are fine; only
+the checksum update goes through th and so lands in the wrong
+place. The result is either a write into freed slab memory or a
+packet leaving with a checksum that does not match its payload.
+
+Fix by re-deriving th from skb->data + protoff immediately after
+skb_ensure_writable() succeeds, so the subsequent checksum update
+targets the linear, writable header.
+
+Fixes: 48b1de4c110a ("netfilter: add SYNPROXY core/target")
+Assisted-by: kres (claude-opus-4-7)
+Signed-off-by: Chris Mason <clm@meta.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_synproxy_core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 3fa3f5dfb26444..6a851ac4dd048f 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -199,6 +199,8 @@ synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,
+ if (skb_ensure_writable(skb, optend))
+ return 0;
+
++ th = (struct tcphdr *)(skb->data + protoff);
++
+ while (optoff < optend) {
+ unsigned char *op = skb->data + optoff;
+
+--
+2.53.0
+
--- /dev/null
+From 474ca2dd9fd541b704fc995088c7265004a9d169 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 20:10:08 +0200
+Subject: netfilter: xt_cpu: prefer raw_smp_processor_id
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit c376f07e16c02239ed44cabb97145d03f65b4d15 ]
+
+With PREEMPT_RCU we get splat:
+
+BUG: using smp_processor_id() in preemptible [..]
+caller is cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+CPU: 1 .. Comm: syz.3.1377 #0 PREEMPT(full)
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
+ check_preemption_disabled+0xd3/0xe0 lib/smp_processor_id.c:47
+ cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+ [..]
+
+Just use raw version instead.
+This is similar to 14d14a5d2957 ("netfilter: nft_meta: use raw_smp_processor_id()").
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Reported-by: syzbot+690d3e3ffa7335ac10eb@syzkaller.appspotmail.com
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/xt_cpu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_cpu.c b/net/netfilter/xt_cpu.c
+index 3bdc302a0f9137..9cb259902a586b 100644
+--- a/net/netfilter/xt_cpu.c
++++ b/net/netfilter/xt_cpu.c
+@@ -34,7 +34,7 @@ static bool cpu_mt(const struct sk_buff *skb, struct xt_action_param *par)
+ {
+ const struct xt_cpu_info *info = par->matchinfo;
+
+- return (info->cpu == smp_processor_id()) ^ info->invert;
++ return (info->cpu == raw_smp_processor_id()) ^ info->invert;
+ }
+
+ static struct xt_match cpu_mt_reg __read_mostly = {
+--
+2.53.0
+
--- /dev/null
+From e32f9da0e5e8c98559a32bdd7f4bfb97ef8472b5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:41 +0000
+Subject: nfc: llcp: Fix use-after-free in llcp_sock_release()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit f4268b466190dae95a7585f69b4f1f8ad097632c ]
+
+llcp_sock_release() unconditionally unlinks the socket from the local
+sockets list. However, if the socket is still in connecting state, it
+is on the connecting list.
+
+Fix this by checking the socket state and unlinking from the correct list.
+
+Fixes: b4011239a08e ("NFC: llcp: Fix non blocking sockets connections")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-1-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_sock.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index 57a2f97004e172..915929cd724f90 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -633,6 +633,8 @@ static int llcp_sock_release(struct socket *sock)
+
+ if (sock->type == SOCK_RAW)
+ nfc_llcp_sock_unlink(&local->raw_sockets, sk);
++ else if (sk->sk_state == LLCP_CONNECTING)
++ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ else
+ nfc_llcp_sock_unlink(&local->sockets, sk);
+
+--
+2.53.0
+
--- /dev/null
+From bca7cd838c840b754401ac406e03bd90bd1ba27e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:42 +0000
+Subject: nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit b493ea2765cc17cb8aa7e7544a4b6dcb05b6ed77 ]
+
+A race condition exists in the NFC LLCP connection state machine where
+the connection acceptance packet (CC) can be processed concurrently with
+socket release. This can lead to a use-after-free of the socket object.
+
+When nfc_llcp_recv_cc() moves the socket from the connecting_sockets
+list to the sockets list, it does so without holding the socket lock.
+If llcp_sock_release() is executing concurrently, it might have already
+unlinked the socket and dropped its references, which can result in
+nfc_llcp_recv_cc() linking a freed socket into the live list.
+
+Fix this by holding lock_sock() during the state transition and list
+movement in nfc_llcp_recv_cc(). After acquiring the lock, check if
+the socket is still hashed to ensure it hasn't already been unlinked
+and marked for destruction by the release path. This aligns the locking
+pattern with recv_hdlc() and recv_disc().
+
+Fixes: a69f32af86e3 ("NFC: Socket linked list")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-2-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_core.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
+index d9562840fa180b..62b0f2d6686eb8 100644
+--- a/net/nfc/llcp_core.c
++++ b/net/nfc/llcp_core.c
+@@ -1216,6 +1216,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+
+ sk = &llcp_sock->sk;
+
++ lock_sock(sk);
++
++ /* Check if socket was destroyed whilst waiting for the lock */
++ if (!sk_hashed(sk)) {
++ release_sock(sk);
++ nfc_llcp_sock_put(llcp_sock);
++ return;
++ }
++
+ /* Unlink from connecting and link to the client array */
+ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ nfc_llcp_sock_link(&local->sockets, sk);
+@@ -1227,6 +1236,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+ sk->sk_state = LLCP_CONNECTED;
+ sk->sk_state_change(sk);
+
++ release_sock(sk);
++
+ nfc_llcp_sock_put(llcp_sock);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From b693df0a9400e622e7eb02304badec065ed62734 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 May 2026 19:55:18 +0800
+Subject: nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems
+
+From: Carl Lee <carl.lee@amd.com>
+
+[ Upstream commit f23bf992d65a42007c517b060ca35cebdea3525a ]
+
+Some ACPI-based platforms report incorrect IRQ trigger types (e.g.
+IRQF_TRIGGER_HIGH), which can lead to interrupt storms.
+
+Use the historically working rising-edge trigger on ACPI systems to
+avoid this regression.
+
+Device Tree-based systems continue to use the firmware-provided
+trigger type.
+
+Fixes: 57be33f85e36 ("nfc: nxp-nci: remove interrupt trigger type")
+Signed-off-by: Carl Lee <carl.lee@amd.com>
+Tested-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Luca Stefani <luca.stefani.ge1@gmail.com>
+Link: https://patch.msgid.link/20260516-nfc-nxp-nci-i2c-restore-irq-trigger-fallback-v3-1-37ba4b6e9086@amd.com
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/nxp-nci/i2c.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
+index b3d34433bd14a0..a6c08175d9dd93 100644
+--- a/drivers/nfc/nxp-nci/i2c.c
++++ b/drivers/nfc/nxp-nci/i2c.c
+@@ -16,6 +16,7 @@
+ #include <linux/delay.h>
+ #include <linux/i2c.h>
+ #include <linux/interrupt.h>
++#include <linux/irq.h>
+ #include <linux/module.h>
+ #include <linux/nfc.h>
+ #include <linux/gpio/consumer.h>
+@@ -267,6 +268,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client)
+ {
+ struct device *dev = &client->dev;
+ struct nxp_nci_i2c_phy *phy;
++ unsigned long irqflags;
+ int r;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+@@ -303,9 +305,26 @@ static int nxp_nci_i2c_probe(struct i2c_client *client)
+ if (r < 0)
+ return r;
+
++ /*
++ * ACPI platforms may report incorrect IRQ trigger types
++ * (e.g. level-high), which can lead to interrupt storms.
++ *
++ * Use the historically stable rising-edge trigger for ACPI devices.
++ *
++ * On non-ACPI systems (e.g. Device Tree), prefer the firmware-
++ * provided trigger type, falling back to rising-edge if not set.
++ */
++ if (ACPI_COMPANION(dev)) {
++ irqflags = IRQF_TRIGGER_RISING;
++ } else {
++ irqflags = irq_get_trigger_type(client->irq);
++ if (!irqflags)
++ irqflags = IRQF_TRIGGER_RISING;
++ }
++
+ r = request_threaded_irq(client->irq, NULL,
+ nxp_nci_i2c_irq_thread_fn,
+- IRQF_ONESHOT,
++ irqflags | IRQF_ONESHOT,
+ NXP_NCI_I2C_DRIVER_NAME, phy);
+ if (r < 0)
+ nfc_err(&client->dev, "Unable to register IRQ handler\n");
+--
+2.53.0
+
--- /dev/null
+From 3e8c69447edbddd4321f2494b202a2fdacc9cd1f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:16 -0400
+Subject: nvme-tcp: store negative errno in queue->tls_err
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 9015985b5eb1a90eb86caf5bce1dfcf1aa38f8ad ]
+
+nvme_tcp_tls_done() assigns queue->tls_err in three branches. The
+ENOKEY lookup failure and the EOPNOTSUPP initializer both store
+negative errnos. The third branch, reached when the handshake
+layer reports a non-zero status, stores -status.
+
+The handshake layer delivers status to the consumer callback as a
+negative errno; the other in-tree consumers --
+xs_tls_handshake_done() and the nvmet target callback -- treat
+their status argument that way. The extra negation in
+nvme_tcp_tls_done() flips the sign, leaving tls_err as a positive
+value (for instance, +EIO), which nvme_tcp_start_tls() then
+returns to its caller.
+
+Drop the extra negation so queue->tls_err uniformly carries a
+negative errno on failure.
+
+Fixes: be8e82caa685 ("nvme-tcp: enable TLS handshake upcall")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-2-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/tcp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
+index 77df3432dfb78e..31406438e3ff2d 100644
+--- a/drivers/nvme/host/tcp.c
++++ b/drivers/nvme/host/tcp.c
+@@ -1719,7 +1719,7 @@ static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid)
+ qid, pskid, status);
+
+ if (status) {
+- queue->tls_err = -status;
++ queue->tls_err = status;
+ goto out_complete;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 6e90a97da649cd482a91d91e149892fe6ebc14d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 2 Jun 2024 23:58:44 -0400
+Subject: remove pointless includes of <linux/fdtable.h>
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit be5498cac2ddb112c5bd7433d5e834a1a2493427 ]
+
+some of those used to be needed, some had been cargo-culted for
+no reason...
+
+Reviewed-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Stable-dep-of: ea5fe6a73ca5 ("net/handshake: Drain pending requests at net namespace exit")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/fcntl.c | 1 -
+ fs/file_table.c | 1 -
+ fs/notify/fanotify/fanotify.c | 1 -
+ fs/notify/fanotify/fanotify_user.c | 1 -
+ fs/overlayfs/copy_up.c | 1 -
+ fs/proc/base.c | 1 -
+ io_uring/io_uring.c | 1 -
+ kernel/bpf/bpf_inode_storage.c | 1 -
+ kernel/bpf/bpf_task_storage.c | 1 -
+ kernel/bpf/token.c | 1 -
+ kernel/exit.c | 1 -
+ kernel/module/dups.c | 1 -
+ kernel/module/kmod.c | 1 -
+ kernel/umh.c | 1 -
+ net/handshake/request.c | 1 -
+ security/apparmor/domain.c | 1 -
+ 16 files changed, 16 deletions(-)
+
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index 3d89de31066ae0..a7947a615db6b4 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -12,7 +12,6 @@
+ #include <linux/fs.h>
+ #include <linux/filelock.h>
+ #include <linux/file.h>
+-#include <linux/fdtable.h>
+ #include <linux/capability.h>
+ #include <linux/dnotify.h>
+ #include <linux/slab.h>
+diff --git a/fs/file_table.c b/fs/file_table.c
+index f7661a70874640..2a08bc93b0b9c1 100644
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -9,7 +9,6 @@
+ #include <linux/string.h>
+ #include <linux/slab.h>
+ #include <linux/file.h>
+-#include <linux/fdtable.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/fs.h>
+diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
+index bb00e1e1683838..4d86a05258b970 100644
+--- a/fs/notify/fanotify/fanotify.c
++++ b/fs/notify/fanotify/fanotify.c
+@@ -1,6 +1,5 @@
+ // SPDX-License-Identifier: GPL-2.0
+ #include <linux/fanotify.h>
+-#include <linux/fdtable.h>
+ #include <linux/fsnotify_backend.h>
+ #include <linux/init.h>
+ #include <linux/jiffies.h>
+diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
+index 93c1619cdad659..b89ad128bf09cf 100644
+--- a/fs/notify/fanotify/fanotify_user.c
++++ b/fs/notify/fanotify/fanotify_user.c
+@@ -1,7 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ #include <linux/fanotify.h>
+ #include <linux/fcntl.h>
+-#include <linux/fdtable.h>
+ #include <linux/file.h>
+ #include <linux/fs.h>
+ #include <linux/anon_inodes.h>
+diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
+index 57f635d050eb5a..75e804bc152ccf 100644
+--- a/fs/overlayfs/copy_up.c
++++ b/fs/overlayfs/copy_up.c
+@@ -16,7 +16,6 @@
+ #include <linux/sched/signal.h>
+ #include <linux/cred.h>
+ #include <linux/namei.h>
+-#include <linux/fdtable.h>
+ #include <linux/ratelimit.h>
+ #include <linux/exportfs.h>
+ #include "overlayfs.h"
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index d060af34a6e837..704cf6a0612ede 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -58,7 +58,6 @@
+ #include <linux/init.h>
+ #include <linux/capability.h>
+ #include <linux/file.h>
+-#include <linux/fdtable.h>
+ #include <linux/generic-radix-tree.h>
+ #include <linux/string.h>
+ #include <linux/seq_file.h>
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index eef59b9eccfab1..e515aeafa87813 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -51,7 +51,6 @@
+ #include <linux/sched/signal.h>
+ #include <linux/fs.h>
+ #include <linux/file.h>
+-#include <linux/fdtable.h>
+ #include <linux/mm.h>
+ #include <linux/mman.h>
+ #include <linux/percpu.h>
+diff --git a/kernel/bpf/bpf_inode_storage.c b/kernel/bpf/bpf_inode_storage.c
+index 29da6d3838f678..e16e79f8cd6dc3 100644
+--- a/kernel/bpf/bpf_inode_storage.c
++++ b/kernel/bpf/bpf_inode_storage.c
+@@ -16,7 +16,6 @@
+ #include <uapi/linux/btf.h>
+ #include <linux/bpf_lsm.h>
+ #include <linux/btf_ids.h>
+-#include <linux/fdtable.h>
+ #include <linux/rcupdate_trace.h>
+
+ DEFINE_BPF_STORAGE_CACHE(inode_cache);
+diff --git a/kernel/bpf/bpf_task_storage.c b/kernel/bpf/bpf_task_storage.c
+index adf6dfe0ba68a4..1eb9852a9f8ebb 100644
+--- a/kernel/bpf/bpf_task_storage.c
++++ b/kernel/bpf/bpf_task_storage.c
+@@ -16,7 +16,6 @@
+ #include <linux/filter.h>
+ #include <uapi/linux/btf.h>
+ #include <linux/btf_ids.h>
+-#include <linux/fdtable.h>
+ #include <linux/rcupdate_trace.h>
+
+ DEFINE_BPF_STORAGE_CACHE(task_cache);
+diff --git a/kernel/bpf/token.c b/kernel/bpf/token.c
+index dcbec1a0dfb33f..26057aa1350398 100644
+--- a/kernel/bpf/token.c
++++ b/kernel/bpf/token.c
+@@ -1,6 +1,5 @@
+ #include <linux/bpf.h>
+ #include <linux/vmalloc.h>
+-#include <linux/fdtable.h>
+ #include <linux/file.h>
+ #include <linux/fs.h>
+ #include <linux/kernel.h>
+diff --git a/kernel/exit.c b/kernel/exit.c
+index b91124b2d334ee..e798078f958c89 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -25,7 +25,6 @@
+ #include <linux/acct.h>
+ #include <linux/tsacct_kern.h>
+ #include <linux/file.h>
+-#include <linux/fdtable.h>
+ #include <linux/freezer.h>
+ #include <linux/binfmts.h>
+ #include <linux/nsproxy.h>
+diff --git a/kernel/module/dups.c b/kernel/module/dups.c
+index 9a92f2f8c9d382..bd2149fbe11738 100644
+--- a/kernel/module/dups.c
++++ b/kernel/module/dups.c
+@@ -18,7 +18,6 @@
+ #include <linux/completion.h>
+ #include <linux/cred.h>
+ #include <linux/file.h>
+-#include <linux/fdtable.h>
+ #include <linux/workqueue.h>
+ #include <linux/security.h>
+ #include <linux/mount.h>
+diff --git a/kernel/module/kmod.c b/kernel/module/kmod.c
+index 0800d989169219..25f25381251281 100644
+--- a/kernel/module/kmod.c
++++ b/kernel/module/kmod.c
+@@ -15,7 +15,6 @@
+ #include <linux/completion.h>
+ #include <linux/cred.h>
+ #include <linux/file.h>
+-#include <linux/fdtable.h>
+ #include <linux/workqueue.h>
+ #include <linux/security.h>
+ #include <linux/mount.h>
+diff --git a/kernel/umh.c b/kernel/umh.c
+index ff1f13a27d29fd..be923427077731 100644
+--- a/kernel/umh.c
++++ b/kernel/umh.c
+@@ -13,7 +13,6 @@
+ #include <linux/completion.h>
+ #include <linux/cred.h>
+ #include <linux/file.h>
+-#include <linux/fdtable.h>
+ #include <linux/fs_struct.h>
+ #include <linux/workqueue.h>
+ #include <linux/security.h>
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 2f58d74f16554b..62efb7e32730ea 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -13,7 +13,6 @@
+ #include <linux/module.h>
+ #include <linux/skbuff.h>
+ #include <linux/inet.h>
+-#include <linux/fdtable.h>
+ #include <linux/rhashtable.h>
+
+ #include <net/sock.h>
+diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
+index cccd61cca509ce..fbfb1d48dc88f2 100644
+--- a/security/apparmor/domain.c
++++ b/security/apparmor/domain.c
+@@ -9,7 +9,6 @@
+ */
+
+ #include <linux/errno.h>
+-#include <linux/fdtable.h>
+ #include <linux/fs.h>
+ #include <linux/file.h>
+ #include <linux/mount.h>
+--
+2.53.0
+
--- /dev/null
+From 9049be25251be93e9fc5e207468e8262b9c5dd80 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 May 2026 14:09:41 -0400
+Subject: scsi: core: Run queues for all non-SDEV_DEL devices from
+ scsi_run_host_queues
+
+From: David Jeffery <djeffery@redhat.com>
+
+[ Upstream commit 7205b58702273baf21d6ba7992e6ba15852325f7 ]
+
+While a SCSI host is in a recovery state, scsi_mq_requeue_cmd() will not
+set the requeue list for a requeued command to be kicked in the future.
+The expectation is a call to scsi_run_host_queues() will kick all SCSI
+devices once the recovery state is cleared.
+
+However, scsi_run_host_queues() uses shost_for_each_device() which uses
+scsi_device_get() and so will ignore devices in a partially removed
+state like SDEV_CANCEL. But these devices may also have requeued
+requests, leaving their requests stuck from not being kicked and causing
+the removal process of the device to hang.
+
+scsi_run_host_queues() needs to run against more devices than the macro
+shost_for_each_device() allows. Instead of using the too limiting
+scsi_device_get() state checks, only ignore devices in SDEV_DEL state or
+when unable to acquire a reference. Attempt to run the queues for all
+other devices when scsi_run_host_queues() is called.
+
+Fixes: 8b566edbdbfb ("scsi: core: Only kick the requeue list if necessary")
+Signed-off-by: David Jeffery <djeffery@redhat.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://patch.msgid.link/20260515180941.9698-1-djeffery@redhat.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_lib.c | 27 +++++++++++++++++++++++++--
+ 1 file changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 55717fd3234be2..d63d10d53a2aad 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -569,10 +569,33 @@ void scsi_requeue_run_queue(struct work_struct *work)
+
+ void scsi_run_host_queues(struct Scsi_Host *shost)
+ {
+- struct scsi_device *sdev;
++ struct scsi_device *sdev, *prev = NULL;
++ unsigned long flags;
+
+- shost_for_each_device(sdev, shost)
++ spin_lock_irqsave(shost->host_lock, flags);
++ __shost_for_each_device(sdev, shost) {
++ /*
++ * Only skip devices so deep into removal they will never need
++ * another kick to their queues. Thus scsi_device_get() cannot
++ * be used as it would skip devices in SDEV_CANCEL state which
++ * may need a queue kick.
++ */
++ if (sdev->sdev_state == SDEV_DEL ||
++ !get_device(&sdev->sdev_gendev))
++ continue;
++ spin_unlock_irqrestore(shost->host_lock, flags);
++
++ if (prev)
++ put_device(&prev->sdev_gendev);
+ scsi_run_queue(sdev->request_queue);
++
++ prev = sdev;
++
++ spin_lock_irqsave(shost->host_lock, flags);
++ }
++ spin_unlock_irqrestore(shost->host_lock, flags);
++ if (prev)
++ put_device(&prev->sdev_gendev);
+ }
+
+ static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
+--
+2.53.0
+
--- /dev/null
+From 42356ccefc100500180c57c828a8ec882d195912 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 11:24:11 +0800
+Subject: sctp: fix race between sctp_wait_for_connect and peeloff
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit f14fe6395a8b3d961a61e138ad7b36ba3626dd4e ]
+
+sctp_wait_for_connect() drops and re-acquires the socket lock while
+waiting for the association to reach ESTABLISHED state. During this
+window, another thread can peeloff the association to a new socket via
+getsockopt(SCTP_SOCKOPT_PEELOFF), changing asoc->base.sk. After
+re-acquiring the old socket lock, sctp_wait_for_connect() returns
+success without noticing the migration — the caller then accesses
+the association under the wrong lock in sctp_datamsg_from_user().
+
+Add the same sk != asoc->base.sk check that sctp_wait_for_sndbuf()
+already has, returning an error if the association was migrated while
+we slept.
+
+Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260527032411.60959-1-kipreyyy@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/socket.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 6b562dd1aae110..3e80cf4e63ff00 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -9377,6 +9377,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
+ release_sock(sk);
+ current_timeo = schedule_timeout(current_timeo);
+ lock_sock(sk);
++ if (sk != asoc->base.sk)
++ goto do_error;
+
+ *timeo_p = current_timeo;
+ }
+--
+2.53.0
+
arm64-debug-split-bkpt32-exception-entry.patch
arm64-debug-remove-debug-exception-registration-infr.patch
arm64-debug-always-unmask-interrupts-in-el0_softstp.patch
+nfc-llcp-fix-use-after-free-in-llcp_sock_release.patch
+nfc-llcp-fix-use-after-free-race-in-nfc_llcp_recv_cc.patch
+xfrm-check-for-underflow-in-xfrm_state_mtu.patch
+nfc-nxp-nci-i2c-use-rising-edge-irq-on-acpi-systems.patch
+kunit-fix-use-after-free-in-debugfs-when-using-kunit.patch
+kernel-fork-validate-exit_signal-in-kernel_clone.patch
+netfilter-synproxy-refresh-tcphdr-after-skb_ensure_w.patch
+netfilter-xt_cpu-prefer-raw_smp_processor_id.patch
+netfilter-ebtables-fix-oob-read-in-compat_mtw_from_u.patch
+tun-free-page-on-short-frame-rejection-in-tun_xdp_on.patch
+tun-free-page-on-build_skb-failure-in-tun_xdp_one.patch
+vsock-keep-poll-shutdown-state-consistent.patch
+net-netlink-fix-sending-unassigned-nsid-after-assign.patch
+net-netlink-don-t-set-nsid-on-local-notifications.patch
+net-smc-do-not-re-initialize-smc-hashtables.patch
+net-iucv-fix-locking-in-.getsockopt.patch
+scsi-core-run-queues-for-all-non-sdev_del-devices-fr.patch
+ipv4-free-net-ipv4.sysctl_local_reserved_ports-after.patch
+alsa-pcm-oss-fix-setup-list-uaf-on-proc-write-error.patch
+asoc-intel-bytcht_es8316-fix-mclk-leak-on-init-error.patch
+net-hsr-fix-potential-oob-access-in-supervision-fram.patch
+accel-ivpu-prevent-uninitialized-data-bug-in-debugfs.patch
+gpio-mxc-fix-irq_high-handling.patch
+net-avoid-checksumming-unreadable-skb-tail-on-trim.patch
+ethtool-rss-fix-hkey-leak-when-indir_size-is-0.patch
+ethtool-module-avoid-leaking-a-netdev-ref-on-module-.patch
+ethtool-module-check-fw_flash_in_progress-under-rtnl.patch
+ethtool-module-fix-cleanup-if-socket-used-for-flashi.patch
+ethtool-cmis-require-exact-cdb-reply-length.patch
+ethtool-cmis-fix-u16-to-u8-truncation-of-msleep_pre_.patch
+net-ethtool-add-new-parameters-and-a-function-to-sup.patch
+net-ethtool-add-support-for-writing-firmware-blocks-.patch
+ethtool-cmis-validate-start_cmd_payload_size-from-mo.patch
+ethtool-cmis-validate-fw-size-against-start_cmd_payl.patch
+cxl-test-update-mock-dev-array-before-calling-platfo.patch
+tunnels-load-network-headers-after-skb_cow-in-iptunn.patch
+vxlan-do-not-reuse-cached-ip_hdr-value-after-skb_tun.patch
+tunnels-do-not-assume-transport-header-in-iptunnel_p.patch
+asoc-codecs-simple-mux-fix-enum-control-bounds-check.patch
+bluetooth-6lowpan-check-skb_clone-return-value-in-se.patch
+bonding-refuse-to-enslave-can-devices.patch
+ethtool-coalesce-cap-profile-updates-at-net_dim_para.patch
+ethtool-linkstate-fix-unbalanced-ethnl_ops_complete-.patch
+ethtool-pse-pd-fix-missing-ethnl_ops_complete.patch
+ethtool-strset-fix-header-attribute-index-in-ethnl_r.patch
+ethtool-eeprom-add-missing-ethnl_ops_begin-_complete.patch
+ethtool-eeprom-add-more-safeties-to-eeprom-netlink-f.patch
+ipv6-rpl-fix-hdrlen-overflow-in-ipv6_rpl_srh_decompr.patch
+net-sched-revert-net-sched-restrict-conditions-for-a.patch
+net-sched-fix-packet-loop-on-netem-when-duplicate-is.patch
+net-sched-act_mirred-move-the-recursion-counter-stru.patch
+net-sched-act_mirred-add-loop-detection.patch
+net-introduce-skb-tc-depth-field-to-track-packet-loo.patch
+net-sched-fix-ethx-ingress-ethy-egress-ethx-ingress-.patch
+net-sched-act_mirred-fix-return-code-in-early-mirred.patch
+net-handshake-use-spin_lock_bh-for-hn_lock.patch
+nvme-tcp-store-negative-errno-in-queue-tls_err.patch
+net-handshake-pass-negative-errno-through-handshake_.patch
+remove-pointless-includes-of-linux-fdtable.h.patch
+net-handshake-take-a-long-lived-file-reference-at-su.patch
+net-handshake-drain-pending-requests-at-net-namespac.patch
+bluetooth-l2cap-clear-chan-ident-on-ecred-reconfigur.patch
+bluetooth-l2cap-fix-possible-crash-on-l2cap_ecred_co.patch
+bluetooth-hci_sync-set-hci_cmd_drain_workqueue-durin.patch
+gpio-virtuser-fix-uninitialized-data-bug-in-gpio_vir.patch
+gpio-rockchip-convert-bank-clk-to-devm_clk_get_enabl.patch
+net-mana-add-null-guards-in-teardown-path-to-prevent.patch
+sctp-fix-race-between-sctp_wait_for_connect-and-peel.patch
+ipv6-fix-possible-infinite-loop-in-rt6_fill_node.patch
+ipv6-fix-possible-infinite-loop-in-fib6_select_path.patch
+net-skbuff-fix-pskb_carve-leaking-zcopy-pages.patch
--- /dev/null
+From 534fe6142d2aef1ed2d9b9c49b1bc163fc996bc0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 09:33:13 -0700
+Subject: tun: free page on build_skb failure in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit aa8963fdce667a42fb7f0bdd2909fadcab02f9a8 ]
+
+When build_skb() fails in tun_xdp_one(), the function sets ret to
+-ENOMEM and jumps to the out label, which returns without freeing the
+page that vhost_net_build_xdp() allocated for the frame. As with the
+short-frame rejection path, tun_sendmsg() discards the per-buffer error
+and still returns total_len, so vhost_tx_batch() takes the success path
+and never frees the page. Each build_skb() failure in a batch leaks one
+page-frag chunk.
+
+Free the page before taking the error path, matching the put_page() the
+other error exits of tun_xdp_one() already perform.
+
+Fixes: 043d222f93ab ("tuntap: accept an array of XDP buffs through sendmsg()")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260521163312.1479805-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 19c33d21bab947..d53e60823bf1bb 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2505,6 +2505,7 @@ static int tun_xdp_one(struct tun_struct *tun,
+ build:
+ skb = build_skb(xdp->data_hard_start, buflen);
+ if (!skb) {
++ put_page(virt_to_head_page(xdp->data));
+ ret = -ENOMEM;
+ goto out;
+ }
+--
+2.53.0
+
--- /dev/null
+From a94901bacf88feabd0a93461d058b8ff3054afdc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 09:00:21 -0700
+Subject: tun: free page on short-frame rejection in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f4feb1e20058e407cb00f45aff47f5b7e19a6bbf ]
+
+tun_xdp_one() returns -EINVAL on a frame shorter than ETH_HLEN without
+freeing the page that vhost_net_build_xdp() allocated for it.
+tun_sendmsg() discards that -EINVAL and still returns total_len, so
+vhost_tx_batch() takes the success path and never frees the page; each
+short frame in a batch leaks one page-frag chunk.
+
+A local process that can open /dev/net/tun and /dev/vhost-net can hit
+this path: it attaches a tun/tap device as the vhost-net backend and
+feeds TX descriptors whose length minus the virtio-net header is below
+ETH_HLEN. Each kick leaks the page-frag chunks for that batch, and a
+tight submission loop exhausts host memory and triggers an OOM panic.
+Free the page before returning -EINVAL, matching the XDP-program error
+path in the same function.
+
+Fixes: 049584807f1d ("tun: add missing verification for short frame")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260520160020.375349-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index fb9d425eff8c1b..19c33d21bab947 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2459,8 +2459,10 @@ static int tun_xdp_one(struct tun_struct *tun,
+ bool skb_xdp = false;
+ struct page *page;
+
+- if (unlikely(datasize < ETH_HLEN))
++ if (unlikely(datasize < ETH_HLEN)) {
++ put_page(virt_to_head_page(xdp->data));
+ return -EINVAL;
++ }
+
+ xdp_prog = rcu_dereference(tun->xdp_prog);
+ if (xdp_prog) {
+--
+2.53.0
+
--- /dev/null
+From ca4fa88756439e4c7f039038925258b39133573d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 11:55:12 +0000
+Subject: tunnels: do not assume transport header in
+ iptunnel_pmtud_check_icmp()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 509323077ef79a26ba0c60bb556e45c12c398b2d ]
+
+In some cases, iptunnel_pmtud_check_icmp() can be called while
+skb transport header is not set.
+
+This triggers an out-of-bound access, because
+(typeof(skb->transport_header))~0U is 65535.
+
+Access the icmp header based on IPv4 network header,
+after making sure icmp->type is present in skb linear part.
+
+Note that iptunnel_pmtud_check_icmpv6()) is fine.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Reported-by: Damiano Melotti <melotti@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260522115512.1519110-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index cf496644d3df6c..d0ceb86e1687a7 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -278,7 +278,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct icmphdr *icmph = icmp_hdr(skb);
+ const struct iphdr *iph = ip_hdr(skb);
+
+ if (mtu < 576 || iph->frag_off != htons(IP_DF))
+@@ -289,9 +288,17 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ ipv4_is_lbcast(iph->saddr) || ipv4_is_multicast(iph->saddr))
+ return 0;
+
+- if (iph->protocol == IPPROTO_ICMP && icmp_is_err(icmph->type))
+- return 0;
++ if (iph->protocol == IPPROTO_ICMP) {
++ const struct icmphdr *icmph;
+
++ if (!pskb_network_may_pull(skb, iph->ihl * 4 +
++ offsetofend(struct icmphdr, type)))
++ return 0;
++ iph = ip_hdr(skb);
++ icmph = (void *)iph + iph->ihl * 4;
++ if (icmp_is_err(icmph->type))
++ return 0;
++ }
+ return iptunnel_pmtud_build_icmp(skb, mtu);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 05efa6e70f6d6d1eac6923e85881c5fa1d20e3c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:13:35 +0000
+Subject: tunnels: load network headers after skb_cow() in
+ iptunnel_pmtud_build_icmp[v6]()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b4bc94353050b1fa7b702bd4c6600710dd926cff ]
+
+Sashiko found that iptunnel_pmtud_build_icmp() and
+iptunnel_pmtud_build_icmpv6() were caching ip_hdr() and ipv6_hdr()
+before an skb_cow() call which can reallocate skb->head.
+
+Fix this possible UAF by initializing the local variables
+after the skb_cow() call.
+
+Remove skb_reset_network_header() calls which were not needed.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525201335.2361845-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 507f2f9ec400ce..cf496644d3df6c 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -210,7 +210,7 @@ EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
+ */
+ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct iphdr *iph = ip_hdr(skb);
++ const struct iphdr *iph;
+ struct icmphdr *icmph;
+ struct iphdr *niph;
+ struct ethhdr eh;
+@@ -224,7 +224,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, 576 - sizeof(*niph) - sizeof(*icmph));
+ if (err)
+@@ -234,7 +233,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ err = skb_cow(skb, sizeof(*niph) + sizeof(*icmph) + ETH_HLEN);
+ if (err)
+ return err;
+-
++ iph = ip_hdr(skb);
+ icmph = skb_push(skb, sizeof(*icmph));
+ *icmph = (struct icmphdr) {
+ .type = ICMP_DEST_UNREACH,
+@@ -306,7 +305,7 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ {
+- const struct ipv6hdr *ip6h = ipv6_hdr(skb);
++ const struct ipv6hdr *ip6h;
+ struct icmp6hdr *icmp6h;
+ struct ipv6hdr *nip6h;
+ struct ethhdr eh;
+@@ -321,7 +320,6 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, IPV6_MIN_MTU - sizeof(*nip6h) - sizeof(*icmp6h));
+ if (err)
+@@ -332,6 +330,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ if (err)
+ return err;
+
++ ip6h = ipv6_hdr(skb);
+ icmp6h = skb_push(skb, sizeof(*icmp6h));
+ *icmp6h = (struct icmp6hdr) {
+ .icmp6_type = ICMPV6_PKT_TOOBIG,
+--
+2.53.0
+
--- /dev/null
+From 5ba4d0d23a92c610446fe70f0cdf079e429f86f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 00:56:36 +0800
+Subject: vsock: keep poll shutdown state consistent
+
+From: Ziyu Zhang <ziyuzhang201@gmail.com>
+
+[ Upstream commit aae9d8a5528b8ee9ff8dc5d3558b8a9f852a724a ]
+
+vsock_poll() reads vsk->peer_shutdown before taking the socket lock
+to set EPOLLHUP and EPOLLRDHUP, then reads it again after taking
+the lock to report EOF readability. A shutdown packet can update
+peer_shutdown while poll is waiting for the lock, so one poll invocation
+can report EOF readability without the corresponding HUP/RDHUP bits.
+
+For connectible sockets, take one peer_shutdown snapshot after
+lock_sock() and use it for all peer-shutdown-derived poll bits. For
+datagram sockets, which do not take lock_sock() in poll(), take one
+lockless READ_ONCE() snapshot and pair it with WRITE_ONCE() on the
+writer side.
+
+This keeps the peer-shutdown-derived bits internally consistent for each
+poll pass.
+
+Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
+Signed-off-by: Ziyu Zhang <ziyuzhang201@gmail.com>
+Link: https://patch.msgid.link/20260519165636.62542-1-ziyuzhang201@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/vmw_vsock/af_vsock.c | 49 ++++++++++++++++---------
+ net/vmw_vsock/hyperv_transport.c | 9 +++--
+ net/vmw_vsock/virtio_transport_common.c | 14 ++++---
+ net/vmw_vsock/vmci_transport.c | 8 ++--
+ 4 files changed, 52 insertions(+), 28 deletions(-)
+
+diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
+index 1db7a1f8e55f6d..f03e00cae028a5 100644
+--- a/net/vmw_vsock/af_vsock.c
++++ b/net/vmw_vsock/af_vsock.c
+@@ -523,7 +523,7 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
+ */
+ sock_reset_flag(sk, SOCK_DONE);
+ sk->sk_state = TCP_CLOSE;
+- vsk->peer_shutdown = 0;
++ WRITE_ONCE(vsk->peer_shutdown, 0);
+ }
+
+ if (sk->sk_type == SOCK_SEQPACKET) {
+@@ -814,7 +814,7 @@ static struct sock *__vsock_create(struct net *net,
+ vsk->rejected = false;
+ vsk->sent_request = false;
+ vsk->ignore_connecting_rst = false;
+- vsk->peer_shutdown = 0;
++ WRITE_ONCE(vsk->peer_shutdown, 0);
+ INIT_DELAYED_WORK(&vsk->connect_work, vsock_connect_timeout);
+ INIT_DELAYED_WORK(&vsk->pending_work, vsock_pending_work);
+
+@@ -1099,6 +1099,25 @@ static int vsock_shutdown(struct socket *sock, int mode)
+ return err;
+ }
+
++static __poll_t vsock_poll_shutdown(struct sock *sk, u32 peer_shutdown)
++{
++ __poll_t mask = 0;
++
++ /* INET sockets treat local write shutdown and peer write shutdown as a
++ * case of EPOLLHUP set.
++ */
++ if (sk->sk_shutdown == SHUTDOWN_MASK ||
++ ((sk->sk_shutdown & SEND_SHUTDOWN) &&
++ (peer_shutdown & SEND_SHUTDOWN)))
++ mask |= EPOLLHUP;
++
++ if (sk->sk_shutdown & RCV_SHUTDOWN ||
++ peer_shutdown & SEND_SHUTDOWN)
++ mask |= EPOLLRDHUP;
++
++ return mask;
++}
++
+ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+ {
+@@ -1116,24 +1135,17 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ /* Signify that there has been an error on this socket. */
+ mask |= EPOLLERR;
+
+- /* INET sockets treat local write shutdown and peer write shutdown as a
+- * case of EPOLLHUP set.
+- */
+- if ((sk->sk_shutdown == SHUTDOWN_MASK) ||
+- ((sk->sk_shutdown & SEND_SHUTDOWN) &&
+- (vsk->peer_shutdown & SEND_SHUTDOWN))) {
+- mask |= EPOLLHUP;
+- }
+-
+- if (sk->sk_shutdown & RCV_SHUTDOWN ||
+- vsk->peer_shutdown & SEND_SHUTDOWN) {
+- mask |= EPOLLRDHUP;
+- }
+-
+ if (sk_is_readable(sk))
+ mask |= EPOLLIN | EPOLLRDNORM;
+
+ if (sock->type == SOCK_DGRAM) {
++ u32 peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++
++ /* DGRAM sockets do not take lock_sock() in poll(), so use one
++ * lockless snapshot for all shutdown-derived mask bits.
++ */
++ mask |= vsock_poll_shutdown(sk, peer_shutdown);
++
+ /* For datagram sockets we can read if there is something in
+ * the queue and write as long as the socket isn't shutdown for
+ * sending.
+@@ -1148,6 +1160,7 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+
+ } else if (sock_type_connectible(sk->sk_type)) {
+ const struct vsock_transport *transport;
++ u32 peer_shutdown;
+
+ lock_sock(sk);
+
+@@ -1180,8 +1193,10 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ * terminated should also be considered read, and we check the
+ * shutdown flag for that.
+ */
++ peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++ mask |= vsock_poll_shutdown(sk, peer_shutdown);
+ if (sk->sk_shutdown & RCV_SHUTDOWN ||
+- vsk->peer_shutdown & SEND_SHUTDOWN) {
++ peer_shutdown & SEND_SHUTDOWN) {
+ mask |= EPOLLIN | EPOLLRDNORM;
+ }
+
+diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
+index 34871ed1a099c6..865e004ee286f2 100644
+--- a/net/vmw_vsock/hyperv_transport.c
++++ b/net/vmw_vsock/hyperv_transport.c
+@@ -264,7 +264,7 @@ static void hvs_do_close_lock_held(struct vsock_sock *vsk,
+ struct sock *sk = sk_vsock(vsk);
+
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+ sk->sk_state_change(sk);
+@@ -593,7 +593,9 @@ static int hvs_update_recv_data(struct hvsock *hvs)
+ return -EIO;
+
+ if (payload_len == 0)
+- hvs->vsk->peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(hvs->vsk->peer_shutdown,
++ READ_ONCE(hvs->vsk->peer_shutdown) |
++ SEND_SHUTDOWN);
+
+ hvs->recv_data_len = payload_len;
+ hvs->recv_data_off = 0;
+@@ -704,7 +706,8 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk)
+ ret = 1;
+ break;
+ case 0:
+- vsk->peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(vsk->peer_shutdown,
++ READ_ONCE(vsk->peer_shutdown) | SEND_SHUTDOWN);
+ ret = 0;
+ break;
+ default: /* -1 */
+diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
+index c182886136b445..b588ccd133eaa7 100644
+--- a/net/vmw_vsock/virtio_transport_common.c
++++ b/net/vmw_vsock/virtio_transport_common.c
+@@ -1234,7 +1234,7 @@ static void virtio_transport_do_close(struct vsock_sock *vsk,
+ struct sock *sk = sk_vsock(vsk);
+
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+ sk->sk_state_change(sk);
+@@ -1437,12 +1437,15 @@ virtio_transport_recv_connected(struct sock *sk,
+ case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
+ sk->sk_write_space(sk);
+ break;
+- case VIRTIO_VSOCK_OP_SHUTDOWN:
++ case VIRTIO_VSOCK_OP_SHUTDOWN: {
++ u32 peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++
+ if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_RCV)
+- vsk->peer_shutdown |= RCV_SHUTDOWN;
++ peer_shutdown |= RCV_SHUTDOWN;
+ if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_SEND)
+- vsk->peer_shutdown |= SEND_SHUTDOWN;
+- if (vsk->peer_shutdown == SHUTDOWN_MASK) {
++ peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(vsk->peer_shutdown, peer_shutdown);
++ if (peer_shutdown == SHUTDOWN_MASK) {
+ if (vsock_stream_has_data(vsk) <= 0 && !sock_flag(sk, SOCK_DONE)) {
+ (void)virtio_transport_reset(vsk, NULL);
+ virtio_transport_do_close(vsk, true);
+@@ -1457,6 +1460,7 @@ virtio_transport_recv_connected(struct sock *sk,
+ if (le32_to_cpu(virtio_vsock_hdr(skb)->flags))
+ sk->sk_state_change(sk);
+ break;
++ }
+ case VIRTIO_VSOCK_OP_RST:
+ virtio_transport_do_close(vsk, true);
+ break;
+diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
+index 4cd11f355e9d6b..443125e48f2481 100644
+--- a/net/vmw_vsock/vmci_transport.c
++++ b/net/vmw_vsock/vmci_transport.c
+@@ -811,7 +811,7 @@ static void vmci_transport_handle_detach(struct sock *sk)
+ /* On a detach the peer will not be sending or receiving
+ * anymore.
+ */
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+
+ /* We should not be sending anymore since the peer won't be
+ * there to receive, but we can still receive if there is data
+@@ -1534,7 +1534,9 @@ static int vmci_transport_recv_connected(struct sock *sk,
+ if (pkt->u.mode) {
+ vsk = vsock_sk(sk);
+
+- vsk->peer_shutdown |= pkt->u.mode;
++ WRITE_ONCE(vsk->peer_shutdown,
++ READ_ONCE(vsk->peer_shutdown) |
++ pkt->u.mode);
+ sk->sk_state_change(sk);
+ }
+ break;
+@@ -1551,7 +1553,7 @@ static int vmci_transport_recv_connected(struct sock *sk,
+ * a clean shutdown.
+ */
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+
+--
+2.53.0
+
--- /dev/null
+From 7a38673e85f230e726cc7061e8841f05b8f951f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:36:42 +0000
+Subject: vxlan: do not reuse cached ip_hdr() value after
+ skb_tunnel_check_pmtu()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 7d9ef0cb271555d8cf39fefe6c981e1493b25ecf ]
+
+skb_tunnel_check_pmtu() can change skb->head.
+
+Reusing old_iph afer skb_tunnel_check_pmtu() can cause an UAF.
+
+Use instead ip_hdr(skb) as done in drivers/net/bareudp.c
+and drivers/net/geneve.c.
+
+Found by Sashiko.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525203642.2389723-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index ed428293b0e579..765d25eee2fe48 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -2541,7 +2541,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
+ vni, md, flags, udp_sum);
+@@ -2601,7 +2601,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip6_dst_hoplimit(ndst);
+ skb_scrub_packet(skb, xnet);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
+--
+2.53.0
+
--- /dev/null
+From 12d3f6f2c51d183a3c95830ff09315181c474972 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:49:14 -0600
+Subject: xfrm: Check for underflow in xfrm_state_mtu
+
+From: David Ahern <dahern@nvidia.com>
+
+[ Upstream commit 742b04d0550b0ec89dcbc99537ec88653bd1ad90 ]
+
+Leo Lin reported OOB write issue in esp component:
+
+ xfrm_state_mtu() returns u32 but performs its arithmetic in unsigned
+ modulo-2^32 space using an attacker-influenced "header_len + authsize +
+ net_adj" subtracted from a small "mtu" argument. A nobody user can
+ install an IPv4 ESP tunnel SA with a large authentication key
+ (XFRMA_ALG_AUTH_TRUNC, e.g. hmac(sha512), 64-byte key, 64-byte trunc),
+ configure a small interface MTU (68 bytes), and set XFRMA_TFCPAD to a
+ large value. When a single UDP datagram is then sent through the
+ tunnel, xfrm_state_mtu() underflows to a near-2^32 value, and
+ esp_output() consumes it as a signed int via:
+
+ padto = min(x->tfcpad, xfrm_state_mtu(x, mtu_cached))
+ esp.tfclen = padto - skb->len (assigned to int)
+
+ esp.tfclen ends up negative (e.g. -207). It is sign-extended to size_t
+ when passed to memset() inside esp_output_fill_trailer(), producing a
+ ~16 EB write of zeroes at skb_tail_pointer(skb). KASAN logs it as
+ "Write of size 18446744073709551537 at addr ffff888...".
+
+Check for underflow and return 1. This causes the sendmsg attempt to
+fail with ENETUNREACH.
+
+Fixes: c5c252389374 ("[XFRM]: Optimize MTU calculation")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Assisted-by: Codex:26.506.31004
+Signed-off-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 6a92d88f9e0363..4823a9c054ae2b 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -3022,10 +3022,14 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ const struct xfrm_type *type = READ_ONCE(x->type);
+ struct crypto_aead *aead;
+ u32 blksize, net_adj = 0;
++ u32 overhead, payload_mtu;
+
+ if (x->km.state != XFRM_STATE_VALID ||
+- !type || type->proto != IPPROTO_ESP)
++ !type || type->proto != IPPROTO_ESP) {
++ if (mtu <= x->props.header_len)
++ return 1;
+ return mtu - x->props.header_len;
++ }
+
+ aead = x->data;
+ blksize = ALIGN(crypto_aead_blocksize(aead), 4);
+@@ -3045,8 +3049,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ break;
+ }
+
+- return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
+- net_adj) & ~(blksize - 1)) + net_adj - 2;
++ overhead = x->props.header_len + crypto_aead_authsize(aead) + net_adj;
++ if (mtu <= overhead)
++ return 1;
++
++ payload_mtu = mtu - overhead;
++ payload_mtu &= ~(blksize - 1);
++ if (payload_mtu <= 2)
++ return 1;
++
++ return payload_mtu + net_adj - 2;
++
+ }
+ EXPORT_SYMBOL_GPL(xfrm_state_mtu);
+
+--
+2.53.0
+
--- /dev/null
+From c94e9cdde08e0e5aa81516381ab511097f6da71b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 00:00:00 +0530
+Subject: accel/rocket: fix UAF via dangling GEM handle in create_bo
+
+From: Dhabaleshwar Das <dhabal123@gmail.com>
+
+[ Upstream commit f706e6a4ce75585af979aec3dcbdce68bc76306b ]
+
+rocket_ioctl_create_bo() inserts a GEM handle into the file's IDR via
+drm_gem_handle_create() early on, then performs several operations that
+can fail (sgt allocation, drm_mm insert, iommu_map). If any fail after
+the handle is live, the error path calls drm_gem_shmem_object_free()
+which kfree's the object without removing the handle from the IDR.
+
+This leaves a dangling handle pointing to freed slab memory. Any
+subsequent ioctl using that handle (PREP_BO, FINI_BO, SUBMIT) calls
+drm_gem_object_lookup() and dereferences freed memory (UAF).
+
+Fix by moving drm_gem_handle_create() to after all fallible operations
+succeed, matching the pattern used by panfrost, lima, and etnaviv.
+
+Also fix drm_mm_insert_node_generic() whose return value was silently
+overwritten by iommu_map_sgtable() on the next line. Add the missing
+error check.
+
+[tomeu: Move handle creation to the very end]
+
+Fixes: 658ebeac3351 ("accel/rocket: Add IOCTL for BO creation")
+Reported-by: Dhabaleshwar Das <dhabal123@gmail.com>
+Signed-off-by: Dhabaleshwar Das <dhabal123@gmail.com>
+Reviewed-by: Tomeu Vizoso <tomeu@tomeuvizoso.net>
+Link: https://patch.msgid.link/20260521165720.2113571-1-tomeu@tomeuvizoso.net
+Signed-off-by: Tomeu Vizoso <tomeu@tomeuvizoso.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/accel/rocket/rocket_gem.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/accel/rocket/rocket_gem.c b/drivers/accel/rocket/rocket_gem.c
+index c3c86e1abd25a3..b1b24d60973e82 100644
+--- a/drivers/accel/rocket/rocket_gem.c
++++ b/drivers/accel/rocket/rocket_gem.c
+@@ -78,11 +78,6 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
+ rkt_obj->size = args->size;
+ rkt_obj->offset = 0;
+
+- ret = drm_gem_handle_create(file, gem_obj, &args->handle);
+- drm_gem_object_put(gem_obj);
+- if (ret)
+- goto err;
+-
+ sgt = drm_gem_shmem_get_pages_sgt(shmem_obj);
+ if (IS_ERR(sgt)) {
+ ret = PTR_ERR(sgt);
+@@ -94,6 +89,8 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
+ rkt_obj->size, PAGE_SIZE,
+ 0, 0);
+ mutex_unlock(&rocket_priv->mm_lock);
++ if (ret)
++ goto err;
+
+ ret = iommu_map_sgtable(rocket_priv->domain->domain,
+ rkt_obj->mm.start,
+@@ -111,8 +108,18 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
+ args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
+ args->dma_address = rkt_obj->mm.start;
+
++ ret = drm_gem_handle_create(file, gem_obj, &args->handle);
++ if (ret)
++ goto err_unmap;
++
++ drm_gem_object_put(gem_obj);
++
+ return 0;
+
++err_unmap:
++ iommu_unmap(rocket_priv->domain->domain,
++ rkt_obj->mm.start, rkt_obj->size);
++
+ err_remove_node:
+ mutex_lock(&rocket_priv->mm_lock);
+ drm_mm_remove_node(&rkt_obj->mm);
+--
+2.53.0
+
--- /dev/null
+From 8353904ca767496700211f3e492511b0b8b5d53f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 22:09:40 -0300
+Subject: ALSA: pcm: oss: Fix setup list UAF on proc write error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit 4cc54bdd54b337e77115be5b55577d1c58608eae ]
+
+snd_pcm_oss_proc_write() links a newly allocated setup entry into the
+OSS setup list before duplicating the task name. If the task-name
+allocation fails, the error path frees the already linked entry and
+leaves setup_list pointing at freed memory.
+
+A later OSS device open can then walk the stale list entry in
+snd_pcm_oss_look_for_setup() and dereference freed memory.
+
+Allocate the task name and initialize the setup entry before publishing
+the entry on setup_list. Also fetch the initial proc read iterator only
+after taking setup_mutex, so all setup_list traversal follows the same
+list lifetime rules.
+
+Reported-by: syzbot+8e498074a794999eb41c@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/6a1062b7.170a0220.35b2b7.0003.GAE@google.com
+Closes: https://syzkaller.appspot.com/bug?extid=8e498074a794999eb41c
+Fixes: 060d77b9c04a ("[ALSA] Fix / clean up PCM-OSS setup hooks")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260522-alsa-pcm-oss-setup-uaf-v1-1-40bdcc4d17e8@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/core/oss/pcm_oss.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index 9b5a3def8d2ce9..59d5153d111329 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -2965,8 +2965,10 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+ {
+ struct snd_pcm_str *pstr = entry->private_data;
+- struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
++ struct snd_pcm_oss_setup *setup;
++
+ guard(mutex)(&pstr->oss.setup_mutex);
++ setup = pstr->oss.setup_list;
+ while (setup) {
+ snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
+ setup->task_name,
+@@ -3051,6 +3053,13 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
+ buffer->error = -ENOMEM;
+ return;
+ }
++ template.task_name = kstrdup(task_name, GFP_KERNEL);
++ if (!template.task_name) {
++ kfree(setup);
++ buffer->error = -ENOMEM;
++ return;
++ }
++ *setup = template;
+ if (pstr->oss.setup_list == NULL)
+ pstr->oss.setup_list = setup;
+ else {
+@@ -3058,12 +3067,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
+ setup1->next; setup1 = setup1->next);
+ setup1->next = setup;
+ }
+- template.task_name = kstrdup(task_name, GFP_KERNEL);
+- if (! template.task_name) {
+- kfree(setup);
+- buffer->error = -ENOMEM;
+- return;
+- }
++ continue;
+ }
+ *setup = template;
+ }
+--
+2.53.0
+
--- /dev/null
+From de0181ab0dd485dbdac3966b2dae85da7aa3818f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 09:24:00 -0300
+Subject: ASoC: codecs: simple-mux: Fix enum control bounds check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit f63ad68e18d774a5d15cd7e405ead63f6b322679 ]
+
+simple_mux_control_put() rejects values greater than e->items, but
+enum control values are zero based. For the two-entry mux used by this
+driver, valid values are 0 and 1, so value 2 must be rejected as well.
+
+Accepting e->items can store an invalid mux state, pass it to the GPIO
+setter, and pass it on to the DAPM mux update path where it is used as
+an index into the enum text array.
+
+Use the same >= e->items check used by the ASoC enum helpers.
+
+Fixes: 342fbb7578d1 ("ASoC: add simple-mux")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260527-asoc-simple-mux-enum-bounds-v1-1-3f805b9fc671@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/simple-mux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/simple-mux.c b/sound/soc/codecs/simple-mux.c
+index 3906964401557d..cedd181ffdaf46 100644
+--- a/sound/soc/codecs/simple-mux.c
++++ b/sound/soc/codecs/simple-mux.c
+@@ -51,7 +51,7 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
+ struct simple_mux *priv = snd_soc_component_get_drvdata(c);
+
+- if (ucontrol->value.enumerated.item[0] > e->items)
++ if (ucontrol->value.enumerated.item[0] >= e->items)
+ return -EINVAL;
+
+ if (priv->mux == ucontrol->value.enumerated.item[0])
+--
+2.53.0
+
--- /dev/null
+From 8c7c2adfae177c0e9b05e5f4613a983cc37ac25a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 13:51:47 -0300
+Subject: ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit afb2a3a9d8369d18122a0d7cd294eba9a98259c6 ]
+
+byt_cht_es8316_init() enables MCLK before configuring the codec sysclk
+and creating the headset jack. If either of those later steps fails, the
+function returns without disabling MCLK, leaving the clock enabled after
+card registration fails.
+
+Track whether this driver enabled MCLK and disable it on the init error
+paths. Add the matching DAI link exit callback so the same clock enable
+is also balanced when ASoC cleans up a successfully initialized link.
+
+Fixes: a03bdaa565cb ("ASoC: Intel: add machine driver for BYT/CHT + ES8316")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260519-asoc-bytcht-es8316-mclk-leak-v1-1-b4a11cdc2afd@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/bytcht_es8316.c | 29 ++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
+index 3b5f63112237ea..25044c0f4703b0 100644
+--- a/sound/soc/intel/boards/bytcht_es8316.c
++++ b/sound/soc/intel/boards/bytcht_es8316.c
+@@ -40,6 +40,7 @@ struct byt_cht_es8316_private {
+ struct gpio_desc *speaker_en_gpio;
+ struct device *codec_dev;
+ bool speaker_en;
++ bool mclk_enabled;
+ };
+
+ enum {
+@@ -170,6 +171,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
+ },
+ };
+
++static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
++{
++ if (!priv->mclk_enabled)
++ return;
++
++ clk_disable_unprepare(priv->mclk);
++ priv->mclk_enabled = false;
++}
++
+ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ {
+ struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component;
+@@ -226,12 +236,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret)
+ dev_err(card->dev, "unable to enable MCLK\n");
++ else
++ priv->mclk_enabled = true;
+
+ ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(runtime, 0), 0, 19200000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set codec clock %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ ret = snd_soc_card_jack_new_pins(card, "Headset",
+@@ -240,13 +252,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ARRAY_SIZE(byt_cht_es8316_jack_pins));
+ if (ret) {
+ dev_err(card->dev, "jack creation failed %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_soc_component_set_jack(codec, &priv->jack, NULL);
+
+ return 0;
++
++err_disable_mclk:
++ byt_cht_es8316_disable_mclk(priv);
++ return ret;
++}
++
++static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
++{
++ struct snd_soc_card *card = runtime->card;
++ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
++
++ byt_cht_es8316_disable_mclk(priv);
+ }
+
+ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+@@ -352,6 +376,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
+ | SND_SOC_DAIFMT_CBC_CFC,
+ .be_hw_params_fixup = byt_cht_es8316_codec_fixup,
+ .init = byt_cht_es8316_init,
++ .exit = byt_cht_es8316_exit,
+ SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
+ },
+ };
+--
+2.53.0
+
--- /dev/null
+From 649cc6a649e6978e5cd04d99322d93ec4b3fac2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 11:21:39 +0800
+Subject: Bluetooth: 6lowpan: check skb_clone() return value in
+ send_mcast_pkt()
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+[ Upstream commit 3c40d381ce04f9575a5d8b542898183c3b4b38dc ]
+
+The skb_clone() function can return NULL if memory allocation fails.
+send_mcast_pkt() calls skb_clone() without checking the return value, which
+can lead to a NULL pointer dereference in send_pkt() when it dereferences
+skb->data.
+Add a NULL check after skb_clone() and skip the peer if the clone fails.
+
+Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/6lowpan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
+index 2c21ae8abadc22..038f01600eebab 100644
+--- a/net/bluetooth/6lowpan.c
++++ b/net/bluetooth/6lowpan.c
+@@ -486,6 +486,8 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
+ int ret;
+
+ local_skb = skb_clone(skb, GFP_ATOMIC);
++ if (!local_skb)
++ continue;
+
+ BT_DBG("xmit %s to %pMR type %u IP %pI6c chan %p",
+ netdev->name,
+--
+2.53.0
+
--- /dev/null
+From 3718dc220ef216425944f12fa86b221d0faa97bb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 10:50:59 -0300
+Subject: Bluetooth: hci_sync: Reset device counters in hci_dev_close_sync()
+
+From: Heitor Alves de Siqueira <halves@igalia.com>
+
+[ Upstream commit cdf88b35e06f1b385f7f6228060ae541d44fbb72 ]
+
+Before resetting or closing the device, protocol counters should also be
+zeroed.
+
+Fixes: d0b137062b2d ("Bluetooth: hci_sync: Rework init stages")
+Signed-off-by: Heitor Alves de Siqueira <halves@igalia.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sync.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 73e429c41e17b5..277de808ebeb5a 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -5338,6 +5338,10 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+ /* Reset device */
+ skb_queue_purge(&hdev->cmd_q);
+ atomic_set(&hdev->cmd_cnt, 1);
++ hdev->acl_cnt = 0;
++ hdev->sco_cnt = 0;
++ hdev->le_cnt = 0;
++ hdev->iso_cnt = 0;
+ if (hci_test_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE) &&
+ !auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
+ set_bit(HCI_INIT, &hdev->flags);
+--
+2.53.0
+
--- /dev/null
+From dec5788e45a54c53a1973b4d0b1f946cf1667526 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 10:50:58 -0300
+Subject: Bluetooth: hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close
+
+From: Heitor Alves de Siqueira <halves@igalia.com>
+
+[ Upstream commit 525daaea459fc215f432de1b8debbd9144bf97b0 ]
+
+Since hci_dev_close_sync() can now be called during the reset path, we
+should also set HCI_CMD_DRAIN_WORKQUEUE. This avoids queuing timeouts
+while the hdev workqueue is being drained.
+
+Fixes: 877afadad2dc ("Bluetooth: When HCI work queue is drained, only queue chained work")
+Signed-off-by: Heitor Alves de Siqueira <halves@igalia.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sync.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index f498ab28f1aa06..73e429c41e17b5 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -5246,6 +5246,12 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+
+ bt_dev_dbg(hdev, "");
+
++ /* Set HCI_DRAIN_WORKQUEUE flag to prevent queuing work during
++ * reset/close. See hci_cmd_work() and handle_cmd_cnt_and_timer().
++ */
++ hci_dev_set_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
++ synchronize_rcu();
++
+ if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+ disable_delayed_work(&hdev->power_off);
+ disable_delayed_work(&hdev->ncmd_timer);
+@@ -5269,6 +5275,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+
+ if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
+ cancel_delayed_work_sync(&hdev->cmd_timer);
++ hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
+ return err;
+ }
+
+@@ -5368,6 +5375,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+ /* Clear flags */
+ hdev->flags &= BIT(HCI_RAW);
+ hci_dev_clear_volatile_flags(hdev);
++ hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
+
+ memset(hdev->eir, 0, sizeof(hdev->eir));
+ memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
+--
+2.53.0
+
--- /dev/null
+From 1aa026fff16eb15eb249ca0fd40da386c5ca0ce9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 18:51:52 +0800
+Subject: Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit 00e1950716c6ed67d74777b2db286b0fa23b4be9 ]
+
+l2cap_ecred_reconf_rsp() returns early on success without clearing
+chan->ident. Every other L2CAP response handler (l2cap_ecred_conn_rsp,
+l2cap_le_connect_rsp, l2cap_config_rsp) clears chan->ident after a
+successful transaction to prevent the channel from matching subsequent
+responses with the recycled ident value.
+
+A remote attacker that completed a reconfiguration as the peer can
+replay a failure response with the stale ident, causing the kernel to
+match and destroy the already-established channel via
+l2cap_chan_del(chan, ECONNRESET).
+
+Clear chan->ident for all matching channels on success, and harden the
+failure path by using l2cap_chan_hold_unless_zero() consistent with
+other L2CAP handlers (l2cap_le_command_rej, __l2cap_get_chan_by_ident).
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 87ebe81277c510..57f5e3c7429e79 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -5466,14 +5466,20 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("result 0x%4.4x", result);
+
+- if (!result)
++ if (!result) {
++ list_for_each_entry(chan, &conn->chan_l, list) {
++ if (chan->ident == cmd->ident)
++ chan->ident = 0;
++ }
+ return 0;
++ }
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
+ if (chan->ident != cmd->ident)
+ continue;
+
+- l2cap_chan_hold(chan);
++ if (!l2cap_chan_hold_unless_zero(chan))
++ continue;
+ l2cap_chan_lock(chan);
+
+ l2cap_chan_del(chan, ECONNRESET);
+--
+2.53.0
+
--- /dev/null
+From 4e9d3d16c00ca5768b40166cd201a5a1bf3dc7fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 May 2026 12:09:42 -0400
+Subject: Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 41c2713b204e6cb6a94587bc6bf6935107df5479 ]
+
+If dcid is received for an already-assigned destination CID the spec
+requires that both channels to be discarded, but calling l2cap_chan_del
+may invalidate the tmp cursor created by list_for_each_entry_safe and
+in fact it is the wrong procedure as the chan->dcid may be assigned
+previously it really needs to be disconnected.
+
+Calling l2cap_chan_clone directly may still lead to l2cap_chan_del so
+instead schedule l2cap_chan_timeout with delay 0 to close the channel
+asynchronously.
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 57f5e3c7429e79..9805908e6c6a06 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -5268,6 +5268,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ cmd_len -= sizeof(*rsp);
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
++ struct l2cap_chan *orig;
+ u16 dcid;
+
+ if (chan->ident != cmd->ident ||
+@@ -5289,8 +5290,10 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
+
++ orig = __l2cap_get_chan_by_dcid(conn, dcid);
++
+ /* Check if dcid is already in use */
+- if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
++ if (dcid && orig) {
+ /* If a device receives a
+ * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
+ * already-assigned Destination CID, then both the
+@@ -5299,10 +5302,24 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ */
+ l2cap_chan_del(chan, ECONNREFUSED);
+ l2cap_chan_unlock(chan);
+- chan = __l2cap_get_chan_by_dcid(conn, dcid);
+- l2cap_chan_lock(chan);
+- l2cap_chan_del(chan, ECONNRESET);
+- l2cap_chan_unlock(chan);
++
++ /* Check that the dcid channel mode is
++ * L2CAP_MODE_EXT_FLOWCTL since this procedure is only
++ * valid for that mode and shouldn't disconnect a dcid
++ * in other modes.
++ */
++ if (orig->mode == L2CAP_MODE_EXT_FLOWCTL) {
++ l2cap_chan_lock(orig);
++ /* Disconnect the original channel as it may be
++ * considered connected since dcid has already
++ * been assigned; don't call l2cap_chan_close
++ * directly since that could lead to
++ * l2cap_chan_del and then removing the channel
++ * from the list while we're iterating over it.
++ */
++ __set_chan_timer(orig, 0);
++ l2cap_chan_unlock(orig);
++ }
+ continue;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 02ee1f8764feca89889e41fbf621bb3e98a6c705 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:33:19 +0200
+Subject: bonding: refuse to enslave CAN devices
+
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+
+[ Upstream commit 8ba68464e4787b6a7ec938826e16124df20fd23d ]
+
+syzbot reported a kernel paging request crash in
+can_rx_unregister() inside net/can/af_can.c. The crash occurs
+because a virtual CAN device (vxcan) is being enslaved to a
+bonding master.
+
+During the enslavement process, the bonding driver mutates
+and modifies the network device states to fit an Ethernet-like
+aggregation model. However, CAN devices operate on a completely
+different Layer 2 architecture, relying on the CAN mid-layer
+private data structure (can_ml_priv) instead of standard
+Ethernet structures. Since bonding does not initialize or
+maintain these CAN structures, subsequent operations on the
+half-enslaved interface (such as closing associated sockets
+via isotp_release) lead to a null-pointer dereference when
+accessing the CAN receiver lists.
+
+Bonding CAN interfaces is architecturally invalid as CAN lacks
+MAC addresses, ARP capabilities, and standard Ethernet
+link-layer mechanisms. While generic loopback devices are
+blocked globally in net/core/dev.c, virtual CAN devices
+bypass this check because they do not carry the IFF_LOOPBACK
+flag, despite acting as local software-loopbacks.
+
+Fix this by explicitly blocking network devices of type
+ARPHRD_CAN from being enslaved at the very beginning of
+bond_enslave(). This prevents illegal state mutations,
+eliminates the resulting KASAN crashes, and avoids potential
+memory leaks from incomplete socket cleanups.
+
+As the CAN support has been added a long time after bonding
+the Fixes-tag points to the introduction of ARPHRD_CAN that
+would have needed a specific handling in bonding_main.c.
+
+Fixes: cd05acfe65ed ("[CAN]: Allocate protocol numbers for PF_CAN")
+Reported-by: syzbot+8ed98cbd0161632bce95@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=8ed98cbd0161632bce95
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260526-bonding-candev-v1-1-ba1df400918a@hartkopp.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 8b1422dda4c080..2132acff2e52c4 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1860,6 +1860,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
+ struct sockaddr_storage ss;
+ int res = 0, i;
+
++ if (slave_dev->type == ARPHRD_CAN) {
++ BOND_NL_ERR(bond_dev, extack,
++ "CAN devices cannot be enslaved");
++ return -EPERM;
++ }
++
+ if (slave_dev->flags & IFF_MASTER &&
+ !netif_is_bond_master(slave_dev)) {
+ BOND_NL_ERR(bond_dev, extack,
+--
+2.53.0
+
--- /dev/null
+From 7ae34c99bb03e7437c026e5634f732cfa1a3f221 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 09:48:16 +0300
+Subject: bridge: Fix sleep in atomic context in netlink path
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 5eec4427b89c2fb2beac54920101e55a2f1c0c21 ]
+
+Since the introduction of the netlink configuration path for bridge
+ports in commit 25c71c75ac87 ("bridge: bridge port parameters over
+netlink"), br_setport() was always called with the bridge lock held
+around it. Back then this decision made sense: The bridge lock protects
+the STP state of the bridge and its ports and at that time the function
+only processed three STP related netlink attributes (cost, priority and
+state).
+
+Nowadays, br_setport() processes a lot more attributes and most of them
+do not need the bridge lock:
+
+* Bridge flags: Only require RTNL. Read locklessly by the data path.
+ Annotations can be added in net-next.
+
+* FDB port flushing: Only requires the FDB lock.
+
+* Multicast attributes: Only require the multicast lock.
+
+* Group forward mask: Only requires RTNL. Read locklessly by the data
+ path. Annotations can be added in net-next.
+
+* Backup port and NHID: Only require RTNL. Read locklessly by the data
+ path.
+
+This is a problem as the bridge calls dev_set_promiscuity() when certain
+bridge port flags change and this function can sleep since the commit
+cited below, resulting in a splat such as [1].
+
+Fix this by reducing the scope of the bridge lock and only take it when
+processing the three STP related attributes that require it. This is
+consistent with the multicast attributes where each attribute acquires
+the multicast lock instead of having one critical section for all
+relevant attributes.
+
+[1]
+BUG: sleeping function called from invalid context at net/core/dev_addr_lists.c:1262
+in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 356, name: bridge
+preempt_count: 201, expected: 0
+RCU nest depth: 0, expected: 0
+2 locks held by bridge/356:
+#0: ffffffff919473a0 (rtnl_mutex){+.+.}-{4:4}, at: rtnetlink_rcv_msg (net/core/rtnetlink.c:80 net/core/rtnetlink.c:7002)
+#1: ffff888115072d58 (&br->lock){+...}-{3:3}, at: br_setlink (./include/linux/spinlock.h:348 net/bridge/br_netlink.c:1117)
+Preemption disabled at:
+ 0x0
+Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+Call Trace:
+<TASK>
+dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
+__might_resched.cold (kernel/sched/core.c:9163)
+netif_rx_mode_run (net/core/dev_addr_lists.c:1262)
+netif_rx_mode_sync (net/core/dev_addr_lists.c:1428)
+dev_set_promiscuity (net/core/dev_api.c:289)
+br_manage_promisc (net/bridge/br_if.c:135 net/bridge/br_if.c:172)
+br_port_flags_change (net/bridge/br_if.c:242 net/bridge/br_if.c:747)
+br_setport (net/bridge/br_netlink.c:1000)
+br_setlink (net/bridge/br_netlink.c:1118)
+rtnl_bridge_setlink (net/core/rtnetlink.c:5572)
+rtnetlink_rcv_msg (net/core/rtnetlink.c:7005)
+netlink_rcv_skb (net/netlink/af_netlink.c:2550)
+netlink_unicast (net/netlink/af_netlink.c:1318 net/netlink/af_netlink.c:1344)
+netlink_sendmsg (net/netlink/af_netlink.c:1894)
+__sock_sendmsg (net/socket.c:787 (discriminator 4) net/socket.c:802 (discriminator 4))
+____sys_sendmsg (net/socket.c:2698)
+___sys_sendmsg (net/socket.c:2752)
+__sys_sendmsg (net/socket.c:2784)
+do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
+entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
+
+Fixes: 78cd408356fe ("net: add missing instance lock to dev_set_promiscuity")
+Reviewed-by: Nikolay Aleksandrov <nikolay@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260526064818.272516-2-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/br_netlink.c | 17 +++++++----------
+ 1 file changed, 7 insertions(+), 10 deletions(-)
+
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
+index 4e2d53b2722104..6d5b2ef5f18d3d 100644
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -1000,19 +1000,25 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[],
+ br_port_flags_change(p, changed_mask);
+
+ if (tb[IFLA_BRPORT_COST]) {
++ spin_lock_bh(&p->br->lock);
+ err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));
++ spin_unlock_bh(&p->br->lock);
+ if (err)
+ return err;
+ }
+
+ if (tb[IFLA_BRPORT_PRIORITY]) {
++ spin_lock_bh(&p->br->lock);
+ err = br_stp_set_port_priority(p, nla_get_u16(tb[IFLA_BRPORT_PRIORITY]));
++ spin_unlock_bh(&p->br->lock);
+ if (err)
+ return err;
+ }
+
+ if (tb[IFLA_BRPORT_STATE]) {
++ spin_lock_bh(&p->br->lock);
+ err = br_set_port_state(p, nla_get_u8(tb[IFLA_BRPORT_STATE]));
++ spin_unlock_bh(&p->br->lock);
+ if (err)
+ return err;
+ }
+@@ -1114,9 +1120,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh, u16 flags,
+ if (err)
+ return err;
+
+- spin_lock_bh(&p->br->lock);
+ err = br_setport(p, tb, extack);
+- spin_unlock_bh(&p->br->lock);
+ } else {
+ /* Binary compatibility with old RSTP */
+ if (nla_len(protinfo) < sizeof(u8))
+@@ -1203,17 +1207,10 @@ static int br_port_slave_changelink(struct net_device *brdev,
+ struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+ {
+- struct net_bridge *br = netdev_priv(brdev);
+- int ret;
+-
+ if (!data)
+ return 0;
+
+- spin_lock_bh(&br->lock);
+- ret = br_setport(br_port_get_rtnl(dev), data, extack);
+- spin_unlock_bh(&br->lock);
+-
+- return ret;
++ return br_setport(br_port_get_rtnl(dev), data, extack);
+ }
+
+ static int br_port_fill_slave_info(struct sk_buff *skb,
+--
+2.53.0
+
--- /dev/null
+From ec010e21cbf9a8f3269aef3359f27e26e9969cd6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 09:48:17 +0300
+Subject: bridge: Fix sleep in atomic context in sysfs path
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 6d34594cc619d0d4b07d5afcad8b5984f3526dcf ]
+
+Since the start of the git history, brport_store() always acquired the
+bridge lock. Back then this decision made sense: The bridge lock
+protects the STP state of the bridge and its ports and at that time the
+function was only used by two STP related attributes (cost and
+priority).
+
+Nowadays, brport_store() processes a lot more attributes and most of
+them do not need the bridge lock:
+
+* Bridge flags: Only require RTNL. Read locklessly by the data path.
+ Annotations can be added in net-next.
+
+* FDB port flushing: Only requires the FDB lock.
+
+* Multicast attributes: Only require the multicast lock.
+
+* Group forward mask: Only requires RTNL. Read locklessly by the data
+ path. Annotations can be added in net-next.
+
+* Backup port: Only requires RTNL. Read locklessly by the data path.
+
+This is a problem as the bridge calls dev_set_promiscuity() when certain
+bridge port flags change and this function can sleep since the commit
+cited below, resulting in a splat such as [1].
+
+Fix this by reducing the scope of the bridge lock and only take it when
+processing the two STP related attributes that require it. Remove the
+now stale comment from br_switchdev_set_port_flag(). The
+SWITCHDEV_F_DEFER flag can be removed in net-next.
+
+[1]
+BUG: sleeping function called from invalid context at net/core/dev_addr_lists.c:1262
+in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 372, name: bash
+preempt_count: 201, expected: 0
+RCU nest depth: 0, expected: 0
+5 locks held by bash/372:
+#0: ffff88810c51c3f0 (sb_writers#7){.+.+}-{0:0}, at: ksys_write (fs/read_write.c:740)
+#1: ffff888115ce9480 (&of->mutex){+.+.}-{4:4}, at: kernfs_fop_write_iter (fs/kernfs/file.c:343)
+#2: ffff88810b9fd330 (kn->active#37){.+.+}-{0:0}, at: kernfs_fop_write_iter (fs/kernfs/file.c:80 fs/kernfs/file.c:344)
+#3: ffffffffa59473a0 (rtnl_mutex){+.+.}-{4:4}, at: brport_store (net/bridge/br_sysfs_if.c:326)
+#4: ffff8881099d2d58 (&br->lock){+...}-{3:3}, at: brport_store (./include/linux/spinlock.h:348 net/bridge/br_sysfs_if.c:345)
+Preemption disabled at:
+ 0x0
+Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+Call Trace:
+<TASK>
+dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
+__might_resched.cold (kernel/sched/core.c:9163)
+netif_rx_mode_run (net/core/dev_addr_lists.c:1262)
+netif_rx_mode_sync (net/core/dev_addr_lists.c:1428)
+dev_set_promiscuity (net/core/dev_api.c:289)
+br_manage_promisc (net/bridge/br_if.c:135 net/bridge/br_if.c:172)
+br_port_flags_change (net/bridge/br_if.c:242 net/bridge/br_if.c:747)
+store_learning (net/bridge/br_sysfs_if.c:79 net/bridge/br_sysfs_if.c:235)
+brport_store (net/bridge/br_sysfs_if.c:346)
+kernfs_fop_write_iter (fs/kernfs/file.c:352)
+new_sync_write (fs/read_write.c:595)
+vfs_write (fs/read_write.c:688)
+ksys_write (fs/read_write.c:740)
+do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
+entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
+
+Fixes: 78cd408356fe ("net: add missing instance lock to dev_set_promiscuity")
+Reviewed-by: Nikolay Aleksandrov <nikolay@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260526064818.272516-3-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/br_switchdev.c | 1 -
+ net/bridge/br_sysfs_if.c | 30 ++++++++++++++++++++++--------
+ 2 files changed, 22 insertions(+), 9 deletions(-)
+
+diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
+index fe3f7bbe86ee62..b5c6e314204f94 100644
+--- a/net/bridge/br_switchdev.c
++++ b/net/bridge/br_switchdev.c
+@@ -99,7 +99,6 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
+ attr.u.brport_flags.val = flags;
+ attr.u.brport_flags.mask = mask;
+
+- /* We run from atomic context here */
+ err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev,
+ &info.info, extack);
+ err = notifier_to_errno(err);
+diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
+index 74fdd8105dca9e..3fe664fd1f5b82 100644
+--- a/net/bridge/br_sysfs_if.c
++++ b/net/bridge/br_sysfs_if.c
+@@ -86,16 +86,34 @@ static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)
+ return sprintf(buf, "%d\n", p->path_cost);
+ }
+
+-static BRPORT_ATTR(path_cost, 0644,
+- show_path_cost, br_stp_set_path_cost);
++static int store_path_cost(struct net_bridge_port *p, unsigned long v)
++{
++ int ret;
++
++ spin_lock_bh(&p->br->lock);
++ ret = br_stp_set_path_cost(p, v);
++ spin_unlock_bh(&p->br->lock);
++ return ret;
++}
++
++static BRPORT_ATTR(path_cost, 0644, show_path_cost, store_path_cost);
+
+ static ssize_t show_priority(struct net_bridge_port *p, char *buf)
+ {
+ return sprintf(buf, "%d\n", p->priority);
+ }
+
+-static BRPORT_ATTR(priority, 0644,
+- show_priority, br_stp_set_port_priority);
++static int store_priority(struct net_bridge_port *p, unsigned long v)
++{
++ int ret;
++
++ spin_lock_bh(&p->br->lock);
++ ret = br_stp_set_port_priority(p, v);
++ spin_unlock_bh(&p->br->lock);
++ return ret;
++}
++
++static BRPORT_ATTR(priority, 0644, show_priority, store_priority);
+
+ static ssize_t show_designated_root(struct net_bridge_port *p, char *buf)
+ {
+@@ -334,17 +352,13 @@ static ssize_t brport_store(struct kobject *kobj,
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+- spin_lock_bh(&p->br->lock);
+ ret = brport_attr->store_raw(p, buf_copy);
+- spin_unlock_bh(&p->br->lock);
+ kfree(buf_copy);
+ } else if (brport_attr->store) {
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ goto out_unlock;
+- spin_lock_bh(&p->br->lock);
+ ret = brport_attr->store(p, val);
+- spin_unlock_bh(&p->br->lock);
+ }
+
+ if (!ret) {
+--
+2.53.0
+
--- /dev/null
+From 20bd511145f9c4b316a8031d166c461dbae99f6c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 20:14:57 +0800
+Subject: cxl/test: Update mock dev array before calling platform_device_add()
+
+From: Li Ming <ming.li@zohomail.com>
+
+[ Upstream commit d90f236f8b9e354848bd226f581db27755ab901d ]
+
+CXL test environment hits the following error sometimes.
+
+ cxl_mem mem9: endpoint7 failed probe
+
+All mock memdevs are platform firmware devices added by cxl_test module,
+and cxl_test module also provides a platform device driver for them to
+create a memdev device to CXL subsystem. cxl_test module uses
+cxl_rcd/mem_single/mem arrays to store different types of mock memdevs.
+CXL drivers calls registered mock functions for a mock memdev by
+checking if a given memdev is in these arrays.
+
+When cxl_test module adds these mock memdevs, it always calls
+platform_device_add() before adding them to a suitable mock memdev
+array. However, there is a small window where CXL drivers calls mock
+function for a added memdev before it added to a mock memdev array. In
+above case, cxl endpoint driver considers a added memdev was not a mock
+memdev, then calling devm_cxl_endpoint_decoders_setup() for it rather
+than mock_endpoint_decoders_setup().
+
+An appropriate solution is that adding a new mock device to a mock
+device array before calling platform_device_add() for it. It can
+guarantee the new mock device is visible to CXL subsystem.
+
+This patch introduces a new helped called cxl_mock_platform_device_add()
+to handle the issue, and uses the function for all mock devices addition.
+
+Fixes: 3a2b97b3210b ("cxl/test: Improve init-order fidelity relative to real-world systems")
+Signed-off-by: Li Ming <ming.li@zohomail.com>
+Tested-by: Alison Schofield <alison.schofield@intel.com>
+Reviewed-by: Alison Schofield <alison.schofield@intel.com>
+Link: https://patch.msgid.link/20260520121457.234404-1-ming.li@zohomail.com
+Signed-off-by: Dave Jiang <dave.jiang@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/cxl/test/cxl.c | 105 ++++++++++++++---------------------
+ 1 file changed, 43 insertions(+), 62 deletions(-)
+
+diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
+index 2d135ca533d02b..5771c75bc58893 100644
+--- a/tools/testing/cxl/test/cxl.c
++++ b/tools/testing/cxl/test/cxl.c
+@@ -1132,6 +1132,23 @@ static void mock_companion(struct acpi_device *adev, struct device *dev)
+ #define SZ_64G (SZ_32G * 2)
+ #endif
+
++static int cxl_mock_platform_device_add(struct platform_device *pdev,
++ struct platform_device **ppdev)
++{
++ int rc;
++
++ if (ppdev)
++ *ppdev = pdev;
++ rc = platform_device_add(pdev);
++ if (rc) {
++ platform_device_put(pdev);
++ if (ppdev)
++ *ppdev = NULL;
++ }
++
++ return rc;
++}
++
+ static __init int cxl_rch_topo_init(void)
+ {
+ int rc, i;
+@@ -1146,13 +1163,10 @@ static __init int cxl_rch_topo_init(void)
+ goto err_bridge;
+
+ mock_companion(adev, &pdev->dev);
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_rch[i]);
++ if (rc)
+ goto err_bridge;
+- }
+
+- cxl_rch[i] = pdev;
+ mock_pci_bus[idx].bridge = &pdev->dev;
+ rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
+ "firmware_node");
+@@ -1204,13 +1218,10 @@ static __init int cxl_single_topo_init(void)
+ goto err_bridge;
+
+ mock_companion(adev, &pdev->dev);
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_hb_single[i]);
++ if (rc)
+ goto err_bridge;
+- }
+
+- cxl_hb_single[i] = pdev;
+ mock_pci_bus[i + NR_CXL_HOST_BRIDGES].bridge = &pdev->dev;
+ rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
+ "physical_node");
+@@ -1229,12 +1240,9 @@ static __init int cxl_single_topo_init(void)
+ goto err_port;
+ pdev->dev.parent = &bridge->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_root_single[i]);
++ if (rc)
+ goto err_port;
+- }
+- cxl_root_single[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_swu_single); i++) {
+@@ -1247,12 +1255,9 @@ static __init int cxl_single_topo_init(void)
+ goto err_uport;
+ pdev->dev.parent = &root_port->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_swu_single[i]);
++ if (rc)
+ goto err_uport;
+- }
+- cxl_swu_single[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_swd_single); i++) {
+@@ -1266,12 +1271,9 @@ static __init int cxl_single_topo_init(void)
+ goto err_dport;
+ pdev->dev.parent = &uport->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_swd_single[i]);
++ if (rc)
+ goto err_dport;
+- }
+- cxl_swd_single[i] = pdev;
+ }
+
+ return 0;
+@@ -1344,12 +1346,9 @@ static int cxl_mem_init(void)
+ pdev->dev.parent = &dport->dev;
+ set_dev_node(&pdev->dev, i % 2);
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_mem[i]);
++ if (rc)
+ goto err_mem;
+- }
+- cxl_mem[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++) {
+@@ -1362,12 +1361,9 @@ static int cxl_mem_init(void)
+ pdev->dev.parent = &dport->dev;
+ set_dev_node(&pdev->dev, i % 2);
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_mem_single[i]);
++ if (rc)
+ goto err_single;
+- }
+- cxl_mem_single[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++) {
+@@ -1381,12 +1377,9 @@ static int cxl_mem_init(void)
+ pdev->dev.parent = &rch->dev;
+ set_dev_node(&pdev->dev, i % 2);
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_rcd[i]);
++ if (rc)
+ goto err_rcd;
+- }
+- cxl_rcd[i] = pdev;
+ }
+
+ return 0;
+@@ -1451,13 +1444,10 @@ static __init int cxl_test_init(void)
+ goto err_bridge;
+
+ mock_companion(adev, &pdev->dev);
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_host_bridge[i]);
++ if (rc)
+ goto err_bridge;
+- }
+
+- cxl_host_bridge[i] = pdev;
+ mock_pci_bus[i].bridge = &pdev->dev;
+ rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
+ "physical_node");
+@@ -1475,12 +1465,9 @@ static __init int cxl_test_init(void)
+ goto err_port;
+ pdev->dev.parent = &bridge->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_root_port[i]);
++ if (rc)
+ goto err_port;
+- }
+- cxl_root_port[i] = pdev;
+ }
+
+ BUILD_BUG_ON(ARRAY_SIZE(cxl_switch_uport) != ARRAY_SIZE(cxl_root_port));
+@@ -1493,12 +1480,9 @@ static __init int cxl_test_init(void)
+ goto err_uport;
+ pdev->dev.parent = &root_port->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_switch_uport[i]);
++ if (rc)
+ goto err_uport;
+- }
+- cxl_switch_uport[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++) {
+@@ -1511,12 +1495,9 @@ static __init int cxl_test_init(void)
+ goto err_dport;
+ pdev->dev.parent = &uport->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_switch_dport[i]);
++ if (rc)
+ goto err_dport;
+- }
+- cxl_switch_dport[i] = pdev;
+ }
+
+ rc = cxl_single_topo_init();
+@@ -1534,9 +1515,9 @@ static __init int cxl_test_init(void)
+ mock_companion(&acpi0017_mock, &cxl_acpi->dev);
+ acpi0017_mock.dev.bus = &platform_bus_type;
+
+- rc = platform_device_add(cxl_acpi);
++ rc = cxl_mock_platform_device_add(cxl_acpi, NULL);
+ if (rc)
+- goto err_root;
++ goto err_rch;
+
+ rc = cxl_mem_init();
+ if (rc)
+--
+2.53.0
+
--- /dev/null
+From 3e1f83ee7c1219adf3c5f51eada0ad850b451c88 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 22:05:32 +0530
+Subject: drm/xe: Restore IDLEDLY regiter on engine reset
+
+From: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
+
+[ Upstream commit f657a6a3ba4c20bc01f5be3752d53498ee1bfe35 ]
+
+Wa_16023105232 programs the register IDLEDLY. The register is reset
+whenever the engine is reset. Therefore it should be added to the GuC
+save-restore register list for it to be restored after reset.
+
+Fixes: 7c53ff050ba8 ("drm/xe: Apply Wa_16023105232")
+Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
+Link: https://patch.msgid.link/20260522163531.1365540-2-balasubramani.vivekanandan@intel.com
+Signed-off-by: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
+(cherry picked from commit df1cfe24743a93b71eab27687e148ab8ae9b69e3)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_guc_ads.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c
+index 0e2bece1d8b83b..db71823b253801 100644
+--- a/drivers/gpu/drm/xe/xe_guc_ads.c
++++ b/drivers/gpu/drm/xe/xe_guc_ads.c
+@@ -772,6 +772,11 @@ static unsigned int guc_mmio_regset_write(struct xe_guc_ads *ads,
+ }
+ }
+
++ if (XE_GT_WA(hwe->gt, 16023105232))
++ guc_mmio_regset_write_one(ads, regset_map,
++ RING_IDLEDLY(hwe->mmio_base),
++ count++);
++
+ return count;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 71887194c285cba821f41e7f6293a7dbf281b6a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:10 -0700
+Subject: ethtool: cmis: fix u16-to-u8 truncation of msleep_pre_rpl
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 3e8c3d464c36bb342fe377b026577c7ec27fdbb4 ]
+
+ethtool_cmis_cdb_compose_args() accepts msleep_pre_rpl as u16 but stores
+it into the u8 field ethtool_cmis_cdb_cmd_args::msleep_pre_rpl, silently
+truncating values >= 256. Seven of the nine call sites pass 1000 ms
+(it's the third argument from the end).
+
+Fixes: a39c84d79625 ("ethtool: cmis_cdb: Add a layer for supporting CDB commands")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-8-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/cmis.h b/net/ethtool/cmis.h
+index 4a9a946cabf05d..778783a0f23c0b 100644
+--- a/net/ethtool/cmis.h
++++ b/net/ethtool/cmis.h
+@@ -63,9 +63,9 @@ struct ethtool_cmis_cdb_request {
+ * struct ethtool_cmis_cdb_cmd_args - CDB commands execution arguments
+ * @req: CDB command fields as described in the CMIS standard.
+ * @max_duration: Maximum duration time for command completion in msec.
++ * @msleep_pre_rpl: Waiting time before checking reply in msec.
+ * @read_write_len_ext: Allowable additional number of byte octets to the LPL
+ * in a READ or a WRITE commands.
+- * @msleep_pre_rpl: Waiting time before checking reply in msec.
+ * @rpl_exp_len: Expected reply length in bytes.
+ * @flags: Validation flags for CDB commands.
+ * @err_msg: Error message to be sent to user space.
+@@ -73,8 +73,8 @@ struct ethtool_cmis_cdb_request {
+ struct ethtool_cmis_cdb_cmd_args {
+ struct ethtool_cmis_cdb_request req;
+ u16 max_duration;
++ u16 msleep_pre_rpl;
+ u8 read_write_len_ext;
+- u8 msleep_pre_rpl;
+ u8 rpl_exp_len;
+ u8 flags;
+ char *err_msg;
+--
+2.53.0
+
--- /dev/null
+From 01f3878a50dcd39f1707981a3568bc4e9a42a228 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:09 -0700
+Subject: ethtool: cmis: require exact CDB reply length
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 6c3f999a9d1338c6c89a9ff4549eafe72bc2e7b1 ]
+
+Malicious SFP module could respond with rpl_len longer than
+what cmis_cdb_process_reply() expected, leading to OOB writes.
+Malicious HW is a bit theoretical but some modules may just
+be buggy and/or the reads may occasionally get corrupted,
+so let's protect the kernel.
+
+The existing check protects from short replies. We need to
+protect from long ones, too. All callers that pass a non-zero
+rpl_exp_len cast the reply payload to a fixed-layout struct
+and read fields at fixed offsets, with no version negotiation
+or short-reply handling:
+
+ - cmis_cdb_validate_password()
+ - cmis_cdb_module_features_get()
+ - cmis_fw_update_fw_mng_features_get()
+
+so let's assume that responses longer than expected do not
+have to be handled gracefully here. Add a warning message
+to make the debug easier in case my understanding is wrong...
+
+Note that page_data->length (argument of kmalloc) comes from
+last arg to ethtool_cmis_page_init() which is rpl_exp_len.
+
+Note2 that AIs also like to point out overflows in args->req.payload
+itself (which is a fixed-size 120 B buffer, on the stack),
+but callers should be reading structs defined by the standard,
+so protecting from requests for more data than max seem like
+defensive programming.
+
+Fixes: a39c84d79625 ("ethtool: cmis_cdb: Add a layer for supporting CDB commands")
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-7-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis_cdb.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/cmis_cdb.c b/net/ethtool/cmis_cdb.c
+index 3057576bc81e3d..fe156991d0becd 100644
+--- a/net/ethtool/cmis_cdb.c
++++ b/net/ethtool/cmis_cdb.c
+@@ -513,8 +513,13 @@ static int cmis_cdb_process_reply(struct net_device *dev,
+ }
+
+ rpl = (struct ethtool_cmis_cdb_rpl *)page_data->data;
+- if ((args->rpl_exp_len > rpl->hdr.rpl_len + rpl_hdr_len) ||
+- !rpl->hdr.rpl_chk_code) {
++ if (rpl->hdr.rpl_len != args->rpl_exp_len) {
++ netdev_warn(dev, "CDB reply length mismatch, expected %u got %u\n",
++ args->rpl_exp_len, rpl->hdr.rpl_len);
++ err = -EIO;
++ goto out;
++ }
++ if (!rpl->hdr.rpl_chk_code) {
+ err = -EIO;
+ goto out;
+ }
+--
+2.53.0
+
--- /dev/null
+From 394f6b454fc4397492d529895d2821cd9ad0418c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:12 -0700
+Subject: ethtool: cmis: validate fw->size against start_cmd_payload_size
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit d5551f4c1800dc714cec86647bdd651ae0de923e ]
+
+cmis_fw_update_start_download() copies start_cmd_payload_size bytes
+from the firmware blob into the CDB LPL vendor_data[] payload without
+validating that the FW has enough data.
+
+Since the start_cmd_payload_size can only be ~120B an image too short
+is most likely corrupted, so reject it.
+
+Fixes: c4f78134d45c ("ethtool: cmis_fw_update: add a layer for supporting firmware update using CDB")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-10-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis_fw_update.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/net/ethtool/cmis_fw_update.c b/net/ethtool/cmis_fw_update.c
+index 16190c97e1f78c..291d04d2776a5c 100644
+--- a/net/ethtool/cmis_fw_update.c
++++ b/net/ethtool/cmis_fw_update.c
+@@ -130,6 +130,14 @@ cmis_fw_update_start_download(struct ethtool_cmis_cdb *cdb,
+ u8 lpl_len;
+ int err;
+
++ if (fw_update->fw->size < vendor_data_size) {
++ ethnl_module_fw_flash_ntf_err(fw_update->dev,
++ &fw_update->ntf_params,
++ "Firmware image too small for module's start payload",
++ NULL);
++ return -EINVAL;
++ }
++
+ pl.image_size = cpu_to_be32(fw_update->fw->size);
+ memcpy(pl.vendor_data, fw_update->fw->data, vendor_data_size);
+
+--
+2.53.0
+
--- /dev/null
+From d92ba0160dd4d91dd6678261f64f5ed7fd6b6b24 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:11 -0700
+Subject: ethtool: cmis: validate start_cmd_payload_size from module
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 12c2496a71f82f63617971ca9b730dffa05cf58b ]
+
+The CMIS firmware update code reads start_cmd_payload_size from
+the module's FW Management Features CDB reply and uses it directly
+as the byte count for memcpy. The destination buffer is 112 bytes
+(ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH - 8). So a malicious
+module (or corrupted response) can cause a OOB write later on in
+cmis_fw_update_start_download().
+
+Let's error out. If modules that expect longer LPL writes actually
+exist we should revisit.
+
+struct cmis_cdb_start_fw_download_pl's definition has to move,
+no change there.
+
+Fixes: c4f78134d45c ("ethtool: cmis_fw_update: add a layer for supporting firmware update using CDB")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-9-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis_fw_update.c | 36 ++++++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 14 deletions(-)
+
+diff --git a/net/ethtool/cmis_fw_update.c b/net/ethtool/cmis_fw_update.c
+index df5f344209c47b..16190c97e1f78c 100644
+--- a/net/ethtool/cmis_fw_update.c
++++ b/net/ethtool/cmis_fw_update.c
+@@ -44,6 +44,20 @@ enum cmis_cdb_fw_write_mechanism {
+ CMIS_CDB_FW_WRITE_MECHANISM_BOTH = 0x11,
+ };
+
++/* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
++ * revision 5.2.
++ * struct cmis_cdb_start_fw_download_pl is a structured layout of the
++ * flat array, ethtool_cmis_cdb_request::payload.
++ */
++struct cmis_cdb_start_fw_download_pl {
++ __struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */,
++ __be32 image_size;
++ __be32 resv1;
++ );
++ u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH -
++ sizeof(struct cmis_cdb_start_fw_download_pl_h)];
++};
++
+ static int
+ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ struct net_device *dev,
+@@ -86,6 +100,14 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ */
+ cdb->read_write_len_ext = rpl->read_write_len_ext;
+ fw_mng->start_cmd_payload_size = rpl->start_cmd_payload_size;
++ if (fw_mng->start_cmd_payload_size >
++ sizeof_field(struct cmis_cdb_start_fw_download_pl, vendor_data)) {
++ ethnl_module_fw_flash_ntf_err(dev, ntf_params,
++ "Start cmd payload size exceeds max LPL payload",
++ NULL);
++ return -EINVAL;
++ }
++
+ fw_mng->write_mechanism =
+ rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL ?
+ CMIS_CDB_FW_WRITE_MECHANISM_LPL :
+@@ -97,20 +119,6 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ return 0;
+ }
+
+-/* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
+- * revision 5.2.
+- * struct cmis_cdb_start_fw_download_pl is a structured layout of the
+- * flat array, ethtool_cmis_cdb_request::payload.
+- */
+-struct cmis_cdb_start_fw_download_pl {
+- __struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */,
+- __be32 image_size;
+- __be32 resv1;
+- );
+- u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH -
+- sizeof(struct cmis_cdb_start_fw_download_pl_h)];
+-};
+-
+ static int
+ cmis_fw_update_start_download(struct ethtool_cmis_cdb *cdb,
+ struct ethtool_cmis_fw_update_params *fw_update,
+--
+2.53.0
+
--- /dev/null
+From 58d233b2ebb5dc1d314c3abf33a320e45d6294f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:24 -0700
+Subject: ethtool: coalesce: cap profile updates at NET_DIM_PARAMS_NUM_PROFILES
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 7281b096b072f6c6e30420e3467d738f2e4c4b57 ]
+
+ethnl_update_profile() walks the ETHTOOL_A_PROFILE_IRQ_MODERATION
+nest list with an index 'i' and writes new_profile[i++] without
+bounding i. The destination is kmemdup()'d at NET_DIM_PARAMS_NUM_PROFILES
+entries (5), but the Netlink nest count is entirely user-controlled.
+Netlink policies do not have support for constraining the number
+of nested entries (or number of multi-attr entries).
+
+Fixes: f750dfe825b9 ("ethtool: provide customized dim profile management")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-2-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/coalesce.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/net/ethtool/coalesce.c b/net/ethtool/coalesce.c
+index 3e18ca1ccc5ef6..cace02d964cb21 100644
+--- a/net/ethtool/coalesce.c
++++ b/net/ethtool/coalesce.c
+@@ -463,6 +463,12 @@ static int ethnl_update_profile(struct net_device *dev,
+
+ nla_for_each_nested_type(nest, ETHTOOL_A_PROFILE_IRQ_MODERATION,
+ nests, rem) {
++ if (i >= NET_DIM_PARAMS_NUM_PROFILES) {
++ NL_SET_BAD_ATTR(extack, nest);
++ ret = -E2BIG;
++ goto err_out;
++ }
++
+ ret = nla_parse_nested(tb, len_irq_moder - 1, nest,
+ coalesce_irq_moderation_policy,
+ extack);
+--
+2.53.0
+
--- /dev/null
+From 637d92e057c693b4597c17b89fe97155723406b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:32 -0700
+Subject: ethtool: eeprom: add missing ethnl_ops_begin() / _complete() during
+ fallback
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 2376586f85f972fefe701f095bb37dcfe7405d21 ]
+
+All ethtool driver op calls should be sandwiched between
+ethnl_ops_begin() / ethnl_ops_complete(). In Netlink eeprom code,
+if the paged access failed we fall back to old API, but we
+first call _complete() and the fallback never does its own
+ethnl_ops_begin(). Move the fallback into the _begin() / _complete()
+section.
+
+Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-10-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/eeprom.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c
+index 3b8209e930fd3a..03cb418a15823b 100644
+--- a/net/ethtool/eeprom.c
++++ b/net/ethtool/eeprom.c
+@@ -140,12 +140,11 @@ static int eeprom_prepare_data(const struct ethnl_req_info *req_base,
+ return 0;
+
+ err_ops:
++ if (ret == -EOPNOTSUPP)
++ ret = eeprom_fallback(request, reply);
+ ethnl_ops_complete(dev);
+ err_free:
+ kfree(page_data.data);
+-
+- if (ret == -EOPNOTSUPP)
+- return eeprom_fallback(request, reply);
+ return ret;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 32e6a7649ddbbac971ff8af78da3dfb63e930df2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:33 -0700
+Subject: ethtool: eeprom: add more safeties to EEPROM Netlink fallback
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 67cfdd9210b99f260b3e0afeb9525e0acc7be31e ]
+
+The Netlink fallback path for reading module EEPROM
+(fallback_set_params()) validates that offset < eeprom_len,
+but does not check that offset + length stays within eeprom_len.
+The ioctl equivalent (ethtool_get_any_eeprom() in ioctl.c) has
+always enforced both bounds:
+
+ if (eeprom.offset + eeprom.len > total_len)
+ return -EINVAL;
+
+This could lead to surprises in both drivers and device FW.
+Add the missing offset + length validation to fallback_set_params(),
+mirroring the ioctl.
+
+Similarly - ethtool core in general, and ethtool_get_any_eeprom()
+in particular tries to zero-init all buffers passed to the drivers
+to avoid any extra work of zeroing things out. eeprom_fallback()
+uses a plain kmalloc(), change it to zalloc.
+
+Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-11-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/eeprom.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c
+index 03cb418a15823b..80af38a6c76acf 100644
+--- a/net/ethtool/eeprom.c
++++ b/net/ethtool/eeprom.c
+@@ -43,6 +43,9 @@ static int fallback_set_params(struct eeprom_req_info *request,
+ if (offset >= modinfo->eeprom_len)
+ return -EINVAL;
+
++ if (length > modinfo->eeprom_len - offset)
++ return -EINVAL;
++
+ eeprom->cmd = ETHTOOL_GMODULEEEPROM;
+ eeprom->len = length;
+ eeprom->offset = offset;
+@@ -68,7 +71,7 @@ static int eeprom_fallback(struct eeprom_req_info *request,
+ if (err < 0)
+ return err;
+
+- data = kmalloc(eeprom.len, GFP_KERNEL);
++ data = kzalloc(eeprom.len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ err = ethtool_get_module_eeprom_call(dev, &eeprom, data);
+--
+2.53.0
+
--- /dev/null
+From 2f4548a2f2a530b33e8fcdf0f35b07c310a7ccd4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:26 -0700
+Subject: ethtool: linkstate: fix unbalanced ethnl_ops_complete() on PHY lookup
+ error
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 596c51ed9e125b12c4d85b4530dfd4c7847634b7 ]
+
+linkstate_prepare_data() calls ethnl_req_get_phydev() before
+ethnl_ops_begin(), but routes its error path through "goto out"
+which calls ethnl_ops_complete().
+
+Fixes: fe55b1d401c6 ("ethtool: linkstate: migrate linkstate functions to support multi-PHY setups")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-4-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/linkstate.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c
+index 05a5f72c99fab1..3dc52a39d34525 100644
+--- a/net/ethtool/linkstate.c
++++ b/net/ethtool/linkstate.c
+@@ -105,10 +105,8 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
+
+ phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_LINKSTATE_HEADER,
+ info->extack);
+- if (IS_ERR(phydev)) {
+- ret = PTR_ERR(phydev);
+- goto out;
+- }
++ if (IS_ERR(phydev))
++ return PTR_ERR(phydev);
+
+ ret = ethnl_ops_begin(dev);
+ if (ret < 0)
+--
+2.53.0
+
--- /dev/null
+From 0f4d67c484013322a6f85a0b0c9379a1e18bc8f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:05 -0700
+Subject: ethtool: module: avoid leaking a netdev ref on module flash errors
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit fb7f511d62692661846c47f199e0afe25c2982db ]
+
+module_flash_fw_schedule() is missing undo for setting
+the "in_progress" flag and taking the netdev reference.
+Delay taking these, the device can't disappear while
+we are holding rtnl_lock.
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-3-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index 05e4c1d785656f..fb61bb47083e62 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -319,8 +319,6 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
+ if (err < 0)
+ goto err_release_firmware;
+
+- dev->ethtool->module_fw_flash_in_progress = true;
+- netdev_hold(dev, &module_fw->dev_tracker, GFP_KERNEL);
+ fw_update->dev = dev;
+ fw_update->ntf_params.portid = info->snd_portid;
+ fw_update->ntf_params.seq = info->snd_seq;
+@@ -335,6 +333,9 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
+ if (err < 0)
+ goto err_release_firmware;
+
++ dev->ethtool->module_fw_flash_in_progress = true;
++ netdev_hold(dev, &module_fw->dev_tracker, GFP_KERNEL);
++
+ schedule_work(&module_fw->work);
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 258ac0ffb852706b67725a68707387bdd7327d6f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:06 -0700
+Subject: ethtool: module: avoid racy updates to dev->ethtool bitfield
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 7a84b965ffc12030af63cd10a8f3a1123ff39b7a ]
+
+When reviewing other changes Gemini points out that we currently
+update module_fw_flash_in_progress without holding any locks.
+Since module_fw_flash_in_progress is part of a bitfield this
+is not great, updates to other fields may be lost.
+
+We could use a bool and sprinkle some READ_ONCE/WRITE_ONCE here
+but seems like the issue is rather than the work is an unusual
+writer. The other writers already hold the right locks. So just
+very briefly take these locks when the work completes.
+
+Note that nothing ever cancels the FW update work, so there's
+no concern with deadlocks vs cancel.
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-4-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index fb61bb47083e62..8929b7fb2fa79c 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -221,14 +221,22 @@ static void module_flash_fw_work_list_del(struct list_head *list)
+ static void module_flash_fw_work(struct work_struct *work)
+ {
+ struct ethtool_module_fw_flash *module_fw;
++ struct net_device *dev;
+
+ module_fw = container_of(work, struct ethtool_module_fw_flash, work);
++ dev = module_fw->fw_update.dev;
+
+ ethtool_cmis_fw_update(&module_fw->fw_update);
+
+ module_flash_fw_work_list_del(&module_fw->list);
+- module_fw->fw_update.dev->ethtool->module_fw_flash_in_progress = false;
+- netdev_put(module_fw->fw_update.dev, &module_fw->dev_tracker);
++
++ rtnl_lock();
++ netdev_lock_ops(dev);
++ dev->ethtool->module_fw_flash_in_progress = false;
++ netdev_unlock_ops(dev);
++ rtnl_unlock();
++
++ netdev_put(dev, &module_fw->dev_tracker);
+ release_firmware(module_fw->fw_update.fw);
+ kfree(module_fw);
+ }
+--
+2.53.0
+
--- /dev/null
+From e477c2b51f6eba050ce3a011a7f097ff75cbe261 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:04 -0700
+Subject: ethtool: module: call ethnl_ops_complete() on module flash errors
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 84371fb58423f997939aacdcbc02d128d76a54e5 ]
+
+When validate() fails we are skipping over ethnl_ops_complete()
+even tho we already called ethnl_ops_begin().
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-2-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index 4d4e0a82579a2b..05e4c1d785656f 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -427,10 +427,11 @@ int ethnl_act_module_fw_flash(struct sk_buff *skb, struct genl_info *info)
+
+ ret = ethnl_module_fw_flash_validate(dev, info->extack);
+ if (ret < 0)
+- goto out_unlock;
++ goto out_complete;
+
+ ret = module_flash_fw(dev, tb, skb, info);
+
++out_complete:
+ ethnl_ops_complete(dev);
+
+ out_unlock:
+--
+2.53.0
+
--- /dev/null
+From 6824894de8ebb2942bcfc2ea19ca807cd75c3800 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:07 -0700
+Subject: ethtool: module: check fw_flash_in_progress under rtnl_lock
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 504eaefa44c8dec50f7499edcb36d24f3aefab2a ]
+
+ethnl_set_module_validate() inspects module_fw_flash_in_progress
+but validate is meant for _input_ validation, not state validation.
+rtnl_lock is not held, yet. Move the check into ethnl_set_module().
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-5-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index 8929b7fb2fa79c..202e4c25280a76 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -120,12 +120,6 @@ ethnl_set_module_validate(struct ethnl_req_info *req_info,
+ if (!tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY])
+ return 0;
+
+- if (req_info->dev->ethtool->module_fw_flash_in_progress) {
+- NL_SET_ERR_MSG(info->extack,
+- "Module firmware flashing is in progress");
+- return -EBUSY;
+- }
+-
+ if (!ops->get_module_power_mode || !ops->set_module_power_mode) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY],
+@@ -148,6 +142,12 @@ ethnl_set_module(struct ethnl_req_info *req_info, struct genl_info *info)
+
+ ops = dev->ethtool_ops;
+
++ if (dev->ethtool->module_fw_flash_in_progress) {
++ NL_SET_ERR_MSG(info->extack,
++ "Module firmware flashing is in progress");
++ return -EBUSY;
++ }
++
+ power_new.policy = nla_get_u8(tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]);
+ ret = ops->get_module_power_mode(dev, &power, info->extack);
+ if (ret < 0)
+--
+2.53.0
+
--- /dev/null
+From 632e6a08d5eb4ad328ab4ac446b37bf5bd72ffc7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:08 -0700
+Subject: ethtool: module: fix cleanup if socket used for flashing multiple
+ devices
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 760d04ebad5c4304f22c0d2251c9623b87a117c8 ]
+
+When a single Netlink socket issues MODULE_FW_FLASH_ACT against multiple
+devices, ethnl_sock_priv_set() overwrites sk_priv->dev on each call,
+retaining only the last one. The socket priv is used on socket close,
+to walk the global work list and mark the uncompleted flashing work
+as "orphaned". Otherwise if another socket reuses the PID it will
+unexpectedly receive the flashing notifications.
+
+Don't record the device, record net pointer instead. The purpose of
+the dev is to scope the work to a netns, anyway. If we store netns
+the overrides are safe/a nop since all flashed devices must be in
+the same netns as the socket.
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-6-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 9 ++++-----
+ net/ethtool/netlink.c | 4 ++--
+ net/ethtool/netlink.h | 4 ++--
+ 3 files changed, 8 insertions(+), 9 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index 202e4c25280a76..9a11e7def0029a 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -291,11 +291,9 @@ void ethnl_module_fw_flash_sock_destroy(struct ethnl_sock_priv *sk_priv)
+
+ spin_lock(&module_fw_flash_work_list_lock);
+ list_for_each_entry(work, &module_fw_flash_work_list, list) {
+- if (work->fw_update.dev == sk_priv->dev &&
+- work->fw_update.ntf_params.portid == sk_priv->portid) {
++ if (work->fw_update.ntf_params.portid == sk_priv->portid &&
++ dev_net(work->fw_update.dev) == sk_priv->net)
+ work->fw_update.ntf_params.closed_sock = true;
+- break;
+- }
+ }
+ spin_unlock(&module_fw_flash_work_list_lock);
+ }
+@@ -332,7 +330,8 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
+ fw_update->ntf_params.seq = info->snd_seq;
+ fw_update->ntf_params.closed_sock = false;
+
+- err = ethnl_sock_priv_set(skb, dev, fw_update->ntf_params.portid,
++ err = ethnl_sock_priv_set(skb, dev_net(dev),
++ fw_update->ntf_params.portid,
+ ETHTOOL_SOCK_TYPE_MODULE_FW_FLASH);
+ if (err < 0)
+ goto err_release_firmware;
+diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
+index 2f813f25f07e1a..28577b878fd5b5 100644
+--- a/net/ethtool/netlink.c
++++ b/net/ethtool/netlink.c
+@@ -52,7 +52,7 @@ const struct nla_policy ethnl_header_policy_phy_stats[] = {
+ [ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1),
+ };
+
+-int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
++int ethnl_sock_priv_set(struct sk_buff *skb, struct net *net, u32 portid,
+ enum ethnl_sock_type type)
+ {
+ struct ethnl_sock_priv *sk_priv;
+@@ -61,7 +61,7 @@ int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
+ if (IS_ERR(sk_priv))
+ return PTR_ERR(sk_priv);
+
+- sk_priv->dev = dev;
++ sk_priv->net = net;
+ sk_priv->portid = portid;
+ sk_priv->type = type;
+
+diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
+index 1d4f9ecb3d263b..3923188097ac0a 100644
+--- a/net/ethtool/netlink.h
++++ b/net/ethtool/netlink.h
+@@ -318,12 +318,12 @@ enum ethnl_sock_type {
+ };
+
+ struct ethnl_sock_priv {
+- struct net_device *dev;
++ struct net *net;
+ u32 portid;
+ enum ethnl_sock_type type;
+ };
+
+-int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
++int ethnl_sock_priv_set(struct sk_buff *skb, struct net *net, u32 portid,
+ enum ethnl_sock_type type);
+
+ /**
+--
+2.53.0
+
--- /dev/null
+From 3cb77c4b69f235db9db4b6d178c7d4db595a5466 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:27 -0700
+Subject: ethtool: pse-pd: fix missing ethnl_ops_complete()
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit ab5bf428fb6bd361163c7247b92750d1d24ca2ed ]
+
+pse_prepare_data() is missing ethnl_ops_complete() if
+ethnl_req_get_phydev() returned an error. Move getting
+phydev up so that we don't have to worry about this
+(similar order to linkstate_prepare_data()).
+
+Note that phydev may still be NULL (this is checked in
+pse_get_pse_attributes()), the goal isn't really to avoid
+the _begin() / _complete() calls, only to simplify the error
+handling.
+
+While at it propagate the original error. Why this code
+overrides the error with -ENODEV but !phydev generates
+-EOPNOTSUPP is unclear to me...
+
+Fixes: 31748765bed3 ("net: ethtool: pse-pd: Target the command to the requested PHY")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-5-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/pse-pd.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c
+index 24def9c9dd54bf..aa4514333d13bd 100644
+--- a/net/ethtool/pse-pd.c
++++ b/net/ethtool/pse-pd.c
+@@ -61,14 +61,14 @@ static int pse_prepare_data(const struct ethnl_req_info *req_base,
+ struct phy_device *phydev;
+ int ret;
+
+- ret = ethnl_ops_begin(dev);
+- if (ret < 0)
+- return ret;
+-
+ phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PSE_HEADER,
+ info->extack);
+ if (IS_ERR(phydev))
+- return -ENODEV;
++ return PTR_ERR(phydev);
++
++ ret = ethnl_ops_begin(dev);
++ if (ret < 0)
++ return ret;
+
+ ret = pse_get_pse_attributes(phydev, info->extack, data);
+
+--
+2.53.0
+
--- /dev/null
+From 2b6a324a6092ff341b79d75115a7d89ebf559b74 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:43 -0700
+Subject: ethtool: rss: add missing errno on RSS context delete
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 3e6c6e9782ff8a8d8ded774b07ad4590cd61d04c ]
+
+Remember to set ret before jumping out if someone tries
+to delete a context on a device which doesn't support
+contexts.
+
+Fixes: fbe09277fa63 ("ethtool: rss: support removing contexts via Netlink")
+Link: https://patch.msgid.link/20260522230647.1705600-3-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index 926be5698ba4cc..688c0e4bba69db 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -1160,8 +1160,10 @@ int ethnl_rss_delete_doit(struct sk_buff *skb, struct genl_info *info)
+ dev = req.dev;
+ ops = dev->ethtool_ops;
+
+- if (!ops->create_rxfh_context)
++ if (!ops->create_rxfh_context) {
++ ret = -EOPNOTSUPP;
+ goto exit_free_dev;
++ }
+
+ rtnl_lock();
+ netdev_lock_ops(dev);
+--
+2.53.0
+
--- /dev/null
+From 1b9d6536f1f48649c5b2f13cc9342ad80b9e35c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:47 -0700
+Subject: ethtool: rss: avoid device context leak on reply-build failure
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 32a9ecde62731c9f7412507709192c84dafc38d1 ]
+
+We wait with filling the reply for new RSS context creation
+until after the driver ->create_rxfh_context call. The driver
+needs to fill some of the defaults in the context. The failure
+of rss_fill_reply() is somewhat theoretical, but doesn't take
+much effort to handle it properly. Call ->remove_rxfh_context().
+
+If the driver's remove callback fails (some implementations like sfc
+can return real command errors from firmware RPCs) - skip the xa_erase
+and kfree, leaving the context in the xarray. This matches how
+ethnl_rss_delete_doit() behaves.
+
+Fixes: a166ab7816c5 ("ethtool: rss: support creating contexts via Netlink")
+Link: https://patch.msgid.link/20260522230647.1705600-7-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index f745ddec6fbab8..b122f67dbde1d6 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -1096,7 +1096,7 @@ int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info)
+ ntf_fail |= rss_fill_reply(rsp, &req.base, &data.base);
+ if (WARN_ON(!hdr || ntf_fail)) {
+ ret = -EMSGSIZE;
+- goto exit_unlock;
++ goto err_remove_ctx;
+ }
+
+ genlmsg_end(rsp, hdr);
+@@ -1124,6 +1124,10 @@ int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info)
+ nlmsg_free(rsp);
+ return ret;
+
++err_remove_ctx:
++ if (ops->remove_rxfh_context(dev, ctx, req.rss_context, NULL))
++ /* leave the context on failure, like ethnl_rss_delete_doit() */
++ goto exit_unlock;
+ err_ctx_id_free:
+ xa_erase(&dev->ethtool->rss_ctx, req.rss_context);
+ err_unlock_free_ctx:
+--
+2.53.0
+
--- /dev/null
+From a6b2877500f8710ed43af00422686dd004d58627 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:42 -0700
+Subject: ethtool: rss: avoid modifying the RSS context response
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit c75b6f6eaacd0b74b832414cc3b9289c3686e941 ]
+
+Gemini says that we're modifying the RSS_CREATE response skb.
+I think it's right, the comment says that unicast() should
+unshare the skb but I'm not entirely sure what I meant there.
+netlink_trim() does a copy but only if skb is not well sized
+(it's at least 2x larger than necessary for the payload).
+
+Fixes: a166ab7816c5 ("ethtool: rss: support creating contexts via Netlink")
+Link: https://patch.msgid.link/20260522230647.1705600-2-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index da5934cceb0757..926be5698ba4cc 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -974,11 +974,17 @@ ethnl_rss_create_validate(struct net_device *dev, struct genl_info *info)
+ }
+
+ static void
+-ethnl_rss_create_send_ntf(struct sk_buff *rsp, struct net_device *dev)
++ethnl_rss_create_send_ntf(const struct sk_buff *rsp, struct net_device *dev)
+ {
+- struct nlmsghdr *nlh = (void *)rsp->data;
+ struct genlmsghdr *genl_hdr;
++ struct nlmsghdr *nlh;
++ struct sk_buff *ntf;
++
++ ntf = skb_copy_expand(rsp, 0, 0, GFP_KERNEL);
++ if (!ntf)
++ return;
+
++ nlh = nlmsg_hdr(ntf);
+ /* Convert the reply into a notification */
+ nlh->nlmsg_pid = 0;
+ nlh->nlmsg_seq = ethnl_bcast_seq_next();
+@@ -986,7 +992,7 @@ ethnl_rss_create_send_ntf(struct sk_buff *rsp, struct net_device *dev)
+ genl_hdr = nlmsg_data(nlh);
+ genl_hdr->cmd = ETHTOOL_MSG_RSS_CREATE_NTF;
+
+- ethnl_multicast(rsp, dev);
++ ethnl_multicast(ntf, dev);
+ }
+
+ int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info)
+@@ -1094,12 +1100,8 @@ int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info)
+
+ genlmsg_end(rsp, hdr);
+
+- /* Use the same skb for the response and the notification,
+- * genlmsg_reply() will copy the skb if it has elevated user count.
+- */
+- skb_get(rsp);
+- ret = genlmsg_reply(rsp, info);
+ ethnl_rss_create_send_ntf(rsp, dev);
++ ret = genlmsg_reply(rsp, info);
+ rsp = NULL;
+
+ exit_unlock:
+--
+2.53.0
+
--- /dev/null
+From e877edeca867eba255eda621fc0c9b87fe8ab13c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:44 -0700
+Subject: ethtool: rss: fix falsely ignoring indir table updates
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 8d60141a32875248ef71d49c9920fa5e2aa40b29 ]
+
+rss_set_prep_indir() compares the new indirection table against the
+current one to determine whether any update is needed. The memcmp
+call passes data->indir_size as the length argument, but indir_size
+is the number of u32 entries, not the byte count.
+
+Fixes: c0ae03588bbb ("ethtool: rss: initial RSS_SET (indirection table handling)")
+Link: https://patch.msgid.link/20260522230647.1705600-4-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index 688c0e4bba69db..4877655f724419 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -684,7 +684,7 @@ rss_set_prep_indir(struct net_device *dev, struct genl_info *info,
+ ethtool_rxfh_indir_default(i, num_rx_rings);
+ }
+
+- *mod |= memcmp(rxfh->indir, data->indir_table, data->indir_size);
++ *mod |= memcmp(rxfh->indir, data->indir_table, alloc_size);
+
+ return 0;
+
+--
+2.53.0
+
--- /dev/null
+From b52bc769fa7c9519a6067d3916c55c8b43371999 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:46 -0700
+Subject: ethtool: rss: fix hkey leak when indir_size is 0
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 78ccf1a70c6378e1f5073a8c2209b5129067b925 ]
+
+rss_get_data_alloc() allocates a single buffer that backs both the
+indirection table and the hash key, but only assigned data->indir_table
+when indir_size was nonzero. The expectation was that no driver
+implements RSS without supporting indirection table but apparently
+enic does just that (it's the only such in-tree driver).
+enic has get_rxfh_key_size but no get_rxfh_indir_size.
+data->indir_table stays as NULL, hkey gets set but rss_get_data_free()
+kfree(data->indir_table) is a nop and the allocation leaks.
+
+Always store the allocation base in data->indir_table so the free path
+is unambiguous. No caller treats indir_table as a sentinel; everything
+keys off indir_size.
+
+Fixes: 7112a04664bf ("ethtool: add netlink based get rss support")
+Link: https://patch.msgid.link/20260522230647.1705600-6-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index 5416aec13b7fe7..f745ddec6fbab8 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -132,8 +132,7 @@ rss_get_data_alloc(struct net_device *dev, struct rss_reply_data *data)
+ if (!rss_config)
+ return -ENOMEM;
+
+- if (data->indir_size)
+- data->indir_table = (u32 *)rss_config;
++ data->indir_table = (u32 *)rss_config;
+ if (data->hkey_size)
+ data->hkey = rss_config + indir_bytes;
+
+--
+2.53.0
+
--- /dev/null
+From 321c11d7e8206244e7a8a8b27c735a5fe32acc09 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:45 -0700
+Subject: ethtool: rss: fix indir_table and hkey leak on get_rxfh failure
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 266297692f97008ca48bc311775c087c59bd7fe3 ]
+
+rss_prepare_get() allocates the indirection table and hash key buffer
+via rss_get_data_alloc(), then calls ops->get_rxfh() to populate them.
+If get_rxfh() fails, the function returns an error without freeing
+the allocation.
+
+Fixes: 4f038a6a02d2 ("net: ethtool: Don't call .cleanup_data when prepare_data fails")
+Link: https://patch.msgid.link/20260522230647.1705600-5-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index 4877655f724419..5416aec13b7fe7 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -168,8 +168,10 @@ rss_prepare_get(const struct rss_req_info *request, struct net_device *dev,
+ rxfh.key = data->hkey;
+
+ ret = ops->get_rxfh(dev, &rxfh);
+- if (ret)
++ if (ret) {
++ rss_get_data_free(data);
+ goto out_unlock;
++ }
+
+ data->hfunc = rxfh.hfunc;
+ data->input_xfrm = rxfh.input_xfrm;
+--
+2.53.0
+
--- /dev/null
+From faabee6674234c8a1f1896028c1580f4f9618b42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:31 -0700
+Subject: ethtool: strset: fix header attribute index in ethnl_req_get_phydev()
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit a8d8bef6b45bf7cc0b1f6110c5cd8d0160a9bad7 ]
+
+strset_prepare_data() passes ETHTOOL_A_HEADER_FLAGS (3) as the header
+attribute to ethnl_req_get_phydev(). This is incorrect, in the main
+attr space 3 is ETHTOOL_A_STRSET_COUNTS_ONLY, not the request
+header attr. The correct constant is ETHTOOL_A_STRSET_HEADER (1).
+
+ethnl_req_get_phydev() only uses this value for the extack,
+so this is not a "functionally visible"(?) bug.
+
+Fixes: e96c93aa4be9 ("net: ethtool: strset: Allow querying phy stats by index")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-9-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/strset.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c
+index f6a67109beda1b..872ca593b97668 100644
+--- a/net/ethtool/strset.c
++++ b/net/ethtool/strset.c
+@@ -309,7 +309,7 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base,
+ return 0;
+ }
+
+- phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_HEADER_FLAGS,
++ phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_STRSET_HEADER,
+ info->extack);
+
+ /* phydev can be NULL, check for errors only */
+--
+2.53.0
+
--- /dev/null
+From ea036757a9073fda66746ba73e5bd50e38672736 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:28 -0700
+Subject: ethtool: tsconfig: fix missing ethnl_ops_complete()
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 6386bd772de64e6760306eb91c7e86163af6c22f ]
+
+tsconfig_prepare_data() calls ethnl_ops_begin(), we need to call
+ethnl_ops_complete() before returning the error.
+
+Fixes: 6e9e2eed4f39 ("net: ethtool: Add support for tsconfig command to get/set hwtstamp config")
+Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-6-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/tsconfig.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/tsconfig.c b/net/ethtool/tsconfig.c
+index 041de8687472bd..a121928038b055 100644
+--- a/net/ethtool/tsconfig.c
++++ b/net/ethtool/tsconfig.c
+@@ -69,8 +69,10 @@ static int tsconfig_prepare_data(const struct ethnl_req_info *req_base,
+ if (ret)
+ goto out;
+
+- if (ts_info.phc_index == -1)
+- return -ENODEV;
++ if (ts_info.phc_index == -1) {
++ ret = -ENODEV;
++ goto out;
++ }
+
+ data->hwprov_desc.index = ts_info.phc_index;
+ data->hwprov_desc.qualifier = ts_info.phc_qualifier;
+--
+2.53.0
+
--- /dev/null
+From 183d1c373f0347a9aae5dcde9ea698c5db266276 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:25 -0700
+Subject: ethtool: tsconfig: fix reply error handling
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit a888bbd43940cada72f7686337741ce86d1cf869 ]
+
+A couple of trivial bugs in error handling in tsconfig_send_reply().
+If we failed to allocate rskb we need to set the error.
+If we did allocate it but failed to send it - we need to remember
+to free it.
+
+Fixes: 6e9e2eed4f39 ("net: ethtool: Add support for tsconfig command to get/set hwtstamp config")
+Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-3-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/tsconfig.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/tsconfig.c b/net/ethtool/tsconfig.c
+index 169b413b31fc5f..041de8687472bd 100644
+--- a/net/ethtool/tsconfig.c
++++ b/net/ethtool/tsconfig.c
+@@ -224,16 +224,21 @@ static int tsconfig_send_reply(struct net_device *dev, struct genl_info *info)
+ reply_len = ret + ethnl_reply_header_size();
+ rskb = ethnl_reply_init(reply_len, dev, ETHTOOL_MSG_TSCONFIG_SET_REPLY,
+ ETHTOOL_A_TSCONFIG_HEADER, info, &reply_payload);
+- if (!rskb)
++ if (!rskb) {
++ ret = -ENOMEM;
+ goto err_cleanup;
++ }
+
+ ret = tsconfig_fill_reply(rskb, &req_info->base, &reply_data->base);
+ if (ret < 0)
+- goto err_cleanup;
++ goto err_free_msg;
+
+ genlmsg_end(rskb, reply_payload);
+ ret = genlmsg_reply(rskb, info);
++ rskb = NULL;
+
++err_free_msg:
++ nlmsg_free(rskb);
+ err_cleanup:
+ kfree(reply_data);
+ kfree(req_info);
+--
+2.53.0
+
--- /dev/null
+From 07d3e946d4f9dfcf01e7ac59f9b5a9fb1ba8cb3d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:30 -0700
+Subject: ethtool: tsinfo: don't pass ERR_PTR to genlmsg_cancel on prepare
+ failure
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit c3fc9976f686f9a95baf87db9d387f218fd65394 ]
+
+The goto err label leads to:
+
+ genlmsg_cancel(skb, ehdr);
+ return ret;
+
+If ethnl_tsinfo_prepare_dump() failed, it has not started a genlmsg.
+There's nothing to cancel, and passing an error pointer to
+genlmsg_cancel() would cause a crash.
+
+Fixes: b9e3f7dc9ed9 ("net: ethtool: tsinfo: Enhance tsinfo to support several hwtstamp by net topology")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-8-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/tsinfo.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/net/ethtool/tsinfo.c b/net/ethtool/tsinfo.c
+index fcc28fca526d82..53f12128a1a580 100644
+--- a/net/ethtool/tsinfo.c
++++ b/net/ethtool/tsinfo.c
+@@ -405,10 +405,8 @@ static int ethnl_tsinfo_dump_one_netdev(struct sk_buff *skb,
+ continue;
+
+ ehdr = ethnl_tsinfo_prepare_dump(skb, dev, reply_data, cb);
+- if (IS_ERR(ehdr)) {
+- ret = PTR_ERR(ehdr);
+- goto err;
+- }
++ if (IS_ERR(ehdr))
++ return PTR_ERR(ehdr);
+
+ reply_data->ts_info.phc_qualifier = ctx->pos_phcqualifier;
+ ret = ops->get_ts_info(dev, &reply_data->ts_info);
+--
+2.53.0
+
--- /dev/null
+From 7e2211ce4c08a8ec3a99d49949f93cda9aec2877 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:29 -0700
+Subject: ethtool: tsinfo: fix uninitialized stats on the by-PHC path
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 1de405699c62c3a9544bcdcfb9eff8a01cfc7582 ]
+
+tsinfo_prepare_data() has two code paths: a "by-PHC" path for
+user-specified hardware timestamping providers, and the old path.
+Commit 89e281ebff72 ("ethtool: init tsinfo stats if requested") added
+ethtool_stats_init() to mark stat slots as ETHTOOL_STAT_NOT_SET before
+the driver callback populates them, but placed the call inside the
+old-path block.
+
+When commit b9e3f7dc9ed9 ("net: ethtool: tsinfo: Enhance tsinfo to
+support several hwtstamp by net topology") added the by-PHC early
+return, it landed above the stats initialization. On that path
+the stats array retains the zero-fill from ethnl_init_reply_data()'s
+zalloc. This leads to the reply including a stats nest with four
+zero-valued attributes that should have been absent.
+
+Reject GET requests for stats with HWTSTAMP_PROVIDER or dump.
+
+Fixes: b9e3f7dc9ed9 ("net: ethtool: tsinfo: Enhance tsinfo to support several hwtstamp by net topology")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-7-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/tsinfo.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/net/ethtool/tsinfo.c b/net/ethtool/tsinfo.c
+index 8c654caa6805a5..fcc28fca526d82 100644
+--- a/net/ethtool/tsinfo.c
++++ b/net/ethtool/tsinfo.c
+@@ -81,6 +81,11 @@ tsinfo_parse_request(struct ethnl_req_info *req_base, struct nlattr **tb,
+ if (!tb[ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER])
+ return 0;
+
++ if (req_base->flags & ETHTOOL_FLAG_STATS) {
++ NL_SET_ERR_MSG(extack, "can't query statistics for a provider");
++ return -EOPNOTSUPP;
++ }
++
+ return ts_parse_hwtst_provider(tb[ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER],
+ &req->hwprov_desc, extack, &mod);
+ }
+@@ -521,6 +526,12 @@ int ethnl_tsinfo_start(struct netlink_callback *cb)
+ if (ret < 0)
+ goto free_reply_data;
+
++ if (req_info->base.flags & ETHTOOL_FLAG_STATS) {
++ NL_SET_ERR_MSG(cb->extack, "stats not supported in dump");
++ ret = -EOPNOTSUPP;
++ goto err_dev_put;
++ }
++
+ ctx->req_info = req_info;
+ ctx->reply_data = reply_data;
+ ctx->pos_ifindex = 0;
+@@ -530,6 +541,8 @@ int ethnl_tsinfo_start(struct netlink_callback *cb)
+
+ return 0;
+
++err_dev_put:
++ ethnl_parse_header_dev_put(&req_info->base);
+ free_reply_data:
+ kfree(reply_data);
+ free_req_info:
+--
+2.53.0
+
--- /dev/null
+From e9212538ef0e994373e57ded91eb1ed4cc781b2c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 09:35:27 +0200
+Subject: gpio: adnp: fix flow control regression caused by scoped_guard()
+
+From: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+
+[ Upstream commit a5c627d90809b793fc053849b3a00609db305776 ]
+
+scoped_guard() is implemented as a for loop. Using it to protect code
+using the continue statement changes the flow as we now only break out
+of the hidden loop inside scoped_guard(), not the original for loop. Use
+a regular code block instead.
+
+Fixes: c7fe19ed3973 ("gpio: adnp: use lock guards for the I2C lock")
+Reported-by: David Lechner <dlechner@baylibre.com>
+Closes: https://lore.kernel.org/all/cde2abb2-4cc8-4fc9-b34a-0c5d2b95779f@baylibre.com/
+Reviewed-by: Linus Walleij <linusw@kernel.org>
+Link: https://patch.msgid.link/20260522073527.9812-1-bartosz.golaszewski@oss.qualcomm.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-adnp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
+index e5ac2d2110137f..fe5bcaa90496aa 100644
+--- a/drivers/gpio/gpio-adnp.c
++++ b/drivers/gpio/gpio-adnp.c
+@@ -237,7 +237,9 @@ static irqreturn_t adnp_irq(int irq, void *data)
+ unsigned long pending;
+ int err;
+
+- scoped_guard(mutex, &adnp->i2c_lock) {
++ {
++ guard(mutex)(&adnp->i2c_lock);
++
+ err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level);
+ if (err < 0)
+ continue;
+--
+2.53.0
+
--- /dev/null
+From affb3074346d5d6b6f11ac84db0e0f739e483db5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:01 +0200
+Subject: gpio: mxc: fix irq_high handling
+
+From: Alexander Stein <alexander.stein@ew.tq-group.com>
+
+[ Upstream commit dac917ed5aead741004db8d0d5151dd577802df8 ]
+
+If port->irq_high is -1 (fsl,imx21-gpio compatible) and gpio_idx is >= 16
+enable_irq_wake() is called with -1 which is wrong.
+
+Fixes: 5f6d1998adeb ("gpio: mxc: release the parent IRQ in runtime suspend")
+Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://patch.msgid.link/20260526063504.25916-1-alexander.stein@ew.tq-group.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-mxc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
+index 441ba95b38cf9b..dbdf0f41b6bb91 100644
+--- a/drivers/gpio/gpio-mxc.c
++++ b/drivers/gpio/gpio-mxc.c
+@@ -469,7 +469,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
+ * the handler is needed only once, but doing it for every port
+ * is more robust and easier.
+ */
+- port->irq_high = -1;
++ port->irq_high = 0;
+ port->mx_irq_handler = mx2_gpio_irq_handler;
+ } else
+ port->mx_irq_handler = mx3_gpio_irq_handler;
+--
+2.53.0
+
--- /dev/null
+From 8eca85a401d248a8643ce188954e2ed6c3117449 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:02:45 +0200
+Subject: gpio: rockchip: convert bank->clk to devm_clk_get_enabled()
+
+From: Marco Scardovi <scardracs@disroot.org>
+
+[ Upstream commit 3e46c18d5d87f063a93ae0fe7662fbf6660459d5 ]
+
+The bank->clk was previously obtained via of_clk_get() and manually
+prepared/enabled. However, it was missing a corresponding clk_put() in
+both the error paths and the remove function, leading to a reference leak.
+
+Convert the allocation to devm_clk_get_enabled(), which also properly
+propagates failures from clk_prepare_enable() that were previously ignored.
+
+The GPIO bank device uses the same OF node as the previous of_clk_get()
+call, so devm_clk_get_enabled(dev, NULL) correctly resolves the same
+clock provider entry.
+
+Fix the reference leak and simplify the code by removing the manual
+clk_disable_unprepare() calls in the probe error paths and in the
+remove function.
+
+Fixes: 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio")
+Assisted-by: Antigravity:gemini-3.5-flash
+Signed-off-by: Marco Scardovi <scardracs@disroot.org>
+Link: https://patch.msgid.link/20260526171050.12785-2-scardracs@disroot.org
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-rockchip.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
+index 0fff4a699f12d1..f910220141f712 100644
+--- a/drivers/gpio/gpio-rockchip.c
++++ b/drivers/gpio/gpio-rockchip.c
+@@ -656,11 +656,10 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ if (!bank->irq)
+ return -EINVAL;
+
+- bank->clk = of_clk_get(bank->of_node, 0);
++ bank->clk = devm_clk_get_enabled(bank->dev, NULL);
+ if (IS_ERR(bank->clk))
+ return PTR_ERR(bank->clk);
+
+- clk_prepare_enable(bank->clk);
+ id = readl(bank->reg_base + gpio_regs_v2.version_id);
+
+ switch (id) {
+@@ -672,7 +671,6 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ bank->db_clk = of_clk_get(bank->of_node, 1);
+ if (IS_ERR(bank->db_clk)) {
+ dev_err(bank->dev, "cannot find debounce clk\n");
+- clk_disable_unprepare(bank->clk);
+ return -EINVAL;
+ }
+ break;
+@@ -751,7 +749,6 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
+
+ ret = rockchip_gpiolib_register(bank);
+ if (ret) {
+- clk_disable_unprepare(bank->clk);
+ mutex_unlock(&bank->deferred_lock);
+ return ret;
+ }
+@@ -792,7 +789,6 @@ static void rockchip_gpio_remove(struct platform_device *pdev)
+ {
+ struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
+
+- clk_disable_unprepare(bank->clk);
+ gpiochip_remove(&bank->gpio_chip);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 7dc30495148ab049146bc3e38ccd9545b81a5e3e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:02:46 +0200
+Subject: gpio: rockchip: teardown bugs and resource leaks
+
+From: Marco Scardovi <scardracs@disroot.org>
+
+[ Upstream commit 9500077678230e36d22bf16d2b9539c13e59a801 ]
+
+Address several teardown issues and resource leaks in the driver's remove
+path and error handling:
+
+1. Debounce clock reference leak: The debounce clock (bank->db_clk) is
+ obtained using of_clk_get() which increments the clock's reference
+ count, but clk_put() is never called. Register a devm action to
+ cleanly release it on unbind. Note that of_clk_get(..., 1) remains
+ necessary over devm_clk_get() because the DT binding does not define
+ clock-names, precluding name-based lookup.
+
+2. Unregistered chained IRQ handler: The chained IRQ handler is not
+ disconnected in remove(). If a stray interrupt fires after the driver
+ is removed, the kernel attempts to execute a stale handler, leading
+ to a panic. Fix this by clearing the handler in remove().
+
+3. IRQ domain leak: The linear IRQ domain and its generic chips are
+ allocated manually during probe but never removed. Remove the IRQ
+ domain during driver teardown to free the associated generic chips
+ and mappings.
+
+Fixes: 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio")
+Assisted-by: Antigravity:gemini-3.5-flash
+Signed-off-by: Marco Scardovi <scardracs@disroot.org>
+Link: https://patch.msgid.link/20260526171050.12785-3-scardracs@disroot.org
+[Bartosz: don't emit an error message on devres allocation failure]
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-rockchip.c | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
+index f910220141f712..1ef0ba956cfd8c 100644
+--- a/drivers/gpio/gpio-rockchip.c
++++ b/drivers/gpio/gpio-rockchip.c
+@@ -638,10 +638,17 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
+ return ret;
+ }
+
++static void rockchip_clk_put(void *data)
++{
++ struct clk *clk = data;
++
++ clk_put(clk);
++}
++
+ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ {
+ struct resource res;
+- int id = 0;
++ int id = 0, ret;
+
+ if (of_address_to_resource(bank->of_node, 0, &res)) {
+ dev_err(bank->dev, "cannot find IO resource for bank\n");
+@@ -673,6 +680,11 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ dev_err(bank->dev, "cannot find debounce clk\n");
+ return -EINVAL;
+ }
++
++ ret = devm_add_action_or_reset(bank->dev, rockchip_clk_put,
++ bank->db_clk);
++ if (ret)
++ return ret;
+ break;
+ case GPIO_TYPE_V1:
+ bank->gpio_regs = &gpio_regs_v1;
+@@ -789,6 +801,9 @@ static void rockchip_gpio_remove(struct platform_device *pdev)
+ {
+ struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
+
++ irq_set_chained_handler_and_data(bank->irq, NULL, NULL);
++ if (bank->domain)
++ irq_domain_remove(bank->domain);
+ gpiochip_remove(&bank->gpio_chip);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From f93379d15c9f67df6bab4a6a6fcc9ab5c2e15897 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 10:15:16 +0300
+Subject: gpio: virtuser: Fix uninitialized data bug in
+ gpio_virtuser_direction_do_write()
+
+From: Dan Carpenter <error27@gmail.com>
+
+[ Upstream commit 8a122b5e72cc0043705f0d524bcd15f0c0b3ec15 ]
+
+If *ppos is non-zero (user-space write split over multiple calls to
+write()) then simple_write_to_buffer() won't initialize the start of the
+buffer. Really, non-zero values for *ppos aren't going to work at all.
+Check for that and return -EINVAL at the start of the function.
+
+Fixes: 91581c4b3f29 ("gpio: virtuser: new virtual testing driver for the GPIO API")
+Signed-off-by: Dan Carpenter <error27@gmail.com>
+Link: https://patch.msgid.link/ahP3BJWWy-m_qI0X@stanley.mountain
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-virtuser.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpio/gpio-virtuser.c b/drivers/gpio/gpio-virtuser.c
+index 252fec5ea38354..1901b4ba558f0c 100644
+--- a/drivers/gpio/gpio-virtuser.c
++++ b/drivers/gpio/gpio-virtuser.c
+@@ -399,7 +399,7 @@ static ssize_t gpio_virtuser_direction_do_write(struct file *file,
+ char buf[32], *trimmed;
+ int ret, dir, val = 0;
+
+- if (count >= sizeof(buf))
++ if (*ppos != 0 || count >= sizeof(buf))
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+@@ -626,7 +626,7 @@ static ssize_t gpio_virtuser_consumer_write(struct file *file,
+ char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2];
+ int ret;
+
+- if (count >= sizeof(buf))
++ if (*ppos != 0 || count >= sizeof(buf))
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos,
+--
+2.53.0
+
--- /dev/null
+From bbfd0abc8a18bc125d503b8190000180e8bec32d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 May 2026 16:32:04 +0800
+Subject: HID: remove duplicate hid_warn_ratelimited definition
+
+From: Liu Kai <lukace97@outlook.com>
+
+[ Upstream commit dd2147375a8fe7c5bc3f1f1b1d3a9567c26faefa ]
+
+The hid_warn_ratelimited macro is defined twice in include/linux/hid.h:
+- first one added by commit 4051ead99888 ("HID: rate-limit hid_warn to
+ prevent log flooding")
+- second one added by commit 1d64624243af ("HID: core: Add
+ printk_ratelimited variants to hid_warn() etc")).
+
+The second definition is correctly grouped with other ratelimited macros.
+Remove the duplicate definition.
+
+Fixes: 1d64624243af ("HID: core: Add printk_ratelimited variants to hid_warn() etc")
+Signed-off-by: Liu Kai <lukace97@outlook.com>
+[bentiss: edited commit message]
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/hid.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 204ada8d12e5c8..29561887bea8c0 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1276,8 +1276,6 @@ void hid_quirks_exit(__u16 bus);
+ dev_notice(&(hid)->dev, fmt, ##__VA_ARGS__)
+ #define hid_warn(hid, fmt, ...) \
+ dev_warn(&(hid)->dev, fmt, ##__VA_ARGS__)
+-#define hid_warn_ratelimited(hid, fmt, ...) \
+- dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
+ #define hid_info(hid, fmt, ...) \
+ dev_info(&(hid)->dev, fmt, ##__VA_ARGS__)
+ #define hid_dbg(hid, fmt, ...) \
+--
+2.53.0
+
--- /dev/null
+From dfe1a80b8eaf7812fda563b7967c6bedb1ea2ae4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 12:21:47 +0000
+Subject: ipv4: free net->ipv4.sysctl_local_reserved_ports after
+ unregister_net_sysctl_table()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 87a1e0fe7776da7ab411be332b4be58ac8840d10 ]
+
+ipv4_sysctl_exit_net() is currently freeing net->ipv4.sysctl_local_reserved_ports
+too soon.
+
+Only after unregister_net_sysctl_table() we can be sure no threads can possibly
+use the sysctls, including /proc/sys/net/ipv4/ip_local_reserved_ports.
+
+Fixes: 122ff243f5f1 ("ipv4: make ip_local_reserved_ports per netns")
+Reported-by: Ji'an Zhou <eilaimemedsnaimel@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260521122147.3584624-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/sysctl_net_ipv4.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 0f1dd75dbf37bf..ce9b077343cac2 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -1669,10 +1669,10 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net)
+ {
+ const struct ctl_table *table;
+
+- kfree(net->ipv4.sysctl_local_reserved_ports);
+ table = net->ipv4.ipv4_hdr->ctl_table_arg;
+ unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
+ kfree(table);
++ kfree(net->ipv4.sysctl_local_reserved_ports);
+ }
+
+ static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
+--
+2.53.0
+
--- /dev/null
+From 9d3976e22d79e4a1b07dba67d3223218be4a3c71 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:31:31 +0800
+Subject: ipv6: fix possible infinite loop in fib6_select_path()
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 9c7da87c2dc860bb17ca1ece942495d28b1ce3b9 ]
+
+Found while auditing the same pattern Sashiko reported in
+rt6_fill_node() [1]. Apply the same fix as
+commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").
+
+Writers holding tb6_lock can list_del_rcu(&first->fib6_siblings)
+without waiting for RCU readers; first->fib6_siblings.next then
+still points into the old ring and this softirq-side walker never
+reaches &first->fib6_siblings as its terminator. fib6_purge_rt()
+always WRITE_ONCE()s first->fib6_nsiblings to 0 before
+list_del_rcu(), so an inside-loop check is a reliable detach signal.
+
+[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev
+
+Fixes: d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260527053133.180695-2-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index cf9546047b5749..f89220929c4e24 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -481,6 +481,9 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
+ const struct fib6_nh *nh = sibling->fib6_nh;
+ int nh_upper_bound;
+
++ if (!READ_ONCE(first->fib6_nsiblings))
++ break;
++
+ nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
+ if (hash > nh_upper_bound)
+ continue;
+--
+2.53.0
+
--- /dev/null
+From 018bd9df99a7885b7085da96c09831b6160dd257 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:31:30 +0800
+Subject: ipv6: fix possible infinite loop in rt6_fill_node()
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 9f72412bcf60144f252b0d6205106abf14344abc ]
+
+Sashiko reported this issue [1]. Apply the same fix as
+commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").
+
+Writers holding tb6_lock can list_del_rcu(&rt->fib6_siblings)
+without waiting for RCU readers; rt->fib6_siblings.next then still
+points into the old ring and this softirq-side walker never reaches
+&rt->fib6_siblings, causing a CPU stall. fib6_del_route() always
+WRITE_ONCE()s rt->fib6_nsiblings to 0 before list_del_rcu(), so an
+inside-loop check is a reliable detach signal.
+
+[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev
+
+Fixes: d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260527053133.180695-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index 446f4de7d6a227..cf9546047b5749 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -5892,6 +5892,8 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
+
+ goto nla_put_failure;
+ }
++ if (!READ_ONCE(rt->fib6_nsiblings))
++ break;
+ }
+
+ rcu_read_unlock();
+--
+2.53.0
+
--- /dev/null
+From aa4e3aef2b26b8c1d3527389570d761e05a3dd25 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 21:10:31 +0530
+Subject: ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress()
+
+From: Rahul Chandelkar <rc@rexion.ai>
+
+[ Upstream commit 9d5e7a46a9f6d8f503b41bfefef70659845f1679 ]
+
+ipv6_rpl_srh_decompress() computes:
+
+ outhdr->hdrlen = (((n + 1) * sizeof(struct in6_addr)) >> 3);
+
+hdrlen is __u8. For n >= 127 the result exceeds 255 and silently
+truncates. With n=127 (cmpri=15, cmpre=15, pad=0, hdrlen=16):
+
+ (128 * 16) >> 3 = 256, truncated to 0 as __u8
+
+The caller in ipv6_rpl_srh_rcv() then places the compressed header
+at buf + ((ohdr->hdrlen + 1) << 3). With hdrlen=0 this is buf + 8,
+but the decompressed region occupies buf[0..2055] (8-byte header
+plus 128 full addresses). The compressed header overlaps the
+decompressed data, and ipv6_rpl_srh_compress() writes into this
+overlap, corrupting the routing header of the forwarded packet.
+
+The existing guard at exthdrs.c:546 checks (n + 1) > 255, which
+prevents n+1 from overflowing unsigned char (the segments_left
+field), but does not prevent the computed hdrlen from overflowing
+__u8. n=127 passes because 128 <= 255, yet hdrlen=256 does not
+fit.
+
+Tighten the bound to (n + 1) > 127. This caps n at 126, giving
+hdrlen = (127 * 16) >> 3 = 254, which fits in __u8. The compressed
+header then lands at buf + ((254 + 1) << 3) = buf + 2040, exactly
+past the decompressed region (buf[0..2039]). No overlap. 127
+segments is well beyond any realistic RPL deployment.
+
+Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
+Signed-off-by: Rahul Chandelkar <rc@rexion.ai>
+Link: https://patch.msgid.link/20260525154031.2290876-1-rc@rexion.ai
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/exthdrs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
+index d15e6094382094..830131b427f098 100644
+--- a/net/ipv6/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -544,7 +544,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
+ * unsigned char which is segments_left field. Should not be
+ * higher than that.
+ */
+- if (r || (n + 1) > 255) {
++ if (r || (n + 1) > 127) {
+ kfree_skb(skb);
+ return -1;
+ }
+--
+2.53.0
+
--- /dev/null
+From fcca61d3635730759712bd3d6b18c31021219c96 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 20:49:56 +0530
+Subject: kernel/fork: validate exit_signal in kernel_clone()
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit 09e7827e785729f391c8d46dc71becce70d296ab ]
+
+When a child process exits, it sends exit_signal to its parent via
+do_notify_parent(). The clone() syscall constructs exit_signal as:
+
+(lower_32_bits(clone_flags) & CSIGNAL)
+
+CSIGNAL is 0xff, so values in the range 65-255 are possible. However,
+valid_signal() only accepts signals up to _NSIG (64 on x86_64). A
+non-zero non-valid exit_signal acts the same as exit_signal == 0: the
+parent process is not signaled when the child terminates.
+
+The syzkaller reproducer triggers this by calling clone() with flags=0x80,
+resulting in exit_signal = (0x80 & CSIGNAL) = 128, which exceeds _NSIG and
+is not a valid signal.
+
+The v1 of this patch added the check only in the clone() syscall handler,
+which is incomplete. kernel_clone() has other callers such as
+sys_ia32_clone() which would remain unprotected. Move the check to
+kernel_clone() to cover all callers.
+
+Since the valid_signal() check is now in kernel_clone() and covers all
+callers including clone3(), the same check in copy_clone_args_from_user()
+becomes redundant and is removed. The higher 32bits check for clone3() is
+kept as it is clone3() specific.
+
+Note that this is a user-visible change: previously, passing an invalid
+exit_signal to clone() was silently accepted. The man page for clone()
+does not document any defined behavior for invalid exit_signal values, so
+rejecting them with -EINVAL is the correct behavior. It is unlikely that
+any sane application relies on passing an invalid exit_signal.
+
+[oleg@redhat.com: the comment above kernel_clone() should be updated]
+ Link: https://lore.kernel.org/abwvgU17W8wuW2-J@redhat.com
+Link: https://lore.kernel.org/20260316151956.563558-1-kartikey406@gmail.com
+Fixes: 3f2c788a1314 ("fork: prevent accidental access to clone3 features")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Reported-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=bbe6b99feefc3a0842de
+Tested-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/all/20260307064202.353405-1-kartikey406@gmail.com/T/ [v1]
+Link: https://lore.kernel.org/all/20260316104536.558108-1-kartikey406@gmail.com/T/ [v2]
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Ben Segall <bsegall@google.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Juri Lelli <juri.lelli@redhat.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: Liam Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
+Cc: Mel Gorman <mgorman@suse.de>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Valentin Schneider <vschneid@redhat.com>
+Cc: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/fork.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 1215d3f52c6d21..521e9d2be6f097 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -2562,8 +2562,6 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
+ *
+ * It copies the process, and if successful kick-starts
+ * it and waits for it to finish using the VM if required.
+- *
+- * args->exit_signal is expected to be checked for sanity by the caller.
+ */
+ pid_t kernel_clone(struct kernel_clone_args *args)
+ {
+@@ -2588,6 +2586,9 @@ pid_t kernel_clone(struct kernel_clone_args *args)
+ (args->pidfd == args->parent_tid))
+ return -EINVAL;
+
++ if (!valid_signal(args->exit_signal))
++ return -EINVAL;
++
+ /*
+ * Determine whether and which event to report to ptracer. When
+ * called from kernel_thread or CLONE_UNTRACED is explicitly
+@@ -2786,11 +2787,9 @@ static noinline int copy_clone_args_from_user(struct kernel_clone_args *kargs,
+ return -EINVAL;
+
+ /*
+- * Verify that higher 32bits of exit_signal are unset and that
+- * it is a valid signal
++ * Verify that higher 32bits of exit_signal are unset
+ */
+- if (unlikely((args.exit_signal & ~((u64)CSIGNAL)) ||
+- !valid_signal(args.exit_signal)))
++ if (unlikely(args.exit_signal & ~((u64)CSIGNAL)))
+ return -EINVAL;
+
+ if ((args.flags & CLONE_INTO_CGROUP) &&
+--
+2.53.0
+
--- /dev/null
+From 547624fcd83637e995485b6fef6128bcfe8c9539 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 22:07:16 +0900
+Subject: ksmbd: fix FSCTL permission bypass by adding a permission check for
+ FSCTL_SET_SPARSE
+
+From: Sean Shen <grayhat@foxmail.com>
+
+[ Upstream commit cc57232cae23c0df91b4a59d0f519141ce9b5b02 ]
+
+FSCTL_SET_SPARSE in fsctl_set_sparse() modifies the file's sparse
+attribute and saves it through xattr without any permission checks.
+
+This exposes two issues:
+
+1) A client on a read-only share can change the sparse attribute
+ on files it opened, even though the share is read-only.
+ Other FSCTL write operations already check
+ test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE),
+ but FSCTL_SET_SPARSE does not.
+
+2) Even on writable shares, clients without FILE_WRITE_DATA or
+ FILE_WRITE_ATTRIBUTES access should not modify the sparse
+ attribute. Similar handle-level checks exist in other functions
+ but are missing here.
+
+Add both share-level writable check and per-handle access check.
+Use goto out on error to avoid leaking file references.
+
+Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
+Cc: Namjae Jeon <linkinjeon@kernel.org>
+Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Cc: Steve French <smfrench@gmail.com>
+Signed-off-by: Sean Shen <grayhat@foxmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/smb2pdu.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index da7b96707186e4..4689aac12c14ea 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -8203,9 +8203,20 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
+ int ret = 0;
+ __le32 old_fattr;
+
++ if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
++ ksmbd_debug(SMB, "User does not have write permission\n");
++ return -EACCES;
++ }
++
+ fp = ksmbd_lookup_fd_fast(work, id);
+ if (!fp)
+ return -ENOENT;
++
++ if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_WRITE_ATTRIBUTES_LE))) {
++ ret = -EACCES;
++ goto out;
++ }
++
+ idmap = file_mnt_idmap(fp->filp);
+
+ old_fattr = fp->f_ci->m_fattr;
+--
+2.53.0
+
--- /dev/null
+From e3871ffbce2816ef17cf496c755149431883c879 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 May 2026 10:48:54 +0200
+Subject: kunit: fix use-after-free in debugfs when using kunit.filter
+
+From: Florian Schmaus <florian.schmaus@codasip.com>
+
+[ Upstream commit fb6988b83b4cafe8db63999c1ddff1b7c66d2ff5 ]
+
+When the kernel is booted with a kunit filter (e.g.,
+kunit.filter="speed!=slow"), the kunit executor dynamically allocates
+copies of the filtered test suites using kmalloc/kmemdup.
+
+During the initial boot execution, kunit_debugfs_create_suite() creates
+debugfs files (such as /sys/kernel/debug/kunit/<suite>/run) and
+permanently stores a pointer to the dynamically allocated suite in the
+inode's i_private field.
+
+Previously, the executor freed this dynamically allocated suite_set
+immediately after executing the boot-time tests. Because the debugfs
+nodes were not destroyed, any subsequent interaction with the debugfs
+`run` file from userspace triggered a use-after-free (UAF). On systems
+with architectural capabilities, like CHERI RISC-V, this resulted in
+an immediate fatal hardware exception due to the invalidation of the
+capability tags on the reclaimed memory. On other architectures, it
+resulted in silent memory corruption.
+
+Fix this UAF by properly coupling the lifetime of the filtered suite
+memory allocation to the lifetime of the kunit subsystem and its
+associated VFS nodes. Ownership of the boot-time suite_set is now
+transferred to a global tracker ('kunit_boot_suites'), and the memory
+is cleanly released in kunit_exit() during module teardown.
+
+Link: https://lore.kernel.org/r/20260507084854.233984-1-florian.schmaus@codasip.com
+Fixes: e2219db280e3 ("kunit: add debugfs /sys/kernel/debug/kunit/<suite>/results display")
+Signed-off-by: Florian Schmaus <florian.schmaus@codasip.com>
+Reviewed-by: Martin Kaiser <martin@kaiser.cx>
+Reviewed-by: David Gow <david@davidgow.net>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/kunit/test.h | 1 +
+ lib/kunit/executor.c | 19 ++++++++++++++++---
+ lib/kunit/test.c | 1 +
+ 3 files changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/include/kunit/test.h b/include/kunit/test.h
+index 5ec5182b5e5751..aedffe2f2d49de 100644
+--- a/include/kunit/test.h
++++ b/include/kunit/test.h
+@@ -613,6 +613,7 @@ unsigned long kunit_vm_mmap(struct kunit *test, struct file *file,
+ unsigned long offset);
+
+ void kunit_cleanup(struct kunit *test);
++void kunit_free_boot_suites(void);
+
+ void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt, ...);
+
+diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
+index 0061d4c7e35170..9abaed8275845f 100644
+--- a/lib/kunit/executor.c
++++ b/lib/kunit/executor.c
+@@ -15,6 +15,16 @@ extern struct kunit_suite * const __kunit_suites_end[];
+ extern struct kunit_suite * const __kunit_init_suites_start[];
+ extern struct kunit_suite * const __kunit_init_suites_end[];
+
++static struct kunit_suite_set kunit_boot_suites;
++
++void kunit_free_boot_suites(void)
++{
++ if (kunit_boot_suites.start) {
++ kunit_free_suite_set(kunit_boot_suites);
++ kunit_boot_suites = (struct kunit_suite_set){ NULL, NULL };
++ }
++}
++
+ static char *action_param;
+
+ module_param_named(action, action_param, charp, 0400);
+@@ -409,9 +419,12 @@ int kunit_run_all_tests(void)
+ pr_err("kunit executor: unknown action '%s'\n", action_param);
+
+ free_out:
+- if (filter_glob_param || filter_param)
+- kunit_free_suite_set(suite_set);
+- else if (init_num_suites > 0)
++ if (filter_glob_param || filter_param) {
++ if (err)
++ kunit_free_suite_set(suite_set);
++ else
++ kunit_boot_suites = suite_set;
++ } else if (init_num_suites > 0)
+ /* Don't use kunit_free_suite_set because suites aren't individually allocated */
+ kfree(suite_set.start);
+
+diff --git a/lib/kunit/test.c b/lib/kunit/test.c
+index 62eb529824c657..f0e1e02a98d8b3 100644
+--- a/lib/kunit/test.c
++++ b/lib/kunit/test.c
+@@ -1056,6 +1056,7 @@ static void __exit kunit_exit(void)
+ kunit_bus_shutdown();
+
+ kunit_debugfs_cleanup();
++ kunit_free_boot_suites();
+ }
+ module_exit(kunit_exit);
+
+--
+2.53.0
+
--- /dev/null
+From e24b727294a59bbfbac7217b908b6364663d1f79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 20 Dec 2025 10:33:26 +0000
+Subject: media: rc: fix race between unregister and urb/irq callbacks
+
+From: Sean Young <sean@mess.org>
+
+[ Upstream commit dccc0c3ddf8f16071736f98a7d6dd46a2d43e037 ]
+
+Some rc device drivers have a race condition between rc_unregister_device()
+and irq or urb callbacks. This is because rc_unregister_device() does two
+things, it marks the device as unregistered so no new commands can be
+issued and then it calls rc_free_device(). This means the driver has no
+chance to cancel any pending urb callbacks or interrupts after the device
+has been marked as unregistered. Those callbacks may access struct rc_dev
+or its members (e.g. struct ir_raw_event_ctrl), which have been freed by
+rc_free_device().
+
+This change removes the implicit call to rc_free_device() from
+rc_unregister_device(). This means that device drivers can call
+rc_unregister_device() in their remove or disconnect function, then cancel
+all the urbs and interrupts before explicitly calling rc_free_device().
+
+Note this is an alternative fix for an issue found by Haotian Zhang, see
+the Closes: tags.
+
+Reported-by: Haotian Zhang <vulab@iscas.ac.cn>
+Closes: https://lore.kernel.org/linux-media/20251114101432.2566-1-vulab@iscas.ac.cn/
+Closes: https://lore.kernel.org/linux-media/20251114101418.2548-1-vulab@iscas.ac.cn/
+Closes: https://lore.kernel.org/linux-media/20251114101346.2530-1-vulab@iscas.ac.cn/
+Closes: https://lore.kernel.org/linux-media/20251114090605.2413-1-vulab@iscas.ac.cn/
+Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Stable-dep-of: 646ebdd31058 ("media: rc: ttusbir: fix inverted error logic")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/sil-sii8620.c | 1 +
+ drivers/hid/hid-picolcd_cir.c | 1 +
+ drivers/media/cec/core/cec-core.c | 2 +-
+ drivers/media/common/siano/smsir.c | 1 +
+ drivers/media/i2c/ir-kbd-i2c.c | 2 ++
+ drivers/media/pci/bt8xx/bttv-input.c | 3 ++-
+ drivers/media/pci/cx23885/cx23885-input.c | 1 +
+ drivers/media/pci/cx88/cx88-input.c | 3 ++-
+ drivers/media/pci/dm1105/dm1105.c | 1 +
+ drivers/media/pci/mantis/mantis_input.c | 1 +
+ drivers/media/pci/saa7134/saa7134-input.c | 1 +
+ drivers/media/pci/smipcie/smipcie-ir.c | 1 +
+ drivers/media/pci/ttpci/budget-ci.c | 1 +
+ drivers/media/rc/ati_remote.c | 6 +++---
+ drivers/media/rc/ene_ir.c | 2 +-
+ drivers/media/rc/fintek-cir.c | 3 ++-
+ drivers/media/rc/igorplugusb.c | 1 +
+ drivers/media/rc/iguanair.c | 1 +
+ drivers/media/rc/img-ir/img-ir-hw.c | 3 ++-
+ drivers/media/rc/img-ir/img-ir-raw.c | 3 ++-
+ drivers/media/rc/imon.c | 3 ++-
+ drivers/media/rc/ir-hix5hd2.c | 2 +-
+ drivers/media/rc/ir_toy.c | 1 +
+ drivers/media/rc/ite-cir.c | 2 +-
+ drivers/media/rc/mceusb.c | 1 +
+ drivers/media/rc/rc-ir-raw.c | 5 -----
+ drivers/media/rc/rc-loopback.c | 1 +
+ drivers/media/rc/rc-main.c | 6 +-----
+ drivers/media/rc/redrat3.c | 4 +++-
+ drivers/media/rc/st_rc.c | 2 +-
+ drivers/media/rc/streamzap.c | 7 ++++---
+ drivers/media/rc/sunxi-cir.c | 1 +
+ drivers/media/rc/ttusbir.c | 2 +-
+ drivers/media/rc/winbond-cir.c | 2 +-
+ drivers/media/rc/xbox_remote.c | 5 +++--
+ drivers/media/usb/au0828/au0828-input.c | 1 +
+ drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 1 +
+ drivers/media/usb/dvb-usb/dvb-usb-remote.c | 6 ++++--
+ drivers/media/usb/em28xx/em28xx-input.c | 1 +
+ drivers/staging/media/av7110/av7110_ir.c | 1 +
+ include/media/rc-core.h | 2 --
+ 41 files changed, 58 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
+index 9e48ad39e1cc99..923e2ed30624b7 100644
+--- a/drivers/gpu/drm/bridge/sil-sii8620.c
++++ b/drivers/gpu/drm/bridge/sil-sii8620.c
+@@ -2221,6 +2221,7 @@ static void sii8620_detach(struct drm_bridge *bridge)
+ return;
+
+ rc_unregister_device(ctx->rc_dev);
++ rc_free_device(ctx->rc_dev);
+ }
+
+ static int sii8620_is_packing_required(struct sii8620 *ctx,
+diff --git a/drivers/hid/hid-picolcd_cir.c b/drivers/hid/hid-picolcd_cir.c
+index d6faa0e00f95ac..6d4c636e1c9f7e 100644
+--- a/drivers/hid/hid-picolcd_cir.c
++++ b/drivers/hid/hid-picolcd_cir.c
+@@ -134,5 +134,6 @@ void picolcd_exit_cir(struct picolcd_data *data)
+
+ data->rc_dev = NULL;
+ rc_unregister_device(rdev);
++ rc_free_device(rdev);
+ }
+
+diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c
+index dd6e24a0899bda..1b8a33c05b3c92 100644
+--- a/drivers/media/cec/core/cec-core.c
++++ b/drivers/media/cec/core/cec-core.c
+@@ -338,8 +338,8 @@ int cec_register_adapter(struct cec_adapter *adap,
+ res = cec_devnode_register(&adap->devnode, adap->owner);
+ if (res) {
+ #ifdef CONFIG_MEDIA_CEC_RC
+- /* Note: rc_unregister also calls rc_free */
+ rc_unregister_device(adap->rc);
++ rc_free_device(adap->rc);
+ adap->rc = NULL;
+ #endif
+ return res;
+diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
+index d85c78c104b990..5f4c0aa7a0d72a 100644
+--- a/drivers/media/common/siano/smsir.c
++++ b/drivers/media/common/siano/smsir.c
+@@ -92,6 +92,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
+ void sms_ir_exit(struct smscore_device_t *coredev)
+ {
+ rc_unregister_device(coredev->ir.dev);
++ rc_free_device(coredev->ir.dev);
+
+ pr_debug("\n");
+ }
+diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
+index 5588cdd7ec20de..60474531700433 100644
+--- a/drivers/media/i2c/ir-kbd-i2c.c
++++ b/drivers/media/i2c/ir-kbd-i2c.c
+@@ -355,6 +355,7 @@ static void ir_work(struct work_struct *work)
+ mutex_unlock(&ir->lock);
+ if (rc == -ENODEV) {
+ rc_unregister_device(ir->rc);
++ rc_free_device(ir->rc);
+ ir->rc = NULL;
+ return;
+ }
+@@ -972,6 +973,7 @@ static void ir_remove(struct i2c_client *client)
+ i2c_unregister_device(ir->tx_c);
+
+ rc_unregister_device(ir->rc);
++ rc_free_device(ir->rc);
+ }
+
+ static const struct i2c_device_id ir_kbd_id[] = {
+diff --git a/drivers/media/pci/bt8xx/bttv-input.c b/drivers/media/pci/bt8xx/bttv-input.c
+index 84aa269248fd36..f84fcf96eca983 100644
+--- a/drivers/media/pci/bt8xx/bttv-input.c
++++ b/drivers/media/pci/bt8xx/bttv-input.c
+@@ -572,8 +572,9 @@ void bttv_input_fini(struct bttv *btv)
+ if (btv->remote == NULL)
+ return;
+
+- bttv_ir_stop(btv);
+ rc_unregister_device(btv->remote->dev);
++ bttv_ir_stop(btv);
++ rc_free_device(btv->remote->dev);
+ kfree(btv->remote);
+ btv->remote = NULL;
+ }
+diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
+index d2e84c6457e0ab..722329ef3fd2cc 100644
+--- a/drivers/media/pci/cx23885/cx23885-input.c
++++ b/drivers/media/pci/cx23885/cx23885-input.c
+@@ -402,6 +402,7 @@ void cx23885_input_fini(struct cx23885_dev *dev)
+ if (dev->kernel_ir == NULL)
+ return;
+ rc_unregister_device(dev->kernel_ir->rc);
++ rc_free_device(dev->kernel_ir->rc);
+ kfree(dev->kernel_ir->phys);
+ kfree(dev->kernel_ir->name);
+ kfree(dev->kernel_ir);
+diff --git a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c
+index b9f2c14d62b408..4757787c3f5935 100644
+--- a/drivers/media/pci/cx88/cx88-input.c
++++ b/drivers/media/pci/cx88/cx88-input.c
+@@ -509,8 +509,9 @@ int cx88_ir_fini(struct cx88_core *core)
+ if (!ir)
+ return 0;
+
+- cx88_ir_stop(core);
+ rc_unregister_device(ir->dev);
++ cx88_ir_stop(core);
++ rc_free_device(ir->dev);
+ kfree(ir);
+
+ /* done */
+diff --git a/drivers/media/pci/dm1105/dm1105.c b/drivers/media/pci/dm1105/dm1105.c
+index 9e9c7c071accce..e1185aa669f480 100644
+--- a/drivers/media/pci/dm1105/dm1105.c
++++ b/drivers/media/pci/dm1105/dm1105.c
+@@ -763,6 +763,7 @@ static int dm1105_ir_init(struct dm1105_dev *dm1105)
+ static void dm1105_ir_exit(struct dm1105_dev *dm1105)
+ {
+ rc_unregister_device(dm1105->ir.dev);
++ rc_free_device(dm1105->ir.dev);
+ }
+
+ static int dm1105_hw_init(struct dm1105_dev *dev)
+diff --git a/drivers/media/pci/mantis/mantis_input.c b/drivers/media/pci/mantis/mantis_input.c
+index 34c0d979240fda..edb4cacf55d229 100644
+--- a/drivers/media/pci/mantis/mantis_input.c
++++ b/drivers/media/pci/mantis/mantis_input.c
+@@ -72,5 +72,6 @@ EXPORT_SYMBOL_GPL(mantis_input_init);
+ void mantis_input_exit(struct mantis_pci *mantis)
+ {
+ rc_unregister_device(mantis->rc);
++ rc_free_device(mantis->rc);
+ }
+ EXPORT_SYMBOL_GPL(mantis_input_exit);
+diff --git a/drivers/media/pci/saa7134/saa7134-input.c b/drivers/media/pci/saa7134/saa7134-input.c
+index 468dbe8d552f82..d39537c95d9d3b 100644
+--- a/drivers/media/pci/saa7134/saa7134-input.c
++++ b/drivers/media/pci/saa7134/saa7134-input.c
+@@ -834,6 +834,7 @@ void saa7134_input_fini(struct saa7134_dev *dev)
+ return;
+
+ rc_unregister_device(dev->remote->dev);
++ rc_free_device(dev->remote->dev);
+ kfree(dev->remote);
+ dev->remote = NULL;
+ }
+diff --git a/drivers/media/pci/smipcie/smipcie-ir.c b/drivers/media/pci/smipcie/smipcie-ir.c
+index c0604d9c70119a..0bbe4fa2d5a84e 100644
+--- a/drivers/media/pci/smipcie/smipcie-ir.c
++++ b/drivers/media/pci/smipcie/smipcie-ir.c
+@@ -181,5 +181,6 @@ void smi_ir_exit(struct smi_dev *dev)
+
+ rc_unregister_device(rc_dev);
+ smi_ir_stop(ir);
++ rc_free_device(rc_dev);
+ ir->rc_dev = NULL;
+ }
+diff --git a/drivers/media/pci/ttpci/budget-ci.c b/drivers/media/pci/ttpci/budget-ci.c
+index 33f08adf4feb10..16973ac8e6a920 100644
+--- a/drivers/media/pci/ttpci/budget-ci.c
++++ b/drivers/media/pci/ttpci/budget-ci.c
+@@ -249,6 +249,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci)
+ cancel_work_sync(&budget_ci->ir.msp430_irq_bh_work);
+
+ rc_unregister_device(budget_ci->ir.dev);
++ rc_free_device(budget_ci->ir.dev);
+ }
+
+ static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
+diff --git a/drivers/media/rc/ati_remote.c b/drivers/media/rc/ati_remote.c
+index a733914a257424..f1fd4765651cac 100644
+--- a/drivers/media/rc/ati_remote.c
++++ b/drivers/media/rc/ati_remote.c
+@@ -921,7 +921,6 @@ static int ati_remote_probe(struct usb_interface *interface,
+ input_free_device(input_dev);
+ exit_unregister_device:
+ rc_unregister_device(rc_dev);
+- rc_dev = NULL;
+ exit_kill_urbs:
+ usb_kill_urb(ati_remote->irq_urb);
+ usb_kill_urb(ati_remote->out_urb);
+@@ -941,18 +940,19 @@ static void ati_remote_disconnect(struct usb_interface *interface)
+ struct ati_remote *ati_remote;
+
+ ati_remote = usb_get_intfdata(interface);
+- usb_set_intfdata(interface, NULL);
+ if (!ati_remote) {
+ dev_warn(&interface->dev, "%s - null device?\n", __func__);
+ return;
+ }
+
++ rc_unregister_device(ati_remote->rdev);
++ usb_set_intfdata(interface, NULL);
+ usb_kill_urb(ati_remote->irq_urb);
+ usb_kill_urb(ati_remote->out_urb);
+ if (ati_remote->idev)
+ input_unregister_device(ati_remote->idev);
+- rc_unregister_device(ati_remote->rdev);
+ ati_remote_free_buffers(ati_remote);
++ rc_free_device(ati_remote->rdev);
+ kfree(ati_remote);
+ }
+
+diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
+index d6c54a3bccc26d..136fc4192265da 100644
+--- a/drivers/media/rc/ene_ir.c
++++ b/drivers/media/rc/ene_ir.c
+@@ -1090,7 +1090,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
+ release_region(dev->hw_io, ENE_IO_SIZE);
+ exit_unregister_device:
+ rc_unregister_device(rdev);
+- rdev = NULL;
+ exit_free_dev_rdev:
+ rc_free_device(rdev);
+ kfree(dev);
+@@ -1110,6 +1109,7 @@ static void ene_remove(struct pnp_dev *pnp_dev)
+ ene_rx_restore_hw_buffer(dev);
+ spin_unlock_irqrestore(&dev->hw_lock, flags);
+
++ rc_free_device(dev->rdev);
+ free_irq(dev->irq, dev);
+ release_region(dev->hw_io, ENE_IO_SIZE);
+ kfree(dev);
+diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
+index 3fb0968efd57d3..9b789097cdd4c3 100644
+--- a/drivers/media/rc/fintek-cir.c
++++ b/drivers/media/rc/fintek-cir.c
+@@ -568,6 +568,7 @@ static void fintek_remove(struct pnp_dev *pdev)
+ struct fintek_dev *fintek = pnp_get_drvdata(pdev);
+ unsigned long flags;
+
++ rc_unregister_device(fintek->rdev);
+ spin_lock_irqsave(&fintek->fintek_lock, flags);
+ /* disable CIR */
+ fintek_disable_cir(fintek);
+@@ -580,7 +581,7 @@ static void fintek_remove(struct pnp_dev *pdev)
+ free_irq(fintek->cir_irq, fintek);
+ release_region(fintek->cir_addr, fintek->cir_port_len);
+
+- rc_unregister_device(fintek->rdev);
++ rc_free_device(fintek->rdev);
+
+ kfree(fintek);
+ }
+diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c
+index e7e31776453c11..439f95e6879fc4 100644
+--- a/drivers/media/rc/igorplugusb.c
++++ b/drivers/media/rc/igorplugusb.c
+@@ -247,6 +247,7 @@ static void igorplugusb_disconnect(struct usb_interface *intf)
+ usb_set_intfdata(intf, NULL);
+ usb_unpoison_urb(ir->urb);
+ usb_free_urb(ir->urb);
++ rc_free_device(ir->rc);
+ kfree(ir->buf_in);
+ kfree(ir->request);
+ }
+diff --git a/drivers/media/rc/iguanair.c b/drivers/media/rc/iguanair.c
+index 8af94246e5916e..7bd6dd7254157a 100644
+--- a/drivers/media/rc/iguanair.c
++++ b/drivers/media/rc/iguanair.c
+@@ -500,6 +500,7 @@ static void iguanair_disconnect(struct usb_interface *intf)
+ usb_set_intfdata(intf, NULL);
+ usb_kill_urb(ir->urb_in);
+ usb_kill_urb(ir->urb_out);
++ rc_free_device(ir->rc);
+ usb_free_urb(ir->urb_in);
+ usb_free_urb(ir->urb_out);
+ usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
+diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c
+index 63f6f5b36838d0..f30adf4d8444dd 100644
+--- a/drivers/media/rc/img-ir/img-ir-hw.c
++++ b/drivers/media/rc/img-ir/img-ir-hw.c
+@@ -1118,9 +1118,10 @@ void img_ir_remove_hw(struct img_ir_priv *priv)
+ struct rc_dev *rdev = hw->rdev;
+ if (!rdev)
+ return;
++ rc_unregister_device(rdev);
+ img_ir_set_decoder(priv, NULL, 0);
+ hw->rdev = NULL;
+- rc_unregister_device(rdev);
++ rc_free_device(rdev);
+ #ifdef CONFIG_COMMON_CLK
+ if (!IS_ERR(priv->clk))
+ clk_notifier_unregister(priv->clk, &hw->clk_nb);
+diff --git a/drivers/media/rc/img-ir/img-ir-raw.c b/drivers/media/rc/img-ir/img-ir-raw.c
+index 92fb7b555a0f65..f1460d4acf3e8a 100644
+--- a/drivers/media/rc/img-ir/img-ir-raw.c
++++ b/drivers/media/rc/img-ir/img-ir-raw.c
+@@ -136,6 +136,7 @@ void img_ir_remove_raw(struct img_ir_priv *priv)
+ if (!rdev)
+ return;
+
++ rc_unregister_device(rdev);
+ /* switch off and disable raw (edge) interrupts */
+ spin_lock_irq(&priv->lock);
+ raw->rdev = NULL;
+@@ -145,7 +146,7 @@ void img_ir_remove_raw(struct img_ir_priv *priv)
+ img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
+ spin_unlock_irq(&priv->lock);
+
+- rc_unregister_device(rdev);
++ rc_free_device(rdev);
+
+ timer_delete_sync(&raw->timer);
+ }
+diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
+index 35b9e07003d889..48534bb52e4d04 100644
+--- a/drivers/media/rc/imon.c
++++ b/drivers/media/rc/imon.c
+@@ -2541,9 +2541,10 @@ static void imon_disconnect(struct usb_interface *interface)
+
+ if (ifnum == 0) {
+ ictx->dev_present_intf0 = false;
++ rc_unregister_device(ictx->rdev);
+ usb_kill_urb(ictx->rx_urb_intf0);
+ input_unregister_device(ictx->idev);
+- rc_unregister_device(ictx->rdev);
++ rc_free_device(ictx->rdev);
+ if (ictx->display_supported) {
+ if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
+ usb_deregister_dev(interface, &imon_lcd_class);
+diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c
+index afd80d2350c6d3..bb0f95833df57e 100644
+--- a/drivers/media/rc/ir-hix5hd2.c
++++ b/drivers/media/rc/ir-hix5hd2.c
+@@ -331,7 +331,6 @@ static int hix5hd2_ir_probe(struct platform_device *pdev)
+
+ regerr:
+ rc_unregister_device(rdev);
+- rdev = NULL;
+ clkerr:
+ clk_disable_unprepare(priv->clock);
+ err:
+@@ -346,6 +345,7 @@ static void hix5hd2_ir_remove(struct platform_device *pdev)
+
+ clk_disable_unprepare(priv->clock);
+ rc_unregister_device(priv->rdev);
++ rc_free_device(priv->rdev);
+ }
+
+ #ifdef CONFIG_PM_SLEEP
+diff --git a/drivers/media/rc/ir_toy.c b/drivers/media/rc/ir_toy.c
+index 533faa11751744..e79de56997a426 100644
+--- a/drivers/media/rc/ir_toy.c
++++ b/drivers/media/rc/ir_toy.c
+@@ -536,6 +536,7 @@ static void irtoy_disconnect(struct usb_interface *intf)
+ usb_free_urb(ir->urb_out);
+ usb_kill_urb(ir->urb_in);
+ usb_free_urb(ir->urb_in);
++ rc_free_device(ir->rc);
+ kfree(ir->in);
+ kfree(ir->out);
+ kfree(ir);
+diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
+index 2bacecb022623e..23afbafb557488 100644
+--- a/drivers/media/rc/ite-cir.c
++++ b/drivers/media/rc/ite-cir.c
+@@ -1414,7 +1414,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
+ release_region(itdev->cir_addr, itdev->params->io_region_size);
+ exit_unregister_device:
+ rc_unregister_device(rdev);
+- rdev = NULL;
+ exit_free_dev_rdev:
+ rc_free_device(rdev);
+ kfree(itdev);
+@@ -1439,6 +1438,7 @@ static void ite_remove(struct pnp_dev *pdev)
+ release_region(dev->cir_addr, dev->params->io_region_size);
+
+ rc_unregister_device(dev->rdev);
++ rc_free_device(dev->rdev);
+
+ kfree(dev);
+ }
+diff --git a/drivers/media/rc/mceusb.c b/drivers/media/rc/mceusb.c
+index 044767eb3a38c9..a4c94fdf767ca1 100644
+--- a/drivers/media/rc/mceusb.c
++++ b/drivers/media/rc/mceusb.c
+@@ -1850,6 +1850,7 @@ static void mceusb_dev_disconnect(struct usb_interface *intf)
+ usb_free_urb(ir->urb_in);
+ usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);
+ usb_put_dev(dev);
++ rc_free_device(ir->rc);
+
+ kfree(ir);
+ }
+diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
+index 5dafe11f61c6b1..76c3d1307f9f1b 100644
+--- a/drivers/media/rc/rc-ir-raw.c
++++ b/drivers/media/rc/rc-ir-raw.c
+@@ -648,9 +648,6 @@ int ir_raw_event_register(struct rc_dev *dev)
+
+ void ir_raw_event_free(struct rc_dev *dev)
+ {
+- if (!dev)
+- return;
+-
+ kfree(dev->raw);
+ dev->raw = NULL;
+ }
+@@ -674,8 +671,6 @@ void ir_raw_event_unregister(struct rc_dev *dev)
+
+ lirc_bpf_free(dev);
+
+- ir_raw_event_free(dev);
+-
+ /*
+ * A user can be calling bpf(BPF_PROG_{QUERY|ATTACH|DETACH}), so
+ * ensure that the raw member is null on unlock; this is how
+diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
+index 8288366f891fc9..a108b057b5fd56 100644
+--- a/drivers/media/rc/rc-loopback.c
++++ b/drivers/media/rc/rc-loopback.c
+@@ -263,6 +263,7 @@ static int __init loop_init(void)
+ static void __exit loop_exit(void)
+ {
+ rc_unregister_device(loopdev.dev);
++ rc_free_device(loopdev.dev);
+ }
+
+ module_init(loop_init);
+diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
+index b9bf5cdcde4ae3..6bdf32cb4a17d8 100644
+--- a/drivers/media/rc/rc-main.c
++++ b/drivers/media/rc/rc-main.c
+@@ -1611,6 +1611,7 @@ static void rc_dev_release(struct device *device)
+ {
+ struct rc_dev *dev = to_rc_dev(device);
+
++ ir_raw_event_free(dev);
+ kfree(dev);
+ }
+
+@@ -1773,7 +1774,6 @@ struct rc_dev *devm_rc_allocate_device(struct device *dev,
+ }
+
+ rc->dev.parent = dev;
+- rc->managed_alloc = true;
+ *dr = rc;
+ devres_add(dev, dr);
+
+@@ -2042,11 +2042,7 @@ void rc_unregister_device(struct rc_dev *dev)
+ device_del(&dev->dev);
+
+ ida_free(&rc_ida, dev->minor);
+-
+- if (!dev->managed_alloc)
+- rc_free_device(dev);
+ }
+-
+ EXPORT_SYMBOL_GPL(rc_unregister_device);
+
+ /*
+diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
+index a49173f54a4d0e..b8289327f6a206 100644
+--- a/drivers/media/rc/redrat3.c
++++ b/drivers/media/rc/redrat3.c
+@@ -1133,11 +1133,13 @@ static void redrat3_dev_disconnect(struct usb_interface *intf)
+ {
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct redrat3_dev *rr3 = usb_get_intfdata(intf);
++ struct rc_dev *rc = rr3->rc;
+
+ usb_set_intfdata(intf, NULL);
+- rc_unregister_device(rr3->rc);
++ rc_unregister_device(rc);
+ led_classdev_unregister(&rr3->led);
+ redrat3_delete(rr3, udev);
++ rc_free_device(rc);
+ }
+
+ static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message)
+diff --git a/drivers/media/rc/st_rc.c b/drivers/media/rc/st_rc.c
+index 6b70bac5f45d6c..0ba06bfc9e14b6 100644
+--- a/drivers/media/rc/st_rc.c
++++ b/drivers/media/rc/st_rc.c
+@@ -203,6 +203,7 @@ static void st_rc_remove(struct platform_device *pdev)
+ device_init_wakeup(&pdev->dev, false);
+ clk_disable_unprepare(rc_dev->sys_clock);
+ rc_unregister_device(rc_dev->rdev);
++ rc_free_device(rc_dev->rdev);
+ }
+
+ static int st_rc_open(struct rc_dev *rdev)
+@@ -334,7 +335,6 @@ static int st_rc_probe(struct platform_device *pdev)
+ return ret;
+ rcerr:
+ rc_unregister_device(rdev);
+- rdev = NULL;
+ clkerr:
+ clk_disable_unprepare(rc_dev->sys_clock);
+ err:
+diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c
+index 8e9b156e430022..8c85b9f30a3a96 100644
+--- a/drivers/media/rc/streamzap.c
++++ b/drivers/media/rc/streamzap.c
+@@ -392,15 +392,16 @@ static void streamzap_disconnect(struct usb_interface *interface)
+ struct streamzap_ir *sz = usb_get_intfdata(interface);
+ struct usb_device *usbdev = interface_to_usbdev(interface);
+
+- usb_set_intfdata(interface, NULL);
+-
+ if (!sz)
+ return;
+
+- usb_kill_urb(sz->urb_in);
+ rc_unregister_device(sz->rdev);
++ usb_set_intfdata(interface, NULL);
++
++ usb_kill_urb(sz->urb_in);
+ usb_free_urb(sz->urb_in);
+ usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
++ rc_free_device(sz->rdev);
+
+ kfree(sz);
+ }
+diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
+index 92ef4e7c6f69fc..cb4c56bf0752a8 100644
+--- a/drivers/media/rc/sunxi-cir.c
++++ b/drivers/media/rc/sunxi-cir.c
+@@ -371,6 +371,7 @@ static void sunxi_ir_remove(struct platform_device *pdev)
+ struct sunxi_ir *ir = platform_get_drvdata(pdev);
+
+ rc_unregister_device(ir->rc);
++ rc_free_device(ir->rc);
+ sunxi_ir_hw_exit(&pdev->dev);
+ }
+
+diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
+index dde446a95eaa93..a670d4b008cb0d 100644
+--- a/drivers/media/rc/ttusbir.c
++++ b/drivers/media/rc/ttusbir.c
+@@ -336,7 +336,6 @@ static int ttusbir_probe(struct usb_interface *intf,
+ return 0;
+ out3:
+ rc_unregister_device(rc);
+- rc = NULL;
+ out2:
+ led_classdev_unregister(&tt->led);
+ out:
+@@ -378,6 +377,7 @@ static void ttusbir_disconnect(struct usb_interface *intf)
+ usb_kill_urb(tt->bulk_urb);
+ usb_free_urb(tt->bulk_urb);
+ kfree(tt->bulk_buffer);
++ rc_free_device(tt->rc);
+ usb_set_intfdata(intf, NULL);
+ kfree(tt);
+ }
+diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
+index 25884a79985c8a..14d8b58e283980 100644
+--- a/drivers/media/rc/winbond-cir.c
++++ b/drivers/media/rc/winbond-cir.c
+@@ -1132,7 +1132,6 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
+ release_region(data->wbase, WAKEUP_IOMEM_LEN);
+ exit_unregister_device:
+ rc_unregister_device(data->dev);
+- data->dev = NULL;
+ exit_free_rc:
+ rc_free_device(data->dev);
+ exit_unregister_led:
+@@ -1163,6 +1162,7 @@ wbcir_remove(struct pnp_dev *device)
+ wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
+
+ rc_unregister_device(data->dev);
++ rc_free_device(data->dev);
+
+ led_classdev_unregister(&data->led);
+
+diff --git a/drivers/media/rc/xbox_remote.c b/drivers/media/rc/xbox_remote.c
+index 0c9c855ced729c..80b7c247932a8f 100644
+--- a/drivers/media/rc/xbox_remote.c
++++ b/drivers/media/rc/xbox_remote.c
+@@ -283,14 +283,15 @@ static void xbox_remote_disconnect(struct usb_interface *interface)
+ struct xbox_remote *xbox_remote;
+
+ xbox_remote = usb_get_intfdata(interface);
+- usb_set_intfdata(interface, NULL);
+ if (!xbox_remote) {
+ dev_warn(&interface->dev, "%s - null device?\n", __func__);
+ return;
+ }
+
+- usb_kill_urb(xbox_remote->irq_urb);
+ rc_unregister_device(xbox_remote->rdev);
++ usb_set_intfdata(interface, NULL);
++ usb_kill_urb(xbox_remote->irq_urb);
++ rc_free_device(xbox_remote->rdev);
+ usb_free_urb(xbox_remote->irq_urb);
+ kfree(xbox_remote->inbuf);
+ kfree(xbox_remote);
+diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c
+index 3d3368202cd018..283ad2c6288cd5 100644
+--- a/drivers/media/usb/au0828/au0828-input.c
++++ b/drivers/media/usb/au0828/au0828-input.c
+@@ -357,6 +357,7 @@ void au0828_rc_unregister(struct au0828_dev *dev)
+ return;
+
+ rc_unregister_device(ir->rc);
++ rc_free_device(ir->rc);
+
+ /* done */
+ kfree(ir);
+diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+index f1c79f351ec8de..17e8961179d14b 100644
+--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
++++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+@@ -187,6 +187,7 @@ static int dvb_usbv2_remote_exit(struct dvb_usb_device *d)
+ if (d->rc_dev) {
+ cancel_delayed_work_sync(&d->rc_query_work);
+ rc_unregister_device(d->rc_dev);
++ rc_free_device(d->rc_dev);
+ d->rc_dev = NULL;
+ }
+
+diff --git a/drivers/media/usb/dvb-usb/dvb-usb-remote.c b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
+index 65e2c9e2cdc99f..6dc11718dfb985 100644
+--- a/drivers/media/usb/dvb-usb/dvb-usb-remote.c
++++ b/drivers/media/usb/dvb-usb/dvb-usb-remote.c
+@@ -347,10 +347,12 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d)
+ {
+ if (d->state & DVB_USB_STATE_REMOTE) {
+ cancel_delayed_work_sync(&d->rc_query_work);
+- if (d->props.rc.mode == DVB_RC_LEGACY)
++ if (d->props.rc.mode == DVB_RC_LEGACY) {
+ input_unregister_device(d->input_dev);
+- else
++ } else {
+ rc_unregister_device(d->rc_dev);
++ rc_free_device(d->rc_dev);
++ }
+ }
+ d->state &= ~DVB_USB_STATE_REMOTE;
+ return 0;
+diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
+index 5f3b00869bdbc9..26f333b5be7325 100644
+--- a/drivers/media/usb/em28xx/em28xx-input.c
++++ b/drivers/media/usb/em28xx/em28xx-input.c
+@@ -853,6 +853,7 @@ static int em28xx_ir_fini(struct em28xx *dev)
+ goto ref_put;
+
+ rc_unregister_device(ir->rc);
++ rc_free_device(ir->rc);
+
+ kfree(ir->i2c_client);
+
+diff --git a/drivers/staging/media/av7110/av7110_ir.c b/drivers/staging/media/av7110/av7110_ir.c
+index 68b3979ba5f20c..fdae467fd7ab81 100644
+--- a/drivers/staging/media/av7110/av7110_ir.c
++++ b/drivers/staging/media/av7110/av7110_ir.c
+@@ -151,6 +151,7 @@ int av7110_ir_init(struct av7110 *av7110)
+ void av7110_ir_exit(struct av7110 *av7110)
+ {
+ rc_unregister_device(av7110->ir.rcdev);
++ rc_free_device(av7110->ir.rcdev);
+ }
+
+ //MODULE_AUTHOR("Holger Waechtler <holger@convergence.de>, Oliver Endriss <o.endriss@gmx.de>");
+diff --git a/include/media/rc-core.h b/include/media/rc-core.h
+index 35c7a0546f02ee..7c964b5ad79269 100644
+--- a/include/media/rc-core.h
++++ b/include/media/rc-core.h
+@@ -81,7 +81,6 @@ struct lirc_fh {
+ /**
+ * struct rc_dev - represents a remote control device
+ * @dev: driver model's view of this device
+- * @managed_alloc: devm_rc_allocate_device was used to create rc_dev
+ * @registered: set to true by rc_register_device(), false by
+ * rc_unregister_device
+ * @idle: used to keep track of RX state
+@@ -156,7 +155,6 @@ struct lirc_fh {
+ */
+ struct rc_dev {
+ struct device dev;
+- bool managed_alloc;
+ bool registered;
+ bool idle;
+ bool encode_wakeup;
+--
+2.53.0
+
--- /dev/null
+From e5e5d46bac5151188892f4c7801d3276e3301b34 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Apr 2026 23:03:09 +0200
+Subject: media: rc: ttusbir: fix inverted error logic
+
+From: Oliver Neukum <oneukum@suse.com>
+
+[ Upstream commit 646ebdd3105809d84ed04aa9e92e47e89cc44502 ]
+
+We have to report ENOMEM if no buffer is allocated.
+Typo dropped a "!". Restore it.
+
+Fixes: 50acaad3d202 ("media: rc: ttusbir: respect DMA coherency rules")
+Cc: stable@vger.kernel.org
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Sean Young <sean@mess.org>
+Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/rc/ttusbir.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
+index a670d4b008cb0d..3452b5aefd2848 100644
+--- a/drivers/media/rc/ttusbir.c
++++ b/drivers/media/rc/ttusbir.c
+@@ -191,7 +191,7 @@ static int ttusbir_probe(struct usb_interface *intf,
+ tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+ buffer = kzalloc(5, GFP_KERNEL);
+ rc = rc_allocate_device(RC_DRIVER_IR_RAW);
+- if (!tt || !rc || buffer) {
++ if (!tt || !rc || !buffer) {
+ ret = -ENOMEM;
+ goto out;
+ }
+--
+2.53.0
+
--- /dev/null
+From bda2bf3f5162bc1c99d8dd439ad2af1a37dcfec2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 14:06:40 +0200
+Subject: net: Avoid checksumming unreadable skb tail on trim
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Björn Töpel <bjorn@kernel.org>
+
+[ Upstream commit 2e357f002c61fd76fd8f12468744a06a5ec48eaa ]
+
+pskb_trim_rcsum_slow() keeps CHECKSUM_COMPLETE valid by subtracting
+the checksum of the bytes removed from the skb tail. That assumes the
+removed bytes can be read.
+
+io_uring zcrx skbs may contain unreadable net_iov frags. With fbnic
+header/data split, small TCP/IPv4 packets can carry Ethernet padding
+in such a frag. ip_rcv_core() trims the skb to iph->tot_len before TCP
+sees it, and the CHECKSUM_COMPLETE adjustment then calls
+skb_checksum() on the padding.
+
+This is exposed by IPv4 because small TCP/IPv4 frames can be shorter
+than the Ethernet minimum payload. TCP/IPv6 frames are large enough in
+the normal zcrx path, so they do not hit the same padding trim.
+
+Keep the existing checksum adjustment for readable skbs. If the
+remaining packet is fully linear, drop CHECKSUM_COMPLETE and let the
+stack validate the packet after trimming. If unreadable payload would
+remain, fail the trim; the checksum cannot be adjusted without reading
+the trimmed tail.
+
+Also clear skb->unreadable when trimming removes all frags.
+
+Fixes: 65249feb6b3d ("net: add support for skbs with unreadable frags")
+Signed-off-by: Björn Töpel <bjorn@kernel.org>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Link: https://patch.msgid.link/20260522120643.242974-1-bjorn@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/skbuff.c | 31 +++++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index a8911f1b90c15d..6618bfa70ca444 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -2739,6 +2739,8 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
+ skb->data_len = 0;
+ skb_set_tail_pointer(skb, len);
+ }
++ if (!skb_shinfo(skb)->nr_frags && !skb_has_frag_list(skb))
++ skb->unreadable = 0;
+
+ if (!skb->sk || skb->destructor == sock_edemux)
+ skb_condense(skb);
+@@ -2746,16 +2748,37 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
+ }
+ EXPORT_SYMBOL(___pskb_trim);
+
++static int pskb_trim_rcsum_complete(struct sk_buff *skb, unsigned int len)
++{
++ int delta = skb->len - len;
++
++ if (skb_frags_readable(skb)) {
++ skb->csum = csum_block_sub(skb->csum,
++ skb_checksum(skb, len, delta, 0),
++ len);
++ return 0;
++ }
++
++ if (len > skb_headlen(skb))
++ return -EFAULT;
++
++ /* The trimmed bytes are unreadable, but the remaining packet can be
++ * checksummed by software after trimming.
++ */
++ skb->ip_summed = CHECKSUM_NONE;
++ return 0;
++}
++
+ /* Note : use pskb_trim_rcsum() instead of calling this directly
+ */
+ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len)
+ {
+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
+- int delta = skb->len - len;
++ int err;
+
+- skb->csum = csum_block_sub(skb->csum,
+- skb_checksum(skb, len, delta, 0),
+- len);
++ err = pskb_trim_rcsum_complete(skb, len);
++ if (err)
++ return err;
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ int hdlen = (len > skb_headlen(skb)) ? skb_headlen(skb) : len;
+ int offset = skb_checksum_start_offset(skb) + skb->csum_offset;
+--
+2.53.0
+
--- /dev/null
+From 47a42c35e7ae4c6e580abf2c6475186bb80bdaec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:17 -0400
+Subject: net/handshake: Pass negative errno through handshake_complete()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 6b22d433aa13f68e3cd9534ca9a5f4277bfa01c2 ]
+
+handshake_complete() declares status as unsigned int and
+tls_handshake_done() negates that value (-status) before handing
+it to the TLS consumer. Consumers match on negative errno
+constants -- xs_tls_handshake_done() has
+
+ switch (status) {
+ case 0:
+ case -EACCES:
+ case -ETIMEDOUT:
+ lower_transport->xprt_err = status;
+ break;
+ default:
+ lower_transport->xprt_err = -EACCES;
+ }
+
+so the API as designed expects callers to pass positive errno
+values that the tlshd shim then negates.
+
+Three internal callers in handshake_nl_accept_doit(), the
+net-exit drain, and a kunit test follow kernel convention and
+pass negative errnos -- -EIO, -ETIMEDOUT, -ETIMEDOUT. The
+implicit conversion to unsigned int turns -ETIMEDOUT into
+0xFFFFFF92; the subsequent -status in tls_handshake_done()
+wraps back to 110, the consumer's switch falls through, and
+the xprt reports -EACCES on what should be -ETIMEDOUT or -EIO.
+
+Fix the API rather than the call sites. The natural kernel
+convention is negative errno in, negative errno out. Change
+handshake_complete() and hp_done to take int status, drop the
+negation in tls_handshake_done(), and negate once in
+handshake_nl_done_doit() where status arrives from the wire
+as an unsigned netlink attribute. The three internal callers
+were already correct under that convention and need no change.
+
+At the same wire boundary, declare MAX_ERRNO as the netlink
+policy upper bound for HANDSHAKE_A_DONE_STATUS. Attribute
+validation rejects out-of-range values before
+handshake_nl_done_doit() runs, and negating a bounded u32 there
+stays within int range -- closing the UBSAN-visible signed-
+integer overflow that an unconstrained u32 would invoke.
+
+Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-3-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/netlink/specs/handshake.yaml | 8 ++++++++
+ net/handshake/genl.c | 3 ++-
+ net/handshake/genl.h | 1 +
+ net/handshake/handshake-test.c | 2 +-
+ net/handshake/handshake.h | 4 ++--
+ net/handshake/netlink.c | 2 +-
+ net/handshake/request.c | 2 +-
+ net/handshake/tlshd.c | 4 ++--
+ 8 files changed, 18 insertions(+), 8 deletions(-)
+
+diff --git a/Documentation/netlink/specs/handshake.yaml b/Documentation/netlink/specs/handshake.yaml
+index 95c3fade7a8d7b..1024297b38513a 100644
+--- a/Documentation/netlink/specs/handshake.yaml
++++ b/Documentation/netlink/specs/handshake.yaml
+@@ -12,6 +12,12 @@ protocol: genetlink
+ doc: Netlink protocol to request a transport layer security handshake.
+
+ definitions:
++ -
++ type: const
++ name: max-errno
++ value: 4095
++ header: linux/err.h
++ scope: kernel
+ -
+ type: enum
+ name: handler-class
+@@ -80,6 +86,8 @@ attribute-sets:
+ -
+ name: status
+ type: u32
++ checks:
++ max: max-errno
+ -
+ name: sockfd
+ type: s32
+diff --git a/net/handshake/genl.c b/net/handshake/genl.c
+index f55d14d7b7269d..a5fa8b27f22423 100644
+--- a/net/handshake/genl.c
++++ b/net/handshake/genl.c
+@@ -9,6 +9,7 @@
+ #include "genl.h"
+
+ #include <uapi/linux/handshake.h>
++#include <linux/err.h>
+
+ /* HANDSHAKE_CMD_ACCEPT - do */
+ static const struct nla_policy handshake_accept_nl_policy[HANDSHAKE_A_ACCEPT_HANDLER_CLASS + 1] = {
+@@ -17,7 +18,7 @@ static const struct nla_policy handshake_accept_nl_policy[HANDSHAKE_A_ACCEPT_HAN
+
+ /* HANDSHAKE_CMD_DONE - do */
+ static const struct nla_policy handshake_done_nl_policy[HANDSHAKE_A_DONE_REMOTE_AUTH + 1] = {
+- [HANDSHAKE_A_DONE_STATUS] = { .type = NLA_U32, },
++ [HANDSHAKE_A_DONE_STATUS] = NLA_POLICY_MAX(NLA_U32, MAX_ERRNO),
+ [HANDSHAKE_A_DONE_SOCKFD] = { .type = NLA_S32, },
+ [HANDSHAKE_A_DONE_REMOTE_AUTH] = { .type = NLA_U32, },
+ };
+diff --git a/net/handshake/genl.h b/net/handshake/genl.h
+index ae72a596f6cc3e..684e5fd684481b 100644
+--- a/net/handshake/genl.h
++++ b/net/handshake/genl.h
+@@ -10,6 +10,7 @@
+ #include <net/genetlink.h>
+
+ #include <uapi/linux/handshake.h>
++#include <linux/err.h>
+
+ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info);
+ int handshake_nl_done_doit(struct sk_buff *skb, struct genl_info *info);
+diff --git a/net/handshake/handshake-test.c b/net/handshake/handshake-test.c
+index 55442b2f518afb..df3948e807a0fd 100644
+--- a/net/handshake/handshake-test.c
++++ b/net/handshake/handshake-test.c
+@@ -25,7 +25,7 @@ static int test_accept_func(struct handshake_req *req, struct genl_info *info,
+ return 0;
+ }
+
+-static void test_done_func(struct handshake_req *req, unsigned int status,
++static void test_done_func(struct handshake_req *req, int status,
+ struct genl_info *info)
+ {
+ }
+diff --git a/net/handshake/handshake.h b/net/handshake/handshake.h
+index a48163765a7a1d..2289b0e274f40a 100644
+--- a/net/handshake/handshake.h
++++ b/net/handshake/handshake.h
+@@ -57,7 +57,7 @@ struct handshake_proto {
+ int (*hp_accept)(struct handshake_req *req,
+ struct genl_info *info, int fd);
+ void (*hp_done)(struct handshake_req *req,
+- unsigned int status,
++ int status,
+ struct genl_info *info);
+ void (*hp_destroy)(struct handshake_req *req);
+ };
+@@ -86,7 +86,7 @@ struct handshake_req *handshake_req_hash_lookup(struct sock *sk);
+ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class);
+ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ gfp_t flags);
+-void handshake_complete(struct handshake_req *req, unsigned int status,
++void handshake_complete(struct handshake_req *req, int status,
+ struct genl_info *info);
+ bool handshake_req_cancel(struct sock *sk);
+
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index 394e270cc505cb..d8211e0ba75c69 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -161,7 +161,7 @@ int handshake_nl_done_doit(struct sk_buff *skb, struct genl_info *info)
+
+ status = -EIO;
+ if (info->attrs[HANDSHAKE_A_DONE_STATUS])
+- status = nla_get_u32(info->attrs[HANDSHAKE_A_DONE_STATUS]);
++ status = -(int)nla_get_u32(info->attrs[HANDSHAKE_A_DONE_STATUS]);
+
+ handshake_complete(req, status, info);
+ sockfd_put(sock);
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 654e55b141cded..62efb7e32730ea 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -284,7 +284,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ }
+ EXPORT_SYMBOL(handshake_req_submit);
+
+-void handshake_complete(struct handshake_req *req, unsigned int status,
++void handshake_complete(struct handshake_req *req, int status,
+ struct genl_info *info)
+ {
+ struct sock *sk = req->hr_sk;
+diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c
+index af294c6cc71731..7567150c2a4f95 100644
+--- a/net/handshake/tlshd.c
++++ b/net/handshake/tlshd.c
+@@ -93,7 +93,7 @@ static void tls_handshake_remote_peerids(struct tls_handshake_req *treq,
+ *
+ */
+ static void tls_handshake_done(struct handshake_req *req,
+- unsigned int status, struct genl_info *info)
++ int status, struct genl_info *info)
+ {
+ struct tls_handshake_req *treq = handshake_req_private(req);
+
+@@ -104,7 +104,7 @@ static void tls_handshake_done(struct handshake_req *req,
+ if (!status)
+ set_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags);
+
+- treq->th_consumer_done(treq->th_consumer_data, -status,
++ treq->th_consumer_done(treq->th_consumer_data, status,
+ treq->th_peerid[0]);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From a33244e7d99f1609cfe06f3fe1cff7cf9163baaa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:15 -0400
+Subject: net/handshake: Use spin_lock_bh for hn_lock
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit cc993e0927ec8bd98ea33377ada03295fcda0f24 ]
+
+nvmet_tcp_state_change(), a socket callback that runs in BH context,
+can reach handshake_req_cancel() via nvmet_tcp_schedule_release_queue()
+and tls_handshake_cancel(). handshake_req_cancel() acquires
+hn->hn_lock with plain spin_lock(). If a process-context thread on
+the same CPU holds hn->hn_lock when a softirq invokes the cancel path,
+the lock attempt deadlocks. This is the only caller that invokes
+tls_handshake_cancel() from BH context; every other consumer calls it
+from process context.
+
+Deferring the cancel to process context in the NVMe target is not
+straightforward: nvmet_tcp_schedule_release_queue() must call
+tls_handshake_cancel() atomically with its state transition to
+DISCONNECTING. If the cancel were deferred, the handshake completion
+callback could fire in the window before the cancel runs, observe the
+unexpected state, and return without dropping its kref on the queue.
+Reworking that interlock is considerably more invasive than hardening
+the handshake lock. Convert all hn->hn_lock acquisitions from
+spin_lock/spin_unlock to spin_lock_bh/spin_unlock_bh so the lock is
+never taken with softirqs enabled.
+
+Fixes: 675b453e0241 ("nvmet-tcp: enable TLS handshake upcall")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-1-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/handshake/netlink.c | 4 ++--
+ net/handshake/request.c | 14 +++++++-------
+ net/handshake/tlshd.c | 2 ++
+ 3 files changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index 7e46d130dce2cd..394e270cc505cb 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -203,10 +203,10 @@ static void __net_exit handshake_net_exit(struct net *net)
+ * accepted and are in progress will be destroyed when
+ * the socket is closed.
+ */
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ set_bit(HANDSHAKE_F_NET_DRAINING, &hn->hn_flags);
+ list_splice_init(&requests, &hn->hn_requests);
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ while (!list_empty(&requests)) {
+ req = list_first_entry(&requests, struct handshake_req, hr_list);
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 6b7e3e0bf3996e..654e55b141cded 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -167,12 +167,12 @@ static bool remove_pending(struct handshake_net *hn, struct handshake_req *req)
+ {
+ bool ret = false;
+
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ if (!list_empty(&req->hr_list)) {
+ __remove_pending_locked(hn, req);
+ ret = true;
+ }
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ return ret;
+ }
+@@ -182,7 +182,7 @@ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class)
+ struct handshake_req *req, *pos;
+
+ req = NULL;
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ list_for_each_entry(pos, &hn->hn_requests, hr_list) {
+ if (pos->hr_proto->hp_handler_class != class)
+ continue;
+@@ -190,7 +190,7 @@ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class)
+ req = pos;
+ break;
+ }
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ return req;
+ }
+@@ -249,7 +249,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ if (READ_ONCE(hn->hn_pending) >= hn->hn_pending_max)
+ goto out_err;
+
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ ret = -EOPNOTSUPP;
+ if (test_bit(HANDSHAKE_F_NET_DRAINING, &hn->hn_flags))
+ goto out_unlock;
+@@ -258,7 +258,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ goto out_unlock;
+ if (!__add_pending_locked(hn, req))
+ goto out_unlock;
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ ret = handshake_genl_notify(net, req->hr_proto, flags);
+ if (ret) {
+@@ -274,7 +274,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ return 0;
+
+ out_unlock:
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+ out_err:
+ /* Restore original destructor so socket teardown still runs on failure */
+ req->hr_sk->sk_destruct = req->hr_odestruct;
+diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c
+index 8f9532a15f43f9..af294c6cc71731 100644
+--- a/net/handshake/tlshd.c
++++ b/net/handshake/tlshd.c
+@@ -425,6 +425,8 @@ EXPORT_SYMBOL(tls_server_hello_psk);
+ * Request cancellation races with request completion. To determine
+ * who won, callers examine the return value from this function.
+ *
++ * Context: May be called from process or softirq context.
++ *
+ * Return values:
+ * %true - Uncompleted handshake request was canceled
+ * %false - Handshake request already completed or not found
+--
+2.53.0
+
--- /dev/null
+From 08e4faeb7394f9a82e7ab35363657b40585aa62d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 22:45:24 +0800
+Subject: net: hibmcge: disable Relaxed Ordering to fix RX packet corruption
+
+From: Jijie Shao <shaojijie@huawei.com>
+
+[ Upstream commit 463a1271aa26eac992851b9d98cc75bc3cd4a1ed ]
+
+When SMMU is disabled, the hibmcge driver may receive corrupted packets.
+The hardware writes packet data and descriptors to the same page, but
+with Relaxed Ordering enabled, PCI write transactions may not be
+strictly ordered. This can cause the driver to observe a valid
+descriptor before the corresponding packet data is fully written.
+
+Fix this by clearing PCI_EXP_DEVCTL_RELAX_EN in the PCI bridge control
+register to ensure strict write ordering between packet data and
+descriptors.
+
+Fixes: f72e25594061 ("net: hibmcge: Implement rx_poll function to receive packets")
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Link: https://patch.msgid.link/20260525144525.94884-2-shaojijie@huawei.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
+index 0b92a2e5e98694..cf0f14aa014cf8 100644
+--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
++++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
+@@ -420,6 +420,9 @@ static int hbg_pci_init(struct pci_dev *pdev)
+ return -ENOMEM;
+
+ pci_set_master(pdev);
++ pcie_capability_clear_word(pdev, PCI_EXP_DEVCTL,
++ PCI_EXP_DEVCTL_RELAX_EN);
++ pci_save_state(pdev);
+ return 0;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 604a3e9565b3d1f5fa85fa3dc850e3c78eaad2a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 15:03:30 +0200
+Subject: net: hsr: fix potential OOB access in supervision frame handling
+
+From: Luka Gejak <luka.gejak@linux.dev>
+
+[ Upstream commit f229426072fc865654a60978bb7fda790a051ff3 ]
+
+Ensure the entire TLV header is linearized before access by adding
+sizeof(struct hsr_sup_tlv) to the pskb_may_pull() calls. Without this,
+a truncated frame could cause an out-of-bounds access.
+
+Fixes: eafaa88b3eb7 ("net: hsr: Add support for redbox supervision frames")
+Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Link: https://patch.msgid.link/20260523130330.61880-1-luka.gejak@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_forward.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
+index aefc9b6936ba0c..299de290ddaa5c 100644
+--- a/net/hsr/hsr_forward.c
++++ b/net/hsr/hsr_forward.c
+@@ -84,7 +84,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
+
+ /* Get next tlv */
+ total_length += hsr_sup_tag->tlv.HSR_TLV_length;
+- if (!pskb_may_pull(skb, total_length))
++ if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
+ return false;
+ skb_pull(skb, total_length);
+ hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data;
+@@ -100,7 +100,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
+
+ /* make sure another tlv follows */
+ total_length += sizeof(struct hsr_sup_tlv) + hsr_sup_tlv->HSR_TLV_length;
+- if (!pskb_may_pull(skb, total_length))
++ if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
+ return false;
+
+ /* get next tlv */
+--
+2.53.0
+
--- /dev/null
+From e443cb27cab1aad8c06f8c21ff977251de1d80fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 07:11:45 -0700
+Subject: net/iucv: fix locking in .getsockopt
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 3589d20a666caf30ad100c960a2de7de390fce88 ]
+
+Mirror iucv_sock_setsockopt() and wrap the whole switch in
+lock_sock()/release_sock(). The pre-existing SO_MSGLIMIT-only lock
+becomes redundant and is removed.
+
+Any AF_IUCV HIPER user can potentially crash the kernel by racing
+recvmsg() with getsockopt(SO_MSGSIZE): the SO_MSGSIZE arm dereferences
+iucv->hs_dev->mtu after iucv_sock_close() (called from the racing
+recvmsg()) has set hs_dev to NULL, producing a NULL pointer dereference
+oops.
+
+Suggested-by: Stanislav Fomichev <sdf.kernel@gmail.com>
+Fixes: 51363b8751a6 ("af_iucv: allow retrieval of maximum message size")
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
+Tested-by: Alexandra Winter <wintera@linux.ibm.com>
+Link: https://patch.msgid.link/20260521-af_iucv_fix2-v1-1-f16b1c510aa9@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/iucv/af_iucv.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index 6c717a7ef29283..c66b90c912e78e 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -1538,7 +1538,7 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+ struct sock *sk = sock->sk;
+ struct iucv_sock *iucv = iucv_sk(sk);
+ unsigned int val;
+- int len;
++ int len, rc;
+
+ if (level != SOL_IUCV)
+ return -ENOPROTOOPT;
+@@ -1551,26 +1551,34 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+
+ len = min_t(unsigned int, len, sizeof(int));
+
++ rc = 0;
++
++ lock_sock(sk);
+ switch (optname) {
+ case SO_IPRMDATA_MSG:
+ val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0;
+ break;
+ case SO_MSGLIMIT:
+- lock_sock(sk);
+ val = (iucv->path != NULL) ? iucv->path->msglim /* connected */
+ : iucv->msglimit; /* default */
+- release_sock(sk);
+ break;
+ case SO_MSGSIZE:
+- if (sk->sk_state == IUCV_OPEN)
+- return -EBADFD;
++ if (sk->sk_state == IUCV_OPEN) {
++ rc = -EBADFD;
++ break;
++ }
+ val = (iucv->hs_dev) ? iucv->hs_dev->mtu -
+ sizeof(struct af_iucv_trans_hdr) - ETH_HLEN :
+ 0x7fffffff;
+ break;
+ default:
+- return -ENOPROTOOPT;
++ rc = -ENOPROTOOPT;
++ break;
+ }
++ release_sock(sk);
++
++ if (rc)
++ return rc;
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+--
+2.53.0
+
--- /dev/null
+From e791dc5b86c87f00ea159d61e83c6bf69b468967 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 01:08:24 -0700
+Subject: net: mana: Add NULL guards in teardown path to prevent panic on
+ attach failure
+
+From: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+
+[ Upstream commit 17bfe0a8c014ee1d542ad352cd6a0a505361664a ]
+
+When queue allocation fails partway through, the error cleanup frees
+and NULLs apc->tx_qp and apc->rxqs. Multiple teardown paths such as
+mana_remove(), mana_change_mtu() recovery, and internal error handling
+in mana_alloc_queues() can subsequently call into functions that
+dereference these pointers without NULL checks:
+
+- mana_chn_setxdp() dereferences apc->rxqs[0], causing a NULL pointer
+ dereference panic (CR2: 0000000000000000 at mana_chn_setxdp+0x26).
+- mana_destroy_vport() iterates apc->rxqs without a NULL check.
+- mana_fence_rqs() iterates apc->rxqs without a NULL check.
+- mana_dealloc_queues() iterates apc->tx_qp without a NULL check.
+
+Add NULL guards for apc->rxqs in mana_fence_rqs(),
+mana_destroy_vport(), and before the mana_chn_setxdp() call. Add a
+NULL guard for apc->tx_qp in mana_dealloc_queues() to skip TX queue
+draining when TX queues were never allocated or already freed.
+
+Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+Link: https://patch.msgid.link/20260525081129.1230035-2-dipayanroy@linux.microsoft.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 70 +++++++++++--------
+ 1 file changed, 41 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index d1eb77d540427d..6ef2a3ee44c6b0 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -1720,6 +1720,9 @@ static void mana_fence_rqs(struct mana_port_context *apc)
+ struct mana_rxq *rxq;
+ int err;
+
++ if (!apc->rxqs)
++ return;
++
+ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+ rxq = apc->rxqs[rxq_idx];
+ err = mana_fence_rq(apc, rxq);
+@@ -2830,13 +2833,16 @@ static void mana_destroy_vport(struct mana_port_context *apc)
+ struct mana_rxq *rxq;
+ u32 rxq_idx;
+
+- for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+- rxq = apc->rxqs[rxq_idx];
+- if (!rxq)
+- continue;
++ if (apc->rxqs) {
+
+- mana_destroy_rxq(apc, rxq, true);
+- apc->rxqs[rxq_idx] = NULL;
++ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
++ rxq = apc->rxqs[rxq_idx];
++ if (!rxq)
++ continue;
++
++ mana_destroy_rxq(apc, rxq, true);
++ apc->rxqs[rxq_idx] = NULL;
++ }
+ }
+
+ mana_destroy_txq(apc);
+@@ -3241,7 +3247,8 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ if (apc->port_is_up)
+ return -EINVAL;
+
+- mana_chn_setxdp(apc, NULL);
++ if (apc->rxqs)
++ mana_chn_setxdp(apc, NULL);
+
+ if (gd->gdma_context->is_pf && !apc->ac->bm_hostmode)
+ mana_pf_deregister_filter(apc);
+@@ -3259,33 +3266,38 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ * number of queues.
+ */
+
+- for (i = 0; i < apc->num_queues; i++) {
+- txq = &apc->tx_qp[i].txq;
+- tsleep = 1000;
+- while (atomic_read(&txq->pending_sends) > 0 &&
+- time_before(jiffies, timeout)) {
+- usleep_range(tsleep, tsleep + 1000);
+- tsleep <<= 1;
+- }
+- if (atomic_read(&txq->pending_sends)) {
+- err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
+- if (err) {
+- netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+- err, atomic_read(&txq->pending_sends),
+- txq->gdma_txq_id);
++ if (apc->tx_qp) {
++ for (i = 0; i < apc->num_queues; i++) {
++ txq = &apc->tx_qp[i].txq;
++ tsleep = 1000;
++ while (atomic_read(&txq->pending_sends) > 0 &&
++ time_before(jiffies, timeout)) {
++ usleep_range(tsleep, tsleep + 1000);
++ tsleep <<= 1;
++ }
++ if (atomic_read(&txq->pending_sends)) {
++ err =
++ pcie_flr(to_pci_dev(gd->gdma_context->dev));
++ if (err) {
++ netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
++ err,
++ atomic_read(&txq->pending_sends),
++ txq->gdma_txq_id);
++ }
++ break;
+ }
+- break;
+ }
+- }
+
+- for (i = 0; i < apc->num_queues; i++) {
+- txq = &apc->tx_qp[i].txq;
+- while ((skb = skb_dequeue(&txq->pending_skbs))) {
+- mana_unmap_skb(skb, apc);
+- dev_kfree_skb_any(skb);
++ for (i = 0; i < apc->num_queues; i++) {
++ txq = &apc->tx_qp[i].txq;
++ while ((skb = skb_dequeue(&txq->pending_skbs))) {
++ mana_unmap_skb(skb, apc);
++ dev_kfree_skb_any(skb);
++ }
++ atomic_set(&txq->pending_sends, 0);
+ }
+- atomic_set(&txq->pending_sends, 0);
+ }
++
+ /* We're 100% sure the queues can no longer be woken up, because
+ * we're sure now mana_poll_tx_cq() can't be running.
+ */
+--
+2.53.0
+
--- /dev/null
+From 2922a922b3d1b6e167b46606ed0b574627f7a7a5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 01:08:25 -0700
+Subject: net: mana: Skip redundant detach on already-detached port
+
+From: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+
+[ Upstream commit 5b05aa36ee24297d7296ca58dfd8c448d0e4cda3 ]
+
+When mana_per_port_queue_reset_work_handler() runs after a previous
+detach succeeded but attach failed, the port is left in a detached
+state with apc->tx_qp and apc->rxqs already freed. Calling
+mana_detach() again unconditionally leads to NULL pointer dereferences
+during queue teardown.
+
+Add an early exit in mana_detach() when the port is already in
+detached state (!netif_device_present) for non-close callers, making
+it safe to call idempotently. This allows the queue reset handler and
+other recovery paths to simply retry mana_attach() without redundant
+teardown.
+
+Fixes: 3b194343c250 ("net: mana: Implement ndo_tx_timeout and serialize queue resets per port.")
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+Link: https://patch.msgid.link/20260525081129.1230035-3-dipayanroy@linux.microsoft.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 6ef2a3ee44c6b0..1f723c0ea12837 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -3322,6 +3322,12 @@ int mana_detach(struct net_device *ndev, bool from_close)
+
+ ASSERT_RTNL();
+
++ /* If already detached (indicates detach succeeded but attach failed
++ * previously). Now skip mana detach and just retry mana_attach.
++ */
++ if (!from_close && !netif_device_present(ndev))
++ return 0;
++
+ apc->port_st_save = apc->port_is_up;
+ apc->port_is_up = false;
+
+--
+2.53.0
+
--- /dev/null
+From 84b76baf8114b699baabfa7199465e44090d70ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 May 2026 01:00:31 +0100
+Subject: net/mlx5: HWS: Reject unsupported remove-header action
+
+From: Prathamesh Deshpande <prathameshdeshpande7@gmail.com>
+
+[ Upstream commit 86f1d0f063e423a5c1982db1e5e7a8eac511e603 ]
+
+mlx5_cmd_hws_packet_reformat_alloc() handles
+MLX5_REFORMAT_TYPE_REMOVE_HDR by looking up a matching HWS remove-header
+action.
+
+If mlx5_fs_get_action_remove_header_vlan() returns NULL, the code only
+logs an error and continues. The function then returns success with a NULL
+HWS action stored in the packet-reformat object.
+
+Return an error when no matching remove-header action is available.
+
+Fixes: aecd9d1020e3 ("net/mlx5: fs, add HWS packet reformat API function")
+Signed-off-by: Prathamesh Deshpande <prathameshdeshpande7@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
+Acked-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260506000054.51797-1-prathameshdeshpande7@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c
+index 6a4c4cccd64342..c45a7ca66ad8ed 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c
+@@ -1323,8 +1323,10 @@ mlx5_cmd_hws_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns,
+ break;
+ case MLX5_REFORMAT_TYPE_REMOVE_HDR:
+ hws_action = mlx5_fs_get_action_remove_header_vlan(fs_ctx, params);
+- if (!hws_action)
++ if (!hws_action) {
+ mlx5_core_err(dev, "Only vlan remove header supported\n");
++ return -EOPNOTSUPP;
++ }
+ break;
+ default:
+ mlx5_core_err(ns->dev, "Packet-reformat not supported(%d)\n",
+--
+2.53.0
+
--- /dev/null
+From 0a31a5650d70f4fccaf4d56e70a49cd2697e221e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:36 +0200
+Subject: net: netlink: don't set nsid on local notifications
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 88b126b39f9757e9debc322d4679239e9af089c7 ]
+
+In most cases, notifications on sockets with NETLINK_LISTEN_ALL_NSID
+do not contain NSID in their ancillary data in case the event is local
+to the listener.
+
+However, when a self-referential NSID is allocated for a namespace,
+every local notification starts sending this ID to the user space.
+
+This is problematic, because the listener cannot tell if those
+notifications are local or not anymore without making extra requests
+to figure out if the provided NSID is local or not. The listener
+can also not figure out the local NSID beforehand as it can be
+allocated at any point in time by other processes, changing the
+structure of the future notifications for everyone.
+
+The value is practically not useful, since it's the namespace's own
+ID that the application has to obtain from other sources in order to
+figure out if it's the same or not. So, for the application it's
+just an extra busy work with no benefits. Moreover, applications
+that do not know about this quirk may be mishandling notifications
+with NSID set as notifications from remote namespaces. This is the
+case for ovs-vswitchd and the iproute2's 'ip monitor' that stops
+printing 'current' and starts printing the nsid number mid-session.
+
+Lack of clear documentation for this behavior is also not helping.
+
+A search though open-source projects doesn't reveal any projects
+that use NETNSA_NSID_NOT_ASSIGNED and rely on metadata to contain
+self-referential NSIDs (expected, since the value is not useful).
+Quite the opposite, as already mentioned, there are few applications
+that rely on NSID to not be present in local events.
+
+Since the value is not useful and actively harmful in some cases,
+let's not report it for local events, making the notifications more
+consistent.
+
+Also adding some blank lines for readability.
+
+Fixes: 59324cf35aba ("netlink: allow to listen "all" netns")
+Reported-by: Matteo Perin <matteo.perin@canonical.com>
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-3-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 0e6dfd01d9b419..1d1b3bd54a916b 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1484,10 +1484,14 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++
+ NETLINK_CB(p->skb2).nsid_is_set = false;
+- NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+- if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+- NETLINK_CB(p->skb2).nsid_is_set = true;
++ if (!net_eq(sock_net(sk), p->net)) {
++ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
++ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
++ NETLINK_CB(p->skb2).nsid_is_set = true;
++ }
++
+ val = netlink_broadcast_deliver(sk, p->skb2);
+ if (val < 0) {
+ netlink_overrun(sk);
+--
+2.53.0
+
--- /dev/null
+From b065309029ea5a81e1836547d84bcb1cc58ebfe1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:35 +0200
+Subject: net: netlink: fix sending unassigned nsid after assigned one
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 70f8592ee90585272018a725054b6eb2ab7e99ca ]
+
+If the current skb is not shared, it is re-used directly for all the
+sockets subscribed to the notification. If we have remote all-nsid
+socket receiving a message first, then the 'nsid_is_set' will be
+set to 'true'. If the nsid is NOT_ASSIGNED for the next socket in
+the list, the 'nsid_is_set' will remain 'true' and the negative value
+is be delivered to the user space. All subsequent nsid values will be
+delivered as well, since there is no code path that sets the flag
+back to 'false'.
+
+Fix that by always dropping the flag to 'false' first.
+
+Fixes: 7212462fa6fd ("netlink: don't send unknown nsid")
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-2-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 2b46c0cd752a31..0e6dfd01d9b419 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1484,6 +1484,7 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++ NETLINK_CB(p->skb2).nsid_is_set = false;
+ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+ NETLINK_CB(p->skb2).nsid_is_set = true;
+--
+2.53.0
+
--- /dev/null
+From 8c1d2e30c6dc44cc920179bd372738ba12172d90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:49 -0400
+Subject: net/sched: Revert "net/sched: Restrict conditions for adding
+ duplicating netems to qdisc tree"
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit eda0b7f203bb166c98d1418b204135bd566ac83b ]
+
+This reverts commit ec8e0e3d7adef940cdf9475e2352c0680189d14e.
+
+The original patch rejects any tree containing two netems when
+either has duplication set, even when they sit on unrelated classes
+of the same classful parent. That broke configurations that have
+worked since netem was introduced.
+
+The re-entrancy problem the original commit was trying to solve is
+handled by later patch using tc_depth flag.
+
+Doing this revert will (re)expose the original bug with multiple
+netem duplication. When this patch is backported make sure
+and get the full series.
+
+Fixes: ec8e0e3d7ade ("net/sched: Restrict conditions for adding duplicating netems to qdisc tree")
+Reported-by: Ji-Soo Chung <jschung2@proton.me>
+Reported-by: Gerlinde <lrGerlinde@mailfence.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220774
+Reported-by: zyc zyc <zyc199902@zohomail.cn>
+Closes: https://lore.kernel.org/all/19adda5a1e2.12410b78222774.9191120410578703463@zohomail.cn/
+Reported-by: Manas Ghandat <ghandatmanas@gmail.com>
+Closes: https://lore.kernel.org/netdev/f69b2c8f-8325-4c2e-a011-6dbc089f30e4@gmail.com/
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-3-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_netem.c | 40 ----------------------------------------
+ 1 file changed, 40 deletions(-)
+
+diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
+index 47db6da905c585..73b3a8ce2f4350 100644
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -1006,41 +1006,6 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+ return 0;
+ }
+
+-static const struct Qdisc_class_ops netem_class_ops;
+-
+-static int check_netem_in_tree(struct Qdisc *sch, bool duplicates,
+- struct netlink_ext_ack *extack)
+-{
+- struct Qdisc *root, *q;
+- unsigned int i;
+-
+- root = qdisc_root_sleeping(sch);
+-
+- if (sch != root && root->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(root))->duplicate)
+- goto err;
+- }
+-
+- if (!qdisc_dev(root))
+- return 0;
+-
+- hash_for_each(qdisc_dev(root)->qdisc_hash, i, q, hash) {
+- if (sch != q && q->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(q))->duplicate)
+- goto err;
+- }
+- }
+-
+- return 0;
+-
+-err:
+- NL_SET_ERR_MSG(extack,
+- "netem: cannot mix duplicating netems with other netems in tree");
+- return -EINVAL;
+-}
+-
+ /* Parse netlink message to set options */
+ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
+@@ -1117,11 +1082,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ q->gap = qopt->gap;
+ q->counter = 0;
+ q->loss = qopt->loss;
+-
+- ret = check_netem_in_tree(sch, qopt->duplicate, extack);
+- if (ret)
+- goto unlock;
+-
+ q->duplicate = qopt->duplicate;
+
+ /* for compatibility with earlier versions.
+--
+2.53.0
+
--- /dev/null
+From ce1b823828a9d42d026f9b1b299a47c1384ab20b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 19:43:53 +0100
+Subject: net: skbuff: fix pskb_carve leaking zcopy pages
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit ff6e798c2eac3ebd0501ad7e796f583fab928de8 ]
+
+When SKBFL_MANAGED_FRAG_REFS is set, frag pages are not refcounted but
+their lifetime is controlled by the attached ubuf_info. To make a copy
+of the skb_shared_info, we either should clear the flag and reference
+the frags, or keep the flag and have frags unreferenced.
+
+pskb_carve_inside_header() and pskb_carve_inside_nonlinear() don't
+follow the rule and thus can leak page references. Let's clear
+SKBFL_MANAGED_FRAG_REFS from the original skb to fix it. It's the
+simplest way to address it, but there are more performant ways to do
+that if it ever becomes a problem.
+
+Link: https://lore.kernel.org/all/20260523085809.26331-1-nvminh232@clc.fitus.edu.vn/
+Fixes: 753f1ca4e1e50 ("net: introduce managed frags infrastructure")
+Reported-by: Minh Nguyen <minhnguyen.080505@gmail.com>
+Reported-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/1e2086aa69217d7f9c8da3d38f5be7160f1b4cd1.1779993185.git.asml.silence@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/skbuff.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 6618bfa70ca444..a52aa79b0fdbaf 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -6772,6 +6772,11 @@ static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off,
+ skb_copy_from_linear_data_offset(skb, off, data, new_hlen);
+ skb->len -= off;
+
++ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
++ * while refcounting frags below.
++ */
++ skb_zcopy_downgrade_managed(skb);
++
+ memcpy((struct skb_shared_info *)(data + size),
+ skb_shinfo(skb),
+ offsetof(struct skb_shared_info,
+@@ -6883,6 +6888,11 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,
+ return -ENOMEM;
+ size = SKB_WITH_OVERHEAD(size);
+
++ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
++ * while refcounting frags below.
++ */
++ skb_zcopy_downgrade_managed(skb);
++
+ memcpy((struct skb_shared_info *)(data + size),
+ skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0]));
+ if (skb_orphan_frags(skb, gfp_mask)) {
+--
+2.53.0
+
--- /dev/null
+From 2e2cca4092c507b7df463f9706010f2085c47330 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 16:56:39 +0200
+Subject: net/smc: Do not re-initialize smc hashtables
+
+From: Alexandra Winter <wintera@linux.ibm.com>
+
+[ Upstream commit 9e4389b0038781f19f97895186ed941ff8ac1678 ]
+
+INIT_HLIST_HEAD(&smc_v*_hashinfo.ht) are called after smc_nl_init(),
+proto_register() and sock_register(). This can lead to smc_v*_hashinfo.ht
+being reset even though hash entries already exist and are being used,
+possibly resulting in a corrupted list.
+
+Remove unnecessary and dangerous re-initialisation of smc_v*_hashinfo.ht in
+smc_init(); it is implicitly initialised to zero anyhow. Add
+HLIST_HEAD_INIT to the definitions for clarity.
+
+Fixes: f16a7dd5cf27 ("smc: netlink interface for SMC sockets")
+Suggested-by: Halil Pasic <pasic@linux.ibm.com>
+Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
+Acked-by: Halil Pasic <pasic@linux.ibm.com>
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Link: https://patch.msgid.link/20260521145639.10317-1-wintera@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index 5915fcdef743d2..21d0c62bcf4644 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -188,10 +188,12 @@ static bool smc_hs_congested(const struct sock *sk)
+
+ struct smc_hashinfo smc_v4_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v4_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ struct smc_hashinfo smc_v6_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v6_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ int smc_hash_sk(struct sock *sk)
+@@ -3595,8 +3597,6 @@ static int __init smc_init(void)
+ pr_err("%s: sock_register fails with %d\n", __func__, rc);
+ goto out_proto6;
+ }
+- INIT_HLIST_HEAD(&smc_v4_hashinfo.ht);
+- INIT_HLIST_HEAD(&smc_v6_hashinfo.ht);
+
+ rc = smc_ib_register_client();
+ if (rc) {
+--
+2.53.0
+
--- /dev/null
+From 1e841a0236db85219d7a6178887759ca393288f9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 01:12:01 -0700
+Subject: net: team: fix NULL pointer dereference in team_xmit during mode
+ change
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit 25fe708bbc59289d3d1ea4b126fbc1b460a072a5 ]
+
+__team_change_mode() clears team->ops with memset() before restoring
+safe dummy handlers via team_adjust_ops(). A concurrent team_xmit()
+running under RCU on another CPU can read team->ops.transmit during
+this window and call a NULL function pointer, crashing the kernel.
+
+The race requires a mode change (CAP_NET_ADMIN) concurrent with
+transmit on the team device.
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000000
+ Oops: 0010 [#1] SMP KASAN NOPTI
+ RIP: 0010:0x0
+ Call Trace:
+ team_xmit (drivers/net/team/team_core.c:1853)
+ dev_hard_start_xmit (net/core/dev.c:3904)
+ __dev_queue_xmit (net/core/dev.c:4871)
+ packet_sendmsg (net/packet/af_packet.c:3109)
+ __sys_sendto (net/socket.c:2265)
+
+The original code assumed that no ports means no traffic, so mode
+changes could freely memset()/memcpy() the ops. AF_PACKET with
+forced carrier breaks that assumption.
+
+Prevent the race instead of making it safe: replace memset()/memcpy()
+with per-field updates that never touch transmit or receive. Those
+two handlers are managed solely by team_adjust_ops(), which already
+installs dummies when tx_en_port_count == 0 (always true during mode
+change since no ports are present). WRITE_ONCE/READ_ONCE prevent
+store/load tearing on the handler pointers.
+
+synchronize_net() before exit_op() drains in-flight readers that may
+still reference old mode state from before port removal switched the
+handlers to dummies.
+
+Fixes: 3d249d4ca7d0 ("net: introduce ethernet teaming device")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260521081159.1491563-3-bestswngs@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/team/team_core.c | 45 +++++++++++++++++++++++++-----------
+ 1 file changed, 32 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
+index 11c8e6551dd357..ff4dcd6035cd10 100644
+--- a/drivers/net/team/team_core.c
++++ b/drivers/net/team/team_core.c
+@@ -535,21 +535,23 @@ static void team_adjust_ops(struct team *team)
+
+ if (!team->en_port_count || !team_is_mode_set(team) ||
+ !team->mode->ops->transmit)
+- team->ops.transmit = team_dummy_transmit;
++ WRITE_ONCE(team->ops.transmit, team_dummy_transmit);
+ else
+- team->ops.transmit = team->mode->ops->transmit;
++ WRITE_ONCE(team->ops.transmit, team->mode->ops->transmit);
+
+ if (!team->en_port_count || !team_is_mode_set(team) ||
+ !team->mode->ops->receive)
+- team->ops.receive = team_dummy_receive;
++ WRITE_ONCE(team->ops.receive, team_dummy_receive);
+ else
+- team->ops.receive = team->mode->ops->receive;
++ WRITE_ONCE(team->ops.receive, team->mode->ops->receive);
+ }
+
+ /*
+- * We can benefit from the fact that it's ensured no port is present
+- * at the time of mode change. Therefore no packets are in fly so there's no
+- * need to set mode operations in any special way.
++ * team_change_mode() ensures no ports are present during mode change,
++ * but lockless readers can still reach team_xmit(). Avoid touching
++ * transmit/receive -- they are already set to dummies by
++ * team_adjust_ops() since no ports are enabled. synchronize_net()
++ * drains in-flight readers before destroying old mode state.
+ */
+ static int __team_change_mode(struct team *team,
+ const struct team_mode *new_mode)
+@@ -558,9 +560,21 @@ static int __team_change_mode(struct team *team,
+ if (team_is_mode_set(team)) {
+ void (*exit_op)(struct team *team) = team->ops.exit;
+
+- /* Clear ops area so no callback is called any longer */
+- memset(&team->ops, 0, sizeof(struct team_mode_ops));
+- team_adjust_ops(team);
++ /* Clear cold-path ops used only under RTNL. transmit and
++ * receive are already dummies (no ports) so leave them
++ * alone -- overwriting them is the source of the race.
++ */
++ team->ops.init = NULL;
++ team->ops.exit = NULL;
++ team->ops.port_enter = NULL;
++ team->ops.port_leave = NULL;
++ team->ops.port_change_dev_addr = NULL;
++ team->ops.port_tx_disabled = NULL;
++
++ /* Wait for in-flight readers before tearing down mode
++ * state they may reference.
++ */
++ synchronize_net();
+
+ if (exit_op)
+ exit_op(team);
+@@ -583,7 +597,12 @@ static int __team_change_mode(struct team *team,
+ }
+
+ team->mode = new_mode;
+- memcpy(&team->ops, new_mode->ops, sizeof(struct team_mode_ops));
++ team->ops.init = new_mode->ops->init;
++ team->ops.exit = new_mode->ops->exit;
++ team->ops.port_enter = new_mode->ops->port_enter;
++ team->ops.port_leave = new_mode->ops->port_leave;
++ team->ops.port_change_dev_addr = new_mode->ops->port_change_dev_addr;
++ team->ops.port_tx_disabled = new_mode->ops->port_tx_disabled;
+ team_adjust_ops(team);
+
+ return 0;
+@@ -744,7 +763,7 @@ static rx_handler_result_t team_handle_frame(struct sk_buff **pskb)
+ /* allow exact match delivery for disabled ports */
+ res = RX_HANDLER_EXACT;
+ } else {
+- res = team->ops.receive(team, port, skb);
++ res = READ_ONCE(team->ops.receive)(team, port, skb);
+ }
+ if (res == RX_HANDLER_ANOTHER) {
+ struct team_pcpu_stats *pcpu_stats;
+@@ -1683,7 +1702,7 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
+
+ tx_success = team_queue_override_transmit(team, skb);
+ if (!tx_success)
+- tx_success = team->ops.transmit(team, skb);
++ tx_success = READ_ONCE(team->ops.transmit)(team, skb);
+ if (tx_success) {
+ struct team_pcpu_stats *pcpu_stats;
+
+--
+2.53.0
+
--- /dev/null
+From 2ed1433987933b7277c9e36cbd38e2150d3ed936 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Apr 2026 02:59:24 +0000
+Subject: net: team: Remove unused team_mode_op, port_enabled
+
+From: Marc Harvey <marcharvey@google.com>
+
+[ Upstream commit 014f249121d73909528df320818fba7693d0ec92 ]
+
+This team_mode_op wasn't used by any of the team modes, so remove it.
+
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: Marc Harvey <marcharvey@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260409-teaming-driver-internal-v7-2-f47e7589685d@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: 25fe708bbc59 ("net: team: fix NULL pointer dereference in team_xmit during mode change")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/team/team_core.c | 2 --
+ include/linux/if_team.h | 1 -
+ 2 files changed, 3 deletions(-)
+
+diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
+index a98f5e5061544c..712d8043e66e17 100644
+--- a/drivers/net/team/team_core.c
++++ b/drivers/net/team/team_core.c
+@@ -945,8 +945,6 @@ static void team_port_enable(struct team *team,
+ team_port_index_hash(team, port->index));
+ team_adjust_ops(team);
+ team_queue_override_port_add(team, port);
+- if (team->ops.port_enabled)
+- team->ops.port_enabled(team, port);
+ team_notify_peers(team);
+ team_mcast_rejoin(team);
+ team_lower_state_changed(port);
+diff --git a/include/linux/if_team.h b/include/linux/if_team.h
+index ce97d891cf720f..0d550d44a1c230 100644
+--- a/include/linux/if_team.h
++++ b/include/linux/if_team.h
+@@ -121,7 +121,6 @@ struct team_mode_ops {
+ int (*port_enter)(struct team *team, struct team_port *port);
+ void (*port_leave)(struct team *team, struct team_port *port);
+ void (*port_change_dev_addr)(struct team *team, struct team_port *port);
+- void (*port_enabled)(struct team *team, struct team_port *port);
+ void (*port_disabled)(struct team *team, struct team_port *port);
+ };
+
+--
+2.53.0
+
--- /dev/null
+From 203bf220d218b45f7299feb33e96437a90f9e2bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Apr 2026 02:59:25 +0000
+Subject: net: team: Rename port_disabled team mode op to port_tx_disabled
+
+From: Marc Harvey <marcharvey@google.com>
+
+[ Upstream commit cfa477df2cc62ba53cb936669886361152b594a7 ]
+
+This team mode op is only used by the load balance mode, and it only
+uses it in the tx path.
+
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: Marc Harvey <marcharvey@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260409-teaming-driver-internal-v7-3-f47e7589685d@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: 25fe708bbc59 ("net: team: fix NULL pointer dereference in team_xmit during mode change")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/team/team_core.c | 4 ++--
+ drivers/net/team/team_mode_loadbalance.c | 4 ++--
+ include/linux/if_team.h | 2 +-
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
+index 712d8043e66e17..11c8e6551dd357 100644
+--- a/drivers/net/team/team_core.c
++++ b/drivers/net/team/team_core.c
+@@ -969,8 +969,8 @@ static void team_port_disable(struct team *team,
+ {
+ if (!team_port_enabled(port))
+ return;
+- if (team->ops.port_disabled)
+- team->ops.port_disabled(team, port);
++ if (team->ops.port_tx_disabled)
++ team->ops.port_tx_disabled(team, port);
+ hlist_del_rcu(&port->hlist);
+ __reconstruct_port_hlist(team, port->index);
+ port->index = -1;
+diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
+index b14538bde2f824..b27e44a4df5f6e 100644
+--- a/drivers/net/team/team_mode_loadbalance.c
++++ b/drivers/net/team/team_mode_loadbalance.c
+@@ -655,7 +655,7 @@ static void lb_port_leave(struct team *team, struct team_port *port)
+ free_percpu(lb_port_priv->pcpu_stats);
+ }
+
+-static void lb_port_disabled(struct team *team, struct team_port *port)
++static void lb_port_tx_disabled(struct team *team, struct team_port *port)
+ {
+ lb_tx_hash_to_port_mapping_null_port(team, port);
+ }
+@@ -665,7 +665,7 @@ static const struct team_mode_ops lb_mode_ops = {
+ .exit = lb_exit,
+ .port_enter = lb_port_enter,
+ .port_leave = lb_port_leave,
+- .port_disabled = lb_port_disabled,
++ .port_tx_disabled = lb_port_tx_disabled,
+ .receive = lb_receive,
+ .transmit = lb_transmit,
+ };
+diff --git a/include/linux/if_team.h b/include/linux/if_team.h
+index 0d550d44a1c230..cd5acf40040d2e 100644
+--- a/include/linux/if_team.h
++++ b/include/linux/if_team.h
+@@ -121,7 +121,7 @@ struct team_mode_ops {
+ int (*port_enter)(struct team *team, struct team_port *port);
+ void (*port_leave)(struct team *team, struct team_port *port);
+ void (*port_change_dev_addr)(struct team *team, struct team_port *port);
+- void (*port_disabled)(struct team *team, struct team_port *port);
++ void (*port_tx_disabled)(struct team *team, struct team_port *port);
+ };
+
+ extern int team_modeop_port_enter(struct team *team, struct team_port *port);
+--
+2.53.0
+
--- /dev/null
+From 643e783857c1c0b549731ca97802ad7f8d16d798 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 22:52:07 +0200
+Subject: netfilter: ebtables: fix OOB read in compat_mtw_from_user
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit f438d1786d657d57790c5d138d6db3fc9fdac392 ]
+
+Luxiao Xu says:
+
+ The function compat_mtw_from_user() converts ebtables extensions from
+ 32-bit user structures to kernel native structures. However, it lacks
+ proper validation of the user-supplied match_size/target_size.
+
+ When certain extensions are processed, the kernel-side translation
+ logic may perform memory accesses based on the extension's expected
+ size. If the user provides a size smaller than what the extension
+ requires, it results in an out-of-bounds read as reported by KASAN.
+
+ This fix introduces a check to ensure match_size is at least as large
+ as the extension's required compatsize. This covers matches, watchers,
+ and targets, while maintaining compatibility with standard targets.
+
+AFAIU this is relevant for matches that need to go though
+match->compat_from_user() call. Those that use plain memcpy with the
+user-provided size are ok because the caller checks that size vs the
+start of the next rule entry offset (which itself is checked vs. total
+size copied from userspace).
+
+The ->compat_from_user() callbacks assume they can read compatsize bytes,
+so they need this extra check.
+
+Based on an earlier patch from Luxiao Xu.
+
+Fixes: 81e675c227ec ("netfilter: ebtables: add CONFIG_COMPAT support")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/netfilter/ebtables.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index 77df9e856c2e73..ecd7baa25d7268 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -1956,6 +1956,25 @@ enum compat_mwt {
+ EBT_COMPAT_TARGET,
+ };
+
++static bool match_size_ok(const struct xt_match *match, unsigned int match_size)
++{
++ u16 csize;
++
++ if (match->matchsize == -1) /* cannot validate ebt_among */
++ return true;
++
++ csize = match->compatsize ? : match->matchsize;
++
++ return match_size >= csize;
++}
++
++static bool tgt_size_ok(const struct xt_target *tgt, unsigned int tgt_size)
++{
++ u16 csize = tgt->compatsize ? : tgt->targetsize;
++
++ return tgt_size >= csize;
++}
++
+ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ enum compat_mwt compat_mwt,
+ struct ebt_entries_buf_state *state,
+@@ -1981,6 +2000,11 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+
++ if (!match_size_ok(match, match_size)) {
++ module_put(match->me);
++ return -EINVAL;
++ }
++
+ off = ebt_compat_match_offset(match, match_size);
+ if (dst) {
+ if (match->compat_from_user)
+@@ -2000,6 +2024,12 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ mwt->u.revision);
+ if (IS_ERR(wt))
+ return PTR_ERR(wt);
++
++ if (!tgt_size_ok(wt, match_size)) {
++ module_put(wt->me);
++ return -EINVAL;
++ }
++
+ off = xt_compat_target_offset(wt);
+
+ if (dst) {
+--
+2.53.0
+
--- /dev/null
+From bfee6a1b3dab7f70873eed83daae7b12a05dc5f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 May 2026 16:37:56 +0200
+Subject: netfilter: nf_tables: fix dst corruption in same register operation
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 18014147d3ee7831dce53fe65d7fc8d428b02552 ]
+
+For lshift and rshift, the shift operations are performed in a loop over
+32-bit words. The loop calculates the shifted value and write it to dst,
+and then immediately reads from src to calculate the carry for the next
+iteration. Because src and dst could point to the same memory location,
+the carry is incorrectly calculated using the newly modified dst value
+instead of the original src value.
+
+Adding a temporary local variable to cache the original value before
+writing to dst and using it for the carry calculation solves the
+problem. In addition, partial overlap is rejected from control plane for
+all kind of operations including byteorder. This was tested with the
+following bytecode:
+
+table test_table ip flags 0 use 1 handle 1
+ip test_table test_chain use 3 type filter hook input prio 0 policy accept packets 0 bytes 0 flags 1
+ip test_table test_chain 2
+ [ immediate reg 1 0x44332211 0x88776655 ]
+ [ bitwise reg 1 = ( reg 1 << 0x08000000 ) ]
+ [ cmp eq reg 1 0x66443322 0x00887766 ]
+ [ counter pkts 0 bytes 0 ]
+ip test_table test_chain 4 3
+ [ immediate reg 1 0x44332211 0x88776655 ]
+ [ bitwise reg 1 = ( reg 1 << 0x08000000 ) ]
+ [ cmp eq reg 1 0x55443322 0x00887766 ]
+ [ counter pkts 21794 bytes 1917798 ]
+
+Fixes: 567d746b55bc ("netfilter: bitwise: add support for shifts.")
+Acked-by: Jeremy Sowden <jeremy@azazel.net>
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables.h | 7 +++++++
+ net/netfilter/nft_bitwise.c | 18 ++++++++++++++----
+ net/netfilter/nft_byteorder.c | 13 ++++++++++---
+ 3 files changed, 31 insertions(+), 7 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index 4dc080f7f27c65..b35e8c02fadcd5 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -188,6 +188,13 @@ static inline u64 nft_reg_load64(const u32 *sreg)
+ return get_unaligned((u64 *)sreg);
+ }
+
++static inline bool nft_reg_overlap(u8 src, u8 dst, u32 len)
++{
++ unsigned int n = DIV_ROUND_UP(len, sizeof(u32));
++
++ return src != dst && src < dst + n && dst < src + n;
++}
++
+ static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
+ unsigned int len)
+ {
+diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
+index af990c600745be..1afb36fb5994db 100644
+--- a/net/netfilter/nft_bitwise.c
++++ b/net/netfilter/nft_bitwise.c
+@@ -43,8 +43,10 @@ static void nft_bitwise_eval_lshift(u32 *dst, const u32 *src,
+ u32 carry = 0;
+
+ for (i = DIV_ROUND_UP(priv->len, sizeof(u32)); i > 0; i--) {
+- dst[i - 1] = (src[i - 1] << shift) | carry;
+- carry = src[i - 1] >> (BITS_PER_TYPE(u32) - shift);
++ u32 tmp_src = src[i - 1];
++
++ dst[i - 1] = (tmp_src << shift) | carry;
++ carry = tmp_src >> (BITS_PER_TYPE(u32) - shift);
+ }
+ }
+
+@@ -56,8 +58,10 @@ static void nft_bitwise_eval_rshift(u32 *dst, const u32 *src,
+ u32 carry = 0;
+
+ for (i = 0; i < DIV_ROUND_UP(priv->len, sizeof(u32)); i++) {
+- dst[i] = carry | (src[i] >> shift);
+- carry = src[i] << (BITS_PER_TYPE(u32) - shift);
++ u32 tmp_src = src[i];
++
++ dst[i] = carry | (tmp_src >> shift);
++ carry = tmp_src << (BITS_PER_TYPE(u32) - shift);
+ }
+ }
+
+@@ -235,6 +239,9 @@ static int nft_bitwise_init_bool(const struct nft_ctx *ctx,
+ &priv->sreg2, priv->len);
+ if (err < 0)
+ return err;
++
++ if (nft_reg_overlap(priv->sreg2, priv->dreg, priv->len))
++ return -EINVAL;
+ }
+
+ return 0;
+@@ -265,6 +272,9 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
+ if (err < 0)
+ return err;
+
++ if (nft_reg_overlap(priv->sreg, priv->dreg, priv->len))
++ return -EINVAL;
++
+ if (tb[NFTA_BITWISE_OP]) {
+ priv->op = ntohl(nla_get_be32(tb[NFTA_BITWISE_OP]));
+ switch (priv->op) {
+diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
+index af9206a3afd181..5e7a7841b789b0 100644
+--- a/net/netfilter/nft_byteorder.c
++++ b/net/netfilter/nft_byteorder.c
+@@ -144,9 +144,16 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
+ if (err < 0)
+ return err;
+
+- return nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
+- &priv->dreg, NULL, NFT_DATA_VALUE,
+- priv->len);
++ err = nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
++ &priv->dreg, NULL, NFT_DATA_VALUE,
++ priv->len);
++ if (err < 0)
++ return err;
++
++ if (nft_reg_overlap(priv->sreg, priv->dreg, priv->len))
++ return -EINVAL;
++
++ return 0;
+ }
+
+ static int nft_byteorder_dump(struct sk_buff *skb,
+--
+2.53.0
+
--- /dev/null
+From 4830d5363650d65456d43a285b1ca3839f7b7d37 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 12:36:14 -0700
+Subject: netfilter: synproxy: refresh tcphdr after skb_ensure_writable
+
+From: Chris Mason <clm@meta.com>
+
+[ Upstream commit 92170e6afe927ab2792a3f71902845789c8e31b1 ]
+
+synproxy_tstamp_adjust() rewrites the TCP timestamp option in place
+and then patches the TCP checksum via inet_proto_csum_replace4() on
+the caller-supplied tcphdr pointer. Both ipv4_synproxy_hook() and
+ipv6_synproxy_hook() obtain that pointer with skb_header_pointer()
+before calling in, so it may either alias skb->head directly or
+point at the caller's on-stack _tcph buffer.
+
+Between obtaining the pointer and using it, the function calls
+skb_ensure_writable(skb, optend), which on a cloned or non-linear
+skb invokes pskb_expand_head() and frees the old skb->head. After
+that point the cached th is stale:
+
+ caller (ipv[46]_synproxy_hook)
+ th = skb_header_pointer(skb, ..., &_tcph)
+ synproxy_tstamp_adjust(skb, protoff, th, ...)
+ skb_ensure_writable(skb, optend)
+ pskb_expand_head() /* kfree(old skb->head) */
+ ...
+ inet_proto_csum_replace4(&th->check, ...)
+ /* writes into freed head, or
+ into the caller's stack copy
+ leaving the on-wire checksum
+ stale */
+
+The option bytes are written through skb->data and are fine; only
+the checksum update goes through th and so lands in the wrong
+place. The result is either a write into freed slab memory or a
+packet leaving with a checksum that does not match its payload.
+
+Fix by re-deriving th from skb->data + protoff immediately after
+skb_ensure_writable() succeeds, so the subsequent checksum update
+targets the linear, writable header.
+
+Fixes: 48b1de4c110a ("netfilter: add SYNPROXY core/target")
+Assisted-by: kres (claude-opus-4-7)
+Signed-off-by: Chris Mason <clm@meta.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_synproxy_core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 3fa3f5dfb26444..6a851ac4dd048f 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -199,6 +199,8 @@ synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,
+ if (skb_ensure_writable(skb, optend))
+ return 0;
+
++ th = (struct tcphdr *)(skb->data + protoff);
++
+ while (optoff < optend) {
+ unsigned char *op = skb->data + optoff;
+
+--
+2.53.0
+
--- /dev/null
+From 38bc8a6c115dc3c07a8ff919578ae71a87058d94 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 20:10:08 +0200
+Subject: netfilter: xt_cpu: prefer raw_smp_processor_id
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit c376f07e16c02239ed44cabb97145d03f65b4d15 ]
+
+With PREEMPT_RCU we get splat:
+
+BUG: using smp_processor_id() in preemptible [..]
+caller is cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+CPU: 1 .. Comm: syz.3.1377 #0 PREEMPT(full)
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
+ check_preemption_disabled+0xd3/0xe0 lib/smp_processor_id.c:47
+ cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+ [..]
+
+Just use raw version instead.
+This is similar to 14d14a5d2957 ("netfilter: nft_meta: use raw_smp_processor_id()").
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Reported-by: syzbot+690d3e3ffa7335ac10eb@syzkaller.appspotmail.com
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/xt_cpu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_cpu.c b/net/netfilter/xt_cpu.c
+index 3bdc302a0f9137..9cb259902a586b 100644
+--- a/net/netfilter/xt_cpu.c
++++ b/net/netfilter/xt_cpu.c
+@@ -34,7 +34,7 @@ static bool cpu_mt(const struct sk_buff *skb, struct xt_action_param *par)
+ {
+ const struct xt_cpu_info *info = par->matchinfo;
+
+- return (info->cpu == smp_processor_id()) ^ info->invert;
++ return (info->cpu == raw_smp_processor_id()) ^ info->invert;
+ }
+
+ static struct xt_match cpu_mt_reg __read_mostly = {
+--
+2.53.0
+
--- /dev/null
+From a94f21950d9c2cbad3089b32f60249705a61f773 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:41 +0000
+Subject: nfc: llcp: Fix use-after-free in llcp_sock_release()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit f4268b466190dae95a7585f69b4f1f8ad097632c ]
+
+llcp_sock_release() unconditionally unlinks the socket from the local
+sockets list. However, if the socket is still in connecting state, it
+is on the connecting list.
+
+Fix this by checking the socket state and unlinking from the correct list.
+
+Fixes: b4011239a08e ("NFC: llcp: Fix non blocking sockets connections")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-1-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_sock.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index 57a2f97004e172..915929cd724f90 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -633,6 +633,8 @@ static int llcp_sock_release(struct socket *sock)
+
+ if (sock->type == SOCK_RAW)
+ nfc_llcp_sock_unlink(&local->raw_sockets, sk);
++ else if (sk->sk_state == LLCP_CONNECTING)
++ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ else
+ nfc_llcp_sock_unlink(&local->sockets, sk);
+
+--
+2.53.0
+
--- /dev/null
+From 6cb2942eb336a91362789fc998f38c57e7ed7f58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:42 +0000
+Subject: nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit b493ea2765cc17cb8aa7e7544a4b6dcb05b6ed77 ]
+
+A race condition exists in the NFC LLCP connection state machine where
+the connection acceptance packet (CC) can be processed concurrently with
+socket release. This can lead to a use-after-free of the socket object.
+
+When nfc_llcp_recv_cc() moves the socket from the connecting_sockets
+list to the sockets list, it does so without holding the socket lock.
+If llcp_sock_release() is executing concurrently, it might have already
+unlinked the socket and dropped its references, which can result in
+nfc_llcp_recv_cc() linking a freed socket into the live list.
+
+Fix this by holding lock_sock() during the state transition and list
+movement in nfc_llcp_recv_cc(). After acquiring the lock, check if
+the socket is still hashed to ensure it hasn't already been unlinked
+and marked for destruction by the release path. This aligns the locking
+pattern with recv_hdlc() and recv_disc().
+
+Fixes: a69f32af86e3 ("NFC: Socket linked list")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-2-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_core.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
+index da8d3add0018f3..c83a00e429852c 100644
+--- a/net/nfc/llcp_core.c
++++ b/net/nfc/llcp_core.c
+@@ -1218,6 +1218,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+
+ sk = &llcp_sock->sk;
+
++ lock_sock(sk);
++
++ /* Check if socket was destroyed whilst waiting for the lock */
++ if (!sk_hashed(sk)) {
++ release_sock(sk);
++ nfc_llcp_sock_put(llcp_sock);
++ return;
++ }
++
+ /* Unlink from connecting and link to the client array */
+ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ nfc_llcp_sock_link(&local->sockets, sk);
+@@ -1229,6 +1238,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+ sk->sk_state = LLCP_CONNECTED;
+ sk->sk_state_change(sk);
+
++ release_sock(sk);
++
+ nfc_llcp_sock_put(llcp_sock);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 26612ad39d67ec0a0ce1de4c003ea619ac4e24ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 May 2026 19:55:18 +0800
+Subject: nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems
+
+From: Carl Lee <carl.lee@amd.com>
+
+[ Upstream commit f23bf992d65a42007c517b060ca35cebdea3525a ]
+
+Some ACPI-based platforms report incorrect IRQ trigger types (e.g.
+IRQF_TRIGGER_HIGH), which can lead to interrupt storms.
+
+Use the historically working rising-edge trigger on ACPI systems to
+avoid this regression.
+
+Device Tree-based systems continue to use the firmware-provided
+trigger type.
+
+Fixes: 57be33f85e36 ("nfc: nxp-nci: remove interrupt trigger type")
+Signed-off-by: Carl Lee <carl.lee@amd.com>
+Tested-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Luca Stefani <luca.stefani.ge1@gmail.com>
+Link: https://patch.msgid.link/20260516-nfc-nxp-nci-i2c-restore-irq-trigger-fallback-v3-1-37ba4b6e9086@amd.com
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/nxp-nci/i2c.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
+index b3d34433bd14a0..a6c08175d9dd93 100644
+--- a/drivers/nfc/nxp-nci/i2c.c
++++ b/drivers/nfc/nxp-nci/i2c.c
+@@ -16,6 +16,7 @@
+ #include <linux/delay.h>
+ #include <linux/i2c.h>
+ #include <linux/interrupt.h>
++#include <linux/irq.h>
+ #include <linux/module.h>
+ #include <linux/nfc.h>
+ #include <linux/gpio/consumer.h>
+@@ -267,6 +268,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client)
+ {
+ struct device *dev = &client->dev;
+ struct nxp_nci_i2c_phy *phy;
++ unsigned long irqflags;
+ int r;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+@@ -303,9 +305,26 @@ static int nxp_nci_i2c_probe(struct i2c_client *client)
+ if (r < 0)
+ return r;
+
++ /*
++ * ACPI platforms may report incorrect IRQ trigger types
++ * (e.g. level-high), which can lead to interrupt storms.
++ *
++ * Use the historically stable rising-edge trigger for ACPI devices.
++ *
++ * On non-ACPI systems (e.g. Device Tree), prefer the firmware-
++ * provided trigger type, falling back to rising-edge if not set.
++ */
++ if (ACPI_COMPANION(dev)) {
++ irqflags = IRQF_TRIGGER_RISING;
++ } else {
++ irqflags = irq_get_trigger_type(client->irq);
++ if (!irqflags)
++ irqflags = IRQF_TRIGGER_RISING;
++ }
++
+ r = request_threaded_irq(client->irq, NULL,
+ nxp_nci_i2c_irq_thread_fn,
+- IRQF_ONESHOT,
++ irqflags | IRQF_ONESHOT,
+ NXP_NCI_I2C_DRIVER_NAME, phy);
+ if (r < 0)
+ nfc_err(&client->dev, "Unable to register IRQ handler\n");
+--
+2.53.0
+
--- /dev/null
+From acfb4c09bcdfaa01c1905a2c3d82e0693773f884 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:16 -0400
+Subject: nvme-tcp: store negative errno in queue->tls_err
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 9015985b5eb1a90eb86caf5bce1dfcf1aa38f8ad ]
+
+nvme_tcp_tls_done() assigns queue->tls_err in three branches. The
+ENOKEY lookup failure and the EOPNOTSUPP initializer both store
+negative errnos. The third branch, reached when the handshake
+layer reports a non-zero status, stores -status.
+
+The handshake layer delivers status to the consumer callback as a
+negative errno; the other in-tree consumers --
+xs_tls_handshake_done() and the nvmet target callback -- treat
+their status argument that way. The extra negation in
+nvme_tcp_tls_done() flips the sign, leaving tls_err as a positive
+value (for instance, +EIO), which nvme_tcp_start_tls() then
+returns to its caller.
+
+Drop the extra negation so queue->tls_err uniformly carries a
+negative errno on failure.
+
+Fixes: be8e82caa685 ("nvme-tcp: enable TLS handshake upcall")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-2-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/tcp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
+index 9a96df1a511c02..afdbcff3d4821e 100644
+--- a/drivers/nvme/host/tcp.c
++++ b/drivers/nvme/host/tcp.c
+@@ -1687,7 +1687,7 @@ static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid)
+ qid, pskid, status);
+
+ if (status) {
+- queue->tls_err = -status;
++ queue->tls_err = status;
+ goto out_complete;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 6bbfc57ed729e96a5c3f1cd80d0ef3d706af24cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 May 2026 14:09:41 -0400
+Subject: scsi: core: Run queues for all non-SDEV_DEL devices from
+ scsi_run_host_queues
+
+From: David Jeffery <djeffery@redhat.com>
+
+[ Upstream commit 7205b58702273baf21d6ba7992e6ba15852325f7 ]
+
+While a SCSI host is in a recovery state, scsi_mq_requeue_cmd() will not
+set the requeue list for a requeued command to be kicked in the future.
+The expectation is a call to scsi_run_host_queues() will kick all SCSI
+devices once the recovery state is cleared.
+
+However, scsi_run_host_queues() uses shost_for_each_device() which uses
+scsi_device_get() and so will ignore devices in a partially removed
+state like SDEV_CANCEL. But these devices may also have requeued
+requests, leaving their requests stuck from not being kicked and causing
+the removal process of the device to hang.
+
+scsi_run_host_queues() needs to run against more devices than the macro
+shost_for_each_device() allows. Instead of using the too limiting
+scsi_device_get() state checks, only ignore devices in SDEV_DEL state or
+when unable to acquire a reference. Attempt to run the queues for all
+other devices when scsi_run_host_queues() is called.
+
+Fixes: 8b566edbdbfb ("scsi: core: Only kick the requeue list if necessary")
+Signed-off-by: David Jeffery <djeffery@redhat.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://patch.msgid.link/20260515180941.9698-1-djeffery@redhat.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_lib.c | 27 +++++++++++++++++++++++++--
+ 1 file changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index 7ddb73cd6d9fe5..3f7ba6d3987f15 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -572,10 +572,33 @@ void scsi_requeue_run_queue(struct work_struct *work)
+
+ void scsi_run_host_queues(struct Scsi_Host *shost)
+ {
+- struct scsi_device *sdev;
++ struct scsi_device *sdev, *prev = NULL;
++ unsigned long flags;
+
+- shost_for_each_device(sdev, shost)
++ spin_lock_irqsave(shost->host_lock, flags);
++ __shost_for_each_device(sdev, shost) {
++ /*
++ * Only skip devices so deep into removal they will never need
++ * another kick to their queues. Thus scsi_device_get() cannot
++ * be used as it would skip devices in SDEV_CANCEL state which
++ * may need a queue kick.
++ */
++ if (sdev->sdev_state == SDEV_DEL ||
++ !get_device(&sdev->sdev_gendev))
++ continue;
++ spin_unlock_irqrestore(shost->host_lock, flags);
++
++ if (prev)
++ put_device(&prev->sdev_gendev);
+ scsi_run_queue(sdev->request_queue);
++
++ prev = sdev;
++
++ spin_lock_irqsave(shost->host_lock, flags);
++ }
++ spin_unlock_irqrestore(shost->host_lock, flags);
++ if (prev)
++ put_device(&prev->sdev_gendev);
+ }
+
+ static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
+--
+2.53.0
+
--- /dev/null
+From a9d1c5d40a10e64c351c5154bfa58289e228be8e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 11:24:11 +0800
+Subject: sctp: fix race between sctp_wait_for_connect and peeloff
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit f14fe6395a8b3d961a61e138ad7b36ba3626dd4e ]
+
+sctp_wait_for_connect() drops and re-acquires the socket lock while
+waiting for the association to reach ESTABLISHED state. During this
+window, another thread can peeloff the association to a new socket via
+getsockopt(SCTP_SOCKOPT_PEELOFF), changing asoc->base.sk. After
+re-acquiring the old socket lock, sctp_wait_for_connect() returns
+success without noticing the migration — the caller then accesses
+the association under the wrong lock in sctp_datamsg_from_user().
+
+Add the same sk != asoc->base.sk check that sctp_wait_for_sndbuf()
+already has, returning an error if the association was migrated while
+we slept.
+
+Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260527032411.60959-1-kipreyyy@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/socket.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 2c5ad53984906c..c763eb3296b3ee 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -9350,6 +9350,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
+ release_sock(sk);
+ current_timeo = schedule_timeout(current_timeo);
+ lock_sock(sk);
++ if (sk != asoc->base.sk)
++ goto do_error;
+
+ *timeo_p = current_timeo;
+ }
+--
+2.53.0
+
xfrm-move-policy_bydst-rcu-sync-from-per-netns-.exit.patch
net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
bcache-fix-uninitialized-closure-object.patch
+nfc-llcp-fix-use-after-free-in-llcp_sock_release.patch
+nfc-llcp-fix-use-after-free-race-in-nfc_llcp_recv_cc.patch
+xfrm-check-for-underflow-in-xfrm_state_mtu.patch
+nfc-nxp-nci-i2c-use-rising-edge-irq-on-acpi-systems.patch
+tools-bootconfig-fix-buf-leaks-in-apply_xbc.patch
+hid-remove-duplicate-hid_warn_ratelimited-definition.patch
+kunit-fix-use-after-free-in-debugfs-when-using-kunit.patch
+accel-rocket-fix-uaf-via-dangling-gem-handle-in-crea.patch
+kernel-fork-validate-exit_signal-in-kernel_clone.patch
+netfilter-synproxy-refresh-tcphdr-after-skb_ensure_w.patch
+netfilter-xt_cpu-prefer-raw_smp_processor_id.patch
+netfilter-ebtables-fix-oob-read-in-compat_mtw_from_u.patch
+netfilter-nf_tables-fix-dst-corruption-in-same-regis.patch
+tun-free-page-on-short-frame-rejection-in-tun_xdp_on.patch
+tun-free-page-on-build_skb-failure-in-tun_xdp_one.patch
+vsock-keep-poll-shutdown-state-consistent.patch
+net-netlink-fix-sending-unassigned-nsid-after-assign.patch
+net-netlink-don-t-set-nsid-on-local-notifications.patch
+net-smc-do-not-re-initialize-smc-hashtables.patch
+net-iucv-fix-locking-in-.getsockopt.patch
+scsi-core-run-queues-for-all-non-sdev_del-devices-fr.patch
+ipv4-free-net-ipv4.sysctl_local_reserved_ports-after.patch
+alsa-pcm-oss-fix-setup-list-uaf-on-proc-write-error.patch
+asoc-intel-bytcht_es8316-fix-mclk-leak-on-init-error.patch
+net-mlx5-hws-reject-unsupported-remove-header-action.patch
+net-hsr-fix-potential-oob-access-in-supervision-fram.patch
+gpio-mxc-fix-irq_high-handling.patch
+net-team-remove-unused-team_mode_op-port_enabled.patch
+net-team-rename-port_disabled-team-mode-op-to-port_t.patch
+net-team-fix-null-pointer-dereference-in-team_xmit-d.patch
+net-avoid-checksumming-unreadable-skb-tail-on-trim.patch
+ethtool-rss-avoid-modifying-the-rss-context-response.patch
+ethtool-rss-add-missing-errno-on-rss-context-delete.patch
+ethtool-rss-fix-falsely-ignoring-indir-table-updates.patch
+ethtool-rss-fix-indir_table-and-hkey-leak-on-get_rxf.patch
+ethtool-rss-fix-hkey-leak-when-indir_size-is-0.patch
+ethtool-rss-avoid-device-context-leak-on-reply-build.patch
+ethtool-module-call-ethnl_ops_complete-on-module-fla.patch
+ethtool-module-avoid-leaking-a-netdev-ref-on-module-.patch
+ethtool-module-avoid-racy-updates-to-dev-ethtool-bit.patch
+ethtool-module-check-fw_flash_in_progress-under-rtnl.patch
+ethtool-module-fix-cleanup-if-socket-used-for-flashi.patch
+ethtool-cmis-require-exact-cdb-reply-length.patch
+ethtool-cmis-fix-u16-to-u8-truncation-of-msleep_pre_.patch
+ethtool-cmis-validate-start_cmd_payload_size-from-mo.patch
+ethtool-cmis-validate-fw-size-against-start_cmd_payl.patch
+cxl-test-update-mock-dev-array-before-calling-platfo.patch
+tunnels-load-network-headers-after-skb_cow-in-iptunn.patch
+vxlan-do-not-reuse-cached-ip_hdr-value-after-skb_tun.patch
+tunnels-do-not-assume-transport-header-in-iptunnel_p.patch
+ksmbd-fix-fsctl-permission-bypass-by-adding-a-permis.patch
+asoc-codecs-simple-mux-fix-enum-control-bounds-check.patch
+drm-xe-restore-idledly-regiter-on-engine-reset.patch
+bluetooth-6lowpan-check-skb_clone-return-value-in-se.patch
+bonding-refuse-to-enslave-can-devices.patch
+bridge-fix-sleep-in-atomic-context-in-netlink-path.patch
+bridge-fix-sleep-in-atomic-context-in-sysfs-path.patch
+ethtool-coalesce-cap-profile-updates-at-net_dim_para.patch
+ethtool-tsconfig-fix-reply-error-handling.patch
+ethtool-linkstate-fix-unbalanced-ethnl_ops_complete-.patch
+ethtool-pse-pd-fix-missing-ethnl_ops_complete.patch
+ethtool-tsconfig-fix-missing-ethnl_ops_complete.patch
+ethtool-tsinfo-fix-uninitialized-stats-on-the-by-phc.patch
+ethtool-tsinfo-don-t-pass-err_ptr-to-genlmsg_cancel-.patch
+ethtool-strset-fix-header-attribute-index-in-ethnl_r.patch
+ethtool-eeprom-add-missing-ethnl_ops_begin-_complete.patch
+ethtool-eeprom-add-more-safeties-to-eeprom-netlink-f.patch
+ipv6-rpl-fix-hdrlen-overflow-in-ipv6_rpl_srh_decompr.patch
+net-sched-revert-net-sched-restrict-conditions-for-a.patch
+net-hibmcge-disable-relaxed-ordering-to-fix-rx-packe.patch
+net-handshake-use-spin_lock_bh-for-hn_lock.patch
+nvme-tcp-store-negative-errno-in-queue-tls_err.patch
+net-handshake-pass-negative-errno-through-handshake_.patch
+bluetooth-l2cap-clear-chan-ident-on-ecred-reconfigur.patch
+bluetooth-l2cap-fix-possible-crash-on-l2cap_ecred_co.patch
+bluetooth-hci_sync-set-hci_cmd_drain_workqueue-durin.patch
+bluetooth-hci_sync-reset-device-counters-in-hci_dev_.patch
+gpio-adnp-fix-flow-control-regression-caused-by-scop.patch
+gpio-virtuser-fix-uninitialized-data-bug-in-gpio_vir.patch
+gpio-rockchip-convert-bank-clk-to-devm_clk_get_enabl.patch
+gpio-rockchip-teardown-bugs-and-resource-leaks.patch
+net-mana-add-null-guards-in-teardown-path-to-prevent.patch
+net-mana-skip-redundant-detach-on-already-detached-p.patch
+sctp-fix-race-between-sctp_wait_for_connect-and-peel.patch
+vsock-virtio-bind-uarg-before-filling-zerocopy-skb.patch
+ipv6-fix-possible-infinite-loop-in-rt6_fill_node.patch
+ipv6-fix-possible-infinite-loop-in-fib6_select_path.patch
+net-skbuff-fix-pskb_carve-leaking-zcopy-pages.patch
+media-rc-fix-race-between-unregister-and-urb-irq-cal.patch
+media-rc-ttusbir-fix-inverted-error-logic.patch
--- /dev/null
+From 695a3801af3a423d02ed4da4025350f397518f68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 11:01:26 +0800
+Subject: tools/bootconfig: Fix buf leaks in apply_xbc
+
+From: Hongtao Lee <lihongtao@kylinos.cn>
+
+[ Upstream commit f42d01aadcedd7bbf4f9a466cabe25c1781dedad ]
+
+If data calloc failed, free the buf before return.
+
+Link: https://lore.kernel.org/all/20260520030126.147782-1-lihongtao@kylinos.cn/
+
+Fixes: 950313ebf79c ("tools: bootconfig: Add bootconfig command")
+Signed-off-by: Hongtao Lee <lihongtao@kylinos.cn>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/bootconfig/main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c
+index 643f707b8f1da1..ddabde20585f21 100644
+--- a/tools/bootconfig/main.c
++++ b/tools/bootconfig/main.c
+@@ -390,8 +390,10 @@ static int apply_xbc(const char *path, const char *xbc_path)
+
+ /* Backup the bootconfig data */
+ data = calloc(size + BOOTCONFIG_ALIGN + BOOTCONFIG_FOOTER_SIZE, 1);
+- if (!data)
++ if (!data) {
++ free(buf);
+ return -ENOMEM;
++ }
+ memcpy(data, buf, size);
+
+ /* Check the data format */
+--
+2.53.0
+
--- /dev/null
+From 6c5887a6154b0b34ab68ee1f60d28719d1bc7b75 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 09:33:13 -0700
+Subject: tun: free page on build_skb failure in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit aa8963fdce667a42fb7f0bdd2909fadcab02f9a8 ]
+
+When build_skb() fails in tun_xdp_one(), the function sets ret to
+-ENOMEM and jumps to the out label, which returns without freeing the
+page that vhost_net_build_xdp() allocated for the frame. As with the
+short-frame rejection path, tun_sendmsg() discards the per-buffer error
+and still returns total_len, so vhost_tx_batch() takes the success path
+and never frees the page. Each build_skb() failure in a batch leaks one
+page-frag chunk.
+
+Free the page before taking the error path, matching the put_page() the
+other error exits of tun_xdp_one() already perform.
+
+Fixes: 043d222f93ab ("tuntap: accept an array of XDP buffs through sendmsg()")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260521163312.1479805-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index afba37965ce3b7..9a767da38c71e7 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2437,6 +2437,7 @@ static int tun_xdp_one(struct tun_struct *tun,
+ build:
+ skb = build_skb(xdp->data_hard_start, buflen);
+ if (!skb) {
++ put_page(virt_to_head_page(xdp->data));
+ ret = -ENOMEM;
+ goto out;
+ }
+--
+2.53.0
+
--- /dev/null
+From 767160ea23e9313076ed069880cfe3c8f799343a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 09:00:21 -0700
+Subject: tun: free page on short-frame rejection in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f4feb1e20058e407cb00f45aff47f5b7e19a6bbf ]
+
+tun_xdp_one() returns -EINVAL on a frame shorter than ETH_HLEN without
+freeing the page that vhost_net_build_xdp() allocated for it.
+tun_sendmsg() discards that -EINVAL and still returns total_len, so
+vhost_tx_batch() takes the success path and never frees the page; each
+short frame in a batch leaks one page-frag chunk.
+
+A local process that can open /dev/net/tun and /dev/vhost-net can hit
+this path: it attaches a tun/tap device as the vhost-net backend and
+feeds TX descriptors whose length minus the virtio-net header is below
+ETH_HLEN. Each kick leaks the page-frag chunks for that batch, and a
+tight submission loop exhausts host memory and triggers an OOM panic.
+Free the page before returning -EINVAL, matching the XDP-program error
+path in the same function.
+
+Fixes: 049584807f1d ("tun: add missing verification for short frame")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260520160020.375349-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 8192740357a09c..afba37965ce3b7 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2392,8 +2392,10 @@ static int tun_xdp_one(struct tun_struct *tun,
+ bool skb_xdp = false;
+ struct page *page;
+
+- if (unlikely(datasize < ETH_HLEN))
++ if (unlikely(datasize < ETH_HLEN)) {
++ put_page(virt_to_head_page(xdp->data));
+ return -EINVAL;
++ }
+
+ xdp_prog = rcu_dereference(tun->xdp_prog);
+ if (xdp_prog) {
+--
+2.53.0
+
--- /dev/null
+From 56f526ea159163503dce217ec7513fe2eb476aea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 11:55:12 +0000
+Subject: tunnels: do not assume transport header in
+ iptunnel_pmtud_check_icmp()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 509323077ef79a26ba0c60bb556e45c12c398b2d ]
+
+In some cases, iptunnel_pmtud_check_icmp() can be called while
+skb transport header is not set.
+
+This triggers an out-of-bound access, because
+(typeof(skb->transport_header))~0U is 65535.
+
+Access the icmp header based on IPv4 network header,
+after making sure icmp->type is present in skb linear part.
+
+Note that iptunnel_pmtud_check_icmpv6()) is fine.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Reported-by: Damiano Melotti <melotti@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260522115512.1519110-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index d5a63155a05597..4b5fd4b13722ca 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -280,7 +280,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct icmphdr *icmph = icmp_hdr(skb);
+ const struct iphdr *iph = ip_hdr(skb);
+
+ if (mtu < 576 || iph->frag_off != htons(IP_DF))
+@@ -291,9 +290,17 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ ipv4_is_lbcast(iph->saddr) || ipv4_is_multicast(iph->saddr))
+ return 0;
+
+- if (iph->protocol == IPPROTO_ICMP && icmp_is_err(icmph->type))
+- return 0;
++ if (iph->protocol == IPPROTO_ICMP) {
++ const struct icmphdr *icmph;
+
++ if (!pskb_network_may_pull(skb, iph->ihl * 4 +
++ offsetofend(struct icmphdr, type)))
++ return 0;
++ iph = ip_hdr(skb);
++ icmph = (void *)iph + iph->ihl * 4;
++ if (icmp_is_err(icmph->type))
++ return 0;
++ }
+ return iptunnel_pmtud_build_icmp(skb, mtu);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From b4c2edc7be9365366aba5f0547ab1d733f9f3d71 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:13:35 +0000
+Subject: tunnels: load network headers after skb_cow() in
+ iptunnel_pmtud_build_icmp[v6]()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b4bc94353050b1fa7b702bd4c6600710dd926cff ]
+
+Sashiko found that iptunnel_pmtud_build_icmp() and
+iptunnel_pmtud_build_icmpv6() were caching ip_hdr() and ipv6_hdr()
+before an skb_cow() call which can reallocate skb->head.
+
+Fix this possible UAF by initializing the local variables
+after the skb_cow() call.
+
+Remove skb_reset_network_header() calls which were not needed.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525201335.2361845-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 5683c328990f49..d5a63155a05597 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -212,7 +212,7 @@ EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
+ */
+ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct iphdr *iph = ip_hdr(skb);
++ const struct iphdr *iph;
+ struct icmphdr *icmph;
+ struct iphdr *niph;
+ struct ethhdr eh;
+@@ -226,7 +226,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, 576 - sizeof(*niph) - sizeof(*icmph));
+ if (err)
+@@ -236,7 +235,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ err = skb_cow(skb, sizeof(*niph) + sizeof(*icmph) + ETH_HLEN);
+ if (err)
+ return err;
+-
++ iph = ip_hdr(skb);
+ icmph = skb_push(skb, sizeof(*icmph));
+ *icmph = (struct icmphdr) {
+ .type = ICMP_DEST_UNREACH,
+@@ -308,7 +307,7 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ {
+- const struct ipv6hdr *ip6h = ipv6_hdr(skb);
++ const struct ipv6hdr *ip6h;
+ struct icmp6hdr *icmp6h;
+ struct ipv6hdr *nip6h;
+ struct ethhdr eh;
+@@ -323,7 +322,6 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, IPV6_MIN_MTU - sizeof(*nip6h) - sizeof(*icmp6h));
+ if (err)
+@@ -334,6 +332,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ if (err)
+ return err;
+
++ ip6h = ipv6_hdr(skb);
+ icmp6h = skb_push(skb, sizeof(*icmp6h));
+ *icmp6h = (struct icmp6hdr) {
+ .icmp6_type = ICMPV6_PKT_TOOBIG,
+--
+2.53.0
+
--- /dev/null
+From 86b3cb82627f19ebd8b6921b555385e4dc773e38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 00:56:36 +0800
+Subject: vsock: keep poll shutdown state consistent
+
+From: Ziyu Zhang <ziyuzhang201@gmail.com>
+
+[ Upstream commit aae9d8a5528b8ee9ff8dc5d3558b8a9f852a724a ]
+
+vsock_poll() reads vsk->peer_shutdown before taking the socket lock
+to set EPOLLHUP and EPOLLRDHUP, then reads it again after taking
+the lock to report EOF readability. A shutdown packet can update
+peer_shutdown while poll is waiting for the lock, so one poll invocation
+can report EOF readability without the corresponding HUP/RDHUP bits.
+
+For connectible sockets, take one peer_shutdown snapshot after
+lock_sock() and use it for all peer-shutdown-derived poll bits. For
+datagram sockets, which do not take lock_sock() in poll(), take one
+lockless READ_ONCE() snapshot and pair it with WRITE_ONCE() on the
+writer side.
+
+This keeps the peer-shutdown-derived bits internally consistent for each
+poll pass.
+
+Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
+Signed-off-by: Ziyu Zhang <ziyuzhang201@gmail.com>
+Link: https://patch.msgid.link/20260519165636.62542-1-ziyuzhang201@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/vmw_vsock/af_vsock.c | 49 ++++++++++++++++---------
+ net/vmw_vsock/hyperv_transport.c | 9 +++--
+ net/vmw_vsock/virtio_transport_common.c | 14 ++++---
+ net/vmw_vsock/vmci_transport.c | 8 ++--
+ 4 files changed, 52 insertions(+), 28 deletions(-)
+
+diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
+index 9d0e1915abbe86..2db48b53e47c77 100644
+--- a/net/vmw_vsock/af_vsock.c
++++ b/net/vmw_vsock/af_vsock.c
+@@ -523,7 +523,7 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
+ */
+ sock_reset_flag(sk, SOCK_DONE);
+ sk->sk_state = TCP_CLOSE;
+- vsk->peer_shutdown = 0;
++ WRITE_ONCE(vsk->peer_shutdown, 0);
+ }
+
+ if (sk->sk_type == SOCK_SEQPACKET) {
+@@ -814,7 +814,7 @@ static struct sock *__vsock_create(struct net *net,
+ vsk->rejected = false;
+ vsk->sent_request = false;
+ vsk->ignore_connecting_rst = false;
+- vsk->peer_shutdown = 0;
++ WRITE_ONCE(vsk->peer_shutdown, 0);
+ INIT_DELAYED_WORK(&vsk->connect_work, vsock_connect_timeout);
+ INIT_DELAYED_WORK(&vsk->pending_work, vsock_pending_work);
+
+@@ -1122,6 +1122,25 @@ static int vsock_shutdown(struct socket *sock, int mode)
+ return err;
+ }
+
++static __poll_t vsock_poll_shutdown(struct sock *sk, u32 peer_shutdown)
++{
++ __poll_t mask = 0;
++
++ /* INET sockets treat local write shutdown and peer write shutdown as a
++ * case of EPOLLHUP set.
++ */
++ if (sk->sk_shutdown == SHUTDOWN_MASK ||
++ ((sk->sk_shutdown & SEND_SHUTDOWN) &&
++ (peer_shutdown & SEND_SHUTDOWN)))
++ mask |= EPOLLHUP;
++
++ if (sk->sk_shutdown & RCV_SHUTDOWN ||
++ peer_shutdown & SEND_SHUTDOWN)
++ mask |= EPOLLRDHUP;
++
++ return mask;
++}
++
+ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+ {
+@@ -1139,24 +1158,17 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ /* Signify that there has been an error on this socket. */
+ mask |= EPOLLERR;
+
+- /* INET sockets treat local write shutdown and peer write shutdown as a
+- * case of EPOLLHUP set.
+- */
+- if ((sk->sk_shutdown == SHUTDOWN_MASK) ||
+- ((sk->sk_shutdown & SEND_SHUTDOWN) &&
+- (vsk->peer_shutdown & SEND_SHUTDOWN))) {
+- mask |= EPOLLHUP;
+- }
+-
+- if (sk->sk_shutdown & RCV_SHUTDOWN ||
+- vsk->peer_shutdown & SEND_SHUTDOWN) {
+- mask |= EPOLLRDHUP;
+- }
+-
+ if (sk_is_readable(sk))
+ mask |= EPOLLIN | EPOLLRDNORM;
+
+ if (sock->type == SOCK_DGRAM) {
++ u32 peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++
++ /* DGRAM sockets do not take lock_sock() in poll(), so use one
++ * lockless snapshot for all shutdown-derived mask bits.
++ */
++ mask |= vsock_poll_shutdown(sk, peer_shutdown);
++
+ /* For datagram sockets we can read if there is something in
+ * the queue and write as long as the socket isn't shutdown for
+ * sending.
+@@ -1171,6 +1183,7 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+
+ } else if (sock_type_connectible(sk->sk_type)) {
+ const struct vsock_transport *transport;
++ u32 peer_shutdown;
+
+ lock_sock(sk);
+
+@@ -1203,8 +1216,10 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ * terminated should also be considered read, and we check the
+ * shutdown flag for that.
+ */
++ peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++ mask |= vsock_poll_shutdown(sk, peer_shutdown);
+ if (sk->sk_shutdown & RCV_SHUTDOWN ||
+- vsk->peer_shutdown & SEND_SHUTDOWN) {
++ peer_shutdown & SEND_SHUTDOWN) {
+ mask |= EPOLLIN | EPOLLRDNORM;
+ }
+
+diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
+index f9dc9b4d302383..4da752b47b116f 100644
+--- a/net/vmw_vsock/hyperv_transport.c
++++ b/net/vmw_vsock/hyperv_transport.c
+@@ -264,7 +264,7 @@ static void hvs_do_close_lock_held(struct vsock_sock *vsk,
+ struct sock *sk = sk_vsock(vsk);
+
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+ sk->sk_state_change(sk);
+@@ -593,7 +593,9 @@ static int hvs_update_recv_data(struct hvsock *hvs)
+ return -EIO;
+
+ if (payload_len == 0)
+- hvs->vsk->peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(hvs->vsk->peer_shutdown,
++ READ_ONCE(hvs->vsk->peer_shutdown) |
++ SEND_SHUTDOWN);
+
+ hvs->recv_data_len = payload_len;
+ hvs->recv_data_off = 0;
+@@ -736,7 +738,8 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk)
+ return ret;
+ return hvs->recv_data_len;
+ case 0:
+- vsk->peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(vsk->peer_shutdown,
++ READ_ONCE(vsk->peer_shutdown) | SEND_SHUTDOWN);
+ ret = 0;
+ break;
+ default: /* -1 */
+diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
+index ed42e08798a967..1e07d3b1a0e800 100644
+--- a/net/vmw_vsock/virtio_transport_common.c
++++ b/net/vmw_vsock/virtio_transport_common.c
+@@ -1206,7 +1206,7 @@ static void virtio_transport_do_close(struct vsock_sock *vsk,
+ struct sock *sk = sk_vsock(vsk);
+
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+ sk->sk_state_change(sk);
+@@ -1409,12 +1409,15 @@ virtio_transport_recv_connected(struct sock *sk,
+ case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
+ sk->sk_write_space(sk);
+ break;
+- case VIRTIO_VSOCK_OP_SHUTDOWN:
++ case VIRTIO_VSOCK_OP_SHUTDOWN: {
++ u32 peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++
+ if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_RCV)
+- vsk->peer_shutdown |= RCV_SHUTDOWN;
++ peer_shutdown |= RCV_SHUTDOWN;
+ if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_SEND)
+- vsk->peer_shutdown |= SEND_SHUTDOWN;
+- if (vsk->peer_shutdown == SHUTDOWN_MASK) {
++ peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(vsk->peer_shutdown, peer_shutdown);
++ if (peer_shutdown == SHUTDOWN_MASK) {
+ if (vsock_stream_has_data(vsk) <= 0 && !sock_flag(sk, SOCK_DONE)) {
+ (void)virtio_transport_reset(vsk, NULL);
+ virtio_transport_do_close(vsk, true);
+@@ -1429,6 +1432,7 @@ virtio_transport_recv_connected(struct sock *sk,
+ if (le32_to_cpu(virtio_vsock_hdr(skb)->flags))
+ sk->sk_state_change(sk);
+ break;
++ }
+ case VIRTIO_VSOCK_OP_RST:
+ virtio_transport_do_close(vsk, true);
+ break;
+diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
+index 4cd11f355e9d6b..443125e48f2481 100644
+--- a/net/vmw_vsock/vmci_transport.c
++++ b/net/vmw_vsock/vmci_transport.c
+@@ -811,7 +811,7 @@ static void vmci_transport_handle_detach(struct sock *sk)
+ /* On a detach the peer will not be sending or receiving
+ * anymore.
+ */
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+
+ /* We should not be sending anymore since the peer won't be
+ * there to receive, but we can still receive if there is data
+@@ -1534,7 +1534,9 @@ static int vmci_transport_recv_connected(struct sock *sk,
+ if (pkt->u.mode) {
+ vsk = vsock_sk(sk);
+
+- vsk->peer_shutdown |= pkt->u.mode;
++ WRITE_ONCE(vsk->peer_shutdown,
++ READ_ONCE(vsk->peer_shutdown) |
++ pkt->u.mode);
+ sk->sk_state_change(sk);
+ }
+ break;
+@@ -1551,7 +1553,7 @@ static int vmci_transport_recv_connected(struct sock *sk,
+ * a clean shutdown.
+ */
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+
+--
+2.53.0
+
--- /dev/null
+From c3c98736e7173eb7601c1bfe46787924caec6364 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 10:33:01 +0800
+Subject: vsock/virtio: bind uarg before filling zerocopy skb
+
+From: Jingguo Tan <tanjingguo@huawei.com>
+
+[ Upstream commit 1e584c304cfb94a759417130b1fc6d30b30c4cce ]
+
+virtio_transport_send_pkt_info() allocates or reuses the zerocopy uarg
+before entering the send loop, but virtio_transport_alloc_skb() still
+fills the skb before it inherits that uarg. When fixed-buffer vectored
+zerocopy hits MAX_SKB_FRAGS, io_sg_from_iter() may partially attach
+managed frags and return -EMSGSIZE. The rollback path call kfree_skb()
+to free an skb that carries SKBFL_MANAGED_FRAG_REFS but no uarg, so
+skb_release_data() falls through to ordinary frag unref.
+
+Pass the uarg into virtio_transport_alloc_skb() and bind it immediately
+before virtio_transport_fill_skb(). This keeps control or no-payload skbs
+untouched while ensuring success and rollback share one lifetime rule.
+
+Fixes: 581512a6dc93 ("vsock/virtio: MSG_ZEROCOPY flag support")
+Signed-off-by: Lin Ma <malin89@huawei.com>
+Signed-off-by: Rongzhen Cui <cuirongzhen@huawei.com>
+Signed-off-by: Jingguo Tan <tanjingguo@huawei.com>
+Acked-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
+Link: https://patch.msgid.link/20260527023301.1075581-1-malin89@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/vmw_vsock/virtio_transport_common.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
+index 1e07d3b1a0e800..c925b5c5b35a57 100644
+--- a/net/vmw_vsock/virtio_transport_common.c
++++ b/net/vmw_vsock/virtio_transport_common.c
+@@ -207,6 +207,7 @@ static u16 virtio_transport_get_type(struct sock *sk)
+ static struct sk_buff *virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
+ size_t payload_len,
+ bool zcopy,
++ struct ubuf_info *uarg,
+ u32 src_cid,
+ u32 src_port,
+ u32 dst_cid,
+@@ -247,6 +248,12 @@ static struct sk_buff *virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *
+ if (info->msg && payload_len > 0) {
+ int err;
+
++ /* Bind the zerocopy lifetime before filling frags so error
++ * rollback frees managed fixed-buffer pages through
++ * the uarg-aware path.
++ */
++ skb_zcopy_set(skb, uarg, NULL);
++
+ err = virtio_transport_fill_skb(skb, info, payload_len, zcopy);
+ if (err)
+ goto out;
+@@ -366,6 +373,7 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
+ skb_len = min(max_skb_len, rest_len);
+
+ skb = virtio_transport_alloc_skb(info, skb_len, can_zcopy,
++ uarg,
+ src_cid, src_port,
+ dst_cid, dst_port);
+ if (!skb) {
+@@ -373,8 +381,6 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
+ break;
+ }
+
+- skb_zcopy_set(skb, uarg, NULL);
+-
+ virtio_transport_inc_tx_pkt(vvs, skb);
+
+ ret = t_ops->send_pkt(skb);
+@@ -1161,7 +1167,7 @@ static int virtio_transport_reset_no_sock(const struct virtio_transport *t,
+ if (!t)
+ return -ENOTCONN;
+
+- reply = virtio_transport_alloc_skb(&info, 0, false,
++ reply = virtio_transport_alloc_skb(&info, 0, false, NULL,
+ le64_to_cpu(hdr->dst_cid),
+ le32_to_cpu(hdr->dst_port),
+ le64_to_cpu(hdr->src_cid),
+--
+2.53.0
+
--- /dev/null
+From 3897216ca1fc418d3628857218bb08c04317baac Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:36:42 +0000
+Subject: vxlan: do not reuse cached ip_hdr() value after
+ skb_tunnel_check_pmtu()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 7d9ef0cb271555d8cf39fefe6c981e1493b25ecf ]
+
+skb_tunnel_check_pmtu() can change skb->head.
+
+Reusing old_iph afer skb_tunnel_check_pmtu() can cause an UAF.
+
+Use instead ip_hdr(skb) as done in drivers/net/bareudp.c
+and drivers/net/geneve.c.
+
+Found by Sashiko.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525203642.2389723-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index d2d0e0bd43716c..a4ff66e354f532 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -2532,7 +2532,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
+ vni, md, flags, udp_sum);
+@@ -2606,7 +2606,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip6_dst_hoplimit(ndst);
+ skb_scrub_packet(skb, xnet);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
+--
+2.53.0
+
--- /dev/null
+From 806f98afcdf628e7f1744c8b16d910975d22c286 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:49:14 -0600
+Subject: xfrm: Check for underflow in xfrm_state_mtu
+
+From: David Ahern <dahern@nvidia.com>
+
+[ Upstream commit 742b04d0550b0ec89dcbc99537ec88653bd1ad90 ]
+
+Leo Lin reported OOB write issue in esp component:
+
+ xfrm_state_mtu() returns u32 but performs its arithmetic in unsigned
+ modulo-2^32 space using an attacker-influenced "header_len + authsize +
+ net_adj" subtracted from a small "mtu" argument. A nobody user can
+ install an IPv4 ESP tunnel SA with a large authentication key
+ (XFRMA_ALG_AUTH_TRUNC, e.g. hmac(sha512), 64-byte key, 64-byte trunc),
+ configure a small interface MTU (68 bytes), and set XFRMA_TFCPAD to a
+ large value. When a single UDP datagram is then sent through the
+ tunnel, xfrm_state_mtu() underflows to a near-2^32 value, and
+ esp_output() consumes it as a signed int via:
+
+ padto = min(x->tfcpad, xfrm_state_mtu(x, mtu_cached))
+ esp.tfclen = padto - skb->len (assigned to int)
+
+ esp.tfclen ends up negative (e.g. -207). It is sign-extended to size_t
+ when passed to memset() inside esp_output_fill_trailer(), producing a
+ ~16 EB write of zeroes at skb_tail_pointer(skb). KASAN logs it as
+ "Write of size 18446744073709551537 at addr ffff888...".
+
+Check for underflow and return 1. This causes the sendmsg attempt to
+fail with ENETUNREACH.
+
+Fixes: c5c252389374 ("[XFRM]: Optimize MTU calculation")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Assisted-by: Codex:26.506.31004
+Signed-off-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index f6ba58f18ac18e..1b81e92e3eee78 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -3113,10 +3113,14 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ const struct xfrm_type *type = READ_ONCE(x->type);
+ struct crypto_aead *aead;
+ u32 blksize, net_adj = 0;
++ u32 overhead, payload_mtu;
+
+ if (x->km.state != XFRM_STATE_VALID ||
+- !type || type->proto != IPPROTO_ESP)
++ !type || type->proto != IPPROTO_ESP) {
++ if (mtu <= x->props.header_len)
++ return 1;
+ return mtu - x->props.header_len;
++ }
+
+ aead = x->data;
+ blksize = ALIGN(crypto_aead_blocksize(aead), 4);
+@@ -3139,8 +3143,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ break;
+ }
+
+- return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
+- net_adj) & ~(blksize - 1)) + net_adj - 2;
++ overhead = x->props.header_len + crypto_aead_authsize(aead) + net_adj;
++ if (mtu <= overhead)
++ return 1;
++
++ payload_mtu = mtu - overhead;
++ payload_mtu &= ~(blksize - 1);
++ if (payload_mtu <= 2)
++ return 1;
++
++ return payload_mtu + net_adj - 2;
++
+ }
+ EXPORT_SYMBOL_GPL(xfrm_state_mtu);
+
+--
+2.53.0
+
--- /dev/null
+From c7726f90e5dfa49ae7d153dba4eb96edb5518569 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 09:24:00 -0300
+Subject: ASoC: codecs: simple-mux: Fix enum control bounds check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit f63ad68e18d774a5d15cd7e405ead63f6b322679 ]
+
+simple_mux_control_put() rejects values greater than e->items, but
+enum control values are zero based. For the two-entry mux used by this
+driver, valid values are 0 and 1, so value 2 must be rejected as well.
+
+Accepting e->items can store an invalid mux state, pass it to the GPIO
+setter, and pass it on to the DAPM mux update path where it is used as
+an index into the enum text array.
+
+Use the same >= e->items check used by the ASoC enum helpers.
+
+Fixes: 342fbb7578d1 ("ASoC: add simple-mux")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260527-asoc-simple-mux-enum-bounds-v1-1-3f805b9fc671@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/simple-mux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/simple-mux.c b/sound/soc/codecs/simple-mux.c
+index bf67de12d20b7f..02ccaa4c9a0804 100644
+--- a/sound/soc/codecs/simple-mux.c
++++ b/sound/soc/codecs/simple-mux.c
+@@ -40,7 +40,7 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
+ struct simple_mux *priv = snd_soc_component_get_drvdata(c);
+
+- if (ucontrol->value.enumerated.item[0] > e->items)
++ if (ucontrol->value.enumerated.item[0] >= e->items)
+ return -EINVAL;
+
+ if (priv->mux == ucontrol->value.enumerated.item[0])
+--
+2.53.0
+
--- /dev/null
+From 039fc69523512acd9447a888c2a337e968467e94 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 13:51:47 -0300
+Subject: ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit afb2a3a9d8369d18122a0d7cd294eba9a98259c6 ]
+
+byt_cht_es8316_init() enables MCLK before configuring the codec sysclk
+and creating the headset jack. If either of those later steps fails, the
+function returns without disabling MCLK, leaving the clock enabled after
+card registration fails.
+
+Track whether this driver enabled MCLK and disable it on the init error
+paths. Add the matching DAI link exit callback so the same clock enable
+is also balanced when ASoC cleans up a successfully initialized link.
+
+Fixes: a03bdaa565cb ("ASoC: Intel: add machine driver for BYT/CHT + ES8316")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260519-asoc-bytcht-es8316-mclk-leak-v1-1-b4a11cdc2afd@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/bytcht_es8316.c | 29 ++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
+index fbd7e1f0783fd9..d334d748f76fb0 100644
+--- a/sound/soc/intel/boards/bytcht_es8316.c
++++ b/sound/soc/intel/boards/bytcht_es8316.c
+@@ -39,6 +39,7 @@ struct byt_cht_es8316_private {
+ struct gpio_desc *speaker_en_gpio;
+ struct device *codec_dev;
+ bool speaker_en;
++ bool mclk_enabled;
+ };
+
+ enum {
+@@ -169,6 +170,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
+ },
+ };
+
++static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
++{
++ if (!priv->mclk_enabled)
++ return;
++
++ clk_disable_unprepare(priv->mclk);
++ priv->mclk_enabled = false;
++}
++
+ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ {
+ struct snd_soc_component *codec = asoc_rtd_to_codec(runtime, 0)->component;
+@@ -225,12 +235,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret)
+ dev_err(card->dev, "unable to enable MCLK\n");
++ else
++ priv->mclk_enabled = true;
+
+ ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(runtime, 0), 0, 19200000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set codec clock %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ ret = snd_soc_card_jack_new_pins(card, "Headset",
+@@ -239,13 +251,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ARRAY_SIZE(byt_cht_es8316_jack_pins));
+ if (ret) {
+ dev_err(card->dev, "jack creation failed %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_soc_component_set_jack(codec, &priv->jack, NULL);
+
+ return 0;
++
++err_disable_mclk:
++ byt_cht_es8316_disable_mclk(priv);
++ return ret;
++}
++
++static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
++{
++ struct snd_soc_card *card = runtime->card;
++ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
++
++ byt_cht_es8316_disable_mclk(priv);
+ }
+
+ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+@@ -355,6 +379,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .init = byt_cht_es8316_init,
++ .exit = byt_cht_es8316_exit,
+ SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
+ },
+ };
+--
+2.53.0
+
--- /dev/null
+From 1030ebb9fe7fdb4d9a59ec56cd58a2ef59f300b8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 11:21:39 +0800
+Subject: Bluetooth: 6lowpan: check skb_clone() return value in
+ send_mcast_pkt()
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+[ Upstream commit 3c40d381ce04f9575a5d8b542898183c3b4b38dc ]
+
+The skb_clone() function can return NULL if memory allocation fails.
+send_mcast_pkt() calls skb_clone() without checking the return value, which
+can lead to a NULL pointer dereference in send_pkt() when it dereferences
+skb->data.
+Add a NULL check after skb_clone() and skip the peer if the clone fails.
+
+Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/6lowpan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
+index e65d4754c94f4c..b3132079573d4d 100644
+--- a/net/bluetooth/6lowpan.c
++++ b/net/bluetooth/6lowpan.c
+@@ -485,6 +485,8 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
+ int ret;
+
+ local_skb = skb_clone(skb, GFP_ATOMIC);
++ if (!local_skb)
++ continue;
+
+ BT_DBG("xmit %s to %pMR type %u IP %pI6c chan %p",
+ netdev->name,
+--
+2.53.0
+
--- /dev/null
+From 70d428f6357dc6f750dd9b44a3925956066ea5a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 18:51:52 +0800
+Subject: Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit 00e1950716c6ed67d74777b2db286b0fa23b4be9 ]
+
+l2cap_ecred_reconf_rsp() returns early on success without clearing
+chan->ident. Every other L2CAP response handler (l2cap_ecred_conn_rsp,
+l2cap_le_connect_rsp, l2cap_config_rsp) clears chan->ident after a
+successful transaction to prevent the channel from matching subsequent
+responses with the recycled ident value.
+
+A remote attacker that completed a reconfiguration as the peer can
+replay a failure response with the stale ident, causing the kernel to
+match and destroy the already-established channel via
+l2cap_chan_del(chan, ECONNRESET).
+
+Clear chan->ident for all matching channels on success, and harden the
+failure path by using l2cap_chan_hold_unless_zero() consistent with
+other L2CAP handlers (l2cap_le_command_rej, __l2cap_get_chan_by_ident).
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index bbaf0070ca6176..0295a18a1cb3d7 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -5393,14 +5393,20 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("result 0x%4.4x", result);
+
+- if (!result)
++ if (!result) {
++ list_for_each_entry(chan, &conn->chan_l, list) {
++ if (chan->ident == cmd->ident)
++ chan->ident = 0;
++ }
+ return 0;
++ }
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
+ if (chan->ident != cmd->ident)
+ continue;
+
+- l2cap_chan_hold(chan);
++ if (!l2cap_chan_hold_unless_zero(chan))
++ continue;
+ l2cap_chan_lock(chan);
+
+ l2cap_chan_del(chan, ECONNRESET);
+--
+2.53.0
+
--- /dev/null
+From 07b8edce9a6ce1d862196700267295326a8ae5e6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 May 2026 12:09:42 -0400
+Subject: Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 41c2713b204e6cb6a94587bc6bf6935107df5479 ]
+
+If dcid is received for an already-assigned destination CID the spec
+requires that both channels to be discarded, but calling l2cap_chan_del
+may invalidate the tmp cursor created by list_for_each_entry_safe and
+in fact it is the wrong procedure as the chan->dcid may be assigned
+previously it really needs to be disconnected.
+
+Calling l2cap_chan_clone directly may still lead to l2cap_chan_del so
+instead schedule l2cap_chan_timeout with delay 0 to close the channel
+asynchronously.
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 0295a18a1cb3d7..1f5d5343d380e4 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -5195,6 +5195,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ cmd_len -= sizeof(*rsp);
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
++ struct l2cap_chan *orig;
+ u16 dcid;
+
+ if (chan->ident != cmd->ident ||
+@@ -5216,8 +5217,10 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
+
++ orig = __l2cap_get_chan_by_dcid(conn, dcid);
++
+ /* Check if dcid is already in use */
+- if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
++ if (dcid && orig) {
+ /* If a device receives a
+ * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
+ * already-assigned Destination CID, then both the
+@@ -5226,10 +5229,24 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ */
+ l2cap_chan_del(chan, ECONNREFUSED);
+ l2cap_chan_unlock(chan);
+- chan = __l2cap_get_chan_by_dcid(conn, dcid);
+- l2cap_chan_lock(chan);
+- l2cap_chan_del(chan, ECONNRESET);
+- l2cap_chan_unlock(chan);
++
++ /* Check that the dcid channel mode is
++ * L2CAP_MODE_EXT_FLOWCTL since this procedure is only
++ * valid for that mode and shouldn't disconnect a dcid
++ * in other modes.
++ */
++ if (orig->mode == L2CAP_MODE_EXT_FLOWCTL) {
++ l2cap_chan_lock(orig);
++ /* Disconnect the original channel as it may be
++ * considered connected since dcid has already
++ * been assigned; don't call l2cap_chan_close
++ * directly since that could lead to
++ * l2cap_chan_del and then removing the channel
++ * from the list while we're iterating over it.
++ */
++ __set_chan_timer(orig, 0);
++ l2cap_chan_unlock(orig);
++ }
+ continue;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 3f560f582a0e428c250d53768d4087a68701d8d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:33:19 +0200
+Subject: bonding: refuse to enslave CAN devices
+
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+
+[ Upstream commit 8ba68464e4787b6a7ec938826e16124df20fd23d ]
+
+syzbot reported a kernel paging request crash in
+can_rx_unregister() inside net/can/af_can.c. The crash occurs
+because a virtual CAN device (vxcan) is being enslaved to a
+bonding master.
+
+During the enslavement process, the bonding driver mutates
+and modifies the network device states to fit an Ethernet-like
+aggregation model. However, CAN devices operate on a completely
+different Layer 2 architecture, relying on the CAN mid-layer
+private data structure (can_ml_priv) instead of standard
+Ethernet structures. Since bonding does not initialize or
+maintain these CAN structures, subsequent operations on the
+half-enslaved interface (such as closing associated sockets
+via isotp_release) lead to a null-pointer dereference when
+accessing the CAN receiver lists.
+
+Bonding CAN interfaces is architecturally invalid as CAN lacks
+MAC addresses, ARP capabilities, and standard Ethernet
+link-layer mechanisms. While generic loopback devices are
+blocked globally in net/core/dev.c, virtual CAN devices
+bypass this check because they do not carry the IFF_LOOPBACK
+flag, despite acting as local software-loopbacks.
+
+Fix this by explicitly blocking network devices of type
+ARPHRD_CAN from being enslaved at the very beginning of
+bond_enslave(). This prevents illegal state mutations,
+eliminates the resulting KASAN crashes, and avoids potential
+memory leaks from incomplete socket cleanups.
+
+As the CAN support has been added a long time after bonding
+the Fixes-tag points to the introduction of ARPHRD_CAN that
+would have needed a specific handling in bonding_main.c.
+
+Fixes: cd05acfe65ed ("[CAN]: Allocate protocol numbers for PF_CAN")
+Reported-by: syzbot+8ed98cbd0161632bce95@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=8ed98cbd0161632bce95
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260526-bonding-candev-v1-1-ba1df400918a@hartkopp.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 029a7f001dd8a0..7732f7023033ed 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1889,6 +1889,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
+ int link_reporting;
+ int res = 0, i;
+
++ if (slave_dev->type == ARPHRD_CAN) {
++ BOND_NL_ERR(bond_dev, extack,
++ "CAN devices cannot be enslaved");
++ return -EPERM;
++ }
++
+ if (slave_dev->flags & IFF_MASTER &&
+ !netif_is_bond_master(slave_dev)) {
+ BOND_NL_ERR(bond_dev, extack,
+--
+2.53.0
+
--- /dev/null
+From af8f6a69281db87e06a62d37f331b285c893aaaa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:32 -0700
+Subject: ethtool: eeprom: add missing ethnl_ops_begin() / _complete() during
+ fallback
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 2376586f85f972fefe701f095bb37dcfe7405d21 ]
+
+All ethtool driver op calls should be sandwiched between
+ethnl_ops_begin() / ethnl_ops_complete(). In Netlink eeprom code,
+if the paged access failed we fall back to old API, but we
+first call _complete() and the fallback never does its own
+ethnl_ops_begin(). Move the fallback into the _begin() / _complete()
+section.
+
+Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-10-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/eeprom.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c
+index 6209c3a9c8f723..15546f2a5e4583 100644
+--- a/net/ethtool/eeprom.c
++++ b/net/ethtool/eeprom.c
+@@ -134,12 +134,11 @@ static int eeprom_prepare_data(const struct ethnl_req_info *req_base,
+ return 0;
+
+ err_ops:
++ if (ret == -EOPNOTSUPP)
++ ret = eeprom_fallback(request, reply);
+ ethnl_ops_complete(dev);
+ err_free:
+ kfree(page_data.data);
+-
+- if (ret == -EOPNOTSUPP)
+- return eeprom_fallback(request, reply);
+ return ret;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 740b8577bd6cfabd23459eb3304cb6feeebeaaa5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:33 -0700
+Subject: ethtool: eeprom: add more safeties to EEPROM Netlink fallback
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 67cfdd9210b99f260b3e0afeb9525e0acc7be31e ]
+
+The Netlink fallback path for reading module EEPROM
+(fallback_set_params()) validates that offset < eeprom_len,
+but does not check that offset + length stays within eeprom_len.
+The ioctl equivalent (ethtool_get_any_eeprom() in ioctl.c) has
+always enforced both bounds:
+
+ if (eeprom.offset + eeprom.len > total_len)
+ return -EINVAL;
+
+This could lead to surprises in both drivers and device FW.
+Add the missing offset + length validation to fallback_set_params(),
+mirroring the ioctl.
+
+Similarly - ethtool core in general, and ethtool_get_any_eeprom()
+in particular tries to zero-init all buffers passed to the drivers
+to avoid any extra work of zeroing things out. eeprom_fallback()
+uses a plain kmalloc(), change it to zalloc.
+
+Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-11-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/eeprom.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c
+index 15546f2a5e4583..4e864824b64d28 100644
+--- a/net/ethtool/eeprom.c
++++ b/net/ethtool/eeprom.c
+@@ -43,6 +43,9 @@ static int fallback_set_params(struct eeprom_req_info *request,
+ if (offset >= modinfo->eeprom_len)
+ return -EINVAL;
+
++ if (length > modinfo->eeprom_len - offset)
++ return -EINVAL;
++
+ eeprom->cmd = ETHTOOL_GMODULEEEPROM;
+ eeprom->len = length;
+ eeprom->offset = offset;
+@@ -68,7 +71,7 @@ static int eeprom_fallback(struct eeprom_req_info *request,
+ if (err < 0)
+ return err;
+
+- data = kmalloc(eeprom.len, GFP_KERNEL);
++ data = kzalloc(eeprom.len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ err = ethtool_get_module_eeprom_call(dev, &eeprom, data);
+--
+2.53.0
+
--- /dev/null
+From 189e711347181b3d03c83f45eff0894bb817dbd7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:01 +0200
+Subject: gpio: mxc: fix irq_high handling
+
+From: Alexander Stein <alexander.stein@ew.tq-group.com>
+
+[ Upstream commit dac917ed5aead741004db8d0d5151dd577802df8 ]
+
+If port->irq_high is -1 (fsl,imx21-gpio compatible) and gpio_idx is >= 16
+enable_irq_wake() is called with -1 which is wrong.
+
+Fixes: 5f6d1998adeb ("gpio: mxc: release the parent IRQ in runtime suspend")
+Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://patch.msgid.link/20260526063504.25916-1-alexander.stein@ew.tq-group.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-mxc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
+index 3cdc2b218a86af..a8ab78ae7fa30c 100644
+--- a/drivers/gpio/gpio-mxc.c
++++ b/drivers/gpio/gpio-mxc.c
+@@ -473,7 +473,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
+ * the handler is needed only once, but doing it for every port
+ * is more robust and easier.
+ */
+- port->irq_high = -1;
++ port->irq_high = 0;
+ port->mx_irq_handler = mx2_gpio_irq_handler;
+ } else
+ port->mx_irq_handler = mx3_gpio_irq_handler;
+--
+2.53.0
+
--- /dev/null
+From aae89ddf77742bfd1e38c2e3735bce14a2545110 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:02:45 +0200
+Subject: gpio: rockchip: convert bank->clk to devm_clk_get_enabled()
+
+From: Marco Scardovi <scardracs@disroot.org>
+
+[ Upstream commit 3e46c18d5d87f063a93ae0fe7662fbf6660459d5 ]
+
+The bank->clk was previously obtained via of_clk_get() and manually
+prepared/enabled. However, it was missing a corresponding clk_put() in
+both the error paths and the remove function, leading to a reference leak.
+
+Convert the allocation to devm_clk_get_enabled(), which also properly
+propagates failures from clk_prepare_enable() that were previously ignored.
+
+The GPIO bank device uses the same OF node as the previous of_clk_get()
+call, so devm_clk_get_enabled(dev, NULL) correctly resolves the same
+clock provider entry.
+
+Fix the reference leak and simplify the code by removing the manual
+clk_disable_unprepare() calls in the probe error paths and in the
+remove function.
+
+Fixes: 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio")
+Assisted-by: Antigravity:gemini-3.5-flash
+Signed-off-by: Marco Scardovi <scardracs@disroot.org>
+Link: https://patch.msgid.link/20260526171050.12785-2-scardracs@disroot.org
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-rockchip.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
+index 752bbc0c3d9db1..ff9a4b8611d7f4 100644
+--- a/drivers/gpio/gpio-rockchip.c
++++ b/drivers/gpio/gpio-rockchip.c
+@@ -647,11 +647,10 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ if (!bank->irq)
+ return -EINVAL;
+
+- bank->clk = of_clk_get(bank->of_node, 0);
++ bank->clk = devm_clk_get_enabled(bank->dev, NULL);
+ if (IS_ERR(bank->clk))
+ return PTR_ERR(bank->clk);
+
+- clk_prepare_enable(bank->clk);
+ id = readl(bank->reg_base + gpio_regs_v2.version_id);
+
+ /* If not gpio v2, that is default to v1. */
+@@ -661,7 +660,6 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ bank->db_clk = of_clk_get(bank->of_node, 1);
+ if (IS_ERR(bank->db_clk)) {
+ dev_err(bank->dev, "cannot find debounce clk\n");
+- clk_disable_unprepare(bank->clk);
+ return -EINVAL;
+ }
+ } else {
+@@ -735,7 +733,6 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
+
+ ret = rockchip_gpiolib_register(bank);
+ if (ret) {
+- clk_disable_unprepare(bank->clk);
+ mutex_unlock(&bank->deferred_lock);
+ return ret;
+ }
+@@ -776,7 +773,6 @@ static int rockchip_gpio_remove(struct platform_device *pdev)
+ {
+ struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
+
+- clk_disable_unprepare(bank->clk);
+ gpiochip_remove(&bank->gpio_chip);
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From 886d2b8dfd6a7279a446fc799e44f0dbde61aab3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 12:21:47 +0000
+Subject: ipv4: free net->ipv4.sysctl_local_reserved_ports after
+ unregister_net_sysctl_table()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 87a1e0fe7776da7ab411be332b4be58ac8840d10 ]
+
+ipv4_sysctl_exit_net() is currently freeing net->ipv4.sysctl_local_reserved_ports
+too soon.
+
+Only after unregister_net_sysctl_table() we can be sure no threads can possibly
+use the sysctls, including /proc/sys/net/ipv4/ip_local_reserved_ports.
+
+Fixes: 122ff243f5f1 ("ipv4: make ip_local_reserved_ports per netns")
+Reported-by: Ji'an Zhou <eilaimemedsnaimel@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260521122147.3584624-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/sysctl_net_ipv4.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 96f1b8d39fac11..9c827751dad6a7 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -1560,10 +1560,10 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net)
+ {
+ struct ctl_table *table;
+
+- kfree(net->ipv4.sysctl_local_reserved_ports);
+ table = net->ipv4.ipv4_hdr->ctl_table_arg;
+ unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
+ kfree(table);
++ kfree(net->ipv4.sysctl_local_reserved_ports);
+ }
+
+ static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
+--
+2.53.0
+
--- /dev/null
+From 1c232a559021e5a1c16a20cd4ed20ef861acd3c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:31:31 +0800
+Subject: ipv6: fix possible infinite loop in fib6_select_path()
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 9c7da87c2dc860bb17ca1ece942495d28b1ce3b9 ]
+
+Found while auditing the same pattern Sashiko reported in
+rt6_fill_node() [1]. Apply the same fix as
+commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").
+
+Writers holding tb6_lock can list_del_rcu(&first->fib6_siblings)
+without waiting for RCU readers; first->fib6_siblings.next then
+still points into the old ring and this softirq-side walker never
+reaches &first->fib6_siblings as its terminator. fib6_purge_rt()
+always WRITE_ONCE()s first->fib6_nsiblings to 0 before
+list_del_rcu(), so an inside-loop check is a reliable detach signal.
+
+[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev
+
+Fixes: d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260527053133.180695-2-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index 69659f2a6aea96..6d80e17c04c0d8 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -484,6 +484,9 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
+ const struct fib6_nh *nh = sibling->fib6_nh;
+ int nh_upper_bound;
+
++ if (!READ_ONCE(first->fib6_nsiblings))
++ break;
++
+ nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
+ if (hash > nh_upper_bound)
+ continue;
+--
+2.53.0
+
--- /dev/null
+From 55d1d536cb1a7ca9a1552cd4c9ee3a0d3bcd2dba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:31:30 +0800
+Subject: ipv6: fix possible infinite loop in rt6_fill_node()
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 9f72412bcf60144f252b0d6205106abf14344abc ]
+
+Sashiko reported this issue [1]. Apply the same fix as
+commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").
+
+Writers holding tb6_lock can list_del_rcu(&rt->fib6_siblings)
+without waiting for RCU readers; rt->fib6_siblings.next then still
+points into the old ring and this softirq-side walker never reaches
+&rt->fib6_siblings, causing a CPU stall. fib6_del_route() always
+WRITE_ONCE()s rt->fib6_nsiblings to 0 before list_del_rcu(), so an
+inside-loop check is a reliable detach signal.
+
+[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev
+
+Fixes: d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260527053133.180695-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index c5b71baf95e7b3..69659f2a6aea96 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -5797,6 +5797,8 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
+
+ goto nla_put_failure;
+ }
++ if (!READ_ONCE(rt->fib6_nsiblings))
++ break;
+ }
+
+ rcu_read_unlock();
+--
+2.53.0
+
--- /dev/null
+From 9d6d5a9a8501b4999151b8fb7b4f4089edd4aa5d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 21:10:31 +0530
+Subject: ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress()
+
+From: Rahul Chandelkar <rc@rexion.ai>
+
+[ Upstream commit 9d5e7a46a9f6d8f503b41bfefef70659845f1679 ]
+
+ipv6_rpl_srh_decompress() computes:
+
+ outhdr->hdrlen = (((n + 1) * sizeof(struct in6_addr)) >> 3);
+
+hdrlen is __u8. For n >= 127 the result exceeds 255 and silently
+truncates. With n=127 (cmpri=15, cmpre=15, pad=0, hdrlen=16):
+
+ (128 * 16) >> 3 = 256, truncated to 0 as __u8
+
+The caller in ipv6_rpl_srh_rcv() then places the compressed header
+at buf + ((ohdr->hdrlen + 1) << 3). With hdrlen=0 this is buf + 8,
+but the decompressed region occupies buf[0..2055] (8-byte header
+plus 128 full addresses). The compressed header overlaps the
+decompressed data, and ipv6_rpl_srh_compress() writes into this
+overlap, corrupting the routing header of the forwarded packet.
+
+The existing guard at exthdrs.c:546 checks (n + 1) > 255, which
+prevents n+1 from overflowing unsigned char (the segments_left
+field), but does not prevent the computed hdrlen from overflowing
+__u8. n=127 passes because 128 <= 255, yet hdrlen=256 does not
+fit.
+
+Tighten the bound to (n + 1) > 127. This caps n at 126, giving
+hdrlen = (127 * 16) >> 3 = 254, which fits in __u8. The compressed
+header then lands at buf + ((254 + 1) << 3) = buf + 2040, exactly
+past the decompressed region (buf[0..2039]). No overlap. 127
+segments is well beyond any realistic RPL deployment.
+
+Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
+Signed-off-by: Rahul Chandelkar <rc@rexion.ai>
+Link: https://patch.msgid.link/20260525154031.2290876-1-rc@rexion.ai
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/exthdrs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
+index 54e71623aac9cc..e1d632c12cc46a 100644
+--- a/net/ipv6/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -546,7 +546,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
+ * unsigned char which is segments_left field. Should not be
+ * higher than that.
+ */
+- if (r || (n + 1) > 255) {
++ if (r || (n + 1) > 127) {
+ kfree_skb(skb);
+ return -1;
+ }
+--
+2.53.0
+
--- /dev/null
+From 36851a9ce229b214ca137515fd27a44d87e2f55a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 20:49:56 +0530
+Subject: kernel/fork: validate exit_signal in kernel_clone()
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit 09e7827e785729f391c8d46dc71becce70d296ab ]
+
+When a child process exits, it sends exit_signal to its parent via
+do_notify_parent(). The clone() syscall constructs exit_signal as:
+
+(lower_32_bits(clone_flags) & CSIGNAL)
+
+CSIGNAL is 0xff, so values in the range 65-255 are possible. However,
+valid_signal() only accepts signals up to _NSIG (64 on x86_64). A
+non-zero non-valid exit_signal acts the same as exit_signal == 0: the
+parent process is not signaled when the child terminates.
+
+The syzkaller reproducer triggers this by calling clone() with flags=0x80,
+resulting in exit_signal = (0x80 & CSIGNAL) = 128, which exceeds _NSIG and
+is not a valid signal.
+
+The v1 of this patch added the check only in the clone() syscall handler,
+which is incomplete. kernel_clone() has other callers such as
+sys_ia32_clone() which would remain unprotected. Move the check to
+kernel_clone() to cover all callers.
+
+Since the valid_signal() check is now in kernel_clone() and covers all
+callers including clone3(), the same check in copy_clone_args_from_user()
+becomes redundant and is removed. The higher 32bits check for clone3() is
+kept as it is clone3() specific.
+
+Note that this is a user-visible change: previously, passing an invalid
+exit_signal to clone() was silently accepted. The man page for clone()
+does not document any defined behavior for invalid exit_signal values, so
+rejecting them with -EINVAL is the correct behavior. It is unlikely that
+any sane application relies on passing an invalid exit_signal.
+
+[oleg@redhat.com: the comment above kernel_clone() should be updated]
+ Link: https://lore.kernel.org/abwvgU17W8wuW2-J@redhat.com
+Link: https://lore.kernel.org/20260316151956.563558-1-kartikey406@gmail.com
+Fixes: 3f2c788a1314 ("fork: prevent accidental access to clone3 features")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Reported-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=bbe6b99feefc3a0842de
+Tested-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/all/20260307064202.353405-1-kartikey406@gmail.com/T/ [v1]
+Link: https://lore.kernel.org/all/20260316104536.558108-1-kartikey406@gmail.com/T/ [v2]
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Ben Segall <bsegall@google.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Juri Lelli <juri.lelli@redhat.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: Liam Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
+Cc: Mel Gorman <mgorman@suse.de>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Valentin Schneider <vschneid@redhat.com>
+Cc: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/fork.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index e280f02b6446ab..d68d40735a082a 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -2870,8 +2870,6 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
+ *
+ * It copies the process, and if successful kick-starts
+ * it and waits for it to finish using the VM if required.
+- *
+- * args->exit_signal is expected to be checked for sanity by the caller.
+ */
+ pid_t kernel_clone(struct kernel_clone_args *args)
+ {
+@@ -2896,6 +2894,9 @@ pid_t kernel_clone(struct kernel_clone_args *args)
+ (args->pidfd == args->parent_tid))
+ return -EINVAL;
+
++ if (!valid_signal(args->exit_signal))
++ return -EINVAL;
++
+ /*
+ * Determine whether and which event to report to ptracer. When
+ * called from kernel_thread or CLONE_UNTRACED is explicitly
+@@ -3098,11 +3099,9 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
+ return -EINVAL;
+
+ /*
+- * Verify that higher 32bits of exit_signal are unset and that
+- * it is a valid signal
++ * Verify that higher 32bits of exit_signal are unset
+ */
+- if (unlikely((args.exit_signal & ~((u64)CSIGNAL)) ||
+- !valid_signal(args.exit_signal)))
++ if (unlikely(args.exit_signal & ~((u64)CSIGNAL)))
+ return -EINVAL;
+
+ if ((args.flags & CLONE_INTO_CGROUP) &&
+--
+2.53.0
+
--- /dev/null
+From 8b8b43d74f66682ed56b0d553934ce970cc1f9ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 22:07:16 +0900
+Subject: ksmbd: fix FSCTL permission bypass by adding a permission check for
+ FSCTL_SET_SPARSE
+
+From: Sean Shen <grayhat@foxmail.com>
+
+[ Upstream commit cc57232cae23c0df91b4a59d0f519141ce9b5b02 ]
+
+FSCTL_SET_SPARSE in fsctl_set_sparse() modifies the file's sparse
+attribute and saves it through xattr without any permission checks.
+
+This exposes two issues:
+
+1) A client on a read-only share can change the sparse attribute
+ on files it opened, even though the share is read-only.
+ Other FSCTL write operations already check
+ test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE),
+ but FSCTL_SET_SPARSE does not.
+
+2) Even on writable shares, clients without FILE_WRITE_DATA or
+ FILE_WRITE_ATTRIBUTES access should not modify the sparse
+ attribute. Similar handle-level checks exist in other functions
+ but are missing here.
+
+Add both share-level writable check and per-handle access check.
+Use goto out on error to avoid leaking file references.
+
+Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
+Cc: Namjae Jeon <linkinjeon@kernel.org>
+Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Cc: Steve French <smfrench@gmail.com>
+Signed-off-by: Sean Shen <grayhat@foxmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/smb2pdu.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index 04d4a784deaf98..97b03f76741ef2 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -8067,9 +8067,20 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
+ int ret = 0;
+ __le32 old_fattr;
+
++ if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
++ ksmbd_debug(SMB, "User does not have write permission\n");
++ return -EACCES;
++ }
++
+ fp = ksmbd_lookup_fd_fast(work, id);
+ if (!fp)
+ return -ENOENT;
++
++ if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_WRITE_ATTRIBUTES_LE))) {
++ ret = -EACCES;
++ goto out;
++ }
++
+ idmap = file_mnt_idmap(fp->filp);
+
+ old_fattr = fp->f_ci->m_fattr;
+--
+2.53.0
+
--- /dev/null
+From fbc479667b40efe1a5a50ad2cb7b73f49fa07a3d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 15:03:30 +0200
+Subject: net: hsr: fix potential OOB access in supervision frame handling
+
+From: Luka Gejak <luka.gejak@linux.dev>
+
+[ Upstream commit f229426072fc865654a60978bb7fda790a051ff3 ]
+
+Ensure the entire TLV header is linearized before access by adding
+sizeof(struct hsr_sup_tlv) to the pskb_may_pull() calls. Without this,
+a truncated frame could cause an out-of-bounds access.
+
+Fixes: eafaa88b3eb7 ("net: hsr: Add support for redbox supervision frames")
+Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Link: https://patch.msgid.link/20260523130330.61880-1-luka.gejak@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_forward.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
+index 3852fd99509f04..7a596c4f603e2d 100644
+--- a/net/hsr/hsr_forward.c
++++ b/net/hsr/hsr_forward.c
+@@ -84,7 +84,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
+
+ /* Get next tlv */
+ total_length += hsr_sup_tag->tlv.HSR_TLV_length;
+- if (!pskb_may_pull(skb, total_length))
++ if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
+ return false;
+ skb_pull(skb, total_length);
+ hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data;
+@@ -100,7 +100,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
+
+ /* make sure another tlv follows */
+ total_length += sizeof(struct hsr_sup_tlv) + hsr_sup_tlv->HSR_TLV_length;
+- if (!pskb_may_pull(skb, total_length))
++ if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
+ return false;
+
+ /* get next tlv */
+--
+2.53.0
+
--- /dev/null
+From fcedd3c64a715fe10a9393ea4bf5db31437f4ea4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 07:11:45 -0700
+Subject: net/iucv: fix locking in .getsockopt
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 3589d20a666caf30ad100c960a2de7de390fce88 ]
+
+Mirror iucv_sock_setsockopt() and wrap the whole switch in
+lock_sock()/release_sock(). The pre-existing SO_MSGLIMIT-only lock
+becomes redundant and is removed.
+
+Any AF_IUCV HIPER user can potentially crash the kernel by racing
+recvmsg() with getsockopt(SO_MSGSIZE): the SO_MSGSIZE arm dereferences
+iucv->hs_dev->mtu after iucv_sock_close() (called from the racing
+recvmsg()) has set hs_dev to NULL, producing a NULL pointer dereference
+oops.
+
+Suggested-by: Stanislav Fomichev <sdf.kernel@gmail.com>
+Fixes: 51363b8751a6 ("af_iucv: allow retrieval of maximum message size")
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
+Tested-by: Alexandra Winter <wintera@linux.ibm.com>
+Link: https://patch.msgid.link/20260521-af_iucv_fix2-v1-1-f16b1c510aa9@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/iucv/af_iucv.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index 0f660b1d3bd51c..e9a9bb0dee065a 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -1539,7 +1539,7 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+ struct sock *sk = sock->sk;
+ struct iucv_sock *iucv = iucv_sk(sk);
+ unsigned int val;
+- int len;
++ int len, rc;
+
+ if (level != SOL_IUCV)
+ return -ENOPROTOOPT;
+@@ -1552,26 +1552,34 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+
+ len = min_t(unsigned int, len, sizeof(int));
+
++ rc = 0;
++
++ lock_sock(sk);
+ switch (optname) {
+ case SO_IPRMDATA_MSG:
+ val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0;
+ break;
+ case SO_MSGLIMIT:
+- lock_sock(sk);
+ val = (iucv->path != NULL) ? iucv->path->msglim /* connected */
+ : iucv->msglimit; /* default */
+- release_sock(sk);
+ break;
+ case SO_MSGSIZE:
+- if (sk->sk_state == IUCV_OPEN)
+- return -EBADFD;
++ if (sk->sk_state == IUCV_OPEN) {
++ rc = -EBADFD;
++ break;
++ }
+ val = (iucv->hs_dev) ? iucv->hs_dev->mtu -
+ sizeof(struct af_iucv_trans_hdr) - ETH_HLEN :
+ 0x7fffffff;
+ break;
+ default:
+- return -ENOPROTOOPT;
++ rc = -ENOPROTOOPT;
++ break;
+ }
++ release_sock(sk);
++
++ if (rc)
++ return rc;
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+--
+2.53.0
+
--- /dev/null
+From bd11f75a6f9ad1296fb4c58e5162b0c43757f5d4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 01:08:24 -0700
+Subject: net: mana: Add NULL guards in teardown path to prevent panic on
+ attach failure
+
+From: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+
+[ Upstream commit 17bfe0a8c014ee1d542ad352cd6a0a505361664a ]
+
+When queue allocation fails partway through, the error cleanup frees
+and NULLs apc->tx_qp and apc->rxqs. Multiple teardown paths such as
+mana_remove(), mana_change_mtu() recovery, and internal error handling
+in mana_alloc_queues() can subsequently call into functions that
+dereference these pointers without NULL checks:
+
+- mana_chn_setxdp() dereferences apc->rxqs[0], causing a NULL pointer
+ dereference panic (CR2: 0000000000000000 at mana_chn_setxdp+0x26).
+- mana_destroy_vport() iterates apc->rxqs without a NULL check.
+- mana_fence_rqs() iterates apc->rxqs without a NULL check.
+- mana_dealloc_queues() iterates apc->tx_qp without a NULL check.
+
+Add NULL guards for apc->rxqs in mana_fence_rqs(),
+mana_destroy_vport(), and before the mana_chn_setxdp() call. Add a
+NULL guard for apc->tx_qp in mana_dealloc_queues() to skip TX queue
+draining when TX queues were never allocated or already freed.
+
+Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+Link: https://patch.msgid.link/20260525081129.1230035-2-dipayanroy@linux.microsoft.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 70 +++++++++++--------
+ 1 file changed, 41 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 343f6e879af39e..3cf4ad1d91f67e 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -1304,6 +1304,9 @@ static void mana_fence_rqs(struct mana_port_context *apc)
+ struct mana_rxq *rxq;
+ int err;
+
++ if (!apc->rxqs)
++ return;
++
+ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+ rxq = apc->rxqs[rxq_idx];
+ err = mana_fence_rq(apc, rxq);
+@@ -2334,13 +2337,16 @@ static void mana_destroy_vport(struct mana_port_context *apc)
+ struct mana_rxq *rxq;
+ u32 rxq_idx;
+
+- for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+- rxq = apc->rxqs[rxq_idx];
+- if (!rxq)
+- continue;
++ if (apc->rxqs) {
+
+- mana_destroy_rxq(apc, rxq, true);
+- apc->rxqs[rxq_idx] = NULL;
++ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
++ rxq = apc->rxqs[rxq_idx];
++ if (!rxq)
++ continue;
++
++ mana_destroy_rxq(apc, rxq, true);
++ apc->rxqs[rxq_idx] = NULL;
++ }
+ }
+
+ mana_destroy_txq(apc);
+@@ -2577,7 +2583,8 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ if (apc->port_is_up)
+ return -EINVAL;
+
+- mana_chn_setxdp(apc, NULL);
++ if (apc->rxqs)
++ mana_chn_setxdp(apc, NULL);
+
+ if (gd->gdma_context->is_pf)
+ mana_pf_deregister_filter(apc);
+@@ -2595,33 +2602,38 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ * number of queues.
+ */
+
+- for (i = 0; i < apc->num_queues; i++) {
+- txq = &apc->tx_qp[i].txq;
+- tsleep = 1000;
+- while (atomic_read(&txq->pending_sends) > 0 &&
+- time_before(jiffies, timeout)) {
+- usleep_range(tsleep, tsleep + 1000);
+- tsleep <<= 1;
+- }
+- if (atomic_read(&txq->pending_sends)) {
+- err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
+- if (err) {
+- netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+- err, atomic_read(&txq->pending_sends),
+- txq->gdma_txq_id);
++ if (apc->tx_qp) {
++ for (i = 0; i < apc->num_queues; i++) {
++ txq = &apc->tx_qp[i].txq;
++ tsleep = 1000;
++ while (atomic_read(&txq->pending_sends) > 0 &&
++ time_before(jiffies, timeout)) {
++ usleep_range(tsleep, tsleep + 1000);
++ tsleep <<= 1;
++ }
++ if (atomic_read(&txq->pending_sends)) {
++ err =
++ pcie_flr(to_pci_dev(gd->gdma_context->dev));
++ if (err) {
++ netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
++ err,
++ atomic_read(&txq->pending_sends),
++ txq->gdma_txq_id);
++ }
++ break;
+ }
+- break;
+ }
+- }
+
+- for (i = 0; i < apc->num_queues; i++) {
+- txq = &apc->tx_qp[i].txq;
+- while ((skb = skb_dequeue(&txq->pending_skbs))) {
+- mana_unmap_skb(skb, apc);
+- dev_kfree_skb_any(skb);
++ for (i = 0; i < apc->num_queues; i++) {
++ txq = &apc->tx_qp[i].txq;
++ while ((skb = skb_dequeue(&txq->pending_skbs))) {
++ mana_unmap_skb(skb, apc);
++ dev_kfree_skb_any(skb);
++ }
++ atomic_set(&txq->pending_sends, 0);
+ }
+- atomic_set(&txq->pending_sends, 0);
+ }
++
+ /* We're 100% sure the queues can no longer be woken up, because
+ * we're sure now mana_poll_tx_cq() can't be running.
+ */
+--
+2.53.0
+
--- /dev/null
+From df346a5056a1641ada9eded25e142c5340a7cfc1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:36 +0200
+Subject: net: netlink: don't set nsid on local notifications
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 88b126b39f9757e9debc322d4679239e9af089c7 ]
+
+In most cases, notifications on sockets with NETLINK_LISTEN_ALL_NSID
+do not contain NSID in their ancillary data in case the event is local
+to the listener.
+
+However, when a self-referential NSID is allocated for a namespace,
+every local notification starts sending this ID to the user space.
+
+This is problematic, because the listener cannot tell if those
+notifications are local or not anymore without making extra requests
+to figure out if the provided NSID is local or not. The listener
+can also not figure out the local NSID beforehand as it can be
+allocated at any point in time by other processes, changing the
+structure of the future notifications for everyone.
+
+The value is practically not useful, since it's the namespace's own
+ID that the application has to obtain from other sources in order to
+figure out if it's the same or not. So, for the application it's
+just an extra busy work with no benefits. Moreover, applications
+that do not know about this quirk may be mishandling notifications
+with NSID set as notifications from remote namespaces. This is the
+case for ovs-vswitchd and the iproute2's 'ip monitor' that stops
+printing 'current' and starts printing the nsid number mid-session.
+
+Lack of clear documentation for this behavior is also not helping.
+
+A search though open-source projects doesn't reveal any projects
+that use NETNSA_NSID_NOT_ASSIGNED and rely on metadata to contain
+self-referential NSIDs (expected, since the value is not useful).
+Quite the opposite, as already mentioned, there are few applications
+that rely on NSID to not be present in local events.
+
+Since the value is not useful and actively harmful in some cases,
+let's not report it for local events, making the notifications more
+consistent.
+
+Also adding some blank lines for readability.
+
+Fixes: 59324cf35aba ("netlink: allow to listen "all" netns")
+Reported-by: Matteo Perin <matteo.perin@canonical.com>
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-3-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index f8d9a04d5d8b11..f3a8c8338d203f 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1484,10 +1484,14 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++
+ NETLINK_CB(p->skb2).nsid_is_set = false;
+- NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+- if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+- NETLINK_CB(p->skb2).nsid_is_set = true;
++ if (!net_eq(sock_net(sk), p->net)) {
++ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
++ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
++ NETLINK_CB(p->skb2).nsid_is_set = true;
++ }
++
+ val = netlink_broadcast_deliver(sk, p->skb2);
+ if (val < 0) {
+ netlink_overrun(sk);
+--
+2.53.0
+
--- /dev/null
+From db98437ed52e551948572283ee4072486c9c3475 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:35 +0200
+Subject: net: netlink: fix sending unassigned nsid after assigned one
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 70f8592ee90585272018a725054b6eb2ab7e99ca ]
+
+If the current skb is not shared, it is re-used directly for all the
+sockets subscribed to the notification. If we have remote all-nsid
+socket receiving a message first, then the 'nsid_is_set' will be
+set to 'true'. If the nsid is NOT_ASSIGNED for the next socket in
+the list, the 'nsid_is_set' will remain 'true' and the negative value
+is be delivered to the user space. All subsequent nsid values will be
+delivered as well, since there is no code path that sets the flag
+back to 'false'.
+
+Fix that by always dropping the flag to 'false' first.
+
+Fixes: 7212462fa6fd ("netlink: don't send unknown nsid")
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-2-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index a5ffda87daf63b..f8d9a04d5d8b11 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1484,6 +1484,7 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++ NETLINK_CB(p->skb2).nsid_is_set = false;
+ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+ NETLINK_CB(p->skb2).nsid_is_set = true;
+--
+2.53.0
+
--- /dev/null
+From a932c98b8851c7876d67b1af2e0141a344502b88 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:49 -0400
+Subject: net/sched: Revert "net/sched: Restrict conditions for adding
+ duplicating netems to qdisc tree"
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit eda0b7f203bb166c98d1418b204135bd566ac83b ]
+
+This reverts commit ec8e0e3d7adef940cdf9475e2352c0680189d14e.
+
+The original patch rejects any tree containing two netems when
+either has duplication set, even when they sit on unrelated classes
+of the same classful parent. That broke configurations that have
+worked since netem was introduced.
+
+The re-entrancy problem the original commit was trying to solve is
+handled by later patch using tc_depth flag.
+
+Doing this revert will (re)expose the original bug with multiple
+netem duplication. When this patch is backported make sure
+and get the full series.
+
+Fixes: ec8e0e3d7ade ("net/sched: Restrict conditions for adding duplicating netems to qdisc tree")
+Reported-by: Ji-Soo Chung <jschung2@proton.me>
+Reported-by: Gerlinde <lrGerlinde@mailfence.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220774
+Reported-by: zyc zyc <zyc199902@zohomail.cn>
+Closes: https://lore.kernel.org/all/19adda5a1e2.12410b78222774.9191120410578703463@zohomail.cn/
+Reported-by: Manas Ghandat <ghandatmanas@gmail.com>
+Closes: https://lore.kernel.org/netdev/f69b2c8f-8325-4c2e-a011-6dbc089f30e4@gmail.com/
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-3-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_netem.c | 40 ----------------------------------------
+ 1 file changed, 40 deletions(-)
+
+diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
+index f8c5c506180858..827489b31626bb 100644
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -1005,41 +1005,6 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+ return 0;
+ }
+
+-static const struct Qdisc_class_ops netem_class_ops;
+-
+-static int check_netem_in_tree(struct Qdisc *sch, bool duplicates,
+- struct netlink_ext_ack *extack)
+-{
+- struct Qdisc *root, *q;
+- unsigned int i;
+-
+- root = qdisc_root_sleeping(sch);
+-
+- if (sch != root && root->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(root))->duplicate)
+- goto err;
+- }
+-
+- if (!qdisc_dev(root))
+- return 0;
+-
+- hash_for_each(qdisc_dev(root)->qdisc_hash, i, q, hash) {
+- if (sch != q && q->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(q))->duplicate)
+- goto err;
+- }
+- }
+-
+- return 0;
+-
+-err:
+- NL_SET_ERR_MSG(extack,
+- "netem: cannot mix duplicating netems with other netems in tree");
+- return -EINVAL;
+-}
+-
+ /* Parse netlink message to set options */
+ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
+@@ -1116,11 +1081,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ q->gap = qopt->gap;
+ q->counter = 0;
+ q->loss = qopt->loss;
+-
+- ret = check_netem_in_tree(sch, qopt->duplicate, extack);
+- if (ret)
+- goto unlock;
+-
+ q->duplicate = qopt->duplicate;
+
+ /* for compatibility with earlier versions.
+--
+2.53.0
+
--- /dev/null
+From 28b57b90365da92cb18898718d1f86b0cf8cd81a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 19:43:53 +0100
+Subject: net: skbuff: fix pskb_carve leaking zcopy pages
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit ff6e798c2eac3ebd0501ad7e796f583fab928de8 ]
+
+When SKBFL_MANAGED_FRAG_REFS is set, frag pages are not refcounted but
+their lifetime is controlled by the attached ubuf_info. To make a copy
+of the skb_shared_info, we either should clear the flag and reference
+the frags, or keep the flag and have frags unreferenced.
+
+pskb_carve_inside_header() and pskb_carve_inside_nonlinear() don't
+follow the rule and thus can leak page references. Let's clear
+SKBFL_MANAGED_FRAG_REFS from the original skb to fix it. It's the
+simplest way to address it, but there are more performant ways to do
+that if it ever becomes a problem.
+
+Link: https://lore.kernel.org/all/20260523085809.26331-1-nvminh232@clc.fitus.edu.vn/
+Fixes: 753f1ca4e1e50 ("net: introduce managed frags infrastructure")
+Reported-by: Minh Nguyen <minhnguyen.080505@gmail.com>
+Reported-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/1e2086aa69217d7f9c8da3d38f5be7160f1b4cd1.1779993185.git.asml.silence@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/skbuff.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 8b05866e93b195..2282b6ad4be21a 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -6397,6 +6397,11 @@ static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off,
+ skb_copy_from_linear_data_offset(skb, off, data, new_hlen);
+ skb->len -= off;
+
++ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
++ * while refcounting frags below.
++ */
++ skb_zcopy_downgrade_managed(skb);
++
+ memcpy((struct skb_shared_info *)(data + size),
+ skb_shinfo(skb),
+ offsetof(struct skb_shared_info,
+@@ -6509,6 +6514,11 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,
+ return -ENOMEM;
+ size = SKB_WITH_OVERHEAD(size);
+
++ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
++ * while refcounting frags below.
++ */
++ skb_zcopy_downgrade_managed(skb);
++
+ memcpy((struct skb_shared_info *)(data + size),
+ skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0]));
+ if (skb_orphan_frags(skb, gfp_mask)) {
+--
+2.53.0
+
--- /dev/null
+From 02743852ff7637214bf2731ea35d49304ab58302 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 16:56:39 +0200
+Subject: net/smc: Do not re-initialize smc hashtables
+
+From: Alexandra Winter <wintera@linux.ibm.com>
+
+[ Upstream commit 9e4389b0038781f19f97895186ed941ff8ac1678 ]
+
+INIT_HLIST_HEAD(&smc_v*_hashinfo.ht) are called after smc_nl_init(),
+proto_register() and sock_register(). This can lead to smc_v*_hashinfo.ht
+being reset even though hash entries already exist and are being used,
+possibly resulting in a corrupted list.
+
+Remove unnecessary and dangerous re-initialisation of smc_v*_hashinfo.ht in
+smc_init(); it is implicitly initialised to zero anyhow. Add
+HLIST_HEAD_INIT to the definitions for clarity.
+
+Fixes: f16a7dd5cf27 ("smc: netlink interface for SMC sockets")
+Suggested-by: Halil Pasic <pasic@linux.ibm.com>
+Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
+Acked-by: Halil Pasic <pasic@linux.ibm.com>
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Link: https://patch.msgid.link/20260521145639.10317-1-wintera@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index 6629fd61be06a6..7a82e1a8a83f4b 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -181,10 +181,12 @@ static bool smc_hs_congested(const struct sock *sk)
+
+ static struct smc_hashinfo smc_v4_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v4_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ static struct smc_hashinfo smc_v6_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v6_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ int smc_hash_sk(struct sock *sk)
+@@ -3579,8 +3581,6 @@ static int __init smc_init(void)
+ pr_err("%s: sock_register fails with %d\n", __func__, rc);
+ goto out_proto6;
+ }
+- INIT_HLIST_HEAD(&smc_v4_hashinfo.ht);
+- INIT_HLIST_HEAD(&smc_v6_hashinfo.ht);
+
+ rc = smc_ib_register_client();
+ if (rc) {
+--
+2.53.0
+
--- /dev/null
+From 18b5a57676c1eff651be3ff4f29bc73fa2f2e66f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Nov 2024 22:08:13 +0100
+Subject: netfilter: bitwise: add support for doing AND, OR and XOR directly
+
+From: Jeremy Sowden <jeremy@azazel.net>
+
+[ Upstream commit b0ccf4f53d968e794a4ea579d5135cc1aaf1a53f ]
+
+Hitherto, these operations have been converted in user space to
+mask-and-xor operations on one register and two immediate values, and it
+is the latter which have been evaluated by the kernel. We add support
+for evaluating these operations directly in kernel space on one register
+and either an immediate value or a second register.
+
+Pablo made a few changes to the original patch:
+
+- EINVAL if NFTA_BITWISE_SREG2 is used with fast version.
+- Allow _AND,_OR,_XOR with _DATA != sizeof(u32)
+- Dump _SREG2 or _DATA with _AND,_OR,_XOR
+
+Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Stable-dep-of: 18014147d3ee ("netfilter: nf_tables: fix dst corruption in same register operation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/uapi/linux/netfilter/nf_tables.h | 8 ++
+ net/netfilter/nft_bitwise.c | 134 +++++++++++++++++++++--
+ 2 files changed, 131 insertions(+), 11 deletions(-)
+
+diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
+index cbb1b58e181fca..f8867f198f3104 100644
+--- a/include/uapi/linux/netfilter/nf_tables.h
++++ b/include/uapi/linux/netfilter/nf_tables.h
+@@ -564,11 +564,17 @@ enum nft_immediate_attributes {
+ * and XOR boolean operations
+ * @NFT_BITWISE_LSHIFT: left-shift operation
+ * @NFT_BITWISE_RSHIFT: right-shift operation
++ * @NFT_BITWISE_AND: and operation
++ * @NFT_BITWISE_OR: or operation
++ * @NFT_BITWISE_XOR: xor operation
+ */
+ enum nft_bitwise_ops {
+ NFT_BITWISE_MASK_XOR,
+ NFT_BITWISE_LSHIFT,
+ NFT_BITWISE_RSHIFT,
++ NFT_BITWISE_AND,
++ NFT_BITWISE_OR,
++ NFT_BITWISE_XOR,
+ };
+ /*
+ * Old name for NFT_BITWISE_MASK_XOR. Retained for backwards-compatibility.
+@@ -586,6 +592,7 @@ enum nft_bitwise_ops {
+ * @NFTA_BITWISE_OP: type of operation (NLA_U32: nft_bitwise_ops)
+ * @NFTA_BITWISE_DATA: argument for non-boolean operations
+ * (NLA_NESTED: nft_data_attributes)
++ * @NFTA_BITWISE_SREG2: second source register (NLA_U32: nft_registers)
+ *
+ * The bitwise expression supports boolean and shift operations. It implements
+ * the boolean operations by performing the following operation:
+@@ -609,6 +616,7 @@ enum nft_bitwise_attributes {
+ NFTA_BITWISE_XOR,
+ NFTA_BITWISE_OP,
+ NFTA_BITWISE_DATA,
++ NFTA_BITWISE_SREG2,
+ __NFTA_BITWISE_MAX
+ };
+ #define NFTA_BITWISE_MAX (__NFTA_BITWISE_MAX - 1)
+diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
+index 86abbe4c1308b3..af990c600745be 100644
+--- a/net/netfilter/nft_bitwise.c
++++ b/net/netfilter/nft_bitwise.c
+@@ -17,6 +17,7 @@
+
+ struct nft_bitwise {
+ u8 sreg;
++ u8 sreg2;
+ u8 dreg;
+ enum nft_bitwise_ops op:8;
+ u8 len;
+@@ -60,28 +61,72 @@ static void nft_bitwise_eval_rshift(u32 *dst, const u32 *src,
+ }
+ }
+
++static void nft_bitwise_eval_and(u32 *dst, const u32 *src, const u32 *src2,
++ const struct nft_bitwise *priv)
++{
++ unsigned int i, n;
++
++ for (i = 0, n = DIV_ROUND_UP(priv->len, sizeof(u32)); i < n; i++)
++ dst[i] = src[i] & src2[i];
++}
++
++static void nft_bitwise_eval_or(u32 *dst, const u32 *src, const u32 *src2,
++ const struct nft_bitwise *priv)
++{
++ unsigned int i, n;
++
++ for (i = 0, n = DIV_ROUND_UP(priv->len, sizeof(u32)); i < n; i++)
++ dst[i] = src[i] | src2[i];
++}
++
++static void nft_bitwise_eval_xor(u32 *dst, const u32 *src, const u32 *src2,
++ const struct nft_bitwise *priv)
++{
++ unsigned int i, n;
++
++ for (i = 0, n = DIV_ROUND_UP(priv->len, sizeof(u32)); i < n; i++)
++ dst[i] = src[i] ^ src2[i];
++}
++
+ void nft_bitwise_eval(const struct nft_expr *expr,
+ struct nft_regs *regs, const struct nft_pktinfo *pkt)
+ {
+ const struct nft_bitwise *priv = nft_expr_priv(expr);
+- const u32 *src = ®s->data[priv->sreg];
++ const u32 *src = ®s->data[priv->sreg], *src2;
+ u32 *dst = ®s->data[priv->dreg];
+
+- switch (priv->op) {
+- case NFT_BITWISE_MASK_XOR:
++ if (priv->op == NFT_BITWISE_MASK_XOR) {
+ nft_bitwise_eval_mask_xor(dst, src, priv);
+- break;
+- case NFT_BITWISE_LSHIFT:
++ return;
++ }
++ if (priv->op == NFT_BITWISE_LSHIFT) {
+ nft_bitwise_eval_lshift(dst, src, priv);
+- break;
+- case NFT_BITWISE_RSHIFT:
++ return;
++ }
++ if (priv->op == NFT_BITWISE_RSHIFT) {
+ nft_bitwise_eval_rshift(dst, src, priv);
+- break;
++ return;
++ }
++
++ src2 = priv->sreg2 ? ®s->data[priv->sreg2] : priv->data.data;
++
++ if (priv->op == NFT_BITWISE_AND) {
++ nft_bitwise_eval_and(dst, src, src2, priv);
++ return;
++ }
++ if (priv->op == NFT_BITWISE_OR) {
++ nft_bitwise_eval_or(dst, src, src2, priv);
++ return;
++ }
++ if (priv->op == NFT_BITWISE_XOR) {
++ nft_bitwise_eval_xor(dst, src, src2, priv);
++ return;
+ }
+ }
+
+ static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = {
+ [NFTA_BITWISE_SREG] = { .type = NLA_U32 },
++ [NFTA_BITWISE_SREG2] = { .type = NLA_U32 },
+ [NFTA_BITWISE_DREG] = { .type = NLA_U32 },
+ [NFTA_BITWISE_LEN] = { .type = NLA_U32 },
+ [NFTA_BITWISE_MASK] = { .type = NLA_NESTED },
+@@ -105,7 +150,8 @@ static int nft_bitwise_init_mask_xor(struct nft_bitwise *priv,
+ };
+ int err;
+
+- if (tb[NFTA_BITWISE_DATA])
++ if (tb[NFTA_BITWISE_DATA] ||
++ tb[NFTA_BITWISE_SREG2])
+ return -EINVAL;
+
+ if (!tb[NFTA_BITWISE_MASK] ||
+@@ -139,7 +185,8 @@ static int nft_bitwise_init_shift(struct nft_bitwise *priv,
+ int err;
+
+ if (tb[NFTA_BITWISE_MASK] ||
+- tb[NFTA_BITWISE_XOR])
++ tb[NFTA_BITWISE_XOR] ||
++ tb[NFTA_BITWISE_SREG2])
+ return -EINVAL;
+
+ if (!tb[NFTA_BITWISE_DATA])
+@@ -158,6 +205,41 @@ static int nft_bitwise_init_shift(struct nft_bitwise *priv,
+ return 0;
+ }
+
++static int nft_bitwise_init_bool(const struct nft_ctx *ctx,
++ struct nft_bitwise *priv,
++ const struct nlattr *const tb[])
++{
++ int err;
++
++ if (tb[NFTA_BITWISE_MASK] ||
++ tb[NFTA_BITWISE_XOR])
++ return -EINVAL;
++
++ if ((!tb[NFTA_BITWISE_DATA] && !tb[NFTA_BITWISE_SREG2]) ||
++ (tb[NFTA_BITWISE_DATA] && tb[NFTA_BITWISE_SREG2]))
++ return -EINVAL;
++
++ if (tb[NFTA_BITWISE_DATA]) {
++ struct nft_data_desc desc = {
++ .type = NFT_DATA_VALUE,
++ .size = sizeof(priv->data),
++ .len = priv->len,
++ };
++
++ err = nft_data_init(NULL, &priv->data, &desc,
++ tb[NFTA_BITWISE_DATA]);
++ if (err < 0)
++ return err;
++ } else {
++ err = nft_parse_register_load(ctx, tb[NFTA_BITWISE_SREG2],
++ &priv->sreg2, priv->len);
++ if (err < 0)
++ return err;
++ }
++
++ return 0;
++}
++
+ static int nft_bitwise_init(const struct nft_ctx *ctx,
+ const struct nft_expr *expr,
+ const struct nlattr * const tb[])
+@@ -189,6 +271,9 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
+ case NFT_BITWISE_MASK_XOR:
+ case NFT_BITWISE_LSHIFT:
+ case NFT_BITWISE_RSHIFT:
++ case NFT_BITWISE_AND:
++ case NFT_BITWISE_OR:
++ case NFT_BITWISE_XOR:
+ break;
+ default:
+ return -EOPNOTSUPP;
+@@ -205,6 +290,11 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
+ case NFT_BITWISE_RSHIFT:
+ err = nft_bitwise_init_shift(priv, tb);
+ break;
++ case NFT_BITWISE_AND:
++ case NFT_BITWISE_OR:
++ case NFT_BITWISE_XOR:
++ err = nft_bitwise_init_bool(ctx, priv, tb);
++ break;
+ }
+
+ return err;
+@@ -233,6 +323,21 @@ static int nft_bitwise_dump_shift(struct sk_buff *skb,
+ return 0;
+ }
+
++static int nft_bitwise_dump_bool(struct sk_buff *skb,
++ const struct nft_bitwise *priv)
++{
++ if (priv->sreg2) {
++ if (nft_dump_register(skb, NFTA_BITWISE_SREG2, priv->sreg2))
++ return -1;
++ } else {
++ if (nft_data_dump(skb, NFTA_BITWISE_DATA, &priv->data,
++ NFT_DATA_VALUE, sizeof(u32)) < 0)
++ return -1;
++ }
++
++ return 0;
++}
++
+ static int nft_bitwise_dump(struct sk_buff *skb,
+ const struct nft_expr *expr, bool reset)
+ {
+@@ -256,6 +361,11 @@ static int nft_bitwise_dump(struct sk_buff *skb,
+ case NFT_BITWISE_RSHIFT:
+ err = nft_bitwise_dump_shift(skb, priv);
+ break;
++ case NFT_BITWISE_AND:
++ case NFT_BITWISE_OR:
++ case NFT_BITWISE_XOR:
++ err = nft_bitwise_dump_bool(skb, priv);
++ break;
+ }
+
+ return err;
+@@ -300,6 +410,7 @@ static bool nft_bitwise_reduce(struct nft_regs_track *track,
+ track->regs[priv->dreg].bitwise &&
+ track->regs[priv->dreg].bitwise->ops == expr->ops &&
+ priv->sreg == bitwise->sreg &&
++ priv->sreg2 == bitwise->sreg2 &&
+ priv->dreg == bitwise->dreg &&
+ priv->op == bitwise->op &&
+ priv->len == bitwise->len &&
+@@ -376,7 +487,8 @@ static int nft_bitwise_fast_init(const struct nft_ctx *ctx,
+ if (err < 0)
+ return err;
+
+- if (tb[NFTA_BITWISE_DATA])
++ if (tb[NFTA_BITWISE_DATA] ||
++ tb[NFTA_BITWISE_SREG2])
+ return -EINVAL;
+
+ if (!tb[NFTA_BITWISE_MASK] ||
+--
+2.53.0
+
--- /dev/null
+From 402652d68fff1a19f21133acfdabb8f34c1905e1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Nov 2024 22:07:51 +0100
+Subject: netfilter: bitwise: rename some boolean operation functions
+
+From: Jeremy Sowden <jeremy@azazel.net>
+
+[ Upstream commit a12143e6084c502fc3cfaa8b717bffc8c14cf806 ]
+
+In the next patch we add support for doing AND, OR and XOR operations
+directly in the kernel, so rename some functions and an enum constant
+related to mask-and-xor boolean operations.
+
+Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Stable-dep-of: 18014147d3ee ("netfilter: nf_tables: fix dst corruption in same register operation")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/uapi/linux/netfilter/nf_tables.h | 10 ++++---
+ net/netfilter/nft_bitwise.c | 34 ++++++++++++------------
+ 2 files changed, 24 insertions(+), 20 deletions(-)
+
+diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
+index 9c29015d09c10f..cbb1b58e181fca 100644
+--- a/include/uapi/linux/netfilter/nf_tables.h
++++ b/include/uapi/linux/netfilter/nf_tables.h
+@@ -560,16 +560,20 @@ enum nft_immediate_attributes {
+ /**
+ * enum nft_bitwise_ops - nf_tables bitwise operations
+ *
+- * @NFT_BITWISE_BOOL: mask-and-xor operation used to implement NOT, AND, OR and
+- * XOR boolean operations
++ * @NFT_BITWISE_MASK_XOR: mask-and-xor operation used to implement NOT, AND, OR
++ * and XOR boolean operations
+ * @NFT_BITWISE_LSHIFT: left-shift operation
+ * @NFT_BITWISE_RSHIFT: right-shift operation
+ */
+ enum nft_bitwise_ops {
+- NFT_BITWISE_BOOL,
++ NFT_BITWISE_MASK_XOR,
+ NFT_BITWISE_LSHIFT,
+ NFT_BITWISE_RSHIFT,
+ };
++/*
++ * Old name for NFT_BITWISE_MASK_XOR. Retained for backwards-compatibility.
++ */
++#define NFT_BITWISE_BOOL NFT_BITWISE_MASK_XOR
+
+ /**
+ * enum nft_bitwise_attributes - nf_tables bitwise expression netlink attributes
+diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
+index 2cfb0104680c62..86abbe4c1308b3 100644
+--- a/net/netfilter/nft_bitwise.c
++++ b/net/netfilter/nft_bitwise.c
+@@ -25,8 +25,8 @@ struct nft_bitwise {
+ struct nft_data data;
+ };
+
+-static void nft_bitwise_eval_bool(u32 *dst, const u32 *src,
+- const struct nft_bitwise *priv)
++static void nft_bitwise_eval_mask_xor(u32 *dst, const u32 *src,
++ const struct nft_bitwise *priv)
+ {
+ unsigned int i;
+
+@@ -68,8 +68,8 @@ void nft_bitwise_eval(const struct nft_expr *expr,
+ u32 *dst = ®s->data[priv->dreg];
+
+ switch (priv->op) {
+- case NFT_BITWISE_BOOL:
+- nft_bitwise_eval_bool(dst, src, priv);
++ case NFT_BITWISE_MASK_XOR:
++ nft_bitwise_eval_mask_xor(dst, src, priv);
+ break;
+ case NFT_BITWISE_LSHIFT:
+ nft_bitwise_eval_lshift(dst, src, priv);
+@@ -90,8 +90,8 @@ static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = {
+ [NFTA_BITWISE_DATA] = { .type = NLA_NESTED },
+ };
+
+-static int nft_bitwise_init_bool(struct nft_bitwise *priv,
+- const struct nlattr *const tb[])
++static int nft_bitwise_init_mask_xor(struct nft_bitwise *priv,
++ const struct nlattr *const tb[])
+ {
+ struct nft_data_desc mask = {
+ .type = NFT_DATA_VALUE,
+@@ -186,7 +186,7 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
+ if (tb[NFTA_BITWISE_OP]) {
+ priv->op = ntohl(nla_get_be32(tb[NFTA_BITWISE_OP]));
+ switch (priv->op) {
+- case NFT_BITWISE_BOOL:
++ case NFT_BITWISE_MASK_XOR:
+ case NFT_BITWISE_LSHIFT:
+ case NFT_BITWISE_RSHIFT:
+ break;
+@@ -194,12 +194,12 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
+ return -EOPNOTSUPP;
+ }
+ } else {
+- priv->op = NFT_BITWISE_BOOL;
++ priv->op = NFT_BITWISE_MASK_XOR;
+ }
+
+ switch(priv->op) {
+- case NFT_BITWISE_BOOL:
+- err = nft_bitwise_init_bool(priv, tb);
++ case NFT_BITWISE_MASK_XOR:
++ err = nft_bitwise_init_mask_xor(priv, tb);
+ break;
+ case NFT_BITWISE_LSHIFT:
+ case NFT_BITWISE_RSHIFT:
+@@ -210,8 +210,8 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
+ return err;
+ }
+
+-static int nft_bitwise_dump_bool(struct sk_buff *skb,
+- const struct nft_bitwise *priv)
++static int nft_bitwise_dump_mask_xor(struct sk_buff *skb,
++ const struct nft_bitwise *priv)
+ {
+ if (nft_data_dump(skb, NFTA_BITWISE_MASK, &priv->mask,
+ NFT_DATA_VALUE, priv->len) < 0)
+@@ -249,8 +249,8 @@ static int nft_bitwise_dump(struct sk_buff *skb,
+ return -1;
+
+ switch (priv->op) {
+- case NFT_BITWISE_BOOL:
+- err = nft_bitwise_dump_bool(skb, priv);
++ case NFT_BITWISE_MASK_XOR:
++ err = nft_bitwise_dump_mask_xor(skb, priv);
+ break;
+ case NFT_BITWISE_LSHIFT:
+ case NFT_BITWISE_RSHIFT:
+@@ -270,7 +270,7 @@ static int nft_bitwise_offload(struct nft_offload_ctx *ctx,
+ const struct nft_bitwise *priv = nft_expr_priv(expr);
+ struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
+
+- if (priv->op != NFT_BITWISE_BOOL)
++ if (priv->op != NFT_BITWISE_MASK_XOR)
+ return -EOPNOTSUPP;
+
+ if (memcmp(&priv->xor, &zero, sizeof(priv->xor)) ||
+@@ -407,7 +407,7 @@ nft_bitwise_fast_dump(struct sk_buff *skb,
+ return -1;
+ if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(sizeof(u32))))
+ return -1;
+- if (nla_put_be32(skb, NFTA_BITWISE_OP, htonl(NFT_BITWISE_BOOL)))
++ if (nla_put_be32(skb, NFTA_BITWISE_OP, htonl(NFT_BITWISE_MASK_XOR)))
+ return -1;
+
+ data.data[0] = priv->mask;
+@@ -502,7 +502,7 @@ nft_bitwise_select_ops(const struct nft_ctx *ctx,
+ return &nft_bitwise_ops;
+
+ if (tb[NFTA_BITWISE_OP] &&
+- ntohl(nla_get_be32(tb[NFTA_BITWISE_OP])) != NFT_BITWISE_BOOL)
++ ntohl(nla_get_be32(tb[NFTA_BITWISE_OP])) != NFT_BITWISE_MASK_XOR)
+ return &nft_bitwise_ops;
+
+ return &nft_bitwise_fast_ops;
+--
+2.53.0
+
--- /dev/null
+From fc5e49514b4e5606b577a8262de548f245dbd1da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 22:52:07 +0200
+Subject: netfilter: ebtables: fix OOB read in compat_mtw_from_user
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit f438d1786d657d57790c5d138d6db3fc9fdac392 ]
+
+Luxiao Xu says:
+
+ The function compat_mtw_from_user() converts ebtables extensions from
+ 32-bit user structures to kernel native structures. However, it lacks
+ proper validation of the user-supplied match_size/target_size.
+
+ When certain extensions are processed, the kernel-side translation
+ logic may perform memory accesses based on the extension's expected
+ size. If the user provides a size smaller than what the extension
+ requires, it results in an out-of-bounds read as reported by KASAN.
+
+ This fix introduces a check to ensure match_size is at least as large
+ as the extension's required compatsize. This covers matches, watchers,
+ and targets, while maintaining compatibility with standard targets.
+
+AFAIU this is relevant for matches that need to go though
+match->compat_from_user() call. Those that use plain memcpy with the
+user-provided size are ok because the caller checks that size vs the
+start of the next rule entry offset (which itself is checked vs. total
+size copied from userspace).
+
+The ->compat_from_user() callbacks assume they can read compatsize bytes,
+so they need this extra check.
+
+Based on an earlier patch from Luxiao Xu.
+
+Fixes: 81e675c227ec ("netfilter: ebtables: add CONFIG_COMPAT support")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/netfilter/ebtables.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index f99e348c8f37fa..bc69406d103df6 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -1952,6 +1952,25 @@ enum compat_mwt {
+ EBT_COMPAT_TARGET,
+ };
+
++static bool match_size_ok(const struct xt_match *match, unsigned int match_size)
++{
++ u16 csize;
++
++ if (match->matchsize == -1) /* cannot validate ebt_among */
++ return true;
++
++ csize = match->compatsize ? : match->matchsize;
++
++ return match_size >= csize;
++}
++
++static bool tgt_size_ok(const struct xt_target *tgt, unsigned int tgt_size)
++{
++ u16 csize = tgt->compatsize ? : tgt->targetsize;
++
++ return tgt_size >= csize;
++}
++
+ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ enum compat_mwt compat_mwt,
+ struct ebt_entries_buf_state *state,
+@@ -1977,6 +1996,11 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+
++ if (!match_size_ok(match, match_size)) {
++ module_put(match->me);
++ return -EINVAL;
++ }
++
+ off = ebt_compat_match_offset(match, match_size);
+ if (dst) {
+ if (match->compat_from_user)
+@@ -1996,6 +2020,12 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ mwt->u.revision);
+ if (IS_ERR(wt))
+ return PTR_ERR(wt);
++
++ if (!tgt_size_ok(wt, match_size)) {
++ module_put(wt->me);
++ return -EINVAL;
++ }
++
+ off = xt_compat_target_offset(wt);
+
+ if (dst) {
+--
+2.53.0
+
--- /dev/null
+From 18720c912aa30fbd207aa4bb1952a5aea40f0ff5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 May 2026 16:37:56 +0200
+Subject: netfilter: nf_tables: fix dst corruption in same register operation
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 18014147d3ee7831dce53fe65d7fc8d428b02552 ]
+
+For lshift and rshift, the shift operations are performed in a loop over
+32-bit words. The loop calculates the shifted value and write it to dst,
+and then immediately reads from src to calculate the carry for the next
+iteration. Because src and dst could point to the same memory location,
+the carry is incorrectly calculated using the newly modified dst value
+instead of the original src value.
+
+Adding a temporary local variable to cache the original value before
+writing to dst and using it for the carry calculation solves the
+problem. In addition, partial overlap is rejected from control plane for
+all kind of operations including byteorder. This was tested with the
+following bytecode:
+
+table test_table ip flags 0 use 1 handle 1
+ip test_table test_chain use 3 type filter hook input prio 0 policy accept packets 0 bytes 0 flags 1
+ip test_table test_chain 2
+ [ immediate reg 1 0x44332211 0x88776655 ]
+ [ bitwise reg 1 = ( reg 1 << 0x08000000 ) ]
+ [ cmp eq reg 1 0x66443322 0x00887766 ]
+ [ counter pkts 0 bytes 0 ]
+ip test_table test_chain 4 3
+ [ immediate reg 1 0x44332211 0x88776655 ]
+ [ bitwise reg 1 = ( reg 1 << 0x08000000 ) ]
+ [ cmp eq reg 1 0x55443322 0x00887766 ]
+ [ counter pkts 21794 bytes 1917798 ]
+
+Fixes: 567d746b55bc ("netfilter: bitwise: add support for shifts.")
+Acked-by: Jeremy Sowden <jeremy@azazel.net>
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables.h | 7 +++++++
+ net/netfilter/nft_bitwise.c | 18 ++++++++++++++----
+ net/netfilter/nft_byteorder.c | 13 ++++++++++---
+ 3 files changed, 31 insertions(+), 7 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index ab0567951e3105..a1f828efc9e3de 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -188,6 +188,13 @@ static inline u64 nft_reg_load64(const u32 *sreg)
+ return get_unaligned((u64 *)sreg);
+ }
+
++static inline bool nft_reg_overlap(u8 src, u8 dst, u32 len)
++{
++ unsigned int n = DIV_ROUND_UP(len, sizeof(u32));
++
++ return src != dst && src < dst + n && dst < src + n;
++}
++
+ static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
+ unsigned int len)
+ {
+diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
+index af990c600745be..1afb36fb5994db 100644
+--- a/net/netfilter/nft_bitwise.c
++++ b/net/netfilter/nft_bitwise.c
+@@ -43,8 +43,10 @@ static void nft_bitwise_eval_lshift(u32 *dst, const u32 *src,
+ u32 carry = 0;
+
+ for (i = DIV_ROUND_UP(priv->len, sizeof(u32)); i > 0; i--) {
+- dst[i - 1] = (src[i - 1] << shift) | carry;
+- carry = src[i - 1] >> (BITS_PER_TYPE(u32) - shift);
++ u32 tmp_src = src[i - 1];
++
++ dst[i - 1] = (tmp_src << shift) | carry;
++ carry = tmp_src >> (BITS_PER_TYPE(u32) - shift);
+ }
+ }
+
+@@ -56,8 +58,10 @@ static void nft_bitwise_eval_rshift(u32 *dst, const u32 *src,
+ u32 carry = 0;
+
+ for (i = 0; i < DIV_ROUND_UP(priv->len, sizeof(u32)); i++) {
+- dst[i] = carry | (src[i] >> shift);
+- carry = src[i] << (BITS_PER_TYPE(u32) - shift);
++ u32 tmp_src = src[i];
++
++ dst[i] = carry | (tmp_src >> shift);
++ carry = tmp_src << (BITS_PER_TYPE(u32) - shift);
+ }
+ }
+
+@@ -235,6 +239,9 @@ static int nft_bitwise_init_bool(const struct nft_ctx *ctx,
+ &priv->sreg2, priv->len);
+ if (err < 0)
+ return err;
++
++ if (nft_reg_overlap(priv->sreg2, priv->dreg, priv->len))
++ return -EINVAL;
+ }
+
+ return 0;
+@@ -265,6 +272,9 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
+ if (err < 0)
+ return err;
+
++ if (nft_reg_overlap(priv->sreg, priv->dreg, priv->len))
++ return -EINVAL;
++
+ if (tb[NFTA_BITWISE_OP]) {
+ priv->op = ntohl(nla_get_be32(tb[NFTA_BITWISE_OP]));
+ switch (priv->op) {
+diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
+index 2f82a444d21bf3..51f5de5c4ca363 100644
+--- a/net/netfilter/nft_byteorder.c
++++ b/net/netfilter/nft_byteorder.c
+@@ -144,9 +144,16 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
+ if (err < 0)
+ return err;
+
+- return nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
+- &priv->dreg, NULL, NFT_DATA_VALUE,
+- priv->len);
++ err = nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
++ &priv->dreg, NULL, NFT_DATA_VALUE,
++ priv->len);
++ if (err < 0)
++ return err;
++
++ if (nft_reg_overlap(priv->sreg, priv->dreg, priv->len))
++ return -EINVAL;
++
++ return 0;
+ }
+
+ static int nft_byteorder_dump(struct sk_buff *skb,
+--
+2.53.0
+
--- /dev/null
+From 60f5b7b86f67777d92041c395866c1f3bec484cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 12:36:14 -0700
+Subject: netfilter: synproxy: refresh tcphdr after skb_ensure_writable
+
+From: Chris Mason <clm@meta.com>
+
+[ Upstream commit 92170e6afe927ab2792a3f71902845789c8e31b1 ]
+
+synproxy_tstamp_adjust() rewrites the TCP timestamp option in place
+and then patches the TCP checksum via inet_proto_csum_replace4() on
+the caller-supplied tcphdr pointer. Both ipv4_synproxy_hook() and
+ipv6_synproxy_hook() obtain that pointer with skb_header_pointer()
+before calling in, so it may either alias skb->head directly or
+point at the caller's on-stack _tcph buffer.
+
+Between obtaining the pointer and using it, the function calls
+skb_ensure_writable(skb, optend), which on a cloned or non-linear
+skb invokes pskb_expand_head() and frees the old skb->head. After
+that point the cached th is stale:
+
+ caller (ipv[46]_synproxy_hook)
+ th = skb_header_pointer(skb, ..., &_tcph)
+ synproxy_tstamp_adjust(skb, protoff, th, ...)
+ skb_ensure_writable(skb, optend)
+ pskb_expand_head() /* kfree(old skb->head) */
+ ...
+ inet_proto_csum_replace4(&th->check, ...)
+ /* writes into freed head, or
+ into the caller's stack copy
+ leaving the on-wire checksum
+ stale */
+
+The option bytes are written through skb->data and are fine; only
+the checksum update goes through th and so lands in the wrong
+place. The result is either a write into freed slab memory or a
+packet leaving with a checksum that does not match its payload.
+
+Fix by re-deriving th from skb->data + protoff immediately after
+skb_ensure_writable() succeeds, so the subsequent checksum update
+targets the linear, writable header.
+
+Fixes: 48b1de4c110a ("netfilter: add SYNPROXY core/target")
+Assisted-by: kres (claude-opus-4-7)
+Signed-off-by: Chris Mason <clm@meta.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_synproxy_core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 16915f8eef2b16..f5a52075691faa 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -199,6 +199,8 @@ synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,
+ if (skb_ensure_writable(skb, optend))
+ return 0;
+
++ th = (struct tcphdr *)(skb->data + protoff);
++
+ while (optoff < optend) {
+ unsigned char *op = skb->data + optoff;
+
+--
+2.53.0
+
--- /dev/null
+From 4e2a3c94b7263ec961465f8b43e8c84b2ab88f31 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 20:10:08 +0200
+Subject: netfilter: xt_cpu: prefer raw_smp_processor_id
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit c376f07e16c02239ed44cabb97145d03f65b4d15 ]
+
+With PREEMPT_RCU we get splat:
+
+BUG: using smp_processor_id() in preemptible [..]
+caller is cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+CPU: 1 .. Comm: syz.3.1377 #0 PREEMPT(full)
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
+ check_preemption_disabled+0xd3/0xe0 lib/smp_processor_id.c:47
+ cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+ [..]
+
+Just use raw version instead.
+This is similar to 14d14a5d2957 ("netfilter: nft_meta: use raw_smp_processor_id()").
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Reported-by: syzbot+690d3e3ffa7335ac10eb@syzkaller.appspotmail.com
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/xt_cpu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_cpu.c b/net/netfilter/xt_cpu.c
+index 3bdc302a0f9137..9cb259902a586b 100644
+--- a/net/netfilter/xt_cpu.c
++++ b/net/netfilter/xt_cpu.c
+@@ -34,7 +34,7 @@ static bool cpu_mt(const struct sk_buff *skb, struct xt_action_param *par)
+ {
+ const struct xt_cpu_info *info = par->matchinfo;
+
+- return (info->cpu == smp_processor_id()) ^ info->invert;
++ return (info->cpu == raw_smp_processor_id()) ^ info->invert;
+ }
+
+ static struct xt_match cpu_mt_reg __read_mostly = {
+--
+2.53.0
+
--- /dev/null
+From a38f68916d1d39d9a3d46c7e2a44629e1273d820 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:41 +0000
+Subject: nfc: llcp: Fix use-after-free in llcp_sock_release()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit f4268b466190dae95a7585f69b4f1f8ad097632c ]
+
+llcp_sock_release() unconditionally unlinks the socket from the local
+sockets list. However, if the socket is still in connecting state, it
+is on the connecting list.
+
+Fix this by checking the socket state and unlinking from the correct list.
+
+Fixes: b4011239a08e ("NFC: llcp: Fix non blocking sockets connections")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-1-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_sock.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index d5344563e525c9..cd1fdf0beefb6b 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -633,6 +633,8 @@ static int llcp_sock_release(struct socket *sock)
+
+ if (sock->type == SOCK_RAW)
+ nfc_llcp_sock_unlink(&local->raw_sockets, sk);
++ else if (sk->sk_state == LLCP_CONNECTING)
++ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ else
+ nfc_llcp_sock_unlink(&local->sockets, sk);
+
+--
+2.53.0
+
--- /dev/null
+From 7b3ff0e2277e1abdc4ea650a01408ec636cd9fd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:42 +0000
+Subject: nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit b493ea2765cc17cb8aa7e7544a4b6dcb05b6ed77 ]
+
+A race condition exists in the NFC LLCP connection state machine where
+the connection acceptance packet (CC) can be processed concurrently with
+socket release. This can lead to a use-after-free of the socket object.
+
+When nfc_llcp_recv_cc() moves the socket from the connecting_sockets
+list to the sockets list, it does so without holding the socket lock.
+If llcp_sock_release() is executing concurrently, it might have already
+unlinked the socket and dropped its references, which can result in
+nfc_llcp_recv_cc() linking a freed socket into the live list.
+
+Fix this by holding lock_sock() during the state transition and list
+movement in nfc_llcp_recv_cc(). After acquiring the lock, check if
+the socket is still hashed to ensure it hasn't already been unlinked
+and marked for destruction by the release path. This aligns the locking
+pattern with recv_hdlc() and recv_disc().
+
+Fixes: a69f32af86e3 ("NFC: Socket linked list")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-2-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_core.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
+index d9562840fa180b..62b0f2d6686eb8 100644
+--- a/net/nfc/llcp_core.c
++++ b/net/nfc/llcp_core.c
+@@ -1216,6 +1216,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+
+ sk = &llcp_sock->sk;
+
++ lock_sock(sk);
++
++ /* Check if socket was destroyed whilst waiting for the lock */
++ if (!sk_hashed(sk)) {
++ release_sock(sk);
++ nfc_llcp_sock_put(llcp_sock);
++ return;
++ }
++
+ /* Unlink from connecting and link to the client array */
+ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ nfc_llcp_sock_link(&local->sockets, sk);
+@@ -1227,6 +1236,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+ sk->sk_state = LLCP_CONNECTED;
+ sk->sk_state_change(sk);
+
++ release_sock(sk);
++
+ nfc_llcp_sock_put(llcp_sock);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 65657174e5b814ac4163e28df16fc74f3f61b22c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 May 2026 19:55:18 +0800
+Subject: nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems
+
+From: Carl Lee <carl.lee@amd.com>
+
+[ Upstream commit f23bf992d65a42007c517b060ca35cebdea3525a ]
+
+Some ACPI-based platforms report incorrect IRQ trigger types (e.g.
+IRQF_TRIGGER_HIGH), which can lead to interrupt storms.
+
+Use the historically working rising-edge trigger on ACPI systems to
+avoid this regression.
+
+Device Tree-based systems continue to use the firmware-provided
+trigger type.
+
+Fixes: 57be33f85e36 ("nfc: nxp-nci: remove interrupt trigger type")
+Signed-off-by: Carl Lee <carl.lee@amd.com>
+Tested-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Luca Stefani <luca.stefani.ge1@gmail.com>
+Link: https://patch.msgid.link/20260516-nfc-nxp-nci-i2c-restore-irq-trigger-fallback-v3-1-37ba4b6e9086@amd.com
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/nxp-nci/i2c.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
+index 5ecbf3366a1de4..e80ce1b97bccc9 100644
+--- a/drivers/nfc/nxp-nci/i2c.c
++++ b/drivers/nfc/nxp-nci/i2c.c
+@@ -16,6 +16,7 @@
+ #include <linux/delay.h>
+ #include <linux/i2c.h>
+ #include <linux/interrupt.h>
++#include <linux/irq.h>
+ #include <linux/module.h>
+ #include <linux/nfc.h>
+ #include <linux/gpio/consumer.h>
+@@ -267,6 +268,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client)
+ {
+ struct device *dev = &client->dev;
+ struct nxp_nci_i2c_phy *phy;
++ unsigned long irqflags;
+ int r;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+@@ -303,9 +305,26 @@ static int nxp_nci_i2c_probe(struct i2c_client *client)
+ if (r < 0)
+ return r;
+
++ /*
++ * ACPI platforms may report incorrect IRQ trigger types
++ * (e.g. level-high), which can lead to interrupt storms.
++ *
++ * Use the historically stable rising-edge trigger for ACPI devices.
++ *
++ * On non-ACPI systems (e.g. Device Tree), prefer the firmware-
++ * provided trigger type, falling back to rising-edge if not set.
++ */
++ if (ACPI_COMPANION(dev)) {
++ irqflags = IRQF_TRIGGER_RISING;
++ } else {
++ irqflags = irq_get_trigger_type(client->irq);
++ if (!irqflags)
++ irqflags = IRQF_TRIGGER_RISING;
++ }
++
+ r = request_threaded_irq(client->irq, NULL,
+ nxp_nci_i2c_irq_thread_fn,
+- IRQF_ONESHOT,
++ irqflags | IRQF_ONESHOT,
+ NXP_NCI_I2C_DRIVER_NAME, phy);
+ if (r < 0)
+ nfc_err(&client->dev, "Unable to register IRQ handler\n");
+--
+2.53.0
+
--- /dev/null
+From b2ff862b5bab1cbbb59bea693b346ba075aa8393 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 May 2026 14:09:41 -0400
+Subject: scsi: core: Run queues for all non-SDEV_DEL devices from
+ scsi_run_host_queues
+
+From: David Jeffery <djeffery@redhat.com>
+
+[ Upstream commit 7205b58702273baf21d6ba7992e6ba15852325f7 ]
+
+While a SCSI host is in a recovery state, scsi_mq_requeue_cmd() will not
+set the requeue list for a requeued command to be kicked in the future.
+The expectation is a call to scsi_run_host_queues() will kick all SCSI
+devices once the recovery state is cleared.
+
+However, scsi_run_host_queues() uses shost_for_each_device() which uses
+scsi_device_get() and so will ignore devices in a partially removed
+state like SDEV_CANCEL. But these devices may also have requeued
+requests, leaving their requests stuck from not being kicked and causing
+the removal process of the device to hang.
+
+scsi_run_host_queues() needs to run against more devices than the macro
+shost_for_each_device() allows. Instead of using the too limiting
+scsi_device_get() state checks, only ignore devices in SDEV_DEL state or
+when unable to acquire a reference. Attempt to run the queues for all
+other devices when scsi_run_host_queues() is called.
+
+Fixes: 8b566edbdbfb ("scsi: core: Only kick the requeue list if necessary")
+Signed-off-by: David Jeffery <djeffery@redhat.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://patch.msgid.link/20260515180941.9698-1-djeffery@redhat.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_lib.c | 27 +++++++++++++++++++++++++--
+ 1 file changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index efd1f1d6e4e9b0..2268e540f28ae6 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -474,10 +474,33 @@ void scsi_requeue_run_queue(struct work_struct *work)
+
+ void scsi_run_host_queues(struct Scsi_Host *shost)
+ {
+- struct scsi_device *sdev;
++ struct scsi_device *sdev, *prev = NULL;
++ unsigned long flags;
+
+- shost_for_each_device(sdev, shost)
++ spin_lock_irqsave(shost->host_lock, flags);
++ __shost_for_each_device(sdev, shost) {
++ /*
++ * Only skip devices so deep into removal they will never need
++ * another kick to their queues. Thus scsi_device_get() cannot
++ * be used as it would skip devices in SDEV_CANCEL state which
++ * may need a queue kick.
++ */
++ if (sdev->sdev_state == SDEV_DEL ||
++ !get_device(&sdev->sdev_gendev))
++ continue;
++ spin_unlock_irqrestore(shost->host_lock, flags);
++
++ if (prev)
++ put_device(&prev->sdev_gendev);
+ scsi_run_queue(sdev->request_queue);
++
++ prev = sdev;
++
++ spin_lock_irqsave(shost->host_lock, flags);
++ }
++ spin_unlock_irqrestore(shost->host_lock, flags);
++ if (prev)
++ put_device(&prev->sdev_gendev);
+ }
+
+ static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
+--
+2.53.0
+
--- /dev/null
+From e9a67f38739eecd796cab49524a8436f3a8679bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 11:24:11 +0800
+Subject: sctp: fix race between sctp_wait_for_connect and peeloff
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit f14fe6395a8b3d961a61e138ad7b36ba3626dd4e ]
+
+sctp_wait_for_connect() drops and re-acquires the socket lock while
+waiting for the association to reach ESTABLISHED state. During this
+window, another thread can peeloff the association to a new socket via
+getsockopt(SCTP_SOCKOPT_PEELOFF), changing asoc->base.sk. After
+re-acquiring the old socket lock, sctp_wait_for_connect() returns
+success without noticing the migration — the caller then accesses
+the association under the wrong lock in sctp_datamsg_from_user().
+
+Add the same sk != asoc->base.sk check that sctp_wait_for_sndbuf()
+already has, returning an error if the association was migrated while
+we slept.
+
+Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260527032411.60959-1-kipreyyy@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/socket.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 98586bcf83cebe..a6a53b0c4ea324 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -9371,6 +9371,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
+ release_sock(sk);
+ current_timeo = schedule_timeout(current_timeo);
+ lock_sock(sk);
++ if (sk != asoc->base.sk)
++ goto do_error;
+
+ *timeo_p = current_timeo;
+ }
+--
+2.53.0
+
drm-remove-plane-hsub-vsub-alignment-requirement-for.patch
bcache-fix-uninitialized-closure-object.patch
net-cpsw_new-fix-potential-unregister-of-netdev-that.patch
+nfc-llcp-fix-use-after-free-in-llcp_sock_release.patch
+nfc-llcp-fix-use-after-free-race-in-nfc_llcp_recv_cc.patch
+xfrm-check-for-underflow-in-xfrm_state_mtu.patch
+nfc-nxp-nci-i2c-use-rising-edge-irq-on-acpi-systems.patch
+kernel-fork-validate-exit_signal-in-kernel_clone.patch
+netfilter-synproxy-refresh-tcphdr-after-skb_ensure_w.patch
+netfilter-xt_cpu-prefer-raw_smp_processor_id.patch
+netfilter-ebtables-fix-oob-read-in-compat_mtw_from_u.patch
+netfilter-bitwise-rename-some-boolean-operation-func.patch
+netfilter-bitwise-add-support-for-doing-and-or-and-x.patch
+netfilter-nf_tables-fix-dst-corruption-in-same-regis.patch
+tun-free-page-on-short-frame-rejection-in-tun_xdp_on.patch
+tun-free-page-on-build_skb-failure-in-tun_xdp_one.patch
+vsock-keep-poll-shutdown-state-consistent.patch
+net-netlink-fix-sending-unassigned-nsid-after-assign.patch
+net-netlink-don-t-set-nsid-on-local-notifications.patch
+net-smc-do-not-re-initialize-smc-hashtables.patch
+net-iucv-fix-locking-in-.getsockopt.patch
+scsi-core-run-queues-for-all-non-sdev_del-devices-fr.patch
+ipv4-free-net-ipv4.sysctl_local_reserved_ports-after.patch
+asoc-intel-bytcht_es8316-fix-mclk-leak-on-init-error.patch
+net-hsr-fix-potential-oob-access-in-supervision-fram.patch
+gpio-mxc-fix-irq_high-handling.patch
+tunnels-load-network-headers-after-skb_cow-in-iptunn.patch
+vxlan-do-not-reuse-cached-ip_hdr-value-after-skb_tun.patch
+tunnels-do-not-assume-transport-header-in-iptunnel_p.patch
+ksmbd-fix-fsctl-permission-bypass-by-adding-a-permis.patch
+asoc-codecs-simple-mux-fix-enum-control-bounds-check.patch
+bluetooth-6lowpan-check-skb_clone-return-value-in-se.patch
+bonding-refuse-to-enslave-can-devices.patch
+ethtool-eeprom-add-missing-ethnl_ops_begin-_complete.patch
+ethtool-eeprom-add-more-safeties-to-eeprom-netlink-f.patch
+ipv6-rpl-fix-hdrlen-overflow-in-ipv6_rpl_srh_decompr.patch
+net-sched-revert-net-sched-restrict-conditions-for-a.patch
+bluetooth-l2cap-clear-chan-ident-on-ecred-reconfigur.patch
+bluetooth-l2cap-fix-possible-crash-on-l2cap_ecred_co.patch
+gpio-rockchip-convert-bank-clk-to-devm_clk_get_enabl.patch
+net-mana-add-null-guards-in-teardown-path-to-prevent.patch
+sctp-fix-race-between-sctp_wait_for_connect-and-peel.patch
+ipv6-fix-possible-infinite-loop-in-rt6_fill_node.patch
+ipv6-fix-possible-infinite-loop-in-fib6_select_path.patch
+net-skbuff-fix-pskb_carve-leaking-zcopy-pages.patch
--- /dev/null
+From d5da23d77f7e9b7ee19a8b1d038f68204ffd9211 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 09:33:13 -0700
+Subject: tun: free page on build_skb failure in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit aa8963fdce667a42fb7f0bdd2909fadcab02f9a8 ]
+
+When build_skb() fails in tun_xdp_one(), the function sets ret to
+-ENOMEM and jumps to the out label, which returns without freeing the
+page that vhost_net_build_xdp() allocated for the frame. As with the
+short-frame rejection path, tun_sendmsg() discards the per-buffer error
+and still returns total_len, so vhost_tx_batch() takes the success path
+and never frees the page. Each build_skb() failure in a batch leaks one
+page-frag chunk.
+
+Free the page before taking the error path, matching the put_page() the
+other error exits of tun_xdp_one() already perform.
+
+Fixes: 043d222f93ab ("tuntap: accept an array of XDP buffs through sendmsg()")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260521163312.1479805-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 88b704b5d0b26e..9a4192d6a4cabf 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2505,6 +2505,7 @@ static int tun_xdp_one(struct tun_struct *tun,
+ build:
+ skb = build_skb(xdp->data_hard_start, buflen);
+ if (!skb) {
++ put_page(virt_to_head_page(xdp->data));
+ ret = -ENOMEM;
+ goto out;
+ }
+--
+2.53.0
+
--- /dev/null
+From eb77e551673698e972547a5d6b8b5424865bd829 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 09:00:21 -0700
+Subject: tun: free page on short-frame rejection in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f4feb1e20058e407cb00f45aff47f5b7e19a6bbf ]
+
+tun_xdp_one() returns -EINVAL on a frame shorter than ETH_HLEN without
+freeing the page that vhost_net_build_xdp() allocated for it.
+tun_sendmsg() discards that -EINVAL and still returns total_len, so
+vhost_tx_batch() takes the success path and never frees the page; each
+short frame in a batch leaks one page-frag chunk.
+
+A local process that can open /dev/net/tun and /dev/vhost-net can hit
+this path: it attaches a tun/tap device as the vhost-net backend and
+feeds TX descriptors whose length minus the virtio-net header is below
+ETH_HLEN. Each kick leaks the page-frag chunks for that batch, and a
+tight submission loop exhausts host memory and triggers an OOM panic.
+Free the page before returning -EINVAL, matching the XDP-program error
+path in the same function.
+
+Fixes: 049584807f1d ("tun: add missing verification for short frame")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260520160020.375349-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 97dbec8d78077d..88b704b5d0b26e 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2459,8 +2459,10 @@ static int tun_xdp_one(struct tun_struct *tun,
+ bool skb_xdp = false;
+ struct page *page;
+
+- if (unlikely(datasize < ETH_HLEN))
++ if (unlikely(datasize < ETH_HLEN)) {
++ put_page(virt_to_head_page(xdp->data));
+ return -EINVAL;
++ }
+
+ xdp_prog = rcu_dereference(tun->xdp_prog);
+ if (xdp_prog) {
+--
+2.53.0
+
--- /dev/null
+From 98d3272a7d817488ae912183d0f8eb90d61d511e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 11:55:12 +0000
+Subject: tunnels: do not assume transport header in
+ iptunnel_pmtud_check_icmp()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 509323077ef79a26ba0c60bb556e45c12c398b2d ]
+
+In some cases, iptunnel_pmtud_check_icmp() can be called while
+skb transport header is not set.
+
+This triggers an out-of-bound access, because
+(typeof(skb->transport_header))~0U is 65535.
+
+Access the icmp header based on IPv4 network header,
+after making sure icmp->type is present in skb linear part.
+
+Note that iptunnel_pmtud_check_icmpv6()) is fine.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Reported-by: Damiano Melotti <melotti@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260522115512.1519110-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 5fb437f040ace7..9f6f1b435d8d72 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -262,7 +262,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct icmphdr *icmph = icmp_hdr(skb);
+ const struct iphdr *iph = ip_hdr(skb);
+
+ if (mtu < 576 || iph->frag_off != htons(IP_DF))
+@@ -273,9 +272,17 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ ipv4_is_lbcast(iph->saddr) || ipv4_is_multicast(iph->saddr))
+ return 0;
+
+- if (iph->protocol == IPPROTO_ICMP && icmp_is_err(icmph->type))
+- return 0;
++ if (iph->protocol == IPPROTO_ICMP) {
++ const struct icmphdr *icmph;
+
++ if (!pskb_network_may_pull(skb, iph->ihl * 4 +
++ offsetofend(struct icmphdr, type)))
++ return 0;
++ iph = ip_hdr(skb);
++ icmph = (void *)iph + iph->ihl * 4;
++ if (icmp_is_err(icmph->type))
++ return 0;
++ }
+ return iptunnel_pmtud_build_icmp(skb, mtu);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 1025d6fb4e752d1157c1da2f519f180a440a94f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:13:35 +0000
+Subject: tunnels: load network headers after skb_cow() in
+ iptunnel_pmtud_build_icmp[v6]()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b4bc94353050b1fa7b702bd4c6600710dd926cff ]
+
+Sashiko found that iptunnel_pmtud_build_icmp() and
+iptunnel_pmtud_build_icmpv6() were caching ip_hdr() and ipv6_hdr()
+before an skb_cow() call which can reallocate skb->head.
+
+Fix this possible UAF by initializing the local variables
+after the skb_cow() call.
+
+Remove skb_reset_network_header() calls which were not needed.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525201335.2361845-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index 75e3d7501752df..5fb437f040ace7 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -194,7 +194,7 @@ EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
+ */
+ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct iphdr *iph = ip_hdr(skb);
++ const struct iphdr *iph;
+ struct icmphdr *icmph;
+ struct iphdr *niph;
+ struct ethhdr eh;
+@@ -208,7 +208,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, 576 - sizeof(*niph) - sizeof(*icmph));
+ if (err)
+@@ -218,7 +217,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ err = skb_cow(skb, sizeof(*niph) + sizeof(*icmph) + ETH_HLEN);
+ if (err)
+ return err;
+-
++ iph = ip_hdr(skb);
+ icmph = skb_push(skb, sizeof(*icmph));
+ *icmph = (struct icmphdr) {
+ .type = ICMP_DEST_UNREACH,
+@@ -290,7 +289,7 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ {
+- const struct ipv6hdr *ip6h = ipv6_hdr(skb);
++ const struct ipv6hdr *ip6h;
+ struct icmp6hdr *icmp6h;
+ struct ipv6hdr *nip6h;
+ struct ethhdr eh;
+@@ -305,7 +304,6 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, IPV6_MIN_MTU - sizeof(*nip6h) - sizeof(*icmp6h));
+ if (err)
+@@ -316,6 +314,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ if (err)
+ return err;
+
++ ip6h = ipv6_hdr(skb);
+ icmp6h = skb_push(skb, sizeof(*icmp6h));
+ *icmp6h = (struct icmp6hdr) {
+ .icmp6_type = ICMPV6_PKT_TOOBIG,
+--
+2.53.0
+
--- /dev/null
+From ac849fac58ec871af3d1e59c66b0a5459f5c24b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 00:56:36 +0800
+Subject: vsock: keep poll shutdown state consistent
+
+From: Ziyu Zhang <ziyuzhang201@gmail.com>
+
+[ Upstream commit aae9d8a5528b8ee9ff8dc5d3558b8a9f852a724a ]
+
+vsock_poll() reads vsk->peer_shutdown before taking the socket lock
+to set EPOLLHUP and EPOLLRDHUP, then reads it again after taking
+the lock to report EOF readability. A shutdown packet can update
+peer_shutdown while poll is waiting for the lock, so one poll invocation
+can report EOF readability without the corresponding HUP/RDHUP bits.
+
+For connectible sockets, take one peer_shutdown snapshot after
+lock_sock() and use it for all peer-shutdown-derived poll bits. For
+datagram sockets, which do not take lock_sock() in poll(), take one
+lockless READ_ONCE() snapshot and pair it with WRITE_ONCE() on the
+writer side.
+
+This keeps the peer-shutdown-derived bits internally consistent for each
+poll pass.
+
+Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
+Signed-off-by: Ziyu Zhang <ziyuzhang201@gmail.com>
+Link: https://patch.msgid.link/20260519165636.62542-1-ziyuzhang201@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/vmw_vsock/af_vsock.c | 49 ++++++++++++++++---------
+ net/vmw_vsock/hyperv_transport.c | 9 +++--
+ net/vmw_vsock/virtio_transport_common.c | 14 ++++---
+ net/vmw_vsock/vmci_transport.c | 8 ++--
+ 4 files changed, 52 insertions(+), 28 deletions(-)
+
+diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
+index 187cc259f820b5..a06f708f300c4a 100644
+--- a/net/vmw_vsock/af_vsock.c
++++ b/net/vmw_vsock/af_vsock.c
+@@ -522,7 +522,7 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
+ */
+ sock_reset_flag(sk, SOCK_DONE);
+ sk->sk_state = TCP_CLOSE;
+- vsk->peer_shutdown = 0;
++ WRITE_ONCE(vsk->peer_shutdown, 0);
+ }
+
+ if (sk->sk_type == SOCK_SEQPACKET) {
+@@ -813,7 +813,7 @@ static struct sock *__vsock_create(struct net *net,
+ vsk->rejected = false;
+ vsk->sent_request = false;
+ vsk->ignore_connecting_rst = false;
+- vsk->peer_shutdown = 0;
++ WRITE_ONCE(vsk->peer_shutdown, 0);
+ INIT_DELAYED_WORK(&vsk->connect_work, vsock_connect_timeout);
+ INIT_DELAYED_WORK(&vsk->pending_work, vsock_pending_work);
+
+@@ -1095,6 +1095,25 @@ static int vsock_shutdown(struct socket *sock, int mode)
+ return err;
+ }
+
++static __poll_t vsock_poll_shutdown(struct sock *sk, u32 peer_shutdown)
++{
++ __poll_t mask = 0;
++
++ /* INET sockets treat local write shutdown and peer write shutdown as a
++ * case of EPOLLHUP set.
++ */
++ if (sk->sk_shutdown == SHUTDOWN_MASK ||
++ ((sk->sk_shutdown & SEND_SHUTDOWN) &&
++ (peer_shutdown & SEND_SHUTDOWN)))
++ mask |= EPOLLHUP;
++
++ if (sk->sk_shutdown & RCV_SHUTDOWN ||
++ peer_shutdown & SEND_SHUTDOWN)
++ mask |= EPOLLRDHUP;
++
++ return mask;
++}
++
+ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+ {
+@@ -1112,24 +1131,17 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ /* Signify that there has been an error on this socket. */
+ mask |= EPOLLERR;
+
+- /* INET sockets treat local write shutdown and peer write shutdown as a
+- * case of EPOLLHUP set.
+- */
+- if ((sk->sk_shutdown == SHUTDOWN_MASK) ||
+- ((sk->sk_shutdown & SEND_SHUTDOWN) &&
+- (vsk->peer_shutdown & SEND_SHUTDOWN))) {
+- mask |= EPOLLHUP;
+- }
+-
+- if (sk->sk_shutdown & RCV_SHUTDOWN ||
+- vsk->peer_shutdown & SEND_SHUTDOWN) {
+- mask |= EPOLLRDHUP;
+- }
+-
+ if (sk_is_readable(sk))
+ mask |= EPOLLIN | EPOLLRDNORM;
+
+ if (sock->type == SOCK_DGRAM) {
++ u32 peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++
++ /* DGRAM sockets do not take lock_sock() in poll(), so use one
++ * lockless snapshot for all shutdown-derived mask bits.
++ */
++ mask |= vsock_poll_shutdown(sk, peer_shutdown);
++
+ /* For datagram sockets we can read if there is something in
+ * the queue and write as long as the socket isn't shutdown for
+ * sending.
+@@ -1144,6 +1156,7 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+
+ } else if (sock_type_connectible(sk->sk_type)) {
+ const struct vsock_transport *transport;
++ u32 peer_shutdown;
+
+ lock_sock(sk);
+
+@@ -1176,8 +1189,10 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ * terminated should also be considered read, and we check the
+ * shutdown flag for that.
+ */
++ peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++ mask |= vsock_poll_shutdown(sk, peer_shutdown);
+ if (sk->sk_shutdown & RCV_SHUTDOWN ||
+- vsk->peer_shutdown & SEND_SHUTDOWN) {
++ peer_shutdown & SEND_SHUTDOWN) {
+ mask |= EPOLLIN | EPOLLRDNORM;
+ }
+
+diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
+index 34871ed1a099c6..865e004ee286f2 100644
+--- a/net/vmw_vsock/hyperv_transport.c
++++ b/net/vmw_vsock/hyperv_transport.c
+@@ -264,7 +264,7 @@ static void hvs_do_close_lock_held(struct vsock_sock *vsk,
+ struct sock *sk = sk_vsock(vsk);
+
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+ sk->sk_state_change(sk);
+@@ -593,7 +593,9 @@ static int hvs_update_recv_data(struct hvsock *hvs)
+ return -EIO;
+
+ if (payload_len == 0)
+- hvs->vsk->peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(hvs->vsk->peer_shutdown,
++ READ_ONCE(hvs->vsk->peer_shutdown) |
++ SEND_SHUTDOWN);
+
+ hvs->recv_data_len = payload_len;
+ hvs->recv_data_off = 0;
+@@ -704,7 +706,8 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk)
+ ret = 1;
+ break;
+ case 0:
+- vsk->peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(vsk->peer_shutdown,
++ READ_ONCE(vsk->peer_shutdown) | SEND_SHUTDOWN);
+ ret = 0;
+ break;
+ default: /* -1 */
+diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
+index d4ff9506eaf6d5..16431ef52799db 100644
+--- a/net/vmw_vsock/virtio_transport_common.c
++++ b/net/vmw_vsock/virtio_transport_common.c
+@@ -1043,7 +1043,7 @@ static void virtio_transport_do_close(struct vsock_sock *vsk,
+ struct sock *sk = sk_vsock(vsk);
+
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+ sk->sk_state_change(sk);
+@@ -1244,12 +1244,15 @@ virtio_transport_recv_connected(struct sock *sk,
+ case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
+ sk->sk_write_space(sk);
+ break;
+- case VIRTIO_VSOCK_OP_SHUTDOWN:
++ case VIRTIO_VSOCK_OP_SHUTDOWN: {
++ u32 peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++
+ if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_RCV)
+- vsk->peer_shutdown |= RCV_SHUTDOWN;
++ peer_shutdown |= RCV_SHUTDOWN;
+ if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_SEND)
+- vsk->peer_shutdown |= SEND_SHUTDOWN;
+- if (vsk->peer_shutdown == SHUTDOWN_MASK) {
++ peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(vsk->peer_shutdown, peer_shutdown);
++ if (peer_shutdown == SHUTDOWN_MASK) {
+ if (vsock_stream_has_data(vsk) <= 0 && !sock_flag(sk, SOCK_DONE)) {
+ (void)virtio_transport_reset(vsk, NULL);
+ virtio_transport_do_close(vsk, true);
+@@ -1264,6 +1267,7 @@ virtio_transport_recv_connected(struct sock *sk,
+ if (le32_to_cpu(virtio_vsock_hdr(skb)->flags))
+ sk->sk_state_change(sk);
+ break;
++ }
+ case VIRTIO_VSOCK_OP_RST:
+ virtio_transport_do_close(vsk, true);
+ break;
+diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
+index 4cd11f355e9d6b..443125e48f2481 100644
+--- a/net/vmw_vsock/vmci_transport.c
++++ b/net/vmw_vsock/vmci_transport.c
+@@ -811,7 +811,7 @@ static void vmci_transport_handle_detach(struct sock *sk)
+ /* On a detach the peer will not be sending or receiving
+ * anymore.
+ */
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+
+ /* We should not be sending anymore since the peer won't be
+ * there to receive, but we can still receive if there is data
+@@ -1534,7 +1534,9 @@ static int vmci_transport_recv_connected(struct sock *sk,
+ if (pkt->u.mode) {
+ vsk = vsock_sk(sk);
+
+- vsk->peer_shutdown |= pkt->u.mode;
++ WRITE_ONCE(vsk->peer_shutdown,
++ READ_ONCE(vsk->peer_shutdown) |
++ pkt->u.mode);
+ sk->sk_state_change(sk);
+ }
+ break;
+@@ -1551,7 +1553,7 @@ static int vmci_transport_recv_connected(struct sock *sk,
+ * a clean shutdown.
+ */
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+
+--
+2.53.0
+
--- /dev/null
+From 2dd2376124ba04bd65611ef2192912e42c3ca6df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:36:42 +0000
+Subject: vxlan: do not reuse cached ip_hdr() value after
+ skb_tunnel_check_pmtu()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 7d9ef0cb271555d8cf39fefe6c981e1493b25ecf ]
+
+skb_tunnel_check_pmtu() can change skb->head.
+
+Reusing old_iph afer skb_tunnel_check_pmtu() can cause an UAF.
+
+Use instead ip_hdr(skb) as done in drivers/net/bareudp.c
+and drivers/net/geneve.c.
+
+Found by Sashiko.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525203642.2389723-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index 1a973dcf256127..958d3be4f99086 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -2607,7 +2607,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
+ vni, md, flags, udp_sum);
+@@ -2670,7 +2670,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip6_dst_hoplimit(ndst);
+ skb_scrub_packet(skb, xnet);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
+--
+2.53.0
+
--- /dev/null
+From cf3c217fc7e297fc037e31a97775ef5f341a6978 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:49:14 -0600
+Subject: xfrm: Check for underflow in xfrm_state_mtu
+
+From: David Ahern <dahern@nvidia.com>
+
+[ Upstream commit 742b04d0550b0ec89dcbc99537ec88653bd1ad90 ]
+
+Leo Lin reported OOB write issue in esp component:
+
+ xfrm_state_mtu() returns u32 but performs its arithmetic in unsigned
+ modulo-2^32 space using an attacker-influenced "header_len + authsize +
+ net_adj" subtracted from a small "mtu" argument. A nobody user can
+ install an IPv4 ESP tunnel SA with a large authentication key
+ (XFRMA_ALG_AUTH_TRUNC, e.g. hmac(sha512), 64-byte key, 64-byte trunc),
+ configure a small interface MTU (68 bytes), and set XFRMA_TFCPAD to a
+ large value. When a single UDP datagram is then sent through the
+ tunnel, xfrm_state_mtu() underflows to a near-2^32 value, and
+ esp_output() consumes it as a signed int via:
+
+ padto = min(x->tfcpad, xfrm_state_mtu(x, mtu_cached))
+ esp.tfclen = padto - skb->len (assigned to int)
+
+ esp.tfclen ends up negative (e.g. -207). It is sign-extended to size_t
+ when passed to memset() inside esp_output_fill_trailer(), producing a
+ ~16 EB write of zeroes at skb_tail_pointer(skb). KASAN logs it as
+ "Write of size 18446744073709551537 at addr ffff888...".
+
+Check for underflow and return 1. This causes the sendmsg attempt to
+fail with ENETUNREACH.
+
+Fixes: c5c252389374 ("[XFRM]: Optimize MTU calculation")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Assisted-by: Codex:26.506.31004
+Signed-off-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 8ba31cf9b31993..6e8860779e2154 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -2860,10 +2860,14 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ const struct xfrm_type *type = READ_ONCE(x->type);
+ struct crypto_aead *aead;
+ u32 blksize, net_adj = 0;
++ u32 overhead, payload_mtu;
+
+ if (x->km.state != XFRM_STATE_VALID ||
+- !type || type->proto != IPPROTO_ESP)
++ !type || type->proto != IPPROTO_ESP) {
++ if (mtu <= x->props.header_len)
++ return 1;
+ return mtu - x->props.header_len;
++ }
+
+ aead = x->data;
+ blksize = ALIGN(crypto_aead_blocksize(aead), 4);
+@@ -2883,8 +2887,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ break;
+ }
+
+- return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
+- net_adj) & ~(blksize - 1)) + net_adj - 2;
++ overhead = x->props.header_len + crypto_aead_authsize(aead) + net_adj;
++ if (mtu <= overhead)
++ return 1;
++
++ payload_mtu = mtu - overhead;
++ payload_mtu &= ~(blksize - 1);
++ if (payload_mtu <= 2)
++ return 1;
++
++ return payload_mtu + net_adj - 2;
++
+ }
+ EXPORT_SYMBOL_GPL(xfrm_state_mtu);
+
+--
+2.53.0
+
--- /dev/null
+From 564b0913fb1d645c6cc17421362708ea1aa98154 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 10:14:42 +0300
+Subject: accel/ivpu: prevent uninitialized data bug in debugfs
+
+From: Dan Carpenter <error27@gmail.com>
+
+[ Upstream commit 44e151be23deb788d9f6124de93823faf6e04e99 ]
+
+The simple_write_to_buffer() will only initialize data starting from
+the *pos offset so if it's non-zero then the first part of the buffer
+uninitialized. Really, if *pos is non-zero then this code won't work
+so just check for that at the start of the function.
+
+Fixes: 320323d2e545 ("accel/ivpu: Add debugfs interface for setting HWS priority bands")
+Signed-off-by: Dan Carpenter <error27@gmail.com>
+Reviewed-by: Karol Wachowski <karol.wachowski@linux.intel.com>
+Signed-off-by: Karol Wachowski <karol.wachowski@linux.intel.com>
+Link: https://patch.msgid.link/ahP24m6Mii9EDL7Q@stanley.mountain
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/accel/ivpu/ivpu_debugfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/accel/ivpu/ivpu_debugfs.c b/drivers/accel/ivpu/ivpu_debugfs.c
+index a09f54fc430206..e93883914bc274 100644
+--- a/drivers/accel/ivpu/ivpu_debugfs.c
++++ b/drivers/accel/ivpu/ivpu_debugfs.c
+@@ -440,7 +440,7 @@ priority_bands_fops_write(struct file *file, const char __user *user_buf, size_t
+ u32 band;
+ int ret;
+
+- if (size >= sizeof(buf))
++ if (*pos != 0 || size >= sizeof(buf))
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, pos, user_buf, size);
+--
+2.53.0
+
--- /dev/null
+From 2bb0f440aee93dcf22269b22a0b3361c206510ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 00:00:00 +0530
+Subject: accel/rocket: fix UAF via dangling GEM handle in create_bo
+
+From: Dhabaleshwar Das <dhabal123@gmail.com>
+
+[ Upstream commit f706e6a4ce75585af979aec3dcbdce68bc76306b ]
+
+rocket_ioctl_create_bo() inserts a GEM handle into the file's IDR via
+drm_gem_handle_create() early on, then performs several operations that
+can fail (sgt allocation, drm_mm insert, iommu_map). If any fail after
+the handle is live, the error path calls drm_gem_shmem_object_free()
+which kfree's the object without removing the handle from the IDR.
+
+This leaves a dangling handle pointing to freed slab memory. Any
+subsequent ioctl using that handle (PREP_BO, FINI_BO, SUBMIT) calls
+drm_gem_object_lookup() and dereferences freed memory (UAF).
+
+Fix by moving drm_gem_handle_create() to after all fallible operations
+succeed, matching the pattern used by panfrost, lima, and etnaviv.
+
+Also fix drm_mm_insert_node_generic() whose return value was silently
+overwritten by iommu_map_sgtable() on the next line. Add the missing
+error check.
+
+[tomeu: Move handle creation to the very end]
+
+Fixes: 658ebeac3351 ("accel/rocket: Add IOCTL for BO creation")
+Reported-by: Dhabaleshwar Das <dhabal123@gmail.com>
+Signed-off-by: Dhabaleshwar Das <dhabal123@gmail.com>
+Reviewed-by: Tomeu Vizoso <tomeu@tomeuvizoso.net>
+Link: https://patch.msgid.link/20260521165720.2113571-1-tomeu@tomeuvizoso.net
+Signed-off-by: Tomeu Vizoso <tomeu@tomeuvizoso.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/accel/rocket/rocket_gem.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/accel/rocket/rocket_gem.c b/drivers/accel/rocket/rocket_gem.c
+index c8084719208a2a..a5fffa51ff3550 100644
+--- a/drivers/accel/rocket/rocket_gem.c
++++ b/drivers/accel/rocket/rocket_gem.c
+@@ -79,11 +79,6 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
+ rkt_obj->size = args->size;
+ rkt_obj->offset = 0;
+
+- ret = drm_gem_handle_create(file, gem_obj, &args->handle);
+- drm_gem_object_put(gem_obj);
+- if (ret)
+- goto err;
+-
+ sgt = drm_gem_shmem_get_pages_sgt(shmem_obj);
+ if (IS_ERR(sgt)) {
+ ret = PTR_ERR(sgt);
+@@ -95,6 +90,8 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
+ rkt_obj->size, PAGE_SIZE,
+ 0, 0);
+ mutex_unlock(&rocket_priv->mm_lock);
++ if (ret)
++ goto err;
+
+ ret = iommu_map_sgtable(rocket_priv->domain->domain,
+ rkt_obj->mm.start,
+@@ -112,8 +109,18 @@ int rocket_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *
+ args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
+ args->dma_address = rkt_obj->mm.start;
+
++ ret = drm_gem_handle_create(file, gem_obj, &args->handle);
++ if (ret)
++ goto err_unmap;
++
++ drm_gem_object_put(gem_obj);
++
+ return 0;
+
++err_unmap:
++ iommu_unmap(rocket_priv->domain->domain,
++ rkt_obj->mm.start, rkt_obj->size);
++
+ err_remove_node:
+ mutex_lock(&rocket_priv->mm_lock);
+ drm_mm_remove_node(&rkt_obj->mm);
+--
+2.53.0
+
--- /dev/null
+From ed968acc372b417b96251efb0f17cb4b2fab8177 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 09:49:30 -0300
+Subject: ALSA: hda: cs35l56: Fix system name string leaks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit a0d9e8df2ebca290c2efff70abc05426e5a476b0 ]
+
+cs35l56_hda_read_acpi() gets an allocated ACPI _SUB string from
+acpi_get_subsystem_id(). On success, that string is used to create the
+firmware system name.
+
+Several error paths after the _SUB lookup can return without releasing
+the allocated string. This includes speaker ID lookup errors other than
+-ENOENT, and errors after a firmware system name has been allocated.
+
+Use scoped cleanup for the temporary _SUB string and make
+cs35l56->system_name device-managed. This releases the temporary _SUB
+string on every error path and lets devres release the firmware system
+name on probe failure and device removal.
+
+Fixes: 6f03b446cbae ("ALSA: hda: cs35l56: Add support for speaker id")
+Fixes: 40b1c2f9b299 ("ALSA: hda/cs35l56: Workaround bad dev-index on Lenovo Yoga Book 9i GenX")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Reviewed-by: Richard Fitzgerald <rf@opensource.cirrus.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Link: https://patch.msgid.link/20260522-alsa-cs35l56-system-name-leak-v4-1-a6154dd09cd9@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/hda/codecs/side-codecs/cs35l56_hda.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda.c b/sound/hda/codecs/side-codecs/cs35l56_hda.c
+index cdbc576569efee..a0ea08eb96a93f 100644
+--- a/sound/hda/codecs/side-codecs/cs35l56_hda.c
++++ b/sound/hda/codecs/side-codecs/cs35l56_hda.c
+@@ -1025,7 +1025,7 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
+ u32 values[HDA_MAX_COMPONENTS];
+ char hid_string[8];
+ struct acpi_device *adev;
+- const char *property, *sub;
++ const char *property;
+ int i, ret;
+
+ /*
+@@ -1047,7 +1047,8 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
+ /* Initialize things that could be overwritten by a fixup */
+ cs35l56->index = -1;
+
+- sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
++ const char *sub __free(kfree) = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
++
+ ret = cs35l56_hda_apply_platform_fixups(cs35l56, sub, &id);
+ if (ret)
+ return ret;
+@@ -1095,15 +1096,16 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
+ ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index,
+ cs35l56->num_amps, -1);
+ if (ret == -ENOENT) {
+- cs35l56->system_name = sub;
++ cs35l56->system_name = devm_kstrdup(cs35l56->base.dev, sub, GFP_KERNEL);
+ } else if (ret >= 0) {
+- cs35l56->system_name = kasprintf(GFP_KERNEL, "%s-spkid%d", sub, ret);
+- kfree(sub);
+- if (!cs35l56->system_name)
+- return -ENOMEM;
++ cs35l56->system_name = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL,
++ "%s-spkid%d", sub, ret);
+ } else {
+ return ret;
+ }
++
++ if (!cs35l56->system_name)
++ return -ENOMEM;
+ }
+
+ cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev,
+@@ -1254,7 +1256,6 @@ void cs35l56_hda_remove(struct device *dev)
+
+ cs_dsp_remove(&cs35l56->cs_dsp);
+
+- kfree(cs35l56->system_name);
+ pm_runtime_put_noidle(cs35l56->base.dev);
+
+ gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
+--
+2.53.0
+
--- /dev/null
+From 8d1a022b4f8644d835bbec9cf08167ad1bd7bc55 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 22:09:40 -0300
+Subject: ALSA: pcm: oss: Fix setup list UAF on proc write error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit 4cc54bdd54b337e77115be5b55577d1c58608eae ]
+
+snd_pcm_oss_proc_write() links a newly allocated setup entry into the
+OSS setup list before duplicating the task name. If the task-name
+allocation fails, the error path frees the already linked entry and
+leaves setup_list pointing at freed memory.
+
+A later OSS device open can then walk the stale list entry in
+snd_pcm_oss_look_for_setup() and dereference freed memory.
+
+Allocate the task name and initialize the setup entry before publishing
+the entry on setup_list. Also fetch the initial proc read iterator only
+after taking setup_mutex, so all setup_list traversal follows the same
+list lifetime rules.
+
+Reported-by: syzbot+8e498074a794999eb41c@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/6a1062b7.170a0220.35b2b7.0003.GAE@google.com
+Closes: https://syzkaller.appspot.com/bug?extid=8e498074a794999eb41c
+Fixes: 060d77b9c04a ("[ALSA] Fix / clean up PCM-OSS setup hooks")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260522-alsa-pcm-oss-setup-uaf-v1-1-40bdcc4d17e8@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/core/oss/pcm_oss.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
+index 6af26ec2ecfd59..b1b4c7d017beea 100644
+--- a/sound/core/oss/pcm_oss.c
++++ b/sound/core/oss/pcm_oss.c
+@@ -2968,8 +2968,10 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
+ struct snd_info_buffer *buffer)
+ {
+ struct snd_pcm_str *pstr = entry->private_data;
+- struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
++ struct snd_pcm_oss_setup *setup;
++
+ guard(mutex)(&pstr->oss.setup_mutex);
++ setup = pstr->oss.setup_list;
+ while (setup) {
+ snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
+ setup->task_name,
+@@ -3054,6 +3056,13 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
+ buffer->error = -ENOMEM;
+ return;
+ }
++ template.task_name = kstrdup(task_name, GFP_KERNEL);
++ if (!template.task_name) {
++ kfree(setup);
++ buffer->error = -ENOMEM;
++ return;
++ }
++ *setup = template;
+ if (pstr->oss.setup_list == NULL)
+ pstr->oss.setup_list = setup;
+ else {
+@@ -3061,12 +3070,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
+ setup1->next; setup1 = setup1->next);
+ setup1->next = setup;
+ }
+- template.task_name = kstrdup(task_name, GFP_KERNEL);
+- if (! template.task_name) {
+- kfree(setup);
+- buffer->error = -ENOMEM;
+- return;
+- }
++ continue;
+ }
+ *setup = template;
+ }
+--
+2.53.0
+
--- /dev/null
+From 959828173499d1f14b397934a4dca342be225927 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 09:24:00 -0300
+Subject: ASoC: codecs: simple-mux: Fix enum control bounds check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit f63ad68e18d774a5d15cd7e405ead63f6b322679 ]
+
+simple_mux_control_put() rejects values greater than e->items, but
+enum control values are zero based. For the two-entry mux used by this
+driver, valid values are 0 and 1, so value 2 must be rejected as well.
+
+Accepting e->items can store an invalid mux state, pass it to the GPIO
+setter, and pass it on to the DAPM mux update path where it is used as
+an index into the enum text array.
+
+Use the same >= e->items check used by the ASoC enum helpers.
+
+Fixes: 342fbb7578d1 ("ASoC: add simple-mux")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260527-asoc-simple-mux-enum-bounds-v1-1-3f805b9fc671@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/simple-mux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/codecs/simple-mux.c b/sound/soc/codecs/simple-mux.c
+index 069555f35f7359..c2f906a3f074ce 100644
+--- a/sound/soc/codecs/simple-mux.c
++++ b/sound/soc/codecs/simple-mux.c
+@@ -51,7 +51,7 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
+ struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
+ struct simple_mux *priv = snd_soc_component_get_drvdata(c);
+
+- if (ucontrol->value.enumerated.item[0] > e->items)
++ if (ucontrol->value.enumerated.item[0] >= e->items)
+ return -EINVAL;
+
+ if (priv->mux == ucontrol->value.enumerated.item[0])
+--
+2.53.0
+
--- /dev/null
+From 99ceb52e3882357e2d6ce74a52d86a113fb6159a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 13:51:47 -0300
+Subject: ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+
+[ Upstream commit afb2a3a9d8369d18122a0d7cd294eba9a98259c6 ]
+
+byt_cht_es8316_init() enables MCLK before configuring the codec sysclk
+and creating the headset jack. If either of those later steps fails, the
+function returns without disabling MCLK, leaving the clock enabled after
+card registration fails.
+
+Track whether this driver enabled MCLK and disable it on the init error
+paths. Add the matching DAI link exit callback so the same clock enable
+is also balanced when ASoC cleans up a successfully initialized link.
+
+Fixes: a03bdaa565cb ("ASoC: Intel: add machine driver for BYT/CHT + ES8316")
+Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
+Link: https://patch.msgid.link/20260519-asoc-bytcht-es8316-mclk-leak-v1-1-b4a11cdc2afd@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/bytcht_es8316.c | 29 ++++++++++++++++++++++++--
+ 1 file changed, 27 insertions(+), 2 deletions(-)
+
+diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
+index 192e2a394ff3d0..ea387dc7427382 100644
+--- a/sound/soc/intel/boards/bytcht_es8316.c
++++ b/sound/soc/intel/boards/bytcht_es8316.c
+@@ -40,6 +40,7 @@ struct byt_cht_es8316_private {
+ struct gpio_desc *speaker_en_gpio;
+ struct device *codec_dev;
+ bool speaker_en;
++ bool mclk_enabled;
+ };
+
+ enum {
+@@ -170,6 +171,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
+ },
+ };
+
++static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
++{
++ if (!priv->mclk_enabled)
++ return;
++
++ clk_disable_unprepare(priv->mclk);
++ priv->mclk_enabled = false;
++}
++
+ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ {
+ struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component;
+@@ -227,12 +237,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ret = clk_prepare_enable(priv->mclk);
+ if (ret)
+ dev_err(card->dev, "unable to enable MCLK\n");
++ else
++ priv->mclk_enabled = true;
+
+ ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(runtime, 0), 0, 19200000,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(card->dev, "can't set codec clock %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ ret = snd_soc_card_jack_new_pins(card, "Headset",
+@@ -241,13 +253,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
+ ARRAY_SIZE(byt_cht_es8316_jack_pins));
+ if (ret) {
+ dev_err(card->dev, "jack creation failed %d\n", ret);
+- return ret;
++ goto err_disable_mclk;
+ }
+
+ snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_soc_component_set_jack(codec, &priv->jack, NULL);
+
+ return 0;
++
++err_disable_mclk:
++ byt_cht_es8316_disable_mclk(priv);
++ return ret;
++}
++
++static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
++{
++ struct snd_soc_card *card = runtime->card;
++ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
++
++ byt_cht_es8316_disable_mclk(priv);
+ }
+
+ static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
+@@ -353,6 +377,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
+ | SND_SOC_DAIFMT_CBC_CFC,
+ .be_hw_params_fixup = byt_cht_es8316_codec_fixup,
+ .init = byt_cht_es8316_init,
++ .exit = byt_cht_es8316_exit,
+ SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
+ },
+ };
+--
+2.53.0
+
--- /dev/null
+From a227639fbfd866fd17e126e0ff263df8ff8893fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:31 -0700
+Subject: blk-mq: reinsert cached request to the list
+
+From: Keith Busch <kbusch@kernel.org>
+
+[ Upstream commit b051bb6bf0a231117036aa607cadf55be8e63910 ]
+
+A previous commit removed an optimization out of caution for a scenario
+that turns out not to be real: all the "queue_exit" goto's are safe to
+reinsert the request into the cached_rq's plug list as they are either
+from a non-blocking path, or a successful merge that already holds the
+queue reference. This optimization is most needed for small sequential
+workloads that successfully merge into larger requests.
+
+Fixes: dc278e9bf2b9 ("blk-mq: pop cached request if it is usable")
+Suggested-by: Ming Lei <tom.leiming@gmail.com>
+Suggested-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Keith Busch <kbusch@kernel.org>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Link: https://patch.msgid.link/20260526153531.2365935-1-kbusch@meta.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-mq.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index 39986a742b981a..061c8ef4484a25 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -3244,7 +3244,7 @@ void blk_mq_submit_bio(struct bio *bio)
+ if (!rq)
+ blk_queue_exit(q);
+ else
+- blk_mq_free_request(rq);
++ rq_list_add_head(&plug->cached_rqs, rq);
+ }
+
+ #ifdef CONFIG_BLK_MQ_STACKING
+--
+2.53.0
+
--- /dev/null
+From c8907a61c18236cd18ddd34f089d2635478d3ab6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 11:21:39 +0800
+Subject: Bluetooth: 6lowpan: check skb_clone() return value in
+ send_mcast_pkt()
+
+From: Zhao Dongdong <zhaodongdong@kylinos.cn>
+
+[ Upstream commit 3c40d381ce04f9575a5d8b542898183c3b4b38dc ]
+
+The skb_clone() function can return NULL if memory allocation fails.
+send_mcast_pkt() calls skb_clone() without checking the return value, which
+can lead to a NULL pointer dereference in send_pkt() when it dereferences
+skb->data.
+Add a NULL check after skb_clone() and skip the peer if the clone fails.
+
+Fixes: 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices")
+Signed-off-by: Zhao Dongdong <zhaodongdong@kylinos.cn>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/6lowpan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
+index 2f03b780b40d84..960a19b3e26da1 100644
+--- a/net/bluetooth/6lowpan.c
++++ b/net/bluetooth/6lowpan.c
+@@ -486,6 +486,8 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
+ int ret;
+
+ local_skb = skb_clone(skb, GFP_ATOMIC);
++ if (!local_skb)
++ continue;
+
+ BT_DBG("xmit %s to %pMR type %u IP %pI6c chan %p",
+ netdev->name,
+--
+2.53.0
+
--- /dev/null
+From 0b8f63d390a8819be50aa98f2fdcdcf0c1bf635b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 10:50:59 -0300
+Subject: Bluetooth: hci_sync: Reset device counters in hci_dev_close_sync()
+
+From: Heitor Alves de Siqueira <halves@igalia.com>
+
+[ Upstream commit cdf88b35e06f1b385f7f6228060ae541d44fbb72 ]
+
+Before resetting or closing the device, protocol counters should also be
+zeroed.
+
+Fixes: d0b137062b2d ("Bluetooth: hci_sync: Rework init stages")
+Signed-off-by: Heitor Alves de Siqueira <halves@igalia.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sync.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 80b71e39656faf..35988eace9e4f4 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -5393,6 +5393,10 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+ /* Reset device */
+ skb_queue_purge(&hdev->cmd_q);
+ atomic_set(&hdev->cmd_cnt, 1);
++ hdev->acl_cnt = 0;
++ hdev->sco_cnt = 0;
++ hdev->le_cnt = 0;
++ hdev->iso_cnt = 0;
+ if (hci_test_quirk(hdev, HCI_QUIRK_RESET_ON_CLOSE) &&
+ !auto_off && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
+ set_bit(HCI_INIT, &hdev->flags);
+--
+2.53.0
+
--- /dev/null
+From 35a912c06c6b00ef57e1ae9934c2f76dccd70f43 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 10:50:58 -0300
+Subject: Bluetooth: hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close
+
+From: Heitor Alves de Siqueira <halves@igalia.com>
+
+[ Upstream commit 525daaea459fc215f432de1b8debbd9144bf97b0 ]
+
+Since hci_dev_close_sync() can now be called during the reset path, we
+should also set HCI_CMD_DRAIN_WORKQUEUE. This avoids queuing timeouts
+while the hdev workqueue is being drained.
+
+Fixes: 877afadad2dc ("Bluetooth: When HCI work queue is drained, only queue chained work")
+Signed-off-by: Heitor Alves de Siqueira <halves@igalia.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/hci_sync.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
+index 426f465be35533..80b71e39656faf 100644
+--- a/net/bluetooth/hci_sync.c
++++ b/net/bluetooth/hci_sync.c
+@@ -5301,6 +5301,12 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+
+ bt_dev_dbg(hdev, "");
+
++ /* Set HCI_DRAIN_WORKQUEUE flag to prevent queuing work during
++ * reset/close. See hci_cmd_work() and handle_cmd_cnt_and_timer().
++ */
++ hci_dev_set_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
++ synchronize_rcu();
++
+ if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+ disable_delayed_work(&hdev->power_off);
+ disable_delayed_work(&hdev->ncmd_timer);
+@@ -5324,6 +5330,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+
+ if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
+ cancel_delayed_work_sync(&hdev->cmd_timer);
++ hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
+ return err;
+ }
+
+@@ -5423,6 +5430,7 @@ int hci_dev_close_sync(struct hci_dev *hdev)
+ /* Clear flags */
+ hdev->flags &= BIT(HCI_RAW);
+ hci_dev_clear_volatile_flags(hdev);
++ hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE);
+
+ memset(hdev->eir, 0, sizeof(hdev->eir));
+ memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
+--
+2.53.0
+
--- /dev/null
+From 1471327a723ed39148ab4b7d9408cf2f29fb3a25 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 18:51:52 +0800
+Subject: Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit 00e1950716c6ed67d74777b2db286b0fa23b4be9 ]
+
+l2cap_ecred_reconf_rsp() returns early on success without clearing
+chan->ident. Every other L2CAP response handler (l2cap_ecred_conn_rsp,
+l2cap_le_connect_rsp, l2cap_config_rsp) clears chan->ident after a
+successful transaction to prevent the channel from matching subsequent
+responses with the recycled ident value.
+
+A remote attacker that completed a reconfiguration as the peer can
+replay a failure response with the stale ident, causing the kernel to
+match and destroy the already-established channel via
+l2cap_chan_del(chan, ECONNRESET).
+
+Clear chan->ident for all matching channels on success, and harden the
+failure path by using l2cap_chan_hold_unless_zero() consistent with
+other L2CAP handlers (l2cap_le_command_rej, __l2cap_get_chan_by_ident).
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 99297d8f2c1f34..83ea31926bd0f8 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -5466,14 +5466,20 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("result 0x%4.4x", result);
+
+- if (!result)
++ if (!result) {
++ list_for_each_entry(chan, &conn->chan_l, list) {
++ if (chan->ident == cmd->ident)
++ chan->ident = 0;
++ }
+ return 0;
++ }
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
+ if (chan->ident != cmd->ident)
+ continue;
+
+- l2cap_chan_hold(chan);
++ if (!l2cap_chan_hold_unless_zero(chan))
++ continue;
+ l2cap_chan_lock(chan);
+
+ l2cap_chan_del(chan, ECONNRESET);
+--
+2.53.0
+
--- /dev/null
+From cc27c20a01b88f545defdcdf3fe543d332ec7ffc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 May 2026 12:09:42 -0400
+Subject: Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 41c2713b204e6cb6a94587bc6bf6935107df5479 ]
+
+If dcid is received for an already-assigned destination CID the spec
+requires that both channels to be discarded, but calling l2cap_chan_del
+may invalidate the tmp cursor created by list_for_each_entry_safe and
+in fact it is the wrong procedure as the chan->dcid may be assigned
+previously it really needs to be disconnected.
+
+Calling l2cap_chan_clone directly may still lead to l2cap_chan_del so
+instead schedule l2cap_chan_timeout with delay 0 to close the channel
+asynchronously.
+
+Fixes: 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/l2cap_core.c | 27 ++++++++++++++++++++++-----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
+index 83ea31926bd0f8..27b5d459e1217c 100644
+--- a/net/bluetooth/l2cap_core.c
++++ b/net/bluetooth/l2cap_core.c
+@@ -5268,6 +5268,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ cmd_len -= sizeof(*rsp);
+
+ list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) {
++ struct l2cap_chan *orig;
+ u16 dcid;
+
+ if (chan->ident != cmd->ident ||
+@@ -5289,8 +5290,10 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+
+ BT_DBG("dcid[%d] 0x%4.4x", i, dcid);
+
++ orig = __l2cap_get_chan_by_dcid(conn, dcid);
++
+ /* Check if dcid is already in use */
+- if (dcid && __l2cap_get_chan_by_dcid(conn, dcid)) {
++ if (dcid && orig) {
+ /* If a device receives a
+ * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an
+ * already-assigned Destination CID, then both the
+@@ -5299,10 +5302,24 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,
+ */
+ l2cap_chan_del(chan, ECONNREFUSED);
+ l2cap_chan_unlock(chan);
+- chan = __l2cap_get_chan_by_dcid(conn, dcid);
+- l2cap_chan_lock(chan);
+- l2cap_chan_del(chan, ECONNRESET);
+- l2cap_chan_unlock(chan);
++
++ /* Check that the dcid channel mode is
++ * L2CAP_MODE_EXT_FLOWCTL since this procedure is only
++ * valid for that mode and shouldn't disconnect a dcid
++ * in other modes.
++ */
++ if (orig->mode == L2CAP_MODE_EXT_FLOWCTL) {
++ l2cap_chan_lock(orig);
++ /* Disconnect the original channel as it may be
++ * considered connected since dcid has already
++ * been assigned; don't call l2cap_chan_close
++ * directly since that could lead to
++ * l2cap_chan_del and then removing the channel
++ * from the list while we're iterating over it.
++ */
++ __set_chan_timer(orig, 0);
++ l2cap_chan_unlock(orig);
++ }
+ continue;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From e456d6c0731704887d708fcb72791b742b7f6683 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 21:33:19 +0200
+Subject: bonding: refuse to enslave CAN devices
+
+From: Oliver Hartkopp <socketcan@hartkopp.net>
+
+[ Upstream commit 8ba68464e4787b6a7ec938826e16124df20fd23d ]
+
+syzbot reported a kernel paging request crash in
+can_rx_unregister() inside net/can/af_can.c. The crash occurs
+because a virtual CAN device (vxcan) is being enslaved to a
+bonding master.
+
+During the enslavement process, the bonding driver mutates
+and modifies the network device states to fit an Ethernet-like
+aggregation model. However, CAN devices operate on a completely
+different Layer 2 architecture, relying on the CAN mid-layer
+private data structure (can_ml_priv) instead of standard
+Ethernet structures. Since bonding does not initialize or
+maintain these CAN structures, subsequent operations on the
+half-enslaved interface (such as closing associated sockets
+via isotp_release) lead to a null-pointer dereference when
+accessing the CAN receiver lists.
+
+Bonding CAN interfaces is architecturally invalid as CAN lacks
+MAC addresses, ARP capabilities, and standard Ethernet
+link-layer mechanisms. While generic loopback devices are
+blocked globally in net/core/dev.c, virtual CAN devices
+bypass this check because they do not carry the IFF_LOOPBACK
+flag, despite acting as local software-loopbacks.
+
+Fix this by explicitly blocking network devices of type
+ARPHRD_CAN from being enslaved at the very beginning of
+bond_enslave(). This prevents illegal state mutations,
+eliminates the resulting KASAN crashes, and avoids potential
+memory leaks from incomplete socket cleanups.
+
+As the CAN support has been added a long time after bonding
+the Fixes-tag points to the introduction of ARPHRD_CAN that
+would have needed a specific handling in bonding_main.c.
+
+Fixes: cd05acfe65ed ("[CAN]: Allocate protocol numbers for PF_CAN")
+Reported-by: syzbot+8ed98cbd0161632bce95@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=8ed98cbd0161632bce95
+Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
+Acked-by: Jay Vosburgh <jv@jvosburgh.net>
+Link: https://patch.msgid.link/20260526-bonding-candev-v1-1-ba1df400918a@hartkopp.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/bonding/bond_main.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index eb49ce486992de..d6a1e814878f28 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1892,6 +1892,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
+ struct sockaddr_storage ss;
+ int res = 0, i;
+
++ if (slave_dev->type == ARPHRD_CAN) {
++ BOND_NL_ERR(bond_dev, extack,
++ "CAN devices cannot be enslaved");
++ return -EPERM;
++ }
++
+ if (slave_dev->flags & IFF_MASTER &&
+ !netif_is_bond_master(slave_dev)) {
+ BOND_NL_ERR(bond_dev, extack,
+--
+2.53.0
+
--- /dev/null
+From 178c953d89bb7ce63cdd15e6f1e3a6bc32f7c5ad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 09:48:16 +0300
+Subject: bridge: Fix sleep in atomic context in netlink path
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 5eec4427b89c2fb2beac54920101e55a2f1c0c21 ]
+
+Since the introduction of the netlink configuration path for bridge
+ports in commit 25c71c75ac87 ("bridge: bridge port parameters over
+netlink"), br_setport() was always called with the bridge lock held
+around it. Back then this decision made sense: The bridge lock protects
+the STP state of the bridge and its ports and at that time the function
+only processed three STP related netlink attributes (cost, priority and
+state).
+
+Nowadays, br_setport() processes a lot more attributes and most of them
+do not need the bridge lock:
+
+* Bridge flags: Only require RTNL. Read locklessly by the data path.
+ Annotations can be added in net-next.
+
+* FDB port flushing: Only requires the FDB lock.
+
+* Multicast attributes: Only require the multicast lock.
+
+* Group forward mask: Only requires RTNL. Read locklessly by the data
+ path. Annotations can be added in net-next.
+
+* Backup port and NHID: Only require RTNL. Read locklessly by the data
+ path.
+
+This is a problem as the bridge calls dev_set_promiscuity() when certain
+bridge port flags change and this function can sleep since the commit
+cited below, resulting in a splat such as [1].
+
+Fix this by reducing the scope of the bridge lock and only take it when
+processing the three STP related attributes that require it. This is
+consistent with the multicast attributes where each attribute acquires
+the multicast lock instead of having one critical section for all
+relevant attributes.
+
+[1]
+BUG: sleeping function called from invalid context at net/core/dev_addr_lists.c:1262
+in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 356, name: bridge
+preempt_count: 201, expected: 0
+RCU nest depth: 0, expected: 0
+2 locks held by bridge/356:
+#0: ffffffff919473a0 (rtnl_mutex){+.+.}-{4:4}, at: rtnetlink_rcv_msg (net/core/rtnetlink.c:80 net/core/rtnetlink.c:7002)
+#1: ffff888115072d58 (&br->lock){+...}-{3:3}, at: br_setlink (./include/linux/spinlock.h:348 net/bridge/br_netlink.c:1117)
+Preemption disabled at:
+ 0x0
+Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+Call Trace:
+<TASK>
+dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
+__might_resched.cold (kernel/sched/core.c:9163)
+netif_rx_mode_run (net/core/dev_addr_lists.c:1262)
+netif_rx_mode_sync (net/core/dev_addr_lists.c:1428)
+dev_set_promiscuity (net/core/dev_api.c:289)
+br_manage_promisc (net/bridge/br_if.c:135 net/bridge/br_if.c:172)
+br_port_flags_change (net/bridge/br_if.c:242 net/bridge/br_if.c:747)
+br_setport (net/bridge/br_netlink.c:1000)
+br_setlink (net/bridge/br_netlink.c:1118)
+rtnl_bridge_setlink (net/core/rtnetlink.c:5572)
+rtnetlink_rcv_msg (net/core/rtnetlink.c:7005)
+netlink_rcv_skb (net/netlink/af_netlink.c:2550)
+netlink_unicast (net/netlink/af_netlink.c:1318 net/netlink/af_netlink.c:1344)
+netlink_sendmsg (net/netlink/af_netlink.c:1894)
+__sock_sendmsg (net/socket.c:787 (discriminator 4) net/socket.c:802 (discriminator 4))
+____sys_sendmsg (net/socket.c:2698)
+___sys_sendmsg (net/socket.c:2752)
+__sys_sendmsg (net/socket.c:2784)
+do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
+entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
+
+Fixes: 78cd408356fe ("net: add missing instance lock to dev_set_promiscuity")
+Reviewed-by: Nikolay Aleksandrov <nikolay@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260526064818.272516-2-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/br_netlink.c | 17 +++++++----------
+ 1 file changed, 7 insertions(+), 10 deletions(-)
+
+diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
+index 0264730938f4b2..2ad502bfbd55e5 100644
+--- a/net/bridge/br_netlink.c
++++ b/net/bridge/br_netlink.c
+@@ -1000,19 +1000,25 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[],
+ br_port_flags_change(p, changed_mask);
+
+ if (tb[IFLA_BRPORT_COST]) {
++ spin_lock_bh(&p->br->lock);
+ err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));
++ spin_unlock_bh(&p->br->lock);
+ if (err)
+ return err;
+ }
+
+ if (tb[IFLA_BRPORT_PRIORITY]) {
++ spin_lock_bh(&p->br->lock);
+ err = br_stp_set_port_priority(p, nla_get_u16(tb[IFLA_BRPORT_PRIORITY]));
++ spin_unlock_bh(&p->br->lock);
+ if (err)
+ return err;
+ }
+
+ if (tb[IFLA_BRPORT_STATE]) {
++ spin_lock_bh(&p->br->lock);
+ err = br_set_port_state(p, nla_get_u8(tb[IFLA_BRPORT_STATE]));
++ spin_unlock_bh(&p->br->lock);
+ if (err)
+ return err;
+ }
+@@ -1114,9 +1120,7 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlh, u16 flags,
+ if (err)
+ return err;
+
+- spin_lock_bh(&p->br->lock);
+ err = br_setport(p, tb, extack);
+- spin_unlock_bh(&p->br->lock);
+ } else {
+ /* Binary compatibility with old RSTP */
+ if (nla_len(protinfo) < sizeof(u8))
+@@ -1203,17 +1207,10 @@ static int br_port_slave_changelink(struct net_device *brdev,
+ struct nlattr *data[],
+ struct netlink_ext_ack *extack)
+ {
+- struct net_bridge *br = netdev_priv(brdev);
+- int ret;
+-
+ if (!data)
+ return 0;
+
+- spin_lock_bh(&br->lock);
+- ret = br_setport(br_port_get_rtnl(dev), data, extack);
+- spin_unlock_bh(&br->lock);
+-
+- return ret;
++ return br_setport(br_port_get_rtnl(dev), data, extack);
+ }
+
+ static int br_port_fill_slave_info(struct sk_buff *skb,
+--
+2.53.0
+
--- /dev/null
+From 1c6f20508c064b8161efaa8ba4f9ef3b551f5752 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 09:48:17 +0300
+Subject: bridge: Fix sleep in atomic context in sysfs path
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 6d34594cc619d0d4b07d5afcad8b5984f3526dcf ]
+
+Since the start of the git history, brport_store() always acquired the
+bridge lock. Back then this decision made sense: The bridge lock
+protects the STP state of the bridge and its ports and at that time the
+function was only used by two STP related attributes (cost and
+priority).
+
+Nowadays, brport_store() processes a lot more attributes and most of
+them do not need the bridge lock:
+
+* Bridge flags: Only require RTNL. Read locklessly by the data path.
+ Annotations can be added in net-next.
+
+* FDB port flushing: Only requires the FDB lock.
+
+* Multicast attributes: Only require the multicast lock.
+
+* Group forward mask: Only requires RTNL. Read locklessly by the data
+ path. Annotations can be added in net-next.
+
+* Backup port: Only requires RTNL. Read locklessly by the data path.
+
+This is a problem as the bridge calls dev_set_promiscuity() when certain
+bridge port flags change and this function can sleep since the commit
+cited below, resulting in a splat such as [1].
+
+Fix this by reducing the scope of the bridge lock and only take it when
+processing the two STP related attributes that require it. Remove the
+now stale comment from br_switchdev_set_port_flag(). The
+SWITCHDEV_F_DEFER flag can be removed in net-next.
+
+[1]
+BUG: sleeping function called from invalid context at net/core/dev_addr_lists.c:1262
+in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 372, name: bash
+preempt_count: 201, expected: 0
+RCU nest depth: 0, expected: 0
+5 locks held by bash/372:
+#0: ffff88810c51c3f0 (sb_writers#7){.+.+}-{0:0}, at: ksys_write (fs/read_write.c:740)
+#1: ffff888115ce9480 (&of->mutex){+.+.}-{4:4}, at: kernfs_fop_write_iter (fs/kernfs/file.c:343)
+#2: ffff88810b9fd330 (kn->active#37){.+.+}-{0:0}, at: kernfs_fop_write_iter (fs/kernfs/file.c:80 fs/kernfs/file.c:344)
+#3: ffffffffa59473a0 (rtnl_mutex){+.+.}-{4:4}, at: brport_store (net/bridge/br_sysfs_if.c:326)
+#4: ffff8881099d2d58 (&br->lock){+...}-{3:3}, at: brport_store (./include/linux/spinlock.h:348 net/bridge/br_sysfs_if.c:345)
+Preemption disabled at:
+ 0x0
+Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
+Call Trace:
+<TASK>
+dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
+__might_resched.cold (kernel/sched/core.c:9163)
+netif_rx_mode_run (net/core/dev_addr_lists.c:1262)
+netif_rx_mode_sync (net/core/dev_addr_lists.c:1428)
+dev_set_promiscuity (net/core/dev_api.c:289)
+br_manage_promisc (net/bridge/br_if.c:135 net/bridge/br_if.c:172)
+br_port_flags_change (net/bridge/br_if.c:242 net/bridge/br_if.c:747)
+store_learning (net/bridge/br_sysfs_if.c:79 net/bridge/br_sysfs_if.c:235)
+brport_store (net/bridge/br_sysfs_if.c:346)
+kernfs_fop_write_iter (fs/kernfs/file.c:352)
+new_sync_write (fs/read_write.c:595)
+vfs_write (fs/read_write.c:688)
+ksys_write (fs/read_write.c:740)
+do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
+entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
+
+Fixes: 78cd408356fe ("net: add missing instance lock to dev_set_promiscuity")
+Reviewed-by: Nikolay Aleksandrov <nikolay@nvidia.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260526064818.272516-3-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/br_switchdev.c | 1 -
+ net/bridge/br_sysfs_if.c | 30 ++++++++++++++++++++++--------
+ 2 files changed, 22 insertions(+), 9 deletions(-)
+
+diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
+index 4fac002922d22a..58257e9e9d30b6 100644
+--- a/net/bridge/br_switchdev.c
++++ b/net/bridge/br_switchdev.c
+@@ -99,7 +99,6 @@ int br_switchdev_set_port_flag(struct net_bridge_port *p,
+ attr.u.brport_flags.val = flags;
+ attr.u.brport_flags.mask = mask;
+
+- /* We run from atomic context here */
+ err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev,
+ &info.info, extack);
+ err = notifier_to_errno(err);
+diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
+index 1f57c36a7fc097..d6df81fa0d13fe 100644
+--- a/net/bridge/br_sysfs_if.c
++++ b/net/bridge/br_sysfs_if.c
+@@ -86,16 +86,34 @@ static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)
+ return sysfs_emit(buf, "%d\n", p->path_cost);
+ }
+
+-static BRPORT_ATTR(path_cost, 0644,
+- show_path_cost, br_stp_set_path_cost);
++static int store_path_cost(struct net_bridge_port *p, unsigned long v)
++{
++ int ret;
++
++ spin_lock_bh(&p->br->lock);
++ ret = br_stp_set_path_cost(p, v);
++ spin_unlock_bh(&p->br->lock);
++ return ret;
++}
++
++static BRPORT_ATTR(path_cost, 0644, show_path_cost, store_path_cost);
+
+ static ssize_t show_priority(struct net_bridge_port *p, char *buf)
+ {
+ return sysfs_emit(buf, "%d\n", p->priority);
+ }
+
+-static BRPORT_ATTR(priority, 0644,
+- show_priority, br_stp_set_port_priority);
++static int store_priority(struct net_bridge_port *p, unsigned long v)
++{
++ int ret;
++
++ spin_lock_bh(&p->br->lock);
++ ret = br_stp_set_port_priority(p, v);
++ spin_unlock_bh(&p->br->lock);
++ return ret;
++}
++
++static BRPORT_ATTR(priority, 0644, show_priority, store_priority);
+
+ static ssize_t show_designated_root(struct net_bridge_port *p, char *buf)
+ {
+@@ -334,17 +352,13 @@ static ssize_t brport_store(struct kobject *kobj,
+ ret = -ENOMEM;
+ goto out_unlock;
+ }
+- spin_lock_bh(&p->br->lock);
+ ret = brport_attr->store_raw(p, buf_copy);
+- spin_unlock_bh(&p->br->lock);
+ kfree(buf_copy);
+ } else if (brport_attr->store) {
+ val = simple_strtoul(buf, &endp, 0);
+ if (endp == buf)
+ goto out_unlock;
+- spin_lock_bh(&p->br->lock);
+ ret = brport_attr->store(p, val);
+- spin_unlock_bh(&p->br->lock);
+ }
+
+ if (!ret) {
+--
+2.53.0
+
--- /dev/null
+From 1b8694628317ca2d2a903b454e4aa534458f9c2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 20:14:57 +0800
+Subject: cxl/test: Update mock dev array before calling platform_device_add()
+
+From: Li Ming <ming.li@zohomail.com>
+
+[ Upstream commit d90f236f8b9e354848bd226f581db27755ab901d ]
+
+CXL test environment hits the following error sometimes.
+
+ cxl_mem mem9: endpoint7 failed probe
+
+All mock memdevs are platform firmware devices added by cxl_test module,
+and cxl_test module also provides a platform device driver for them to
+create a memdev device to CXL subsystem. cxl_test module uses
+cxl_rcd/mem_single/mem arrays to store different types of mock memdevs.
+CXL drivers calls registered mock functions for a mock memdev by
+checking if a given memdev is in these arrays.
+
+When cxl_test module adds these mock memdevs, it always calls
+platform_device_add() before adding them to a suitable mock memdev
+array. However, there is a small window where CXL drivers calls mock
+function for a added memdev before it added to a mock memdev array. In
+above case, cxl endpoint driver considers a added memdev was not a mock
+memdev, then calling devm_cxl_endpoint_decoders_setup() for it rather
+than mock_endpoint_decoders_setup().
+
+An appropriate solution is that adding a new mock device to a mock
+device array before calling platform_device_add() for it. It can
+guarantee the new mock device is visible to CXL subsystem.
+
+This patch introduces a new helped called cxl_mock_platform_device_add()
+to handle the issue, and uses the function for all mock devices addition.
+
+Fixes: 3a2b97b3210b ("cxl/test: Improve init-order fidelity relative to real-world systems")
+Signed-off-by: Li Ming <ming.li@zohomail.com>
+Tested-by: Alison Schofield <alison.schofield@intel.com>
+Reviewed-by: Alison Schofield <alison.schofield@intel.com>
+Link: https://patch.msgid.link/20260520121457.234404-1-ming.li@zohomail.com
+Signed-off-by: Dave Jiang <dave.jiang@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/cxl/test/cxl.c | 105 ++++++++++++++---------------------
+ 1 file changed, 43 insertions(+), 62 deletions(-)
+
+diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
+index 81e2aef3627a44..f4c26441fc41af 100644
+--- a/tools/testing/cxl/test/cxl.c
++++ b/tools/testing/cxl/test/cxl.c
+@@ -1144,6 +1144,23 @@ static void mock_companion(struct acpi_device *adev, struct device *dev)
+ #define SZ_64G (SZ_32G * 2)
+ #endif
+
++static int cxl_mock_platform_device_add(struct platform_device *pdev,
++ struct platform_device **ppdev)
++{
++ int rc;
++
++ if (ppdev)
++ *ppdev = pdev;
++ rc = platform_device_add(pdev);
++ if (rc) {
++ platform_device_put(pdev);
++ if (ppdev)
++ *ppdev = NULL;
++ }
++
++ return rc;
++}
++
+ static __init int cxl_rch_topo_init(void)
+ {
+ int rc, i;
+@@ -1158,13 +1175,10 @@ static __init int cxl_rch_topo_init(void)
+ goto err_bridge;
+
+ mock_companion(adev, &pdev->dev);
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_rch[i]);
++ if (rc)
+ goto err_bridge;
+- }
+
+- cxl_rch[i] = pdev;
+ mock_pci_bus[idx].bridge = &pdev->dev;
+ rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
+ "firmware_node");
+@@ -1216,13 +1230,10 @@ static __init int cxl_single_topo_init(void)
+ goto err_bridge;
+
+ mock_companion(adev, &pdev->dev);
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_hb_single[i]);
++ if (rc)
+ goto err_bridge;
+- }
+
+- cxl_hb_single[i] = pdev;
+ mock_pci_bus[i + NR_CXL_HOST_BRIDGES].bridge = &pdev->dev;
+ rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
+ "physical_node");
+@@ -1241,12 +1252,9 @@ static __init int cxl_single_topo_init(void)
+ goto err_port;
+ pdev->dev.parent = &bridge->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_root_single[i]);
++ if (rc)
+ goto err_port;
+- }
+- cxl_root_single[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_swu_single); i++) {
+@@ -1259,12 +1267,9 @@ static __init int cxl_single_topo_init(void)
+ goto err_uport;
+ pdev->dev.parent = &root_port->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_swu_single[i]);
++ if (rc)
+ goto err_uport;
+- }
+- cxl_swu_single[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_swd_single); i++) {
+@@ -1278,12 +1283,9 @@ static __init int cxl_single_topo_init(void)
+ goto err_dport;
+ pdev->dev.parent = &uport->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_swd_single[i]);
++ if (rc)
+ goto err_dport;
+- }
+- cxl_swd_single[i] = pdev;
+ }
+
+ return 0;
+@@ -1356,12 +1358,9 @@ static int cxl_mem_init(void)
+ pdev->dev.parent = &dport->dev;
+ set_dev_node(&pdev->dev, i % 2);
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_mem[i]);
++ if (rc)
+ goto err_mem;
+- }
+- cxl_mem[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_mem_single); i++) {
+@@ -1374,12 +1373,9 @@ static int cxl_mem_init(void)
+ pdev->dev.parent = &dport->dev;
+ set_dev_node(&pdev->dev, i % 2);
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_mem_single[i]);
++ if (rc)
+ goto err_single;
+- }
+- cxl_mem_single[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_rcd); i++) {
+@@ -1393,12 +1389,9 @@ static int cxl_mem_init(void)
+ pdev->dev.parent = &rch->dev;
+ set_dev_node(&pdev->dev, i % 2);
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_rcd[i]);
++ if (rc)
+ goto err_rcd;
+- }
+- cxl_rcd[i] = pdev;
+ }
+
+ return 0;
+@@ -1463,13 +1456,10 @@ static __init int cxl_test_init(void)
+ goto err_bridge;
+
+ mock_companion(adev, &pdev->dev);
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_host_bridge[i]);
++ if (rc)
+ goto err_bridge;
+- }
+
+- cxl_host_bridge[i] = pdev;
+ mock_pci_bus[i].bridge = &pdev->dev;
+ rc = sysfs_create_link(&pdev->dev.kobj, &pdev->dev.kobj,
+ "physical_node");
+@@ -1487,12 +1477,9 @@ static __init int cxl_test_init(void)
+ goto err_port;
+ pdev->dev.parent = &bridge->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_root_port[i]);
++ if (rc)
+ goto err_port;
+- }
+- cxl_root_port[i] = pdev;
+ }
+
+ BUILD_BUG_ON(ARRAY_SIZE(cxl_switch_uport) != ARRAY_SIZE(cxl_root_port));
+@@ -1505,12 +1492,9 @@ static __init int cxl_test_init(void)
+ goto err_uport;
+ pdev->dev.parent = &root_port->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_switch_uport[i]);
++ if (rc)
+ goto err_uport;
+- }
+- cxl_switch_uport[i] = pdev;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(cxl_switch_dport); i++) {
+@@ -1523,12 +1507,9 @@ static __init int cxl_test_init(void)
+ goto err_dport;
+ pdev->dev.parent = &uport->dev;
+
+- rc = platform_device_add(pdev);
+- if (rc) {
+- platform_device_put(pdev);
++ rc = cxl_mock_platform_device_add(pdev, &cxl_switch_dport[i]);
++ if (rc)
+ goto err_dport;
+- }
+- cxl_switch_dport[i] = pdev;
+ }
+
+ rc = cxl_single_topo_init();
+@@ -1546,9 +1527,9 @@ static __init int cxl_test_init(void)
+ mock_companion(&acpi0017_mock, &cxl_acpi->dev);
+ acpi0017_mock.dev.bus = &platform_bus_type;
+
+- rc = platform_device_add(cxl_acpi);
++ rc = cxl_mock_platform_device_add(cxl_acpi, NULL);
+ if (rc)
+- goto err_root;
++ goto err_rch;
+
+ rc = cxl_mem_init();
+ if (rc)
+--
+2.53.0
+
--- /dev/null
+From e1fc70f17d041e2f925e9ce9ac9e1151af5b103b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 09:45:23 +0200
+Subject: dpll: export __dpll_device_change_ntf() for use under dpll_lock
+
+From: Ivan Vecera <ivecera@redhat.com>
+
+[ Upstream commit 20040b2a3cb992f84d3db4c086b909eb9b906b31 ]
+
+Export __dpll_device_change_ntf() so that drivers can send device
+change notifications from within device callbacks, which are already
+called under dpll_lock. Using dpll_device_change_ntf() in that
+context would deadlock.
+
+Add lockdep_assert_held() to catch misuse without the lock held.
+
+Signed-off-by: Ivan Vecera <ivecera@redhat.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Link: https://patch.msgid.link/20260526074525.1451008-2-ivecera@redhat.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: d733f519f644 ("dpll: zl3073x: use __dpll_device_change_ntf() and remove change_work")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dpll/dpll_netlink.c | 13 +++++++++++--
+ include/linux/dpll.h | 1 +
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
+index 95ae786e98aab3..72aa5f4d5d3114 100644
+--- a/drivers/dpll/dpll_netlink.c
++++ b/drivers/dpll/dpll_netlink.c
+@@ -771,12 +771,21 @@ int dpll_device_delete_ntf(struct dpll_device *dpll)
+ return dpll_device_event_send(DPLL_CMD_DEVICE_DELETE_NTF, dpll);
+ }
+
+-static int
+-__dpll_device_change_ntf(struct dpll_device *dpll)
++/**
++ * __dpll_device_change_ntf - notify that the dpll device has been changed
++ * @dpll: registered dpll pointer
++ *
++ * Context: caller must hold dpll_lock. Suitable for use inside device
++ * callbacks which are already invoked under dpll_lock.
++ * Return: 0 if succeeds, error code otherwise.
++ */
++int __dpll_device_change_ntf(struct dpll_device *dpll)
+ {
++ lockdep_assert_held(&dpll_lock);
+ dpll_device_notify(dpll, DPLL_DEVICE_CHANGED);
+ return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll);
+ }
++EXPORT_SYMBOL_GPL(__dpll_device_change_ntf);
+
+ /**
+ * dpll_device_change_ntf - notify that the dpll device has been changed
+diff --git a/include/linux/dpll.h b/include/linux/dpll.h
+index 8f97120ee7b37d..a77d5741dd3932 100644
+--- a/include/linux/dpll.h
++++ b/include/linux/dpll.h
+@@ -274,6 +274,7 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
+ int dpll_pin_ref_sync_pair_add(struct dpll_pin *pin,
+ struct dpll_pin *ref_sync_pin);
+
++int __dpll_device_change_ntf(struct dpll_device *dpll);
+ int dpll_device_change_ntf(struct dpll_device *dpll);
+
+ int __dpll_pin_change_ntf(struct dpll_pin *pin);
+--
+2.53.0
+
--- /dev/null
+From 85afbb582fa268e65be2e196f1179b169301526a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Feb 2026 11:53:00 +0100
+Subject: dpll: zl3073x: add die temperature reporting for supported chips
+
+From: Ivan Vecera <ivecera@redhat.com>
+
+[ Upstream commit 3a97e02b3e91e4d40095ad9bb6e466d8d7c1a1bc ]
+
+Some zl3073x chip variants (0x1Exx, 0x2Exx and 0x3FC4) provide a die
+temperature status register with 0.1 C resolution.
+
+Add a ZL3073X_FLAG_DIE_TEMP chip flag to identify these variants and
+implement zl3073x_dpll_temp_get() as the dpll_device_ops.temp_get
+callback. The register value is converted from 0.1 C units to
+millidegrees as expected by the DPLL subsystem.
+
+To support per-instance ops selection, copy the base dpll_device_ops
+into struct zl3073x_dpll and conditionally set .temp_get during device
+registration based on the chip flag.
+
+Signed-off-by: Ivan Vecera <ivecera@redhat.com>
+Link: https://patch.msgid.link/20260227105300.710272-3-ivecera@redhat.com
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: d733f519f644 ("dpll: zl3073x: use __dpll_device_change_ntf() and remove change_work")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dpll/zl3073x/core.c | 22 +++++++++++-----------
+ drivers/dpll/zl3073x/core.h | 2 ++
+ drivers/dpll/zl3073x/dpll.c | 28 +++++++++++++++++++++++++---
+ drivers/dpll/zl3073x/dpll.h | 2 ++
+ drivers/dpll/zl3073x/regs.h | 2 ++
+ 5 files changed, 42 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/dpll/zl3073x/core.c b/drivers/dpll/zl3073x/core.c
+index c8af3430104505..10e036ccf08f05 100644
+--- a/drivers/dpll/zl3073x/core.c
++++ b/drivers/dpll/zl3073x/core.c
+@@ -30,18 +30,18 @@ static const struct zl3073x_chip_info zl3073x_chip_ids[] = {
+ ZL_CHIP_INFO(0x0E95, 3, ZL3073X_FLAG_REF_PHASE_COMP_32),
+ ZL_CHIP_INFO(0x0E96, 4, ZL3073X_FLAG_REF_PHASE_COMP_32),
+ ZL_CHIP_INFO(0x0E97, 5, ZL3073X_FLAG_REF_PHASE_COMP_32),
+- ZL_CHIP_INFO(0x1E93, 1, 0),
+- ZL_CHIP_INFO(0x1E94, 2, 0),
+- ZL_CHIP_INFO(0x1E95, 3, 0),
+- ZL_CHIP_INFO(0x1E96, 4, 0),
+- ZL_CHIP_INFO(0x1E97, 5, 0),
++ ZL_CHIP_INFO(0x1E93, 1, ZL3073X_FLAG_DIE_TEMP),
++ ZL_CHIP_INFO(0x1E94, 2, ZL3073X_FLAG_DIE_TEMP),
++ ZL_CHIP_INFO(0x1E95, 3, ZL3073X_FLAG_DIE_TEMP),
++ ZL_CHIP_INFO(0x1E96, 4, ZL3073X_FLAG_DIE_TEMP),
++ ZL_CHIP_INFO(0x1E97, 5, ZL3073X_FLAG_DIE_TEMP),
+ ZL_CHIP_INFO(0x1F60, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
+- ZL_CHIP_INFO(0x2E93, 1, 0),
+- ZL_CHIP_INFO(0x2E94, 2, 0),
+- ZL_CHIP_INFO(0x2E95, 3, 0),
+- ZL_CHIP_INFO(0x2E96, 4, 0),
+- ZL_CHIP_INFO(0x2E97, 5, 0),
+- ZL_CHIP_INFO(0x3FC4, 2, 0),
++ ZL_CHIP_INFO(0x2E93, 1, ZL3073X_FLAG_DIE_TEMP),
++ ZL_CHIP_INFO(0x2E94, 2, ZL3073X_FLAG_DIE_TEMP),
++ ZL_CHIP_INFO(0x2E95, 3, ZL3073X_FLAG_DIE_TEMP),
++ ZL_CHIP_INFO(0x2E96, 4, ZL3073X_FLAG_DIE_TEMP),
++ ZL_CHIP_INFO(0x2E97, 5, ZL3073X_FLAG_DIE_TEMP),
++ ZL_CHIP_INFO(0x3FC4, 2, ZL3073X_FLAG_DIE_TEMP),
+ };
+
+ #define ZL_RANGE_OFFSET 0x80
+diff --git a/drivers/dpll/zl3073x/core.h b/drivers/dpll/zl3073x/core.h
+index fde5c8371fbd28..b6f22ee1c0bd1b 100644
+--- a/drivers/dpll/zl3073x/core.h
++++ b/drivers/dpll/zl3073x/core.h
+@@ -32,11 +32,13 @@ struct zl3073x_dpll;
+
+ enum zl3073x_flags {
+ ZL3073X_FLAG_REF_PHASE_COMP_32_BIT,
++ ZL3073X_FLAG_DIE_TEMP_BIT,
+ ZL3073X_FLAGS_NBITS /* must be last */
+ };
+
+ #define __ZL3073X_FLAG(name) BIT(ZL3073X_FLAG_ ## name ## _BIT)
+ #define ZL3073X_FLAG_REF_PHASE_COMP_32 __ZL3073X_FLAG(REF_PHASE_COMP_32)
++#define ZL3073X_FLAG_DIE_TEMP __ZL3073X_FLAG(DIE_TEMP)
+
+ /**
+ * struct zl3073x_chip_info - chip variant identification
+diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
+index aaa14ea5e670fd..c201c974a7f9a4 100644
+--- a/drivers/dpll/zl3073x/dpll.c
++++ b/drivers/dpll/zl3073x/dpll.c
+@@ -1065,6 +1065,25 @@ zl3073x_dpll_output_pin_state_on_dpll_get(const struct dpll_pin *dpll_pin,
+ return 0;
+ }
+
++static int
++zl3073x_dpll_temp_get(const struct dpll_device *dpll, void *dpll_priv,
++ s32 *temp, struct netlink_ext_ack *extack)
++{
++ struct zl3073x_dpll *zldpll = dpll_priv;
++ struct zl3073x_dev *zldev = zldpll->dev;
++ u16 val;
++ int rc;
++
++ rc = zl3073x_read_u16(zldev, ZL_REG_DIE_TEMP_STATUS, &val);
++ if (rc)
++ return rc;
++
++ /* Register value is in units of 0.1 C, convert to millidegrees */
++ *temp = (s16)val * 100;
++
++ return 0;
++}
++
+ static int
+ zl3073x_dpll_lock_status_get(const struct dpll_device *dpll, void *dpll_priv,
+ enum dpll_lock_status *status,
+@@ -1671,6 +1690,10 @@ zl3073x_dpll_device_register(struct zl3073x_dpll *zldpll)
+ zldpll->forced_ref = FIELD_GET(ZL_DPLL_MODE_REFSEL_REF,
+ dpll_mode_refsel);
+
++ zldpll->ops = zl3073x_dpll_device_ops;
++ if (zldev->info->flags & ZL3073X_FLAG_DIE_TEMP)
++ zldpll->ops.temp_get = zl3073x_dpll_temp_get;
++
+ zldpll->dpll_dev = dpll_device_get(zldev->clock_id, zldpll->id,
+ THIS_MODULE, &zldpll->tracker);
+ if (IS_ERR(zldpll->dpll_dev)) {
+@@ -1682,7 +1705,7 @@ zl3073x_dpll_device_register(struct zl3073x_dpll *zldpll)
+
+ rc = dpll_device_register(zldpll->dpll_dev,
+ zl3073x_prop_dpll_type_get(zldev, zldpll->id),
+- &zl3073x_dpll_device_ops, zldpll);
++ &zldpll->ops, zldpll);
+ if (rc) {
+ dpll_device_put(zldpll->dpll_dev, &zldpll->tracker);
+ zldpll->dpll_dev = NULL;
+@@ -1705,8 +1728,7 @@ zl3073x_dpll_device_unregister(struct zl3073x_dpll *zldpll)
+
+ cancel_work_sync(&zldpll->change_work);
+
+- dpll_device_unregister(zldpll->dpll_dev, &zl3073x_dpll_device_ops,
+- zldpll);
++ dpll_device_unregister(zldpll->dpll_dev, &zldpll->ops, zldpll);
+ dpll_device_put(zldpll->dpll_dev, &zldpll->tracker);
+ zldpll->dpll_dev = NULL;
+ }
+diff --git a/drivers/dpll/zl3073x/dpll.h b/drivers/dpll/zl3073x/dpll.h
+index c65c798c37927f..278a24f357c9bd 100644
+--- a/drivers/dpll/zl3073x/dpll.h
++++ b/drivers/dpll/zl3073x/dpll.h
+@@ -17,6 +17,7 @@
+ * @forced_ref: selected reference in forced reference lock mode
+ * @check_count: periodic check counter
+ * @phase_monitor: is phase offset monitor enabled
++ * @ops: DPLL device operations for this instance
+ * @dpll_dev: pointer to registered DPLL device
+ * @tracker: tracking object for the acquired reference
+ * @lock_status: last saved DPLL lock status
+@@ -31,6 +32,7 @@ struct zl3073x_dpll {
+ u8 forced_ref;
+ u8 check_count;
+ bool phase_monitor;
++ struct dpll_device_ops ops;
+ struct dpll_device *dpll_dev;
+ dpll_tracker tracker;
+ enum dpll_lock_status lock_status;
+diff --git a/drivers/dpll/zl3073x/regs.h b/drivers/dpll/zl3073x/regs.h
+index 5573d7188406bb..19c598daa784ca 100644
+--- a/drivers/dpll/zl3073x/regs.h
++++ b/drivers/dpll/zl3073x/regs.h
+@@ -78,6 +78,8 @@
+ #define ZL_REG_RESET_STATUS ZL_REG(0, 0x18, 1)
+ #define ZL_REG_RESET_STATUS_RESET BIT(0)
+
++#define ZL_REG_DIE_TEMP_STATUS ZL_REG(0, 0x44, 2)
++
+ /*************************
+ * Register Page 2, Status
+ *************************/
+--
+2.53.0
+
--- /dev/null
+From 3dac0b76c78970a25972d9e63870f94dbfed9ba6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 27 Feb 2026 11:52:59 +0100
+Subject: dpll: zl3073x: detect DPLL channel count from chip ID at runtime
+
+From: Ivan Vecera <ivecera@redhat.com>
+
+[ Upstream commit 4845f2fff730f0cdf8f7fe6401c8b871891cf1cb ]
+
+Replace the five per-variant zl3073x_chip_info structures and their
+exported symbol definitions with a single consolidated chip ID lookup
+table. The chip variant is now detected at runtime by reading the chip
+ID register from hardware and looking it up in the table, rather than
+being selected at compile time via the bus driver match data.
+
+Repurpose struct zl3073x_chip_info to hold a single chip ID, its
+channel count, and a flags field. Introduce enum zl3073x_flags with
+ZL3073X_FLAG_REF_PHASE_COMP_32 to replace the chip_id switch statement
+in zl3073x_dev_is_ref_phase_comp_32bit(). Store a pointer to the
+detected chip_info entry in struct zl3073x_dev for runtime access.
+
+This simplifies the bus drivers by removing per-variant .data and
+.driver_data references from the I2C/SPI match tables, and makes
+adding support for new chip variants a single-line table addition.
+
+Signed-off-by: Ivan Vecera <ivecera@redhat.com>
+Link: https://patch.msgid.link/20260227105300.710272-2-ivecera@redhat.com
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: d733f519f644 ("dpll: zl3073x: use __dpll_device_change_ntf() and remove change_work")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dpll/zl3073x/core.c | 118 ++++++++++--------------------------
+ drivers/dpll/zl3073x/core.h | 57 +++++++++--------
+ drivers/dpll/zl3073x/i2c.c | 37 ++++-------
+ drivers/dpll/zl3073x/spi.c | 37 ++++-------
+ 4 files changed, 82 insertions(+), 167 deletions(-)
+
+diff --git a/drivers/dpll/zl3073x/core.c b/drivers/dpll/zl3073x/core.c
+index 37f3c33570eef2..c8af3430104505 100644
+--- a/drivers/dpll/zl3073x/core.c
++++ b/drivers/dpll/zl3073x/core.c
+@@ -20,79 +20,30 @@
+ #include "dpll.h"
+ #include "regs.h"
+
+-/* Chip IDs for zl30731 */
+-static const u16 zl30731_ids[] = {
+- 0x0E93,
+- 0x1E93,
+- 0x2E93,
++#define ZL_CHIP_INFO(_id, _nchannels, _flags) \
++ { .id = (_id), .num_channels = (_nchannels), .flags = (_flags) }
++
++static const struct zl3073x_chip_info zl3073x_chip_ids[] = {
++ ZL_CHIP_INFO(0x0E30, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
++ ZL_CHIP_INFO(0x0E93, 1, ZL3073X_FLAG_REF_PHASE_COMP_32),
++ ZL_CHIP_INFO(0x0E94, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
++ ZL_CHIP_INFO(0x0E95, 3, ZL3073X_FLAG_REF_PHASE_COMP_32),
++ ZL_CHIP_INFO(0x0E96, 4, ZL3073X_FLAG_REF_PHASE_COMP_32),
++ ZL_CHIP_INFO(0x0E97, 5, ZL3073X_FLAG_REF_PHASE_COMP_32),
++ ZL_CHIP_INFO(0x1E93, 1, 0),
++ ZL_CHIP_INFO(0x1E94, 2, 0),
++ ZL_CHIP_INFO(0x1E95, 3, 0),
++ ZL_CHIP_INFO(0x1E96, 4, 0),
++ ZL_CHIP_INFO(0x1E97, 5, 0),
++ ZL_CHIP_INFO(0x1F60, 2, ZL3073X_FLAG_REF_PHASE_COMP_32),
++ ZL_CHIP_INFO(0x2E93, 1, 0),
++ ZL_CHIP_INFO(0x2E94, 2, 0),
++ ZL_CHIP_INFO(0x2E95, 3, 0),
++ ZL_CHIP_INFO(0x2E96, 4, 0),
++ ZL_CHIP_INFO(0x2E97, 5, 0),
++ ZL_CHIP_INFO(0x3FC4, 2, 0),
+ };
+
+-const struct zl3073x_chip_info zl30731_chip_info = {
+- .ids = zl30731_ids,
+- .num_ids = ARRAY_SIZE(zl30731_ids),
+- .num_channels = 1,
+-};
+-EXPORT_SYMBOL_NS_GPL(zl30731_chip_info, "ZL3073X");
+-
+-/* Chip IDs for zl30732 */
+-static const u16 zl30732_ids[] = {
+- 0x0E30,
+- 0x0E94,
+- 0x1E94,
+- 0x1F60,
+- 0x2E94,
+- 0x3FC4,
+-};
+-
+-const struct zl3073x_chip_info zl30732_chip_info = {
+- .ids = zl30732_ids,
+- .num_ids = ARRAY_SIZE(zl30732_ids),
+- .num_channels = 2,
+-};
+-EXPORT_SYMBOL_NS_GPL(zl30732_chip_info, "ZL3073X");
+-
+-/* Chip IDs for zl30733 */
+-static const u16 zl30733_ids[] = {
+- 0x0E95,
+- 0x1E95,
+- 0x2E95,
+-};
+-
+-const struct zl3073x_chip_info zl30733_chip_info = {
+- .ids = zl30733_ids,
+- .num_ids = ARRAY_SIZE(zl30733_ids),
+- .num_channels = 3,
+-};
+-EXPORT_SYMBOL_NS_GPL(zl30733_chip_info, "ZL3073X");
+-
+-/* Chip IDs for zl30734 */
+-static const u16 zl30734_ids[] = {
+- 0x0E96,
+- 0x1E96,
+- 0x2E96,
+-};
+-
+-const struct zl3073x_chip_info zl30734_chip_info = {
+- .ids = zl30734_ids,
+- .num_ids = ARRAY_SIZE(zl30734_ids),
+- .num_channels = 4,
+-};
+-EXPORT_SYMBOL_NS_GPL(zl30734_chip_info, "ZL3073X");
+-
+-/* Chip IDs for zl30735 */
+-static const u16 zl30735_ids[] = {
+- 0x0E97,
+- 0x1E97,
+- 0x2E97,
+-};
+-
+-const struct zl3073x_chip_info zl30735_chip_info = {
+- .ids = zl30735_ids,
+- .num_ids = ARRAY_SIZE(zl30735_ids),
+- .num_channels = 5,
+-};
+-EXPORT_SYMBOL_NS_GPL(zl30735_chip_info, "ZL3073X");
+-
+ #define ZL_RANGE_OFFSET 0x80
+ #define ZL_PAGE_SIZE 0x80
+ #define ZL_NUM_PAGES 256
+@@ -942,7 +893,7 @@ static void zl3073x_dev_dpll_fini(void *ptr)
+ }
+
+ static int
+-zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
++zl3073x_devm_dpll_init(struct zl3073x_dev *zldev)
+ {
+ struct kthread_worker *kworker;
+ struct zl3073x_dpll *zldpll;
+@@ -952,7 +903,7 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
+ INIT_LIST_HEAD(&zldev->dplls);
+
+ /* Allocate all DPLLs */
+- for (i = 0; i < num_dplls; i++) {
++ for (i = 0; i < zldev->info->num_channels; i++) {
+ zldpll = zl3073x_dpll_alloc(zldev, i);
+ if (IS_ERR(zldpll)) {
+ dev_err_probe(zldev->dev, PTR_ERR(zldpll),
+@@ -992,14 +943,12 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
+ /**
+ * zl3073x_dev_probe - initialize zl3073x device
+ * @zldev: pointer to zl3073x device
+- * @chip_info: chip info based on compatible
+ *
+ * Common initialization of zl3073x device structure.
+ *
+ * Returns: 0 on success, <0 on error
+ */
+-int zl3073x_dev_probe(struct zl3073x_dev *zldev,
+- const struct zl3073x_chip_info *chip_info)
++int zl3073x_dev_probe(struct zl3073x_dev *zldev)
+ {
+ u16 id, revision, fw_ver;
+ unsigned int i;
+@@ -1011,18 +960,17 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev,
+ if (rc)
+ return rc;
+
+- /* Check it matches */
+- for (i = 0; i < chip_info->num_ids; i++) {
+- if (id == chip_info->ids[i])
++ /* Detect chip variant */
++ for (i = 0; i < ARRAY_SIZE(zl3073x_chip_ids); i++) {
++ if (zl3073x_chip_ids[i].id == id)
+ break;
+ }
+
+- if (i == chip_info->num_ids) {
++ if (i == ARRAY_SIZE(zl3073x_chip_ids))
+ return dev_err_probe(zldev->dev, -ENODEV,
+- "Unknown or non-match chip ID: 0x%0x\n",
+- id);
+- }
+- zldev->chip_id = id;
++ "Unknown chip ID: 0x%04x\n", id);
++
++ zldev->info = &zl3073x_chip_ids[i];
+
+ /* Read revision, firmware version and custom config version */
+ rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision);
+@@ -1061,7 +1009,7 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev,
+ "Failed to initialize mutex\n");
+
+ /* Register DPLL channels */
+- rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels);
++ rc = zl3073x_devm_dpll_init(zldev);
+ if (rc)
+ return rc;
+
+diff --git a/drivers/dpll/zl3073x/core.h b/drivers/dpll/zl3073x/core.h
+index fd2af3c62a7d5c..fde5c8371fbd28 100644
+--- a/drivers/dpll/zl3073x/core.h
++++ b/drivers/dpll/zl3073x/core.h
+@@ -30,12 +30,32 @@ struct zl3073x_dpll;
+ #define ZL3073X_NUM_PINS (ZL3073X_NUM_INPUT_PINS + \
+ ZL3073X_NUM_OUTPUT_PINS)
+
++enum zl3073x_flags {
++ ZL3073X_FLAG_REF_PHASE_COMP_32_BIT,
++ ZL3073X_FLAGS_NBITS /* must be last */
++};
++
++#define __ZL3073X_FLAG(name) BIT(ZL3073X_FLAG_ ## name ## _BIT)
++#define ZL3073X_FLAG_REF_PHASE_COMP_32 __ZL3073X_FLAG(REF_PHASE_COMP_32)
++
++/**
++ * struct zl3073x_chip_info - chip variant identification
++ * @id: chip ID
++ * @num_channels: number of DPLL channels supported by this variant
++ * @flags: chip variant flags
++ */
++struct zl3073x_chip_info {
++ u16 id;
++ u8 num_channels;
++ unsigned long flags;
++};
++
+ /**
+ * struct zl3073x_dev - zl3073x device
+ * @dev: pointer to device
+ * @regmap: regmap to access device registers
++ * @info: detected chip info
+ * @multiop_lock: to serialize multiple register operations
+- * @chip_id: chip ID read from hardware
+ * @ref: array of input references' invariants
+ * @out: array of outs' invariants
+ * @synth: array of synths' invariants
+@@ -46,10 +66,10 @@ struct zl3073x_dpll;
+ * @phase_avg_factor: phase offset measurement averaging factor
+ */
+ struct zl3073x_dev {
+- struct device *dev;
+- struct regmap *regmap;
+- struct mutex multiop_lock;
+- u16 chip_id;
++ struct device *dev;
++ struct regmap *regmap;
++ const struct zl3073x_chip_info *info;
++ struct mutex multiop_lock;
+
+ /* Invariants */
+ struct zl3073x_ref ref[ZL3073X_NUM_REFS];
+@@ -68,22 +88,10 @@ struct zl3073x_dev {
+ u8 phase_avg_factor;
+ };
+
+-struct zl3073x_chip_info {
+- const u16 *ids;
+- size_t num_ids;
+- int num_channels;
+-};
+-
+-extern const struct zl3073x_chip_info zl30731_chip_info;
+-extern const struct zl3073x_chip_info zl30732_chip_info;
+-extern const struct zl3073x_chip_info zl30733_chip_info;
+-extern const struct zl3073x_chip_info zl30734_chip_info;
+-extern const struct zl3073x_chip_info zl30735_chip_info;
+ extern const struct regmap_config zl3073x_regmap_config;
+
+ struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev);
+-int zl3073x_dev_probe(struct zl3073x_dev *zldev,
+- const struct zl3073x_chip_info *chip_info);
++int zl3073x_dev_probe(struct zl3073x_dev *zldev);
+
+ int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full);
+ void zl3073x_dev_stop(struct zl3073x_dev *zldev);
+@@ -158,18 +166,7 @@ int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel);
+ static inline bool
+ zl3073x_dev_is_ref_phase_comp_32bit(struct zl3073x_dev *zldev)
+ {
+- switch (zldev->chip_id) {
+- case 0x0E30:
+- case 0x0E93:
+- case 0x0E94:
+- case 0x0E95:
+- case 0x0E96:
+- case 0x0E97:
+- case 0x1F60:
+- return true;
+- default:
+- return false;
+- }
++ return zldev->info->flags & ZL3073X_FLAG_REF_PHASE_COMP_32;
+ }
+
+ static inline bool
+diff --git a/drivers/dpll/zl3073x/i2c.c b/drivers/dpll/zl3073x/i2c.c
+index 7bbfdd4ed8671d..979df85826abcc 100644
+--- a/drivers/dpll/zl3073x/i2c.c
++++ b/drivers/dpll/zl3073x/i2c.c
+@@ -22,40 +22,25 @@ static int zl3073x_i2c_probe(struct i2c_client *client)
+ return dev_err_probe(dev, PTR_ERR(zldev->regmap),
+ "Failed to initialize regmap\n");
+
+- return zl3073x_dev_probe(zldev, i2c_get_match_data(client));
++ return zl3073x_dev_probe(zldev);
+ }
+
+ static const struct i2c_device_id zl3073x_i2c_id[] = {
+- {
+- .name = "zl30731",
+- .driver_data = (kernel_ulong_t)&zl30731_chip_info,
+- },
+- {
+- .name = "zl30732",
+- .driver_data = (kernel_ulong_t)&zl30732_chip_info,
+- },
+- {
+- .name = "zl30733",
+- .driver_data = (kernel_ulong_t)&zl30733_chip_info,
+- },
+- {
+- .name = "zl30734",
+- .driver_data = (kernel_ulong_t)&zl30734_chip_info,
+- },
+- {
+- .name = "zl30735",
+- .driver_data = (kernel_ulong_t)&zl30735_chip_info,
+- },
++ { "zl30731" },
++ { "zl30732" },
++ { "zl30733" },
++ { "zl30734" },
++ { "zl30735" },
+ { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(i2c, zl3073x_i2c_id);
+
+ static const struct of_device_id zl3073x_i2c_of_match[] = {
+- { .compatible = "microchip,zl30731", .data = &zl30731_chip_info },
+- { .compatible = "microchip,zl30732", .data = &zl30732_chip_info },
+- { .compatible = "microchip,zl30733", .data = &zl30733_chip_info },
+- { .compatible = "microchip,zl30734", .data = &zl30734_chip_info },
+- { .compatible = "microchip,zl30735", .data = &zl30735_chip_info },
++ { .compatible = "microchip,zl30731" },
++ { .compatible = "microchip,zl30732" },
++ { .compatible = "microchip,zl30733" },
++ { .compatible = "microchip,zl30734" },
++ { .compatible = "microchip,zl30735" },
+ { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, zl3073x_i2c_of_match);
+diff --git a/drivers/dpll/zl3073x/spi.c b/drivers/dpll/zl3073x/spi.c
+index af901b4d6dda06..f024f42b78d05f 100644
+--- a/drivers/dpll/zl3073x/spi.c
++++ b/drivers/dpll/zl3073x/spi.c
+@@ -22,40 +22,25 @@ static int zl3073x_spi_probe(struct spi_device *spi)
+ return dev_err_probe(dev, PTR_ERR(zldev->regmap),
+ "Failed to initialize regmap\n");
+
+- return zl3073x_dev_probe(zldev, spi_get_device_match_data(spi));
++ return zl3073x_dev_probe(zldev);
+ }
+
+ static const struct spi_device_id zl3073x_spi_id[] = {
+- {
+- .name = "zl30731",
+- .driver_data = (kernel_ulong_t)&zl30731_chip_info
+- },
+- {
+- .name = "zl30732",
+- .driver_data = (kernel_ulong_t)&zl30732_chip_info,
+- },
+- {
+- .name = "zl30733",
+- .driver_data = (kernel_ulong_t)&zl30733_chip_info,
+- },
+- {
+- .name = "zl30734",
+- .driver_data = (kernel_ulong_t)&zl30734_chip_info,
+- },
+- {
+- .name = "zl30735",
+- .driver_data = (kernel_ulong_t)&zl30735_chip_info,
+- },
++ { "zl30731" },
++ { "zl30732" },
++ { "zl30733" },
++ { "zl30734" },
++ { "zl30735" },
+ { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(spi, zl3073x_spi_id);
+
+ static const struct of_device_id zl3073x_spi_of_match[] = {
+- { .compatible = "microchip,zl30731", .data = &zl30731_chip_info },
+- { .compatible = "microchip,zl30732", .data = &zl30732_chip_info },
+- { .compatible = "microchip,zl30733", .data = &zl30733_chip_info },
+- { .compatible = "microchip,zl30734", .data = &zl30734_chip_info },
+- { .compatible = "microchip,zl30735", .data = &zl30735_chip_info },
++ { .compatible = "microchip,zl30731" },
++ { .compatible = "microchip,zl30732" },
++ { .compatible = "microchip,zl30733" },
++ { .compatible = "microchip,zl30734" },
++ { .compatible = "microchip,zl30735" },
+ { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, zl3073x_spi_of_match);
+--
+2.53.0
+
--- /dev/null
+From 9087e846d722a4fba9f263ff9430a9f19be5c7cc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 09:45:24 +0200
+Subject: dpll: zl3073x: use __dpll_device_change_ntf() and remove change_work
+
+From: Ivan Vecera <ivecera@redhat.com>
+
+[ Upstream commit d733f519f6443540f8359461a34e3b0042099bbe ]
+
+The change_work was introduced to send device change notifications
+from DPLL device callbacks without deadlocking on dpll_lock, since
+the callbacks are already invoked under that lock. Now that
+__dpll_device_change_ntf() is exported for callers that already
+hold dpll_lock, use it directly and remove the change_work
+infrastructure entirely.
+
+This eliminates a race condition where change_work could be
+re-scheduled after cancel_work_sync() during device teardown,
+potentially causing the handler to dereference a freed or NULL
+dpll_dev pointer.
+
+Fixes: 9363b4837659 ("dpll: zl3073x: Allow to configure phase offset averaging factor")
+Signed-off-by: Ivan Vecera <ivecera@redhat.com>
+Link: https://patch.msgid.link/20260526074525.1451008-3-ivecera@redhat.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dpll/zl3073x/dpll.c | 26 +++++++++-----------------
+ drivers/dpll/zl3073x/dpll.h | 2 --
+ 2 files changed, 9 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c
+index c201c974a7f9a4..70c91948c7da8d 100644
+--- a/drivers/dpll/zl3073x/dpll.c
++++ b/drivers/dpll/zl3073x/dpll.c
+@@ -1193,15 +1193,6 @@ zl3073x_dpll_phase_offset_avg_factor_get(const struct dpll_device *dpll,
+ return 0;
+ }
+
+-static void
+-zl3073x_dpll_change_work(struct work_struct *work)
+-{
+- struct zl3073x_dpll *zldpll;
+-
+- zldpll = container_of(work, struct zl3073x_dpll, change_work);
+- dpll_device_change_ntf(zldpll->dpll_dev);
+-}
+-
+ static int
+ zl3073x_dpll_phase_offset_avg_factor_set(const struct dpll_device *dpll,
+ void *dpll_priv, u32 factor,
+@@ -1227,8 +1218,10 @@ zl3073x_dpll_phase_offset_avg_factor_set(const struct dpll_device *dpll,
+ * we have to send a notification for other DPLL devices.
+ */
+ list_for_each_entry(item, &zldpll->dev->dplls, list) {
+- if (item != zldpll)
+- schedule_work(&item->change_work);
++ struct dpll_device *dpll_dev = READ_ONCE(item->dpll_dev);
++
++ if (item != zldpll && dpll_dev)
++ __dpll_device_change_ntf(dpll_dev);
+ }
+
+ return 0;
+@@ -1724,13 +1717,13 @@ zl3073x_dpll_device_register(struct zl3073x_dpll *zldpll)
+ static void
+ zl3073x_dpll_device_unregister(struct zl3073x_dpll *zldpll)
+ {
+- WARN(!zldpll->dpll_dev, "DPLL device is not registered\n");
++ struct dpll_device *dpll_dev = READ_ONCE(zldpll->dpll_dev);
+
+- cancel_work_sync(&zldpll->change_work);
++ WARN(!dpll_dev, "DPLL device is not registered\n");
+
+- dpll_device_unregister(zldpll->dpll_dev, &zldpll->ops, zldpll);
+- dpll_device_put(zldpll->dpll_dev, &zldpll->tracker);
+- zldpll->dpll_dev = NULL;
++ WRITE_ONCE(zldpll->dpll_dev, NULL);
++ dpll_device_unregister(dpll_dev, &zldpll->ops, zldpll);
++ dpll_device_put(dpll_dev, &zldpll->tracker);
+ }
+
+ /**
+@@ -1976,7 +1969,6 @@ zl3073x_dpll_alloc(struct zl3073x_dev *zldev, u8 ch)
+ zldpll->dev = zldev;
+ zldpll->id = ch;
+ INIT_LIST_HEAD(&zldpll->pins);
+- INIT_WORK(&zldpll->change_work, zl3073x_dpll_change_work);
+
+ return zldpll;
+ }
+diff --git a/drivers/dpll/zl3073x/dpll.h b/drivers/dpll/zl3073x/dpll.h
+index 278a24f357c9bd..241253212f7d57 100644
+--- a/drivers/dpll/zl3073x/dpll.h
++++ b/drivers/dpll/zl3073x/dpll.h
+@@ -22,7 +22,6 @@
+ * @tracker: tracking object for the acquired reference
+ * @lock_status: last saved DPLL lock status
+ * @pins: list of pins
+- * @change_work: device change notification work
+ */
+ struct zl3073x_dpll {
+ struct list_head list;
+@@ -37,7 +36,6 @@ struct zl3073x_dpll {
+ dpll_tracker tracker;
+ enum dpll_lock_status lock_status;
+ struct list_head pins;
+- struct work_struct change_work;
+ };
+
+ struct zl3073x_dpll *zl3073x_dpll_alloc(struct zl3073x_dev *zldev, u8 ch);
+--
+2.53.0
+
--- /dev/null
+From 1306c5b24b5b65cb690ad7ce8f3be661f2c1b5aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 16 Apr 2026 18:37:44 +0200
+Subject: drm/i915/aux: use polling when irqs are unavailable
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Michał Grzelak <michal.grzelak@intel.com>
+
+[ Upstream commit 202e77cf2e839e1adc804433322dc5c9ee511c9f ]
+
+PTL with physically disconnected display was observed to have 40s longer
+execution time when testing xe_fault_injection@xe_guc_mmio_send_recv.
+The issue has not been seen when reverting commit 40a9f77a28fa ("Revert
+"drm/i915/dp: change aux_ctl reg read to polling read"").
+
+Apparently the configuration suffers from not having AUX enabled when
+using interrupts. One probable cause can be xe enabling interrupts too
+late: interrupts need memory allocations which currently can't be done
+before the display FB takeover is done.
+
+As for now, use polling for AUX in case interrupts are unavailable.
+
+Fixes: 40a9f77a28fa ("Revert "drm/i915/dp: change aux_ctl reg read to polling read"")
+Suggested-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Signed-off-by: Michał Grzelak <michal.grzelak@intel.com>
+Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Link: https://patch.msgid.link/20260416163744.288107-1-michal.grzelak@intel.com
+(cherry picked from commit 05e0550b65cd1604bd515fbc65f522bce4c10a87)
+Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_dp_aux.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c
+index b20ec3e589fadc..9c9b6410366d5c 100644
+--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
++++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
+@@ -12,6 +12,7 @@
+ #include "intel_dp.h"
+ #include "intel_dp_aux.h"
+ #include "intel_dp_aux_regs.h"
++#include "intel_parent.h"
+ #include "intel_pps.h"
+ #include "intel_quirks.h"
+ #include "intel_tc.h"
+@@ -60,18 +61,29 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp)
+ struct intel_display *display = to_intel_display(intel_dp);
+ i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
+ const unsigned int timeout_ms = 10;
++ bool done = true;
+ u32 status;
+- bool done;
++ int ret;
+
++ if (intel_parent_irq_enabled(display)) {
+ #define C (((status = intel_de_read_notrace(display, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
+- done = wait_event_timeout(display->gmbus.wait_queue, C,
+- msecs_to_jiffies_timeout(timeout_ms));
++ done = wait_event_timeout(display->gmbus.wait_queue, C,
++ msecs_to_jiffies_timeout(timeout_ms));
++
++#undef C
++ } else {
++ ret = intel_de_wait_ms(display, ch_ctl,
++ DP_AUX_CH_CTL_SEND_BUSY, 0,
++ timeout_ms, &status);
++
++ if (ret == -ETIMEDOUT)
++ done = false;
++ }
+
+ if (!done)
+ drm_err(display->drm,
+ "%s: did not complete or timeout within %ums (status 0x%08x)\n",
+ intel_dp->aux.name, timeout_ms, status);
+-#undef C
+
+ return status;
+ }
+--
+2.53.0
+
--- /dev/null
+From a1a6c6d3e5d15f7e92b8c260bcf13e3cfff779fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 22:05:32 +0530
+Subject: drm/xe: Restore IDLEDLY regiter on engine reset
+
+From: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
+
+[ Upstream commit f657a6a3ba4c20bc01f5be3752d53498ee1bfe35 ]
+
+Wa_16023105232 programs the register IDLEDLY. The register is reset
+whenever the engine is reset. Therefore it should be added to the GuC
+save-restore register list for it to be restored after reset.
+
+Fixes: 7c53ff050ba8 ("drm/xe: Apply Wa_16023105232")
+Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
+Link: https://patch.msgid.link/20260522163531.1365540-2-balasubramani.vivekanandan@intel.com
+Signed-off-by: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
+(cherry picked from commit df1cfe24743a93b71eab27687e148ab8ae9b69e3)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/xe/xe_guc_ads.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/gpu/drm/xe/xe_guc_ads.c b/drivers/gpu/drm/xe/xe_guc_ads.c
+index f4cbc030f4c81b..904225cbff0d8a 100644
+--- a/drivers/gpu/drm/xe/xe_guc_ads.c
++++ b/drivers/gpu/drm/xe/xe_guc_ads.c
+@@ -770,6 +770,11 @@ static unsigned int guc_mmio_regset_write(struct xe_guc_ads *ads,
+ }
+ }
+
++ if (XE_GT_WA(hwe->gt, 16023105232))
++ guc_mmio_regset_write_one(ads, regset_map,
++ RING_IDLEDLY(hwe->mmio_base),
++ count++);
++
+ return count;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From e3d5ae76091ea58f31ca35eee643a7f009d535da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 09:27:17 +0200
+Subject: esp: fix page frag reference leak on skb_to_sgvec failure
+
+From: e521588 <alessandro.schino@sbb.ch>
+
+[ Upstream commit 2982e599fff6faa21c8df147d96fc7af6c1a2f24 ]
+
+In esp_output_tail(), when esp->inplace is false, the old skb page frags
+are replaced with a new page from the xfrm page_frag cache. The source
+scatterlist (sg) is built from the old frags before the replacement, and
+esp_ssg_unref() is responsible for releasing the old page references
+after the crypto operation completes.
+
+However, if the second skb_to_sgvec() call (which builds the destination
+scatterlist from the new page) fails, the code jumps to error_free which
+only calls kfree(tmp). The old page frag references captured in the
+source scatterlist are never released:
+
+ 1. sg[] is built from old frags via skb_to_sgvec() (no extra get_page)
+ 2. nr_frags is set to 1 and frag[0] is replaced with the new page
+ 3. Second skb_to_sgvec() fails -> goto error_free
+ 4. kfree(tmp) frees the sg[] memory but old frags are not unref'd
+ 5. kfree_skb() only releases frag[0] (the new page), not the old ones
+
+Fix this by adding a bool parameter to esp_ssg_unref() that, when true,
+unconditionally unrefs the source scatterlist frags without checking
+req->src and req->dst, since those fields are not yet initialized by
+aead_request_set_crypt() at the point of the error. Existing callers
+pass false to preserve the original behavior.
+
+The same issue exists in both esp4 and esp6 as the code is identical.
+
+Fixes: cac2661c53f3 ("esp4: Avoid skb_cow_data whenever possible")
+Fixes: 03e2a30f6a27 ("esp6: Avoid skb_cow_data whenever possible")
+
+Signed-off-by: Alessandro Schino <7991aleschino@gmail.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/esp4.c | 12 +++++++-----
+ net/ipv6/esp6.c | 12 +++++++-----
+ 2 files changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
+index 6a5febbdbee493..8314d7bddcb715 100644
+--- a/net/ipv4/esp4.c
++++ b/net/ipv4/esp4.c
+@@ -96,7 +96,7 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
+ __alignof__(struct scatterlist));
+ }
+
+-static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
++static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb, bool already_unref)
+ {
+ struct crypto_aead *aead = x->data;
+ int extralen = 0;
+@@ -113,7 +113,7 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
+ /* Unref skb_frag_pages in the src scatterlist if necessary.
+ * Skip the first sg which comes from skb->data.
+ */
+- if (req->src != req->dst)
++ if (already_unref || req->src != req->dst)
+ for (sg = sg_next(req->src); sg; sg = sg_next(sg))
+ skb_page_unref(page_to_netmem(sg_page(sg)),
+ skb->pp_recycle);
+@@ -220,7 +220,7 @@ static void esp_output_done(void *data, int err)
+ }
+
+ tmp = ESP_SKB_CB(skb)->tmp;
+- esp_ssg_unref(x, tmp, skb);
++ esp_ssg_unref(x, tmp, skb, false);
+ kfree(tmp);
+
+ if (xo && (xo->flags & XFRM_DEV_RESUME)) {
+@@ -569,8 +569,10 @@ int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
+ err = skb_to_sgvec(skb, dsg,
+ (unsigned char *)esph - skb->data,
+ assoclen + ivlen + esp->clen + alen);
+- if (unlikely(err < 0))
++ if (unlikely(err < 0)) {
++ esp_ssg_unref(x, tmp, skb, true);
+ goto error_free;
++ }
+ }
+
+ if ((x->props.flags & XFRM_STATE_ESN))
+@@ -602,7 +604,7 @@ int esp_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
+ }
+
+ if (sg != dsg)
+- esp_ssg_unref(x, tmp, skb);
++ esp_ssg_unref(x, tmp, skb, false);
+
+ if (!err && x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)
+ err = esp_output_tail_tcp(x, skb);
+diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
+index 9c06c5a1419dc4..9d0c4957ac6276 100644
+--- a/net/ipv6/esp6.c
++++ b/net/ipv6/esp6.c
+@@ -113,7 +113,7 @@ static inline struct scatterlist *esp_req_sg(struct crypto_aead *aead,
+ __alignof__(struct scatterlist));
+ }
+
+-static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
++static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb, bool already_unref)
+ {
+ struct crypto_aead *aead = x->data;
+ int extralen = 0;
+@@ -130,7 +130,7 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)
+ /* Unref skb_frag_pages in the src scatterlist if necessary.
+ * Skip the first sg which comes from skb->data.
+ */
+- if (req->src != req->dst)
++ if (already_unref || req->src != req->dst)
+ for (sg = sg_next(req->src); sg; sg = sg_next(sg))
+ skb_page_unref(page_to_netmem(sg_page(sg)),
+ skb->pp_recycle);
+@@ -254,7 +254,7 @@ static void esp_output_done(void *data, int err)
+ }
+
+ tmp = ESP_SKB_CB(skb)->tmp;
+- esp_ssg_unref(x, tmp, skb);
++ esp_ssg_unref(x, tmp, skb, false);
+ kfree(tmp);
+
+ esp_output_encap_csum(skb);
+@@ -600,8 +600,10 @@ int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
+ err = skb_to_sgvec(skb, dsg,
+ (unsigned char *)esph - skb->data,
+ assoclen + ivlen + esp->clen + alen);
+- if (unlikely(err < 0))
++ if (unlikely(err < 0)) {
++ esp_ssg_unref(x, tmp, skb, true);
+ goto error_free;
++ }
+ }
+
+ if ((x->props.flags & XFRM_STATE_ESN))
+@@ -634,7 +636,7 @@ int esp6_output_tail(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
+ }
+
+ if (sg != dsg)
+- esp_ssg_unref(x, tmp, skb);
++ esp_ssg_unref(x, tmp, skb, false);
+
+ if (!err && x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP)
+ err = esp_output_tail_tcp(x, skb);
+--
+2.53.0
+
--- /dev/null
+From 2dca642becb9dc2f2f618672bf5b8224075c5055 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:10 -0700
+Subject: ethtool: cmis: fix u16-to-u8 truncation of msleep_pre_rpl
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 3e8c3d464c36bb342fe377b026577c7ec27fdbb4 ]
+
+ethtool_cmis_cdb_compose_args() accepts msleep_pre_rpl as u16 but stores
+it into the u8 field ethtool_cmis_cdb_cmd_args::msleep_pre_rpl, silently
+truncating values >= 256. Seven of the nine call sites pass 1000 ms
+(it's the third argument from the end).
+
+Fixes: a39c84d79625 ("ethtool: cmis_cdb: Add a layer for supporting CDB commands")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-8-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/cmis.h b/net/ethtool/cmis.h
+index 4a9a946cabf05d..778783a0f23c0b 100644
+--- a/net/ethtool/cmis.h
++++ b/net/ethtool/cmis.h
+@@ -63,9 +63,9 @@ struct ethtool_cmis_cdb_request {
+ * struct ethtool_cmis_cdb_cmd_args - CDB commands execution arguments
+ * @req: CDB command fields as described in the CMIS standard.
+ * @max_duration: Maximum duration time for command completion in msec.
++ * @msleep_pre_rpl: Waiting time before checking reply in msec.
+ * @read_write_len_ext: Allowable additional number of byte octets to the LPL
+ * in a READ or a WRITE commands.
+- * @msleep_pre_rpl: Waiting time before checking reply in msec.
+ * @rpl_exp_len: Expected reply length in bytes.
+ * @flags: Validation flags for CDB commands.
+ * @err_msg: Error message to be sent to user space.
+@@ -73,8 +73,8 @@ struct ethtool_cmis_cdb_request {
+ struct ethtool_cmis_cdb_cmd_args {
+ struct ethtool_cmis_cdb_request req;
+ u16 max_duration;
++ u16 msleep_pre_rpl;
+ u8 read_write_len_ext;
+- u8 msleep_pre_rpl;
+ u8 rpl_exp_len;
+ u8 flags;
+ char *err_msg;
+--
+2.53.0
+
--- /dev/null
+From e87c6d88d165888efbf2a4d6902294a2b5646f7b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:09 -0700
+Subject: ethtool: cmis: require exact CDB reply length
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 6c3f999a9d1338c6c89a9ff4549eafe72bc2e7b1 ]
+
+Malicious SFP module could respond with rpl_len longer than
+what cmis_cdb_process_reply() expected, leading to OOB writes.
+Malicious HW is a bit theoretical but some modules may just
+be buggy and/or the reads may occasionally get corrupted,
+so let's protect the kernel.
+
+The existing check protects from short replies. We need to
+protect from long ones, too. All callers that pass a non-zero
+rpl_exp_len cast the reply payload to a fixed-layout struct
+and read fields at fixed offsets, with no version negotiation
+or short-reply handling:
+
+ - cmis_cdb_validate_password()
+ - cmis_cdb_module_features_get()
+ - cmis_fw_update_fw_mng_features_get()
+
+so let's assume that responses longer than expected do not
+have to be handled gracefully here. Add a warning message
+to make the debug easier in case my understanding is wrong...
+
+Note that page_data->length (argument of kmalloc) comes from
+last arg to ethtool_cmis_page_init() which is rpl_exp_len.
+
+Note2 that AIs also like to point out overflows in args->req.payload
+itself (which is a fixed-size 120 B buffer, on the stack),
+but callers should be reading structs defined by the standard,
+so protecting from requests for more data than max seem like
+defensive programming.
+
+Fixes: a39c84d79625 ("ethtool: cmis_cdb: Add a layer for supporting CDB commands")
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-7-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis_cdb.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/cmis_cdb.c b/net/ethtool/cmis_cdb.c
+index 3670ca42dd403e..f3a53a98446099 100644
+--- a/net/ethtool/cmis_cdb.c
++++ b/net/ethtool/cmis_cdb.c
+@@ -513,8 +513,13 @@ static int cmis_cdb_process_reply(struct net_device *dev,
+ }
+
+ rpl = (struct ethtool_cmis_cdb_rpl *)page_data->data;
+- if ((args->rpl_exp_len > rpl->hdr.rpl_len + rpl_hdr_len) ||
+- !rpl->hdr.rpl_chk_code) {
++ if (rpl->hdr.rpl_len != args->rpl_exp_len) {
++ netdev_warn(dev, "CDB reply length mismatch, expected %u got %u\n",
++ args->rpl_exp_len, rpl->hdr.rpl_len);
++ err = -EIO;
++ goto out;
++ }
++ if (!rpl->hdr.rpl_chk_code) {
+ err = -EIO;
+ goto out;
+ }
+--
+2.53.0
+
--- /dev/null
+From ce13c0943b6b3e93ab040edd59c762a758768d88 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:12 -0700
+Subject: ethtool: cmis: validate fw->size against start_cmd_payload_size
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit d5551f4c1800dc714cec86647bdd651ae0de923e ]
+
+cmis_fw_update_start_download() copies start_cmd_payload_size bytes
+from the firmware blob into the CDB LPL vendor_data[] payload without
+validating that the FW has enough data.
+
+Since the start_cmd_payload_size can only be ~120B an image too short
+is most likely corrupted, so reject it.
+
+Fixes: c4f78134d45c ("ethtool: cmis_fw_update: add a layer for supporting firmware update using CDB")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-10-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis_fw_update.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/net/ethtool/cmis_fw_update.c b/net/ethtool/cmis_fw_update.c
+index 16190c97e1f78c..291d04d2776a5c 100644
+--- a/net/ethtool/cmis_fw_update.c
++++ b/net/ethtool/cmis_fw_update.c
+@@ -130,6 +130,14 @@ cmis_fw_update_start_download(struct ethtool_cmis_cdb *cdb,
+ u8 lpl_len;
+ int err;
+
++ if (fw_update->fw->size < vendor_data_size) {
++ ethnl_module_fw_flash_ntf_err(fw_update->dev,
++ &fw_update->ntf_params,
++ "Firmware image too small for module's start payload",
++ NULL);
++ return -EINVAL;
++ }
++
+ pl.image_size = cpu_to_be32(fw_update->fw->size);
+ memcpy(pl.vendor_data, fw_update->fw->data, vendor_data_size);
+
+--
+2.53.0
+
--- /dev/null
+From a627e6e43c8d38d63fb877ea6d251fb1e058b668 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:11 -0700
+Subject: ethtool: cmis: validate start_cmd_payload_size from module
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 12c2496a71f82f63617971ca9b730dffa05cf58b ]
+
+The CMIS firmware update code reads start_cmd_payload_size from
+the module's FW Management Features CDB reply and uses it directly
+as the byte count for memcpy. The destination buffer is 112 bytes
+(ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH - 8). So a malicious
+module (or corrupted response) can cause a OOB write later on in
+cmis_fw_update_start_download().
+
+Let's error out. If modules that expect longer LPL writes actually
+exist we should revisit.
+
+struct cmis_cdb_start_fw_download_pl's definition has to move,
+no change there.
+
+Fixes: c4f78134d45c ("ethtool: cmis_fw_update: add a layer for supporting firmware update using CDB")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-9-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/cmis_fw_update.c | 36 ++++++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 14 deletions(-)
+
+diff --git a/net/ethtool/cmis_fw_update.c b/net/ethtool/cmis_fw_update.c
+index df5f344209c47b..16190c97e1f78c 100644
+--- a/net/ethtool/cmis_fw_update.c
++++ b/net/ethtool/cmis_fw_update.c
+@@ -44,6 +44,20 @@ enum cmis_cdb_fw_write_mechanism {
+ CMIS_CDB_FW_WRITE_MECHANISM_BOTH = 0x11,
+ };
+
++/* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
++ * revision 5.2.
++ * struct cmis_cdb_start_fw_download_pl is a structured layout of the
++ * flat array, ethtool_cmis_cdb_request::payload.
++ */
++struct cmis_cdb_start_fw_download_pl {
++ __struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */,
++ __be32 image_size;
++ __be32 resv1;
++ );
++ u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH -
++ sizeof(struct cmis_cdb_start_fw_download_pl_h)];
++};
++
+ static int
+ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ struct net_device *dev,
+@@ -86,6 +100,14 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ */
+ cdb->read_write_len_ext = rpl->read_write_len_ext;
+ fw_mng->start_cmd_payload_size = rpl->start_cmd_payload_size;
++ if (fw_mng->start_cmd_payload_size >
++ sizeof_field(struct cmis_cdb_start_fw_download_pl, vendor_data)) {
++ ethnl_module_fw_flash_ntf_err(dev, ntf_params,
++ "Start cmd payload size exceeds max LPL payload",
++ NULL);
++ return -EINVAL;
++ }
++
+ fw_mng->write_mechanism =
+ rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL ?
+ CMIS_CDB_FW_WRITE_MECHANISM_LPL :
+@@ -97,20 +119,6 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
+ return 0;
+ }
+
+-/* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
+- * revision 5.2.
+- * struct cmis_cdb_start_fw_download_pl is a structured layout of the
+- * flat array, ethtool_cmis_cdb_request::payload.
+- */
+-struct cmis_cdb_start_fw_download_pl {
+- __struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */,
+- __be32 image_size;
+- __be32 resv1;
+- );
+- u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH -
+- sizeof(struct cmis_cdb_start_fw_download_pl_h)];
+-};
+-
+ static int
+ cmis_fw_update_start_download(struct ethtool_cmis_cdb *cdb,
+ struct ethtool_cmis_fw_update_params *fw_update,
+--
+2.53.0
+
--- /dev/null
+From bd28fbf9a69ba891490fd79cce95a1d2a0987637 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:24 -0700
+Subject: ethtool: coalesce: cap profile updates at NET_DIM_PARAMS_NUM_PROFILES
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 7281b096b072f6c6e30420e3467d738f2e4c4b57 ]
+
+ethnl_update_profile() walks the ETHTOOL_A_PROFILE_IRQ_MODERATION
+nest list with an index 'i' and writes new_profile[i++] without
+bounding i. The destination is kmemdup()'d at NET_DIM_PARAMS_NUM_PROFILES
+entries (5), but the Netlink nest count is entirely user-controlled.
+Netlink policies do not have support for constraining the number
+of nested entries (or number of multi-attr entries).
+
+Fixes: f750dfe825b9 ("ethtool: provide customized dim profile management")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-2-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/coalesce.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/net/ethtool/coalesce.c b/net/ethtool/coalesce.c
+index 3e18ca1ccc5ef6..cace02d964cb21 100644
+--- a/net/ethtool/coalesce.c
++++ b/net/ethtool/coalesce.c
+@@ -463,6 +463,12 @@ static int ethnl_update_profile(struct net_device *dev,
+
+ nla_for_each_nested_type(nest, ETHTOOL_A_PROFILE_IRQ_MODERATION,
+ nests, rem) {
++ if (i >= NET_DIM_PARAMS_NUM_PROFILES) {
++ NL_SET_BAD_ATTR(extack, nest);
++ ret = -E2BIG;
++ goto err_out;
++ }
++
+ ret = nla_parse_nested(tb, len_irq_moder - 1, nest,
+ coalesce_irq_moderation_policy,
+ extack);
+--
+2.53.0
+
--- /dev/null
+From ee819def2d239de46f6048a568fe4038f25855b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:32 -0700
+Subject: ethtool: eeprom: add missing ethnl_ops_begin() / _complete() during
+ fallback
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 2376586f85f972fefe701f095bb37dcfe7405d21 ]
+
+All ethtool driver op calls should be sandwiched between
+ethnl_ops_begin() / ethnl_ops_complete(). In Netlink eeprom code,
+if the paged access failed we fall back to old API, but we
+first call _complete() and the fallback never does its own
+ethnl_ops_begin(). Move the fallback into the _begin() / _complete()
+section.
+
+Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-10-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/eeprom.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c
+index 3b8209e930fd3a..03cb418a15823b 100644
+--- a/net/ethtool/eeprom.c
++++ b/net/ethtool/eeprom.c
+@@ -140,12 +140,11 @@ static int eeprom_prepare_data(const struct ethnl_req_info *req_base,
+ return 0;
+
+ err_ops:
++ if (ret == -EOPNOTSUPP)
++ ret = eeprom_fallback(request, reply);
+ ethnl_ops_complete(dev);
+ err_free:
+ kfree(page_data.data);
+-
+- if (ret == -EOPNOTSUPP)
+- return eeprom_fallback(request, reply);
+ return ret;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 037295e26c47f64f130ff17a0f629a7bd1724b2e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:33 -0700
+Subject: ethtool: eeprom: add more safeties to EEPROM Netlink fallback
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 67cfdd9210b99f260b3e0afeb9525e0acc7be31e ]
+
+The Netlink fallback path for reading module EEPROM
+(fallback_set_params()) validates that offset < eeprom_len,
+but does not check that offset + length stays within eeprom_len.
+The ioctl equivalent (ethtool_get_any_eeprom() in ioctl.c) has
+always enforced both bounds:
+
+ if (eeprom.offset + eeprom.len > total_len)
+ return -EINVAL;
+
+This could lead to surprises in both drivers and device FW.
+Add the missing offset + length validation to fallback_set_params(),
+mirroring the ioctl.
+
+Similarly - ethtool core in general, and ethtool_get_any_eeprom()
+in particular tries to zero-init all buffers passed to the drivers
+to avoid any extra work of zeroing things out. eeprom_fallback()
+uses a plain kmalloc(), change it to zalloc.
+
+Fixes: 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-11-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/eeprom.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/eeprom.c b/net/ethtool/eeprom.c
+index 03cb418a15823b..80af38a6c76acf 100644
+--- a/net/ethtool/eeprom.c
++++ b/net/ethtool/eeprom.c
+@@ -43,6 +43,9 @@ static int fallback_set_params(struct eeprom_req_info *request,
+ if (offset >= modinfo->eeprom_len)
+ return -EINVAL;
+
++ if (length > modinfo->eeprom_len - offset)
++ return -EINVAL;
++
+ eeprom->cmd = ETHTOOL_GMODULEEEPROM;
+ eeprom->len = length;
+ eeprom->offset = offset;
+@@ -68,7 +71,7 @@ static int eeprom_fallback(struct eeprom_req_info *request,
+ if (err < 0)
+ return err;
+
+- data = kmalloc(eeprom.len, GFP_KERNEL);
++ data = kzalloc(eeprom.len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ err = ethtool_get_module_eeprom_call(dev, &eeprom, data);
+--
+2.53.0
+
--- /dev/null
+From 38b98152586b77499f2df4274075e6648caa4c24 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:26 -0700
+Subject: ethtool: linkstate: fix unbalanced ethnl_ops_complete() on PHY lookup
+ error
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 596c51ed9e125b12c4d85b4530dfd4c7847634b7 ]
+
+linkstate_prepare_data() calls ethnl_req_get_phydev() before
+ethnl_ops_begin(), but routes its error path through "goto out"
+which calls ethnl_ops_complete().
+
+Fixes: fe55b1d401c6 ("ethtool: linkstate: migrate linkstate functions to support multi-PHY setups")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-4-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/linkstate.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/net/ethtool/linkstate.c b/net/ethtool/linkstate.c
+index 05a5f72c99fab1..3dc52a39d34525 100644
+--- a/net/ethtool/linkstate.c
++++ b/net/ethtool/linkstate.c
+@@ -105,10 +105,8 @@ static int linkstate_prepare_data(const struct ethnl_req_info *req_base,
+
+ phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_LINKSTATE_HEADER,
+ info->extack);
+- if (IS_ERR(phydev)) {
+- ret = PTR_ERR(phydev);
+- goto out;
+- }
++ if (IS_ERR(phydev))
++ return PTR_ERR(phydev);
+
+ ret = ethnl_ops_begin(dev);
+ if (ret < 0)
+--
+2.53.0
+
--- /dev/null
+From 23c8dba54d8c60b29d05026c25a7fc2f1a7ff465 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:05 -0700
+Subject: ethtool: module: avoid leaking a netdev ref on module flash errors
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit fb7f511d62692661846c47f199e0afe25c2982db ]
+
+module_flash_fw_schedule() is missing undo for setting
+the "in_progress" flag and taking the netdev reference.
+Delay taking these, the device can't disappear while
+we are holding rtnl_lock.
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-3-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index 8047c14f7ee370..594a49fdd7fd06 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -319,8 +319,6 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
+ if (err < 0)
+ goto err_release_firmware;
+
+- dev->ethtool->module_fw_flash_in_progress = true;
+- netdev_hold(dev, &module_fw->dev_tracker, GFP_KERNEL);
+ fw_update->dev = dev;
+ fw_update->ntf_params.portid = info->snd_portid;
+ fw_update->ntf_params.seq = info->snd_seq;
+@@ -335,6 +333,9 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
+ if (err < 0)
+ goto err_release_firmware;
+
++ dev->ethtool->module_fw_flash_in_progress = true;
++ netdev_hold(dev, &module_fw->dev_tracker, GFP_KERNEL);
++
+ schedule_work(&module_fw->work);
+
+ return 0;
+--
+2.53.0
+
--- /dev/null
+From c324e0df6028d324a1c09461e852bf53e0450e7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:06 -0700
+Subject: ethtool: module: avoid racy updates to dev->ethtool bitfield
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 7a84b965ffc12030af63cd10a8f3a1123ff39b7a ]
+
+When reviewing other changes Gemini points out that we currently
+update module_fw_flash_in_progress without holding any locks.
+Since module_fw_flash_in_progress is part of a bitfield this
+is not great, updates to other fields may be lost.
+
+We could use a bool and sprinkle some READ_ONCE/WRITE_ONCE here
+but seems like the issue is rather than the work is an unusual
+writer. The other writers already hold the right locks. So just
+very briefly take these locks when the work completes.
+
+Note that nothing ever cancels the FW update work, so there's
+no concern with deadlocks vs cancel.
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-4-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 12 ++++++++++--
+ 1 file changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index 594a49fdd7fd06..ce4ce514edca89 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -221,14 +221,22 @@ static void module_flash_fw_work_list_del(struct list_head *list)
+ static void module_flash_fw_work(struct work_struct *work)
+ {
+ struct ethtool_module_fw_flash *module_fw;
++ struct net_device *dev;
+
+ module_fw = container_of(work, struct ethtool_module_fw_flash, work);
++ dev = module_fw->fw_update.dev;
+
+ ethtool_cmis_fw_update(&module_fw->fw_update);
+
+ module_flash_fw_work_list_del(&module_fw->list);
+- module_fw->fw_update.dev->ethtool->module_fw_flash_in_progress = false;
+- netdev_put(module_fw->fw_update.dev, &module_fw->dev_tracker);
++
++ rtnl_lock();
++ netdev_lock_ops(dev);
++ dev->ethtool->module_fw_flash_in_progress = false;
++ netdev_unlock_ops(dev);
++ rtnl_unlock();
++
++ netdev_put(dev, &module_fw->dev_tracker);
+ release_firmware(module_fw->fw_update.fw);
+ kfree(module_fw);
+ }
+--
+2.53.0
+
--- /dev/null
+From 435553a917bdaa1dfc9469d8cdc1e4140d3100b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:04 -0700
+Subject: ethtool: module: call ethnl_ops_complete() on module flash errors
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 84371fb58423f997939aacdcbc02d128d76a54e5 ]
+
+When validate() fails we are skipping over ethnl_ops_complete()
+even tho we already called ethnl_ops_begin().
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-2-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index 0a761bf4771e11..8047c14f7ee370 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -427,10 +427,11 @@ int ethnl_act_module_fw_flash(struct sk_buff *skb, struct genl_info *info)
+
+ ret = ethnl_module_fw_flash_validate(dev, info->extack);
+ if (ret < 0)
+- goto out_unlock;
++ goto out_complete;
+
+ ret = module_flash_fw(dev, tb, skb, info);
+
++out_complete:
+ ethnl_ops_complete(dev);
+
+ out_unlock:
+--
+2.53.0
+
--- /dev/null
+From 6fd890d3905671ca0d32603e23f02426807a819f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:07 -0700
+Subject: ethtool: module: check fw_flash_in_progress under rtnl_lock
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 504eaefa44c8dec50f7499edcb36d24f3aefab2a ]
+
+ethnl_set_module_validate() inspects module_fw_flash_in_progress
+but validate is meant for _input_ validation, not state validation.
+rtnl_lock is not held, yet. Move the check into ethnl_set_module().
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-5-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index ce4ce514edca89..373326e49d150e 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -120,12 +120,6 @@ ethnl_set_module_validate(struct ethnl_req_info *req_info,
+ if (!tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY])
+ return 0;
+
+- if (req_info->dev->ethtool->module_fw_flash_in_progress) {
+- NL_SET_ERR_MSG(info->extack,
+- "Module firmware flashing is in progress");
+- return -EBUSY;
+- }
+-
+ if (!ops->get_module_power_mode || !ops->set_module_power_mode) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY],
+@@ -148,6 +142,12 @@ ethnl_set_module(struct ethnl_req_info *req_info, struct genl_info *info)
+
+ ops = dev->ethtool_ops;
+
++ if (dev->ethtool->module_fw_flash_in_progress) {
++ NL_SET_ERR_MSG(info->extack,
++ "Module firmware flashing is in progress");
++ return -EBUSY;
++ }
++
+ power_new.policy = nla_get_u8(tb[ETHTOOL_A_MODULE_POWER_MODE_POLICY]);
+ ret = ops->get_module_power_mode(dev, &power, info->extack);
+ if (ret < 0)
+--
+2.53.0
+
--- /dev/null
+From 4277857e3371b603b23d436a698c1fd550a6f91b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:13:08 -0700
+Subject: ethtool: module: fix cleanup if socket used for flashing multiple
+ devices
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 760d04ebad5c4304f22c0d2251c9623b87a117c8 ]
+
+When a single Netlink socket issues MODULE_FW_FLASH_ACT against multiple
+devices, ethnl_sock_priv_set() overwrites sk_priv->dev on each call,
+retaining only the last one. The socket priv is used on socket close,
+to walk the global work list and mark the uncompleted flashing work
+as "orphaned". Otherwise if another socket reuses the PID it will
+unexpectedly receive the flashing notifications.
+
+Don't record the device, record net pointer instead. The purpose of
+the dev is to scope the work to a netns, anyway. If we store netns
+the overrides are safe/a nop since all flashed devices must be in
+the same netns as the socket.
+
+Fixes: 32b4c8b53ee7 ("ethtool: Add ability to flash transceiver modules' firmware")
+Reviewed-by: Danielle Ratson <danieller@nvidia.com>
+Link: https://patch.msgid.link/20260522231312.1710836-6-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/module.c | 9 ++++-----
+ net/ethtool/netlink.c | 4 ++--
+ net/ethtool/netlink.h | 4 ++--
+ 3 files changed, 8 insertions(+), 9 deletions(-)
+
+diff --git a/net/ethtool/module.c b/net/ethtool/module.c
+index 373326e49d150e..6eb83f6b3d267c 100644
+--- a/net/ethtool/module.c
++++ b/net/ethtool/module.c
+@@ -291,11 +291,9 @@ void ethnl_module_fw_flash_sock_destroy(struct ethnl_sock_priv *sk_priv)
+
+ spin_lock(&module_fw_flash_work_list_lock);
+ list_for_each_entry(work, &module_fw_flash_work_list, list) {
+- if (work->fw_update.dev == sk_priv->dev &&
+- work->fw_update.ntf_params.portid == sk_priv->portid) {
++ if (work->fw_update.ntf_params.portid == sk_priv->portid &&
++ dev_net(work->fw_update.dev) == sk_priv->net)
+ work->fw_update.ntf_params.closed_sock = true;
+- break;
+- }
+ }
+ spin_unlock(&module_fw_flash_work_list_lock);
+ }
+@@ -332,7 +330,8 @@ module_flash_fw_schedule(struct net_device *dev, const char *file_name,
+ fw_update->ntf_params.seq = info->snd_seq;
+ fw_update->ntf_params.closed_sock = false;
+
+- err = ethnl_sock_priv_set(skb, dev, fw_update->ntf_params.portid,
++ err = ethnl_sock_priv_set(skb, dev_net(dev),
++ fw_update->ntf_params.portid,
+ ETHTOOL_SOCK_TYPE_MODULE_FW_FLASH);
+ if (err < 0)
+ goto err_release_firmware;
+diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
+index 6e5f0f4f815a1a..4cf928da607252 100644
+--- a/net/ethtool/netlink.c
++++ b/net/ethtool/netlink.c
+@@ -52,7 +52,7 @@ const struct nla_policy ethnl_header_policy_phy_stats[] = {
+ [ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1),
+ };
+
+-int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
++int ethnl_sock_priv_set(struct sk_buff *skb, struct net *net, u32 portid,
+ enum ethnl_sock_type type)
+ {
+ struct ethnl_sock_priv *sk_priv;
+@@ -61,7 +61,7 @@ int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
+ if (IS_ERR(sk_priv))
+ return PTR_ERR(sk_priv);
+
+- sk_priv->dev = dev;
++ sk_priv->net = net;
+ sk_priv->portid = portid;
+ sk_priv->type = type;
+
+diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
+index 89010eaa67dfcd..65c24f627b218f 100644
+--- a/net/ethtool/netlink.h
++++ b/net/ethtool/netlink.h
+@@ -318,12 +318,12 @@ enum ethnl_sock_type {
+ };
+
+ struct ethnl_sock_priv {
+- struct net_device *dev;
++ struct net *net;
+ u32 portid;
+ enum ethnl_sock_type type;
+ };
+
+-int ethnl_sock_priv_set(struct sk_buff *skb, struct net_device *dev, u32 portid,
++int ethnl_sock_priv_set(struct sk_buff *skb, struct net *net, u32 portid,
+ enum ethnl_sock_type type);
+
+ /**
+--
+2.53.0
+
--- /dev/null
+From e789513d907129b0d1859ee78bd50288aa380a53 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:27 -0700
+Subject: ethtool: pse-pd: fix missing ethnl_ops_complete()
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit ab5bf428fb6bd361163c7247b92750d1d24ca2ed ]
+
+pse_prepare_data() is missing ethnl_ops_complete() if
+ethnl_req_get_phydev() returned an error. Move getting
+phydev up so that we don't have to worry about this
+(similar order to linkstate_prepare_data()).
+
+Note that phydev may still be NULL (this is checked in
+pse_get_pse_attributes()), the goal isn't really to avoid
+the _begin() / _complete() calls, only to simplify the error
+handling.
+
+While at it propagate the original error. Why this code
+overrides the error with -ENODEV but !phydev generates
+-EOPNOTSUPP is unclear to me...
+
+Fixes: 31748765bed3 ("net: ethtool: pse-pd: Target the command to the requested PHY")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-5-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/pse-pd.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c
+index 24def9c9dd54bf..aa4514333d13bd 100644
+--- a/net/ethtool/pse-pd.c
++++ b/net/ethtool/pse-pd.c
+@@ -61,14 +61,14 @@ static int pse_prepare_data(const struct ethnl_req_info *req_base,
+ struct phy_device *phydev;
+ int ret;
+
+- ret = ethnl_ops_begin(dev);
+- if (ret < 0)
+- return ret;
+-
+ phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PSE_HEADER,
+ info->extack);
+ if (IS_ERR(phydev))
+- return -ENODEV;
++ return PTR_ERR(phydev);
++
++ ret = ethnl_ops_begin(dev);
++ if (ret < 0)
++ return ret;
+
+ ret = pse_get_pse_attributes(phydev, info->extack, data);
+
+--
+2.53.0
+
--- /dev/null
+From 0d6d66ae9eacc703a24f730adde29fbfb418e267 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:43 -0700
+Subject: ethtool: rss: add missing errno on RSS context delete
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 3e6c6e9782ff8a8d8ded774b07ad4590cd61d04c ]
+
+Remember to set ret before jumping out if someone tries
+to delete a context on a device which doesn't support
+contexts.
+
+Fixes: fbe09277fa63 ("ethtool: rss: support removing contexts via Netlink")
+Link: https://patch.msgid.link/20260522230647.1705600-3-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index 926be5698ba4cc..688c0e4bba69db 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -1160,8 +1160,10 @@ int ethnl_rss_delete_doit(struct sk_buff *skb, struct genl_info *info)
+ dev = req.dev;
+ ops = dev->ethtool_ops;
+
+- if (!ops->create_rxfh_context)
++ if (!ops->create_rxfh_context) {
++ ret = -EOPNOTSUPP;
+ goto exit_free_dev;
++ }
+
+ rtnl_lock();
+ netdev_lock_ops(dev);
+--
+2.53.0
+
--- /dev/null
+From fd7cb3983dc035e257226b2029edba581e951a02 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:47 -0700
+Subject: ethtool: rss: avoid device context leak on reply-build failure
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 32a9ecde62731c9f7412507709192c84dafc38d1 ]
+
+We wait with filling the reply for new RSS context creation
+until after the driver ->create_rxfh_context call. The driver
+needs to fill some of the defaults in the context. The failure
+of rss_fill_reply() is somewhat theoretical, but doesn't take
+much effort to handle it properly. Call ->remove_rxfh_context().
+
+If the driver's remove callback fails (some implementations like sfc
+can return real command errors from firmware RPCs) - skip the xa_erase
+and kfree, leaving the context in the xarray. This matches how
+ethnl_rss_delete_doit() behaves.
+
+Fixes: a166ab7816c5 ("ethtool: rss: support creating contexts via Netlink")
+Link: https://patch.msgid.link/20260522230647.1705600-7-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index f745ddec6fbab8..b122f67dbde1d6 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -1096,7 +1096,7 @@ int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info)
+ ntf_fail |= rss_fill_reply(rsp, &req.base, &data.base);
+ if (WARN_ON(!hdr || ntf_fail)) {
+ ret = -EMSGSIZE;
+- goto exit_unlock;
++ goto err_remove_ctx;
+ }
+
+ genlmsg_end(rsp, hdr);
+@@ -1124,6 +1124,10 @@ int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info)
+ nlmsg_free(rsp);
+ return ret;
+
++err_remove_ctx:
++ if (ops->remove_rxfh_context(dev, ctx, req.rss_context, NULL))
++ /* leave the context on failure, like ethnl_rss_delete_doit() */
++ goto exit_unlock;
+ err_ctx_id_free:
+ xa_erase(&dev->ethtool->rss_ctx, req.rss_context);
+ err_unlock_free_ctx:
+--
+2.53.0
+
--- /dev/null
+From faa3701e72e78b2298ea270b053dac19c6203082 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:42 -0700
+Subject: ethtool: rss: avoid modifying the RSS context response
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit c75b6f6eaacd0b74b832414cc3b9289c3686e941 ]
+
+Gemini says that we're modifying the RSS_CREATE response skb.
+I think it's right, the comment says that unicast() should
+unshare the skb but I'm not entirely sure what I meant there.
+netlink_trim() does a copy but only if skb is not well sized
+(it's at least 2x larger than necessary for the payload).
+
+Fixes: a166ab7816c5 ("ethtool: rss: support creating contexts via Netlink")
+Link: https://patch.msgid.link/20260522230647.1705600-2-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index da5934cceb0757..926be5698ba4cc 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -974,11 +974,17 @@ ethnl_rss_create_validate(struct net_device *dev, struct genl_info *info)
+ }
+
+ static void
+-ethnl_rss_create_send_ntf(struct sk_buff *rsp, struct net_device *dev)
++ethnl_rss_create_send_ntf(const struct sk_buff *rsp, struct net_device *dev)
+ {
+- struct nlmsghdr *nlh = (void *)rsp->data;
+ struct genlmsghdr *genl_hdr;
++ struct nlmsghdr *nlh;
++ struct sk_buff *ntf;
++
++ ntf = skb_copy_expand(rsp, 0, 0, GFP_KERNEL);
++ if (!ntf)
++ return;
+
++ nlh = nlmsg_hdr(ntf);
+ /* Convert the reply into a notification */
+ nlh->nlmsg_pid = 0;
+ nlh->nlmsg_seq = ethnl_bcast_seq_next();
+@@ -986,7 +992,7 @@ ethnl_rss_create_send_ntf(struct sk_buff *rsp, struct net_device *dev)
+ genl_hdr = nlmsg_data(nlh);
+ genl_hdr->cmd = ETHTOOL_MSG_RSS_CREATE_NTF;
+
+- ethnl_multicast(rsp, dev);
++ ethnl_multicast(ntf, dev);
+ }
+
+ int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info)
+@@ -1094,12 +1100,8 @@ int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info)
+
+ genlmsg_end(rsp, hdr);
+
+- /* Use the same skb for the response and the notification,
+- * genlmsg_reply() will copy the skb if it has elevated user count.
+- */
+- skb_get(rsp);
+- ret = genlmsg_reply(rsp, info);
+ ethnl_rss_create_send_ntf(rsp, dev);
++ ret = genlmsg_reply(rsp, info);
+ rsp = NULL;
+
+ exit_unlock:
+--
+2.53.0
+
--- /dev/null
+From 197579e2f979fa3bfbe5847727d195a1ee8fbcce Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:44 -0700
+Subject: ethtool: rss: fix falsely ignoring indir table updates
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 8d60141a32875248ef71d49c9920fa5e2aa40b29 ]
+
+rss_set_prep_indir() compares the new indirection table against the
+current one to determine whether any update is needed. The memcmp
+call passes data->indir_size as the length argument, but indir_size
+is the number of u32 entries, not the byte count.
+
+Fixes: c0ae03588bbb ("ethtool: rss: initial RSS_SET (indirection table handling)")
+Link: https://patch.msgid.link/20260522230647.1705600-4-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index 688c0e4bba69db..4877655f724419 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -684,7 +684,7 @@ rss_set_prep_indir(struct net_device *dev, struct genl_info *info,
+ ethtool_rxfh_indir_default(i, num_rx_rings);
+ }
+
+- *mod |= memcmp(rxfh->indir, data->indir_table, data->indir_size);
++ *mod |= memcmp(rxfh->indir, data->indir_table, alloc_size);
+
+ return 0;
+
+--
+2.53.0
+
--- /dev/null
+From ffe42842b2d707cb7f5e1be7355fc9bfd39a509f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:46 -0700
+Subject: ethtool: rss: fix hkey leak when indir_size is 0
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 78ccf1a70c6378e1f5073a8c2209b5129067b925 ]
+
+rss_get_data_alloc() allocates a single buffer that backs both the
+indirection table and the hash key, but only assigned data->indir_table
+when indir_size was nonzero. The expectation was that no driver
+implements RSS without supporting indirection table but apparently
+enic does just that (it's the only such in-tree driver).
+enic has get_rxfh_key_size but no get_rxfh_indir_size.
+data->indir_table stays as NULL, hkey gets set but rss_get_data_free()
+kfree(data->indir_table) is a nop and the allocation leaks.
+
+Always store the allocation base in data->indir_table so the free path
+is unambiguous. No caller treats indir_table as a sentinel; everything
+keys off indir_size.
+
+Fixes: 7112a04664bf ("ethtool: add netlink based get rss support")
+Link: https://patch.msgid.link/20260522230647.1705600-6-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index 5416aec13b7fe7..f745ddec6fbab8 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -132,8 +132,7 @@ rss_get_data_alloc(struct net_device *dev, struct rss_reply_data *data)
+ if (!rss_config)
+ return -ENOMEM;
+
+- if (data->indir_size)
+- data->indir_table = (u32 *)rss_config;
++ data->indir_table = (u32 *)rss_config;
+ if (data->hkey_size)
+ data->hkey = rss_config + indir_bytes;
+
+--
+2.53.0
+
--- /dev/null
+From 364ef4eb6b6a58d4d0b4e4a5485b5dc28890262c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 16:06:45 -0700
+Subject: ethtool: rss: fix indir_table and hkey leak on get_rxfh failure
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 266297692f97008ca48bc311775c087c59bd7fe3 ]
+
+rss_prepare_get() allocates the indirection table and hash key buffer
+via rss_get_data_alloc(), then calls ops->get_rxfh() to populate them.
+If get_rxfh() fails, the function returns an error without freeing
+the allocation.
+
+Fixes: 4f038a6a02d2 ("net: ethtool: Don't call .cleanup_data when prepare_data fails")
+Link: https://patch.msgid.link/20260522230647.1705600-5-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/rss.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/ethtool/rss.c b/net/ethtool/rss.c
+index 4877655f724419..5416aec13b7fe7 100644
+--- a/net/ethtool/rss.c
++++ b/net/ethtool/rss.c
+@@ -168,8 +168,10 @@ rss_prepare_get(const struct rss_req_info *request, struct net_device *dev,
+ rxfh.key = data->hkey;
+
+ ret = ops->get_rxfh(dev, &rxfh);
+- if (ret)
++ if (ret) {
++ rss_get_data_free(data);
+ goto out_unlock;
++ }
+
+ data->hfunc = rxfh.hfunc;
+ data->input_xfrm = rxfh.input_xfrm;
+--
+2.53.0
+
--- /dev/null
+From c9d696dd1160472043a4c815b1e36b10d5e4ff95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:31 -0700
+Subject: ethtool: strset: fix header attribute index in ethnl_req_get_phydev()
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit a8d8bef6b45bf7cc0b1f6110c5cd8d0160a9bad7 ]
+
+strset_prepare_data() passes ETHTOOL_A_HEADER_FLAGS (3) as the header
+attribute to ethnl_req_get_phydev(). This is incorrect, in the main
+attr space 3 is ETHTOOL_A_STRSET_COUNTS_ONLY, not the request
+header attr. The correct constant is ETHTOOL_A_STRSET_HEADER (1).
+
+ethnl_req_get_phydev() only uses this value for the extack,
+so this is not a "functionally visible"(?) bug.
+
+Fixes: e96c93aa4be9 ("net: ethtool: strset: Allow querying phy stats by index")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-9-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/strset.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ethtool/strset.c b/net/ethtool/strset.c
+index f6a67109beda1b..872ca593b97668 100644
+--- a/net/ethtool/strset.c
++++ b/net/ethtool/strset.c
+@@ -309,7 +309,7 @@ static int strset_prepare_data(const struct ethnl_req_info *req_base,
+ return 0;
+ }
+
+- phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_HEADER_FLAGS,
++ phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_STRSET_HEADER,
+ info->extack);
+
+ /* phydev can be NULL, check for errors only */
+--
+2.53.0
+
--- /dev/null
+From fe14dfb0cbc18ca6a70b022e3896c127a0a45bde Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:28 -0700
+Subject: ethtool: tsconfig: fix missing ethnl_ops_complete()
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 6386bd772de64e6760306eb91c7e86163af6c22f ]
+
+tsconfig_prepare_data() calls ethnl_ops_begin(), we need to call
+ethnl_ops_complete() before returning the error.
+
+Fixes: 6e9e2eed4f39 ("net: ethtool: Add support for tsconfig command to get/set hwtstamp config")
+Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-6-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/tsconfig.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/tsconfig.c b/net/ethtool/tsconfig.c
+index 966c769c72677f..990dca9a3fc564 100644
+--- a/net/ethtool/tsconfig.c
++++ b/net/ethtool/tsconfig.c
+@@ -69,8 +69,10 @@ static int tsconfig_prepare_data(const struct ethnl_req_info *req_base,
+ if (ret)
+ goto out;
+
+- if (ts_info.phc_index == -1)
+- return -ENODEV;
++ if (ts_info.phc_index == -1) {
++ ret = -ENODEV;
++ goto out;
++ }
+
+ data->hwprov_desc.index = ts_info.phc_index;
+ data->hwprov_desc.qualifier = ts_info.phc_qualifier;
+--
+2.53.0
+
--- /dev/null
+From 4819737df5bdc3ca659a57227aa2933bf504fc91 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:25 -0700
+Subject: ethtool: tsconfig: fix reply error handling
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit a888bbd43940cada72f7686337741ce86d1cf869 ]
+
+A couple of trivial bugs in error handling in tsconfig_send_reply().
+If we failed to allocate rskb we need to set the error.
+If we did allocate it but failed to send it - we need to remember
+to free it.
+
+Fixes: 6e9e2eed4f39 ("net: ethtool: Add support for tsconfig command to get/set hwtstamp config")
+Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
+Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-3-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/tsconfig.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/net/ethtool/tsconfig.c b/net/ethtool/tsconfig.c
+index e49e612a68c2c0..966c769c72677f 100644
+--- a/net/ethtool/tsconfig.c
++++ b/net/ethtool/tsconfig.c
+@@ -224,16 +224,21 @@ static int tsconfig_send_reply(struct net_device *dev, struct genl_info *info)
+ reply_len = ret + ethnl_reply_header_size();
+ rskb = ethnl_reply_init(reply_len, dev, ETHTOOL_MSG_TSCONFIG_SET_REPLY,
+ ETHTOOL_A_TSCONFIG_HEADER, info, &reply_payload);
+- if (!rskb)
++ if (!rskb) {
++ ret = -ENOMEM;
+ goto err_cleanup;
++ }
+
+ ret = tsconfig_fill_reply(rskb, &req_info->base, &reply_data->base);
+ if (ret < 0)
+- goto err_cleanup;
++ goto err_free_msg;
+
+ genlmsg_end(rskb, reply_payload);
+ ret = genlmsg_reply(rskb, info);
++ rskb = NULL;
+
++err_free_msg:
++ nlmsg_free(rskb);
+ err_cleanup:
+ kfree(reply_data);
+ kfree(req_info);
+--
+2.53.0
+
--- /dev/null
+From c3bc87e1fee5346980304db27bf47d63b2ae47af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:30 -0700
+Subject: ethtool: tsinfo: don't pass ERR_PTR to genlmsg_cancel on prepare
+ failure
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit c3fc9976f686f9a95baf87db9d387f218fd65394 ]
+
+The goto err label leads to:
+
+ genlmsg_cancel(skb, ehdr);
+ return ret;
+
+If ethnl_tsinfo_prepare_dump() failed, it has not started a genlmsg.
+There's nothing to cancel, and passing an error pointer to
+genlmsg_cancel() would cause a crash.
+
+Fixes: b9e3f7dc9ed9 ("net: ethtool: tsinfo: Enhance tsinfo to support several hwtstamp by net topology")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-8-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/tsinfo.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/net/ethtool/tsinfo.c b/net/ethtool/tsinfo.c
+index cb1491e0a28bac..64e6016a7a1772 100644
+--- a/net/ethtool/tsinfo.c
++++ b/net/ethtool/tsinfo.c
+@@ -405,10 +405,8 @@ static int ethnl_tsinfo_dump_one_netdev(struct sk_buff *skb,
+ continue;
+
+ ehdr = ethnl_tsinfo_prepare_dump(skb, dev, reply_data, cb);
+- if (IS_ERR(ehdr)) {
+- ret = PTR_ERR(ehdr);
+- goto err;
+- }
++ if (IS_ERR(ehdr))
++ return PTR_ERR(ehdr);
+
+ reply_data->ts_info.phc_qualifier = ctx->pos_phcqualifier;
+ ret = ops->get_ts_info(dev, &reply_data->ts_info);
+--
+2.53.0
+
--- /dev/null
+From 547d8b6755488b890f877b151b8f04890c537bea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:29 -0700
+Subject: ethtool: tsinfo: fix uninitialized stats on the by-PHC path
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 1de405699c62c3a9544bcdcfb9eff8a01cfc7582 ]
+
+tsinfo_prepare_data() has two code paths: a "by-PHC" path for
+user-specified hardware timestamping providers, and the old path.
+Commit 89e281ebff72 ("ethtool: init tsinfo stats if requested") added
+ethtool_stats_init() to mark stat slots as ETHTOOL_STAT_NOT_SET before
+the driver callback populates them, but placed the call inside the
+old-path block.
+
+When commit b9e3f7dc9ed9 ("net: ethtool: tsinfo: Enhance tsinfo to
+support several hwtstamp by net topology") added the by-PHC early
+return, it landed above the stats initialization. On that path
+the stats array retains the zero-fill from ethnl_init_reply_data()'s
+zalloc. This leads to the reply including a stats nest with four
+zero-valued attributes that should have been absent.
+
+Reject GET requests for stats with HWTSTAMP_PROVIDER or dump.
+
+Fixes: b9e3f7dc9ed9 ("net: ethtool: tsinfo: Enhance tsinfo to support several hwtstamp by net topology")
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Link: https://patch.msgid.link/20260526153533.2779187-7-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ethtool/tsinfo.c | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+
+diff --git a/net/ethtool/tsinfo.c b/net/ethtool/tsinfo.c
+index c0145c752d2f8b..cb1491e0a28bac 100644
+--- a/net/ethtool/tsinfo.c
++++ b/net/ethtool/tsinfo.c
+@@ -81,6 +81,11 @@ tsinfo_parse_request(struct ethnl_req_info *req_base, struct nlattr **tb,
+ if (!tb[ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER])
+ return 0;
+
++ if (req_base->flags & ETHTOOL_FLAG_STATS) {
++ NL_SET_ERR_MSG(extack, "can't query statistics for a provider");
++ return -EOPNOTSUPP;
++ }
++
+ return ts_parse_hwtst_provider(tb[ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER],
+ &req->hwprov_desc, extack, &mod);
+ }
+@@ -521,6 +526,12 @@ int ethnl_tsinfo_start(struct netlink_callback *cb)
+ if (ret < 0)
+ goto free_reply_data;
+
++ if (req_info->base.flags & ETHTOOL_FLAG_STATS) {
++ NL_SET_ERR_MSG(cb->extack, "stats not supported in dump");
++ ret = -EOPNOTSUPP;
++ goto err_dev_put;
++ }
++
+ ctx->req_info = req_info;
+ ctx->reply_data = reply_data;
+ ctx->pos_ifindex = 0;
+@@ -530,6 +541,8 @@ int ethnl_tsinfo_start(struct netlink_callback *cb)
+
+ return 0;
+
++err_dev_put:
++ ethnl_parse_header_dev_put(&req_info->base);
+ free_reply_data:
+ kfree(reply_data);
+ free_req_info:
+--
+2.53.0
+
--- /dev/null
+From e4087ffb82072afe9d635ba50f4bae9e67a6fc05 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 09:35:27 +0200
+Subject: gpio: adnp: fix flow control regression caused by scoped_guard()
+
+From: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+
+[ Upstream commit a5c627d90809b793fc053849b3a00609db305776 ]
+
+scoped_guard() is implemented as a for loop. Using it to protect code
+using the continue statement changes the flow as we now only break out
+of the hidden loop inside scoped_guard(), not the original for loop. Use
+a regular code block instead.
+
+Fixes: c7fe19ed3973 ("gpio: adnp: use lock guards for the I2C lock")
+Reported-by: David Lechner <dlechner@baylibre.com>
+Closes: https://lore.kernel.org/all/cde2abb2-4cc8-4fc9-b34a-0c5d2b95779f@baylibre.com/
+Reviewed-by: Linus Walleij <linusw@kernel.org>
+Link: https://patch.msgid.link/20260522073527.9812-1-bartosz.golaszewski@oss.qualcomm.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-adnp.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
+index e5ac2d2110137f..fe5bcaa90496aa 100644
+--- a/drivers/gpio/gpio-adnp.c
++++ b/drivers/gpio/gpio-adnp.c
+@@ -237,7 +237,9 @@ static irqreturn_t adnp_irq(int irq, void *data)
+ unsigned long pending;
+ int err;
+
+- scoped_guard(mutex, &adnp->i2c_lock) {
++ {
++ guard(mutex)(&adnp->i2c_lock);
++
+ err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level);
+ if (err < 0)
+ continue;
+--
+2.53.0
+
--- /dev/null
+From 9aff72d05d5c0f628301257534f677cbd8c5085c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 08:35:01 +0200
+Subject: gpio: mxc: fix irq_high handling
+
+From: Alexander Stein <alexander.stein@ew.tq-group.com>
+
+[ Upstream commit dac917ed5aead741004db8d0d5151dd577802df8 ]
+
+If port->irq_high is -1 (fsl,imx21-gpio compatible) and gpio_idx is >= 16
+enable_irq_wake() is called with -1 which is wrong.
+
+Fixes: 5f6d1998adeb ("gpio: mxc: release the parent IRQ in runtime suspend")
+Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://patch.msgid.link/20260526063504.25916-1-alexander.stein@ew.tq-group.com
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-mxc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
+index 647b6f4861b744..12f11a6c96653c 100644
+--- a/drivers/gpio/gpio-mxc.c
++++ b/drivers/gpio/gpio-mxc.c
+@@ -469,7 +469,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
+ * the handler is needed only once, but doing it for every port
+ * is more robust and easier.
+ */
+- port->irq_high = -1;
++ port->irq_high = 0;
+ port->mx_irq_handler = mx2_gpio_irq_handler;
+ } else
+ port->mx_irq_handler = mx3_gpio_irq_handler;
+--
+2.53.0
+
--- /dev/null
+From 5984d5b25d011db16b6c794b47f97aed9636d7ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:02:45 +0200
+Subject: gpio: rockchip: convert bank->clk to devm_clk_get_enabled()
+
+From: Marco Scardovi <scardracs@disroot.org>
+
+[ Upstream commit 3e46c18d5d87f063a93ae0fe7662fbf6660459d5 ]
+
+The bank->clk was previously obtained via of_clk_get() and manually
+prepared/enabled. However, it was missing a corresponding clk_put() in
+both the error paths and the remove function, leading to a reference leak.
+
+Convert the allocation to devm_clk_get_enabled(), which also properly
+propagates failures from clk_prepare_enable() that were previously ignored.
+
+The GPIO bank device uses the same OF node as the previous of_clk_get()
+call, so devm_clk_get_enabled(dev, NULL) correctly resolves the same
+clock provider entry.
+
+Fix the reference leak and simplify the code by removing the manual
+clk_disable_unprepare() calls in the probe error paths and in the
+remove function.
+
+Fixes: 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio")
+Assisted-by: Antigravity:gemini-3.5-flash
+Signed-off-by: Marco Scardovi <scardracs@disroot.org>
+Link: https://patch.msgid.link/20260526171050.12785-2-scardracs@disroot.org
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-rockchip.c | 6 +-----
+ 1 file changed, 1 insertion(+), 5 deletions(-)
+
+diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
+index 0fff4a699f12d1..f910220141f712 100644
+--- a/drivers/gpio/gpio-rockchip.c
++++ b/drivers/gpio/gpio-rockchip.c
+@@ -656,11 +656,10 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ if (!bank->irq)
+ return -EINVAL;
+
+- bank->clk = of_clk_get(bank->of_node, 0);
++ bank->clk = devm_clk_get_enabled(bank->dev, NULL);
+ if (IS_ERR(bank->clk))
+ return PTR_ERR(bank->clk);
+
+- clk_prepare_enable(bank->clk);
+ id = readl(bank->reg_base + gpio_regs_v2.version_id);
+
+ switch (id) {
+@@ -672,7 +671,6 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ bank->db_clk = of_clk_get(bank->of_node, 1);
+ if (IS_ERR(bank->db_clk)) {
+ dev_err(bank->dev, "cannot find debounce clk\n");
+- clk_disable_unprepare(bank->clk);
+ return -EINVAL;
+ }
+ break;
+@@ -751,7 +749,6 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
+
+ ret = rockchip_gpiolib_register(bank);
+ if (ret) {
+- clk_disable_unprepare(bank->clk);
+ mutex_unlock(&bank->deferred_lock);
+ return ret;
+ }
+@@ -792,7 +789,6 @@ static void rockchip_gpio_remove(struct platform_device *pdev)
+ {
+ struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
+
+- clk_disable_unprepare(bank->clk);
+ gpiochip_remove(&bank->gpio_chip);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 6b190e68f9aa881bd5f5a82a7c5f19062d079730 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 19:02:46 +0200
+Subject: gpio: rockchip: teardown bugs and resource leaks
+
+From: Marco Scardovi <scardracs@disroot.org>
+
+[ Upstream commit 9500077678230e36d22bf16d2b9539c13e59a801 ]
+
+Address several teardown issues and resource leaks in the driver's remove
+path and error handling:
+
+1. Debounce clock reference leak: The debounce clock (bank->db_clk) is
+ obtained using of_clk_get() which increments the clock's reference
+ count, but clk_put() is never called. Register a devm action to
+ cleanly release it on unbind. Note that of_clk_get(..., 1) remains
+ necessary over devm_clk_get() because the DT binding does not define
+ clock-names, precluding name-based lookup.
+
+2. Unregistered chained IRQ handler: The chained IRQ handler is not
+ disconnected in remove(). If a stray interrupt fires after the driver
+ is removed, the kernel attempts to execute a stale handler, leading
+ to a panic. Fix this by clearing the handler in remove().
+
+3. IRQ domain leak: The linear IRQ domain and its generic chips are
+ allocated manually during probe but never removed. Remove the IRQ
+ domain during driver teardown to free the associated generic chips
+ and mappings.
+
+Fixes: 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio")
+Assisted-by: Antigravity:gemini-3.5-flash
+Signed-off-by: Marco Scardovi <scardracs@disroot.org>
+Link: https://patch.msgid.link/20260526171050.12785-3-scardracs@disroot.org
+[Bartosz: don't emit an error message on devres allocation failure]
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-rockchip.c | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
+index f910220141f712..1ef0ba956cfd8c 100644
+--- a/drivers/gpio/gpio-rockchip.c
++++ b/drivers/gpio/gpio-rockchip.c
+@@ -638,10 +638,17 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
+ return ret;
+ }
+
++static void rockchip_clk_put(void *data)
++{
++ struct clk *clk = data;
++
++ clk_put(clk);
++}
++
+ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ {
+ struct resource res;
+- int id = 0;
++ int id = 0, ret;
+
+ if (of_address_to_resource(bank->of_node, 0, &res)) {
+ dev_err(bank->dev, "cannot find IO resource for bank\n");
+@@ -673,6 +680,11 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+ dev_err(bank->dev, "cannot find debounce clk\n");
+ return -EINVAL;
+ }
++
++ ret = devm_add_action_or_reset(bank->dev, rockchip_clk_put,
++ bank->db_clk);
++ if (ret)
++ return ret;
+ break;
+ case GPIO_TYPE_V1:
+ bank->gpio_regs = &gpio_regs_v1;
+@@ -789,6 +801,9 @@ static void rockchip_gpio_remove(struct platform_device *pdev)
+ {
+ struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
+
++ irq_set_chained_handler_and_data(bank->irq, NULL, NULL);
++ if (bank->domain)
++ irq_domain_remove(bank->domain);
+ gpiochip_remove(&bank->gpio_chip);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 15f2fc579a4fb8ff836c58cfc9d011b7828e3add Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 10:15:16 +0300
+Subject: gpio: virtuser: Fix uninitialized data bug in
+ gpio_virtuser_direction_do_write()
+
+From: Dan Carpenter <error27@gmail.com>
+
+[ Upstream commit 8a122b5e72cc0043705f0d524bcd15f0c0b3ec15 ]
+
+If *ppos is non-zero (user-space write split over multiple calls to
+write()) then simple_write_to_buffer() won't initialize the start of the
+buffer. Really, non-zero values for *ppos aren't going to work at all.
+Check for that and return -EINVAL at the start of the function.
+
+Fixes: 91581c4b3f29 ("gpio: virtuser: new virtual testing driver for the GPIO API")
+Signed-off-by: Dan Carpenter <error27@gmail.com>
+Link: https://patch.msgid.link/ahP3BJWWy-m_qI0X@stanley.mountain
+Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-virtuser.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpio/gpio-virtuser.c b/drivers/gpio/gpio-virtuser.c
+index 955b5efc283ef5..c6f16cb02bf6b8 100644
+--- a/drivers/gpio/gpio-virtuser.c
++++ b/drivers/gpio/gpio-virtuser.c
+@@ -399,7 +399,7 @@ static ssize_t gpio_virtuser_direction_do_write(struct file *file,
+ char buf[32], *trimmed;
+ int ret, dir, val = 0;
+
+- if (count >= sizeof(buf))
++ if (*ppos != 0 || count >= sizeof(buf))
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
+@@ -624,7 +624,7 @@ static ssize_t gpio_virtuser_consumer_write(struct file *file,
+ char buf[GPIO_VIRTUSER_NAME_BUF_LEN + 2];
+ int ret;
+
+- if (count >= sizeof(buf))
++ if (*ppos != 0 || count >= sizeof(buf))
+ return -EINVAL;
+
+ ret = simple_write_to_buffer(buf, GPIO_VIRTUSER_NAME_BUF_LEN, ppos,
+--
+2.53.0
+
--- /dev/null
+From c978f9e8dfcc900acff83041b76d773ac13e293a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 May 2026 16:32:04 +0800
+Subject: HID: remove duplicate hid_warn_ratelimited definition
+
+From: Liu Kai <lukace97@outlook.com>
+
+[ Upstream commit dd2147375a8fe7c5bc3f1f1b1d3a9567c26faefa ]
+
+The hid_warn_ratelimited macro is defined twice in include/linux/hid.h:
+- first one added by commit 4051ead99888 ("HID: rate-limit hid_warn to
+ prevent log flooding")
+- second one added by commit 1d64624243af ("HID: core: Add
+ printk_ratelimited variants to hid_warn() etc")).
+
+The second definition is correctly grouped with other ratelimited macros.
+Remove the duplicate definition.
+
+Fixes: 1d64624243af ("HID: core: Add printk_ratelimited variants to hid_warn() etc")
+Signed-off-by: Liu Kai <lukace97@outlook.com>
+[bentiss: edited commit message]
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/hid.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/include/linux/hid.h b/include/linux/hid.h
+index 101e05acf931a5..c9e0ebe9c75270 100644
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -1284,8 +1284,6 @@ void hid_quirks_exit(__u16 bus);
+ dev_notice(&(hid)->dev, fmt, ##__VA_ARGS__)
+ #define hid_warn(hid, fmt, ...) \
+ dev_warn(&(hid)->dev, fmt, ##__VA_ARGS__)
+-#define hid_warn_ratelimited(hid, fmt, ...) \
+- dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__)
+ #define hid_info(hid, fmt, ...) \
+ dev_info(&(hid)->dev, fmt, ##__VA_ARGS__)
+ #define hid_dbg(hid, fmt, ...) \
+--
+2.53.0
+
--- /dev/null
+From 55c128606073a42ce30811703a73053e46d35a53 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 12:21:47 +0000
+Subject: ipv4: free net->ipv4.sysctl_local_reserved_ports after
+ unregister_net_sysctl_table()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 87a1e0fe7776da7ab411be332b4be58ac8840d10 ]
+
+ipv4_sysctl_exit_net() is currently freeing net->ipv4.sysctl_local_reserved_ports
+too soon.
+
+Only after unregister_net_sysctl_table() we can be sure no threads can possibly
+use the sysctls, including /proc/sys/net/ipv4/ip_local_reserved_ports.
+
+Fixes: 122ff243f5f1 ("ipv4: make ip_local_reserved_ports per netns")
+Reported-by: Ji'an Zhou <eilaimemedsnaimel@gmail.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Cong Wang <xiyou.wangcong@gmail.com>
+Reviewed-by: Jason Xing <kerneljasonxing@gmail.com>
+Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Link: https://patch.msgid.link/20260521122147.3584624-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/sysctl_net_ipv4.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
+index 5654cc9c8a0b9e..e47df4d706a9cd 100644
+--- a/net/ipv4/sysctl_net_ipv4.c
++++ b/net/ipv4/sysctl_net_ipv4.c
+@@ -1698,10 +1698,10 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net)
+ {
+ const struct ctl_table *table;
+
+- kfree(net->ipv4.sysctl_local_reserved_ports);
+ table = net->ipv4.ipv4_hdr->ctl_table_arg;
+ unregister_net_sysctl_table(net->ipv4.ipv4_hdr);
+ kfree(table);
++ kfree(net->ipv4.sysctl_local_reserved_ports);
+ }
+
+ static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
+--
+2.53.0
+
--- /dev/null
+From 0e9f2f0f7b61ab6f16e0d83d28aa893042404627 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:31:31 +0800
+Subject: ipv6: fix possible infinite loop in fib6_select_path()
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 9c7da87c2dc860bb17ca1ece942495d28b1ce3b9 ]
+
+Found while auditing the same pattern Sashiko reported in
+rt6_fill_node() [1]. Apply the same fix as
+commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").
+
+Writers holding tb6_lock can list_del_rcu(&first->fib6_siblings)
+without waiting for RCU readers; first->fib6_siblings.next then
+still points into the old ring and this softirq-side walker never
+reaches &first->fib6_siblings as its terminator. fib6_purge_rt()
+always WRITE_ONCE()s first->fib6_nsiblings to 0 before
+list_del_rcu(), so an inside-loop check is a reliable detach signal.
+
+[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev
+
+Fixes: d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260527053133.180695-2-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index 398e873072bbfb..9a45ecdd7b853c 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -481,6 +481,9 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
+ const struct fib6_nh *nh = sibling->fib6_nh;
+ int nh_upper_bound;
+
++ if (!READ_ONCE(first->fib6_nsiblings))
++ break;
++
+ nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
+ if (hash > nh_upper_bound)
+ continue;
+--
+2.53.0
+
--- /dev/null
+From 165f5786a691227b7d6197905485bc0395eab4ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 13:31:30 +0800
+Subject: ipv6: fix possible infinite loop in rt6_fill_node()
+
+From: Jiayuan Chen <jiayuan.chen@linux.dev>
+
+[ Upstream commit 9f72412bcf60144f252b0d6205106abf14344abc ]
+
+Sashiko reported this issue [1]. Apply the same fix as
+commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").
+
+Writers holding tb6_lock can list_del_rcu(&rt->fib6_siblings)
+without waiting for RCU readers; rt->fib6_siblings.next then still
+points into the old ring and this softirq-side walker never reaches
+&rt->fib6_siblings, causing a CPU stall. fib6_del_route() always
+WRITE_ONCE()s rt->fib6_nsiblings to 0 before list_del_rcu(), so an
+inside-loop check is a reliable detach signal.
+
+[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev
+
+Fixes: d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
+Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20260527053133.180695-1-jiayuan.chen@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/route.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/ipv6/route.c b/net/ipv6/route.c
+index cb521700cee7ed..398e873072bbfb 100644
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -5891,6 +5891,8 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
+
+ goto nla_put_failure;
+ }
++ if (!READ_ONCE(rt->fib6_nsiblings))
++ break;
+ }
+
+ rcu_read_unlock();
+--
+2.53.0
+
--- /dev/null
+From 13865a97cf43376e9c365cc3602035cc0d13b553 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 21:10:31 +0530
+Subject: ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress()
+
+From: Rahul Chandelkar <rc@rexion.ai>
+
+[ Upstream commit 9d5e7a46a9f6d8f503b41bfefef70659845f1679 ]
+
+ipv6_rpl_srh_decompress() computes:
+
+ outhdr->hdrlen = (((n + 1) * sizeof(struct in6_addr)) >> 3);
+
+hdrlen is __u8. For n >= 127 the result exceeds 255 and silently
+truncates. With n=127 (cmpri=15, cmpre=15, pad=0, hdrlen=16):
+
+ (128 * 16) >> 3 = 256, truncated to 0 as __u8
+
+The caller in ipv6_rpl_srh_rcv() then places the compressed header
+at buf + ((ohdr->hdrlen + 1) << 3). With hdrlen=0 this is buf + 8,
+but the decompressed region occupies buf[0..2055] (8-byte header
+plus 128 full addresses). The compressed header overlaps the
+decompressed data, and ipv6_rpl_srh_compress() writes into this
+overlap, corrupting the routing header of the forwarded packet.
+
+The existing guard at exthdrs.c:546 checks (n + 1) > 255, which
+prevents n+1 from overflowing unsigned char (the segments_left
+field), but does not prevent the computed hdrlen from overflowing
+__u8. n=127 passes because 128 <= 255, yet hdrlen=256 does not
+fit.
+
+Tighten the bound to (n + 1) > 127. This caps n at 126, giving
+hdrlen = (127 * 16) >> 3 = 254, which fits in __u8. The compressed
+header then lands at buf + ((254 + 1) << 3) = buf + 2040, exactly
+past the decompressed region (buf[0..2039]). No overlap. 127
+segments is well beyond any realistic RPL deployment.
+
+Fixes: 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
+Signed-off-by: Rahul Chandelkar <rc@rexion.ai>
+Link: https://patch.msgid.link/20260525154031.2290876-1-rc@rexion.ai
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/exthdrs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
+index cf90f933ca1ada..3757317e8151e0 100644
+--- a/net/ipv6/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -544,7 +544,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)
+ * unsigned char which is segments_left field. Should not be
+ * higher than that.
+ */
+- if (r || (n + 1) > 255) {
++ if (r || (n + 1) > 127) {
+ kfree_skb(skb);
+ return -1;
+ }
+--
+2.53.0
+
--- /dev/null
+From 8e2042f9ba5741e337370a16551934b0f431b7b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 Mar 2026 20:49:56 +0530
+Subject: kernel/fork: validate exit_signal in kernel_clone()
+
+From: Deepanshu Kartikey <kartikey406@gmail.com>
+
+[ Upstream commit 09e7827e785729f391c8d46dc71becce70d296ab ]
+
+When a child process exits, it sends exit_signal to its parent via
+do_notify_parent(). The clone() syscall constructs exit_signal as:
+
+(lower_32_bits(clone_flags) & CSIGNAL)
+
+CSIGNAL is 0xff, so values in the range 65-255 are possible. However,
+valid_signal() only accepts signals up to _NSIG (64 on x86_64). A
+non-zero non-valid exit_signal acts the same as exit_signal == 0: the
+parent process is not signaled when the child terminates.
+
+The syzkaller reproducer triggers this by calling clone() with flags=0x80,
+resulting in exit_signal = (0x80 & CSIGNAL) = 128, which exceeds _NSIG and
+is not a valid signal.
+
+The v1 of this patch added the check only in the clone() syscall handler,
+which is incomplete. kernel_clone() has other callers such as
+sys_ia32_clone() which would remain unprotected. Move the check to
+kernel_clone() to cover all callers.
+
+Since the valid_signal() check is now in kernel_clone() and covers all
+callers including clone3(), the same check in copy_clone_args_from_user()
+becomes redundant and is removed. The higher 32bits check for clone3() is
+kept as it is clone3() specific.
+
+Note that this is a user-visible change: previously, passing an invalid
+exit_signal to clone() was silently accepted. The man page for clone()
+does not document any defined behavior for invalid exit_signal values, so
+rejecting them with -EINVAL is the correct behavior. It is unlikely that
+any sane application relies on passing an invalid exit_signal.
+
+[oleg@redhat.com: the comment above kernel_clone() should be updated]
+ Link: https://lore.kernel.org/abwvgU17W8wuW2-J@redhat.com
+Link: https://lore.kernel.org/20260316151956.563558-1-kartikey406@gmail.com
+Fixes: 3f2c788a1314 ("fork: prevent accidental access to clone3 features")
+Signed-off-by: Deepanshu Kartikey <Kartikey406@gmail.com>
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Reported-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=bbe6b99feefc3a0842de
+Tested-by: syzbot+bbe6b99feefc3a0842de@syzkaller.appspotmail.com
+Link: https://lore.kernel.org/all/20260307064202.353405-1-kartikey406@gmail.com/T/ [v1]
+Link: https://lore.kernel.org/all/20260316104536.558108-1-kartikey406@gmail.com/T/ [v2]
+Acked-by: Oleg Nesterov <oleg@redhat.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Ben Segall <bsegall@google.com>
+Cc: Christian Brauner <brauner@kernel.org>
+Cc: David Hildenbrand <david@kernel.org>
+Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Juri Lelli <juri.lelli@redhat.com>
+Cc: Kees Cook <kees@kernel.org>
+Cc: Liam Howlett <liam@infradead.org>
+Cc: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
+Cc: Mel Gorman <mgorman@suse.de>
+Cc: Mike Rapoport <rppt@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Suren Baghdasaryan <surenb@google.com>
+Cc: Valentin Schneider <vschneid@redhat.com>
+Cc: Vincent Guittot <vincent.guittot@linaro.org>
+Cc: Vlastimil Babka <vbabka@kernel.org>
+Cc: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/fork.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 73622ad0665a07..bcde8e2843fb97 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -2606,8 +2606,6 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node)
+ *
+ * It copies the process, and if successful kick-starts
+ * it and waits for it to finish using the VM if required.
+- *
+- * args->exit_signal is expected to be checked for sanity by the caller.
+ */
+ pid_t kernel_clone(struct kernel_clone_args *args)
+ {
+@@ -2632,6 +2630,9 @@ pid_t kernel_clone(struct kernel_clone_args *args)
+ (args->pidfd == args->parent_tid))
+ return -EINVAL;
+
++ if (!valid_signal(args->exit_signal))
++ return -EINVAL;
++
+ /*
+ * Determine whether and which event to report to ptracer. When
+ * called from kernel_thread or CLONE_UNTRACED is explicitly
+@@ -2830,11 +2831,9 @@ static noinline int copy_clone_args_from_user(struct kernel_clone_args *kargs,
+ return -EINVAL;
+
+ /*
+- * Verify that higher 32bits of exit_signal are unset and that
+- * it is a valid signal
++ * Verify that higher 32bits of exit_signal are unset
+ */
+- if (unlikely((args.exit_signal & ~((u64)CSIGNAL)) ||
+- !valid_signal(args.exit_signal)))
++ if (unlikely(args.exit_signal & ~((u64)CSIGNAL)))
+ return -EINVAL;
+
+ if ((args.flags & CLONE_INTO_CGROUP) &&
+--
+2.53.0
+
--- /dev/null
+From 3cf7fd18201f3829d9b400331cd5dd626d1e0142 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 22:07:16 +0900
+Subject: ksmbd: fix FSCTL permission bypass by adding a permission check for
+ FSCTL_SET_SPARSE
+
+From: Sean Shen <grayhat@foxmail.com>
+
+[ Upstream commit cc57232cae23c0df91b4a59d0f519141ce9b5b02 ]
+
+FSCTL_SET_SPARSE in fsctl_set_sparse() modifies the file's sparse
+attribute and saves it through xattr without any permission checks.
+
+This exposes two issues:
+
+1) A client on a read-only share can change the sparse attribute
+ on files it opened, even though the share is read-only.
+ Other FSCTL write operations already check
+ test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE),
+ but FSCTL_SET_SPARSE does not.
+
+2) Even on writable shares, clients without FILE_WRITE_DATA or
+ FILE_WRITE_ATTRIBUTES access should not modify the sparse
+ attribute. Similar handle-level checks exist in other functions
+ but are missing here.
+
+Add both share-level writable check and per-handle access check.
+Use goto out on error to avoid leaking file references.
+
+Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
+Cc: Namjae Jeon <linkinjeon@kernel.org>
+Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
+Cc: Steve French <smfrench@gmail.com>
+Signed-off-by: Sean Shen <grayhat@foxmail.com>
+Acked-by: Namjae Jeon <linkinjeon@kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/smb/server/smb2pdu.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
+index 3a8a739c025fb7..64ef1b8b37f8ad 100644
+--- a/fs/smb/server/smb2pdu.c
++++ b/fs/smb/server/smb2pdu.c
+@@ -8202,9 +8202,20 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
+ int ret = 0;
+ __le32 old_fattr;
+
++ if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
++ ksmbd_debug(SMB, "User does not have write permission\n");
++ return -EACCES;
++ }
++
+ fp = ksmbd_lookup_fd_fast(work, id);
+ if (!fp)
+ return -ENOENT;
++
++ if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_WRITE_ATTRIBUTES_LE))) {
++ ret = -EACCES;
++ goto out;
++ }
++
+ idmap = file_mnt_idmap(fp->filp);
+
+ old_fattr = fp->f_ci->m_fattr;
+--
+2.53.0
+
--- /dev/null
+From 24af084aa70b0ebc3ba5365f20e1b0815dd3fbb0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 May 2026 10:48:54 +0200
+Subject: kunit: fix use-after-free in debugfs when using kunit.filter
+
+From: Florian Schmaus <florian.schmaus@codasip.com>
+
+[ Upstream commit fb6988b83b4cafe8db63999c1ddff1b7c66d2ff5 ]
+
+When the kernel is booted with a kunit filter (e.g.,
+kunit.filter="speed!=slow"), the kunit executor dynamically allocates
+copies of the filtered test suites using kmalloc/kmemdup.
+
+During the initial boot execution, kunit_debugfs_create_suite() creates
+debugfs files (such as /sys/kernel/debug/kunit/<suite>/run) and
+permanently stores a pointer to the dynamically allocated suite in the
+inode's i_private field.
+
+Previously, the executor freed this dynamically allocated suite_set
+immediately after executing the boot-time tests. Because the debugfs
+nodes were not destroyed, any subsequent interaction with the debugfs
+`run` file from userspace triggered a use-after-free (UAF). On systems
+with architectural capabilities, like CHERI RISC-V, this resulted in
+an immediate fatal hardware exception due to the invalidation of the
+capability tags on the reclaimed memory. On other architectures, it
+resulted in silent memory corruption.
+
+Fix this UAF by properly coupling the lifetime of the filtered suite
+memory allocation to the lifetime of the kunit subsystem and its
+associated VFS nodes. Ownership of the boot-time suite_set is now
+transferred to a global tracker ('kunit_boot_suites'), and the memory
+is cleanly released in kunit_exit() during module teardown.
+
+Link: https://lore.kernel.org/r/20260507084854.233984-1-florian.schmaus@codasip.com
+Fixes: e2219db280e3 ("kunit: add debugfs /sys/kernel/debug/kunit/<suite>/results display")
+Signed-off-by: Florian Schmaus <florian.schmaus@codasip.com>
+Reviewed-by: Martin Kaiser <martin@kaiser.cx>
+Reviewed-by: David Gow <david@davidgow.net>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/kunit/test.h | 1 +
+ lib/kunit/executor.c | 19 ++++++++++++++++---
+ lib/kunit/test.c | 1 +
+ 3 files changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/include/kunit/test.h b/include/kunit/test.h
+index 9cd1594ab697d9..ce0573e196ce75 100644
+--- a/include/kunit/test.h
++++ b/include/kunit/test.h
+@@ -613,6 +613,7 @@ unsigned long kunit_vm_mmap(struct kunit *test, struct file *file,
+ unsigned long offset);
+
+ void kunit_cleanup(struct kunit *test);
++void kunit_free_boot_suites(void);
+
+ void __printf(2, 3) kunit_log_append(struct string_stream *log, const char *fmt, ...);
+
+diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
+index 1fef217de11db1..b0f8a41d61d367 100644
+--- a/lib/kunit/executor.c
++++ b/lib/kunit/executor.c
+@@ -15,6 +15,16 @@ extern struct kunit_suite * const __kunit_suites_end[];
+ extern struct kunit_suite * const __kunit_init_suites_start[];
+ extern struct kunit_suite * const __kunit_init_suites_end[];
+
++static struct kunit_suite_set kunit_boot_suites;
++
++void kunit_free_boot_suites(void)
++{
++ if (kunit_boot_suites.start) {
++ kunit_free_suite_set(kunit_boot_suites);
++ kunit_boot_suites = (struct kunit_suite_set){ NULL, NULL };
++ }
++}
++
+ static char *action_param;
+
+ module_param_named(action, action_param, charp, 0400);
+@@ -411,9 +421,12 @@ int kunit_run_all_tests(void)
+ pr_err("kunit executor: unknown action '%s'\n", action_param);
+
+ free_out:
+- if (filter_glob_param || filter_param)
+- kunit_free_suite_set(suite_set);
+- else if (init_num_suites > 0)
++ if (filter_glob_param || filter_param) {
++ if (err)
++ kunit_free_suite_set(suite_set);
++ else
++ kunit_boot_suites = suite_set;
++ } else if (init_num_suites > 0)
+ /* Don't use kunit_free_suite_set because suites aren't individually allocated */
+ kfree(suite_set.start);
+
+diff --git a/lib/kunit/test.c b/lib/kunit/test.c
+index 41e1c89799b6a7..99773e000e1b77 100644
+--- a/lib/kunit/test.c
++++ b/lib/kunit/test.c
+@@ -1075,6 +1075,7 @@ static void __exit kunit_exit(void)
+ kunit_bus_shutdown();
+
+ kunit_debugfs_cleanup();
++ kunit_free_boot_suites();
+ }
+ module_exit(kunit_exit);
+
+--
+2.53.0
+
--- /dev/null
+From a7143d3ec18f53d308b13cd88e690526a14c8e59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 14:06:40 +0200
+Subject: net: Avoid checksumming unreadable skb tail on trim
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Björn Töpel <bjorn@kernel.org>
+
+[ Upstream commit 2e357f002c61fd76fd8f12468744a06a5ec48eaa ]
+
+pskb_trim_rcsum_slow() keeps CHECKSUM_COMPLETE valid by subtracting
+the checksum of the bytes removed from the skb tail. That assumes the
+removed bytes can be read.
+
+io_uring zcrx skbs may contain unreadable net_iov frags. With fbnic
+header/data split, small TCP/IPv4 packets can carry Ethernet padding
+in such a frag. ip_rcv_core() trims the skb to iph->tot_len before TCP
+sees it, and the CHECKSUM_COMPLETE adjustment then calls
+skb_checksum() on the padding.
+
+This is exposed by IPv4 because small TCP/IPv4 frames can be shorter
+than the Ethernet minimum payload. TCP/IPv6 frames are large enough in
+the normal zcrx path, so they do not hit the same padding trim.
+
+Keep the existing checksum adjustment for readable skbs. If the
+remaining packet is fully linear, drop CHECKSUM_COMPLETE and let the
+stack validate the packet after trimming. If unreadable payload would
+remain, fail the trim; the checksum cannot be adjusted without reading
+the trimmed tail.
+
+Also clear skb->unreadable when trimming removes all frags.
+
+Fixes: 65249feb6b3d ("net: add support for skbs with unreadable frags")
+Signed-off-by: Björn Töpel <bjorn@kernel.org>
+Reviewed-by: Breno Leitao <leitao@debian.org>
+Link: https://patch.msgid.link/20260522120643.242974-1-bjorn@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/skbuff.c | 31 +++++++++++++++++++++++++++----
+ 1 file changed, 27 insertions(+), 4 deletions(-)
+
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 28bd8304796d7a..13af6f35428d52 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -2811,6 +2811,8 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
+ skb->data_len = 0;
+ skb_set_tail_pointer(skb, len);
+ }
++ if (!skb_shinfo(skb)->nr_frags && !skb_has_frag_list(skb))
++ skb->unreadable = 0;
+
+ if (!skb->sk || skb->destructor == sock_edemux)
+ skb_condense(skb);
+@@ -2818,16 +2820,37 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
+ }
+ EXPORT_SYMBOL(___pskb_trim);
+
++static int pskb_trim_rcsum_complete(struct sk_buff *skb, unsigned int len)
++{
++ int delta = skb->len - len;
++
++ if (skb_frags_readable(skb)) {
++ skb->csum = csum_block_sub(skb->csum,
++ skb_checksum(skb, len, delta, 0),
++ len);
++ return 0;
++ }
++
++ if (len > skb_headlen(skb))
++ return -EFAULT;
++
++ /* The trimmed bytes are unreadable, but the remaining packet can be
++ * checksummed by software after trimming.
++ */
++ skb->ip_summed = CHECKSUM_NONE;
++ return 0;
++}
++
+ /* Note : use pskb_trim_rcsum() instead of calling this directly
+ */
+ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len)
+ {
+ if (skb->ip_summed == CHECKSUM_COMPLETE) {
+- int delta = skb->len - len;
++ int err;
+
+- skb->csum = csum_block_sub(skb->csum,
+- skb_checksum(skb, len, delta, 0),
+- len);
++ err = pskb_trim_rcsum_complete(skb, len);
++ if (err)
++ return err;
+ } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ int hdlen = (len > skb_headlen(skb)) ? skb_headlen(skb) : len;
+ int offset = skb_checksum_start_offset(skb) + skb->csum_offset;
+--
+2.53.0
+
--- /dev/null
+From 0931ecae42ad61cc1eddcb4ad81df6fa680a1311 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:22 -0400
+Subject: net/handshake: Drain pending requests at net namespace exit
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit ea5fe6a73ca57e5150b8a38b341aef2636eb72f0 ]
+
+The arguments to list_splice_init() in handshake_net_exit() are
+reversed. The call moves the local empty "requests" list onto
+hn->hn_requests, leaving the local list empty, so the subsequent
+drain loop runs zero iterations. Pending handshake requests that
+had not yet been accepted are not torn down when the net namespace
+is destroyed; each one keeps a reference on a socket file and on
+the handshake_req allocation.
+
+Pass the source and destination in the documented order
+(list_splice_init(list, head) moves list onto head) so the pending
+list is transferred to the local scratch list and drained through
+handshake_complete().
+
+Fixing the splice direction exposes a list-corruption race. After
+the splice each req->hr_list still has non-empty link pointers,
+threading the stack-local scratch list rather than hn_requests.
+A concurrent handshake_req_cancel() -- for example, from sunrpc's
+TLS timeout on a kernel socket whose netns reference was not
+taken -- finds the request through the rhashtable, calls
+remove_pending(), and sees !list_empty(&req->hr_list).
+__remove_pending_locked() then list_del_init()s an entry off the
+scratch list while the drain iterates, corrupting it. The same
+call arriving after the drain loop has run list_del() on an
+entry hits LIST_POISON instead.
+
+Have remove_pending() check HANDSHAKE_F_NET_DRAINING under
+hn_lock and report not-found when drain is in progress. The
+drain has already taken ownership; handshake_complete()'s existing
+test_and_set on HANDSHAKE_F_REQ_COMPLETED still arbitrates
+between drain and cancel for who calls the consumer's hp_done. Use
+list_del_init() rather than list_del() in the drain so req->hr_list
+does not carry LIST_POISON after drain releases the entry.
+
+The DRAINING guard in remove_pending() makes cancel return false,
+but cancel still falls through to test_and_set_bit on
+HANDSHAKE_F_REQ_COMPLETED and drops the request's hr_file reference.
+Without another pin, if that is the last reference, sk_destruct frees
+the request while it is still linked on the drain loop's local list.
+Pin each request's hr_file under hn_lock before releasing the list,
+and drop that drain pin after the loop finishes with the request.
+
+Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-8-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/handshake/netlink.c | 10 ++++++++--
+ net/handshake/request.c | 5 ++++-
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index 21d6cbd52fcdb6..3fd4fef9bab1a4 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -201,13 +201,19 @@ static void __net_exit handshake_net_exit(struct net *net)
+ */
+ spin_lock_bh(&hn->hn_lock);
+ set_bit(HANDSHAKE_F_NET_DRAINING, &hn->hn_flags);
+- list_splice_init(&requests, &hn->hn_requests);
++ list_splice_init(&hn->hn_requests, &requests);
++ list_for_each_entry(req, &requests, hr_list)
++ get_file(req->hr_file);
+ spin_unlock_bh(&hn->hn_lock);
+
+ while (!list_empty(&requests)) {
++ struct file *file;
++
+ req = list_first_entry(&requests, struct handshake_req, hr_list);
+- list_del(&req->hr_list);
++ file = req->hr_file;
++ list_del_init(&req->hr_list);
+ handshake_complete(req, -ETIMEDOUT, NULL);
++ fput(file);
+ }
+ }
+
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index e2d7ee7ce6e0e0..2f1ab6eb9538c5 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -163,13 +163,16 @@ static void __remove_pending_locked(struct handshake_net *hn,
+ * otherwise %false.
+ *
+ * If @req was on a pending list, it has not yet been accepted.
++ * Returns %false when the net namespace is draining; the drain
++ * loop has taken ownership of the pending list.
+ */
+ static bool remove_pending(struct handshake_net *hn, struct handshake_req *req)
+ {
+ bool ret = false;
+
+ spin_lock_bh(&hn->hn_lock);
+- if (!list_empty(&req->hr_list)) {
++ if (!test_bit(HANDSHAKE_F_NET_DRAINING, &hn->hn_flags) &&
++ !list_empty(&req->hr_list)) {
+ __remove_pending_locked(hn, req);
+ ret = true;
+ }
+--
+2.53.0
+
--- /dev/null
+From 3ad739a55523fe3e66ddedbf7bf5782ecc3ccb0c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:19 -0400
+Subject: net/handshake: hand off the pinned file reference to accept_doit
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit f4251190e58b209999c1ba9e6d2976136a1be055 ]
+
+handshake_req_next() removes the request from the per-net
+pending list and drops hn_lock before handshake_nl_accept_doit()
+reads req->hr_sk->sk_socket and dereferences sock->file (once in
+FD_PREPARE() and again in get_file()). In that window a
+consumer running tls_handshake_cancel() followed by sockfd_put()
+(svc_sock_free) or __fput_sync() (xs_reset_transport) releases
+sock->file. sock_release() then runs sock_orphan(), zeroing
+sk_socket, and frees the struct socket. The accept-side code
+either reads NULL through sk_socket or chases freed memory.
+
+The submit-side sock_hold() does not prevent this. sk_refcnt
+protects struct sock, but struct socket and sock->file are
+independently refcounted via the file descriptor the consumer
+owns. Pinning sk leaves sock and sock->file unprotected.
+
+Retarget the accept-side dereferences at req->hr_file, which was
+pinned at submit time, instead of req->hr_sk->sk_socket->file.
+Pinning on its own is not sufficient: a consumer that cancels
+between handshake_req_next() returning and accept_doit reaching
+FD_PREPARE() takes the !remove_pending() branch in
+handshake_req_cancel() and drops hr_file before the accept side
+takes its own reference. Hand off an additional file reference
+inside handshake_req_next(), under hn_lock, so the accept side
+operates on a reference that no concurrent handshake_req_cancel()
+can revoke. FD_PREPARE() consumes that handed-off reference,
+either by transferring it to the new fd in fd_publish() or by
+dropping it in the cleanup destructor on error; the explicit
+get_file() that previously balanced FD_PREPARE() is therefore
+redundant and goes away.
+
+Update handshake_req_cancel_test2 and _test3 to simulate the
+FD_PREPARE() consumption with an fput() so the kunit file-count
+assertions stay balanced.
+
+Reported-by: Chris Mason <clm@meta.com>
+Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-5-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/handshake/handshake-test.c | 8 ++++++++
+ net/handshake/netlink.c | 7 ++-----
+ net/handshake/request.c | 18 ++++++++++++++++++
+ 3 files changed, 28 insertions(+), 5 deletions(-)
+
+diff --git a/net/handshake/handshake-test.c b/net/handshake/handshake-test.c
+index df3948e807a0fd..9cc7a95f41207e 100644
+--- a/net/handshake/handshake-test.c
++++ b/net/handshake/handshake-test.c
+@@ -375,6 +375,10 @@ static void handshake_req_cancel_test2(struct kunit *test)
+ /* Pretend to accept this request */
+ next = handshake_req_next(hn, HANDSHAKE_HANDLER_CLASS_TLSHD);
+ KUNIT_ASSERT_PTR_EQ(test, req, next);
++ /* Simulate FD_PREPARE() consuming the file reference handed
++ * off by handshake_req_next(); see handshake_nl_accept_doit().
++ */
++ fput(filp);
+
+ /* Act */
+ result = handshake_req_cancel(sock->sk);
+@@ -417,6 +421,10 @@ static void handshake_req_cancel_test3(struct kunit *test)
+ /* Pretend to accept this request */
+ next = handshake_req_next(hn, HANDSHAKE_HANDLER_CLASS_TLSHD);
+ KUNIT_ASSERT_PTR_EQ(test, req, next);
++ /* Simulate FD_PREPARE() consuming the file reference handed
++ * off by handshake_req_next(); see handshake_nl_accept_doit().
++ */
++ fput(filp);
+
+ /* Pretend to complete this request */
+ handshake_complete(next, -ETIMEDOUT, NULL);
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index 039344979de934..561dfa6fa7711a 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -92,7 +92,6 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info)
+ struct net *net = sock_net(skb->sk);
+ struct handshake_net *hn = handshake_pernet(net);
+ struct handshake_req *req = NULL;
+- struct socket *sock;
+ int class, err;
+
+ err = -EOPNOTSUPP;
+@@ -107,15 +106,13 @@ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info)
+ err = -EAGAIN;
+ req = handshake_req_next(hn, class);
+ if (req) {
+- sock = req->hr_sk->sk_socket;
+-
+- FD_PREPARE(fdf, O_CLOEXEC, sock->file);
++ FD_PREPARE(fdf, O_CLOEXEC, req->hr_file);
+ if (fdf.err) {
++ fput(req->hr_file); /* drop ref from handshake_req_next() */
+ err = fdf.err;
+ goto out_complete;
+ }
+
+- get_file(sock->file); /* FD_PREPARE() consumes a reference. */
+ err = req->hr_proto->hp_accept(req, info, fd_prepare_fd(fdf));
+ if (err)
+ goto out_complete; /* Automatic cleanup handles fput */
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 97f9f823994994..22e4b414ad1d7f 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -177,6 +177,17 @@ static bool remove_pending(struct handshake_net *hn, struct handshake_req *req)
+ return ret;
+ }
+
++/**
++ * handshake_req_next - Return the next queued handshake request
++ * @hn: per-net handshake state
++ * @class: handler class to match
++ *
++ * On a non-NULL return, the caller owns an extra reference
++ * on @req->hr_file. FD_PREPARE() consumes it on success; on
++ * the FD_PREPARE() failure path the caller must fput() it.
++ *
++ * Return: pointer to a removed handshake_req, or NULL.
++ */
+ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class)
+ {
+ struct handshake_req *req, *pos;
+@@ -187,6 +198,13 @@ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class)
+ if (pos->hr_proto->hp_handler_class != class)
+ continue;
+ __remove_pending_locked(hn, pos);
++ /* Hand off a file reference to the accept side under
++ * hn_lock. A concurrent handshake_req_cancel() can drop
++ * hr_file before accept reaches FD_PREPARE(); this extra
++ * reference keeps the file alive until FD_PREPARE() takes
++ * ownership.
++ */
++ get_file(pos->hr_file);
+ req = pos;
+ break;
+ }
+--
+2.53.0
+
--- /dev/null
+From 72d8327f969d3d48e94f6823e951024e4ae84577 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:17 -0400
+Subject: net/handshake: Pass negative errno through handshake_complete()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 6b22d433aa13f68e3cd9534ca9a5f4277bfa01c2 ]
+
+handshake_complete() declares status as unsigned int and
+tls_handshake_done() negates that value (-status) before handing
+it to the TLS consumer. Consumers match on negative errno
+constants -- xs_tls_handshake_done() has
+
+ switch (status) {
+ case 0:
+ case -EACCES:
+ case -ETIMEDOUT:
+ lower_transport->xprt_err = status;
+ break;
+ default:
+ lower_transport->xprt_err = -EACCES;
+ }
+
+so the API as designed expects callers to pass positive errno
+values that the tlshd shim then negates.
+
+Three internal callers in handshake_nl_accept_doit(), the
+net-exit drain, and a kunit test follow kernel convention and
+pass negative errnos -- -EIO, -ETIMEDOUT, -ETIMEDOUT. The
+implicit conversion to unsigned int turns -ETIMEDOUT into
+0xFFFFFF92; the subsequent -status in tls_handshake_done()
+wraps back to 110, the consumer's switch falls through, and
+the xprt reports -EACCES on what should be -ETIMEDOUT or -EIO.
+
+Fix the API rather than the call sites. The natural kernel
+convention is negative errno in, negative errno out. Change
+handshake_complete() and hp_done to take int status, drop the
+negation in tls_handshake_done(), and negate once in
+handshake_nl_done_doit() where status arrives from the wire
+as an unsigned netlink attribute. The three internal callers
+were already correct under that convention and need no change.
+
+At the same wire boundary, declare MAX_ERRNO as the netlink
+policy upper bound for HANDSHAKE_A_DONE_STATUS. Attribute
+validation rejects out-of-range values before
+handshake_nl_done_doit() runs, and negating a bounded u32 there
+stays within int range -- closing the UBSAN-visible signed-
+integer overflow that an unconstrained u32 would invoke.
+
+Fixes: 3b3009ea8abb ("net/handshake: Create a NETLINK service for handling handshake requests")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-3-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/netlink/specs/handshake.yaml | 8 ++++++++
+ net/handshake/genl.c | 3 ++-
+ net/handshake/genl.h | 1 +
+ net/handshake/handshake-test.c | 2 +-
+ net/handshake/handshake.h | 4 ++--
+ net/handshake/netlink.c | 2 +-
+ net/handshake/request.c | 2 +-
+ net/handshake/tlshd.c | 4 ++--
+ 8 files changed, 18 insertions(+), 8 deletions(-)
+
+diff --git a/Documentation/netlink/specs/handshake.yaml b/Documentation/netlink/specs/handshake.yaml
+index 95c3fade7a8d7b..1024297b38513a 100644
+--- a/Documentation/netlink/specs/handshake.yaml
++++ b/Documentation/netlink/specs/handshake.yaml
+@@ -12,6 +12,12 @@ protocol: genetlink
+ doc: Netlink protocol to request a transport layer security handshake.
+
+ definitions:
++ -
++ type: const
++ name: max-errno
++ value: 4095
++ header: linux/err.h
++ scope: kernel
+ -
+ type: enum
+ name: handler-class
+@@ -80,6 +86,8 @@ attribute-sets:
+ -
+ name: status
+ type: u32
++ checks:
++ max: max-errno
+ -
+ name: sockfd
+ type: s32
+diff --git a/net/handshake/genl.c b/net/handshake/genl.c
+index 8706126094915d..4b20cd9cdd0e09 100644
+--- a/net/handshake/genl.c
++++ b/net/handshake/genl.c
+@@ -10,6 +10,7 @@
+ #include "genl.h"
+
+ #include <uapi/linux/handshake.h>
++#include <linux/err.h>
+
+ /* HANDSHAKE_CMD_ACCEPT - do */
+ static const struct nla_policy handshake_accept_nl_policy[HANDSHAKE_A_ACCEPT_HANDLER_CLASS + 1] = {
+@@ -18,7 +19,7 @@ static const struct nla_policy handshake_accept_nl_policy[HANDSHAKE_A_ACCEPT_HAN
+
+ /* HANDSHAKE_CMD_DONE - do */
+ static const struct nla_policy handshake_done_nl_policy[HANDSHAKE_A_DONE_REMOTE_AUTH + 1] = {
+- [HANDSHAKE_A_DONE_STATUS] = { .type = NLA_U32, },
++ [HANDSHAKE_A_DONE_STATUS] = NLA_POLICY_MAX(NLA_U32, MAX_ERRNO),
+ [HANDSHAKE_A_DONE_SOCKFD] = { .type = NLA_S32, },
+ [HANDSHAKE_A_DONE_REMOTE_AUTH] = { .type = NLA_U32, },
+ };
+diff --git a/net/handshake/genl.h b/net/handshake/genl.h
+index 8d3e18672dafcf..46b65f131669a6 100644
+--- a/net/handshake/genl.h
++++ b/net/handshake/genl.h
+@@ -11,6 +11,7 @@
+ #include <net/genetlink.h>
+
+ #include <uapi/linux/handshake.h>
++#include <linux/err.h>
+
+ int handshake_nl_accept_doit(struct sk_buff *skb, struct genl_info *info);
+ int handshake_nl_done_doit(struct sk_buff *skb, struct genl_info *info);
+diff --git a/net/handshake/handshake-test.c b/net/handshake/handshake-test.c
+index 55442b2f518afb..df3948e807a0fd 100644
+--- a/net/handshake/handshake-test.c
++++ b/net/handshake/handshake-test.c
+@@ -25,7 +25,7 @@ static int test_accept_func(struct handshake_req *req, struct genl_info *info,
+ return 0;
+ }
+
+-static void test_done_func(struct handshake_req *req, unsigned int status,
++static void test_done_func(struct handshake_req *req, int status,
+ struct genl_info *info)
+ {
+ }
+diff --git a/net/handshake/handshake.h b/net/handshake/handshake.h
+index a48163765a7a1d..2289b0e274f40a 100644
+--- a/net/handshake/handshake.h
++++ b/net/handshake/handshake.h
+@@ -57,7 +57,7 @@ struct handshake_proto {
+ int (*hp_accept)(struct handshake_req *req,
+ struct genl_info *info, int fd);
+ void (*hp_done)(struct handshake_req *req,
+- unsigned int status,
++ int status,
+ struct genl_info *info);
+ void (*hp_destroy)(struct handshake_req *req);
+ };
+@@ -86,7 +86,7 @@ struct handshake_req *handshake_req_hash_lookup(struct sock *sk);
+ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class);
+ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ gfp_t flags);
+-void handshake_complete(struct handshake_req *req, unsigned int status,
++void handshake_complete(struct handshake_req *req, int status,
+ struct genl_info *info);
+ bool handshake_req_cancel(struct sock *sk);
+
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index 97114ec8027a5a..039344979de934 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -160,7 +160,7 @@ int handshake_nl_done_doit(struct sk_buff *skb, struct genl_info *info)
+
+ status = -EIO;
+ if (info->attrs[HANDSHAKE_A_DONE_STATUS])
+- status = nla_get_u32(info->attrs[HANDSHAKE_A_DONE_STATUS]);
++ status = -(int)nla_get_u32(info->attrs[HANDSHAKE_A_DONE_STATUS]);
+
+ handshake_complete(req, status, info);
+ sockfd_put(sock);
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 5d4a17f902d201..97f9f823994994 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -284,7 +284,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ }
+ EXPORT_SYMBOL(handshake_req_submit);
+
+-void handshake_complete(struct handshake_req *req, unsigned int status,
++void handshake_complete(struct handshake_req *req, int status,
+ struct genl_info *info)
+ {
+ struct sock *sk = req->hr_sk;
+diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c
+index af294c6cc71731..7567150c2a4f95 100644
+--- a/net/handshake/tlshd.c
++++ b/net/handshake/tlshd.c
+@@ -93,7 +93,7 @@ static void tls_handshake_remote_peerids(struct tls_handshake_req *treq,
+ *
+ */
+ static void tls_handshake_done(struct handshake_req *req,
+- unsigned int status, struct genl_info *info)
++ int status, struct genl_info *info)
+ {
+ struct tls_handshake_req *treq = handshake_req_private(req);
+
+@@ -104,7 +104,7 @@ static void tls_handshake_done(struct handshake_req *req,
+ if (!status)
+ set_bit(HANDSHAKE_F_REQ_SESSION, &req->hr_flags);
+
+- treq->th_consumer_done(treq->th_consumer_data, -status,
++ treq->th_consumer_done(treq->th_consumer_data, status,
+ treq->th_peerid[0]);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 86969bc5abab447646c757cfd5030956913cbd9d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:18 -0400
+Subject: net/handshake: Take a long-lived file reference at submit
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 09dba37eee70d0596e26645015f1aa95a9848e9d ]
+
+handshake_nl_accept_doit() needs the file pointer backing
+req->hr_sk->sk_socket to survive the window between
+handshake_req_next() and the subsequent FD_PREPARE() and get_file().
+The submit-side sock_hold() does not provide that. sk_refcnt keeps
+struct sock alive, but struct socket is owned by sock->file: when
+the consumer fputs the last file reference, sock_release() tears
+the socket down regardless of any sock_hold.
+
+Add an hr_file pointer to struct handshake_req and acquire an
+explicit reference on sock->file during handshake_req_submit().
+handshake_complete() and handshake_req_cancel() release the
+reference on the completion-bit-winning path.
+
+The submit error path must also release the file reference, but
+after rhashtable insertion a concurrent handshake_req_cancel() can
+discover the request and race the error path. Gate the error-path
+cleanup -- sk_destruct restoration, fput, and request destruction
+-- with test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED), the same
+serialization handshake_complete() and handshake_req_cancel()
+already use. When cancel has already claimed ownership, the submit
+error path returns without touching the request; socket teardown
+handles final destruction.
+
+The accept-side dereferences are not yet retargeted; that change
+comes in the next patch.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-4-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: ea5fe6a73ca5 ("net/handshake: Drain pending requests at net namespace exit")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/handshake/handshake.h | 2 ++
+ net/handshake/netlink.c | 6 ------
+ net/handshake/request.c | 42 ++++++++++++++++++++++++++++++++-------
+ 3 files changed, 37 insertions(+), 13 deletions(-)
+
+diff --git a/net/handshake/handshake.h b/net/handshake/handshake.h
+index 2289b0e274f40a..da61cadd1ad3e7 100644
+--- a/net/handshake/handshake.h
++++ b/net/handshake/handshake.h
+@@ -24,6 +24,7 @@ enum hn_flags_bits {
+ HANDSHAKE_F_NET_DRAINING,
+ };
+
++struct file;
+ struct handshake_proto;
+
+ /* One handshake request */
+@@ -32,6 +33,7 @@ struct handshake_req {
+ struct rhash_head hr_rhash;
+ unsigned long hr_flags;
+ const struct handshake_proto *hr_proto;
++ struct file *hr_file;
+ struct sock *hr_sk;
+ void (*hr_odestruct)(struct sock *sk);
+
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index 561dfa6fa7711a..21d6cbd52fcdb6 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -207,12 +207,6 @@ static void __net_exit handshake_net_exit(struct net *net)
+ while (!list_empty(&requests)) {
+ req = list_first_entry(&requests, struct handshake_req, hr_list);
+ list_del(&req->hr_list);
+-
+- /*
+- * Requests on this list have not yet been
+- * accepted, so they do not have an fd to put.
+- */
+-
+ handshake_complete(req, -ETIMEDOUT, NULL);
+ }
+ }
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 22e4b414ad1d7f..e2d7ee7ce6e0e0 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -13,6 +13,7 @@
+ #include <linux/module.h>
+ #include <linux/skbuff.h>
+ #include <linux/inet.h>
++#include <linux/file.h>
+ #include <linux/rhashtable.h>
+
+ #include <net/sock.h>
+@@ -233,9 +234,16 @@ EXPORT_SYMBOL_IF_KUNIT(handshake_req_next);
+ * A zero return value from handshake_req_submit() means that
+ * exactly one subsequent completion callback is guaranteed.
+ *
+- * A negative return value from handshake_req_submit() means that
+- * no completion callback will be done and that @req has been
+- * destroyed.
++ * A negative return value from handshake_req_submit() guarantees that
++ * no completion callback will occur and that @req is no longer owned by
++ * the caller. If cancellation wins the completion race after the request
++ * has been published, final destruction is deferred until socket teardown.
++ *
++ * The caller must hold a reference on @sock->file for the duration
++ * of this call. Once the request is published to the accept side, a
++ * concurrent completion or cancellation may release the request's pin on
++ * @sock->file; the caller's reference is what keeps @sock->sk valid until
++ * handshake_req_submit() returns.
+ */
+ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ gfp_t flags)
+@@ -254,6 +262,14 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ kfree(req);
+ return -EINVAL;
+ }
++
++ /*
++ * Pin sock->file for the lifetime of the request so the
++ * accept side does not race a consumer that releases the
++ * socket while a handshake is pending.
++ */
++ req->hr_file = get_file(sock->file);
++
+ req->hr_odestruct = req->hr_sk->sk_destruct;
+ req->hr_sk->sk_destruct = handshake_sk_destruct;
+
+@@ -285,7 +301,11 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ goto out_err;
+ }
+
+- /* Prevent socket release while a handshake request is pending */
++ /*
++ * Pin struct sock so sk_destruct does not run until the
++ * handshake completion path releases it; struct socket is
++ * held separately via hr_file above.
++ */
+ sock_hold(req->hr_sk);
+
+ trace_handshake_submit(net, req, req->hr_sk);
+@@ -294,10 +314,13 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ out_unlock:
+ spin_unlock_bh(&hn->hn_lock);
+ out_err:
+- /* Restore original destructor so socket teardown still runs on failure */
+- req->hr_sk->sk_destruct = req->hr_odestruct;
+ trace_handshake_submit_err(net, req, req->hr_sk, ret);
+- handshake_req_destroy(req);
++ if (!test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) {
++ /* Restore original destructor so socket teardown still runs. */
++ req->hr_sk->sk_destruct = req->hr_odestruct;
++ fput(req->hr_file);
++ handshake_req_destroy(req);
++ }
+ return ret;
+ }
+ EXPORT_SYMBOL(handshake_req_submit);
+@@ -309,11 +332,15 @@ void handshake_complete(struct handshake_req *req, int status,
+ struct net *net = sock_net(sk);
+
+ if (!test_and_set_bit(HANDSHAKE_F_REQ_COMPLETED, &req->hr_flags)) {
++ struct file *file = req->hr_file;
++
+ trace_handshake_complete(net, req, sk, status);
+ req->hr_proto->hp_done(req, status, info);
+
+ /* Handshake request is no longer pending */
+ sock_put(sk);
++
++ fput(file);
+ }
+ }
+ EXPORT_SYMBOL_IF_KUNIT(handshake_complete);
+@@ -362,6 +389,7 @@ bool handshake_req_cancel(struct sock *sk)
+
+ /* Handshake request is no longer pending */
+ sock_put(sk);
++ fput(req->hr_file);
+ return true;
+ }
+ EXPORT_SYMBOL(handshake_req_cancel);
+--
+2.53.0
+
--- /dev/null
+From 752b199c12287a17ee46b936125afd25c4f1e549 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:15 -0400
+Subject: net/handshake: Use spin_lock_bh for hn_lock
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit cc993e0927ec8bd98ea33377ada03295fcda0f24 ]
+
+nvmet_tcp_state_change(), a socket callback that runs in BH context,
+can reach handshake_req_cancel() via nvmet_tcp_schedule_release_queue()
+and tls_handshake_cancel(). handshake_req_cancel() acquires
+hn->hn_lock with plain spin_lock(). If a process-context thread on
+the same CPU holds hn->hn_lock when a softirq invokes the cancel path,
+the lock attempt deadlocks. This is the only caller that invokes
+tls_handshake_cancel() from BH context; every other consumer calls it
+from process context.
+
+Deferring the cancel to process context in the NVMe target is not
+straightforward: nvmet_tcp_schedule_release_queue() must call
+tls_handshake_cancel() atomically with its state transition to
+DISCONNECTING. If the cancel were deferred, the handshake completion
+callback could fire in the window before the cancel runs, observe the
+unexpected state, and return without dropping its kref on the queue.
+Reworking that interlock is considerably more invasive than hardening
+the handshake lock. Convert all hn->hn_lock acquisitions from
+spin_lock/spin_unlock to spin_lock_bh/spin_unlock_bh so the lock is
+never taken with softirqs enabled.
+
+Fixes: 675b453e0241 ("nvmet-tcp: enable TLS handshake upcall")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-1-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/handshake/netlink.c | 4 ++--
+ net/handshake/request.c | 14 +++++++-------
+ net/handshake/tlshd.c | 2 ++
+ 3 files changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/net/handshake/netlink.c b/net/handshake/netlink.c
+index b989456fc4c5ff..97114ec8027a5a 100644
+--- a/net/handshake/netlink.c
++++ b/net/handshake/netlink.c
+@@ -202,10 +202,10 @@ static void __net_exit handshake_net_exit(struct net *net)
+ * accepted and are in progress will be destroyed when
+ * the socket is closed.
+ */
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ set_bit(HANDSHAKE_F_NET_DRAINING, &hn->hn_flags);
+ list_splice_init(&requests, &hn->hn_requests);
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ while (!list_empty(&requests)) {
+ req = list_first_entry(&requests, struct handshake_req, hr_list);
+diff --git a/net/handshake/request.c b/net/handshake/request.c
+index 2829adbeb149b0..5d4a17f902d201 100644
+--- a/net/handshake/request.c
++++ b/net/handshake/request.c
+@@ -167,12 +167,12 @@ static bool remove_pending(struct handshake_net *hn, struct handshake_req *req)
+ {
+ bool ret = false;
+
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ if (!list_empty(&req->hr_list)) {
+ __remove_pending_locked(hn, req);
+ ret = true;
+ }
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ return ret;
+ }
+@@ -182,7 +182,7 @@ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class)
+ struct handshake_req *req, *pos;
+
+ req = NULL;
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ list_for_each_entry(pos, &hn->hn_requests, hr_list) {
+ if (pos->hr_proto->hp_handler_class != class)
+ continue;
+@@ -190,7 +190,7 @@ struct handshake_req *handshake_req_next(struct handshake_net *hn, int class)
+ req = pos;
+ break;
+ }
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ return req;
+ }
+@@ -249,7 +249,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ if (READ_ONCE(hn->hn_pending) >= hn->hn_pending_max)
+ goto out_err;
+
+- spin_lock(&hn->hn_lock);
++ spin_lock_bh(&hn->hn_lock);
+ ret = -EOPNOTSUPP;
+ if (test_bit(HANDSHAKE_F_NET_DRAINING, &hn->hn_flags))
+ goto out_unlock;
+@@ -258,7 +258,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ goto out_unlock;
+ if (!__add_pending_locked(hn, req))
+ goto out_unlock;
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+
+ ret = handshake_genl_notify(net, req->hr_proto, flags);
+ if (ret) {
+@@ -274,7 +274,7 @@ int handshake_req_submit(struct socket *sock, struct handshake_req *req,
+ return 0;
+
+ out_unlock:
+- spin_unlock(&hn->hn_lock);
++ spin_unlock_bh(&hn->hn_lock);
+ out_err:
+ /* Restore original destructor so socket teardown still runs on failure */
+ req->hr_sk->sk_destruct = req->hr_odestruct;
+diff --git a/net/handshake/tlshd.c b/net/handshake/tlshd.c
+index 8f9532a15f43f9..af294c6cc71731 100644
+--- a/net/handshake/tlshd.c
++++ b/net/handshake/tlshd.c
+@@ -425,6 +425,8 @@ EXPORT_SYMBOL(tls_server_hello_psk);
+ * Request cancellation races with request completion. To determine
+ * who won, callers examine the return value from this function.
+ *
++ * Context: May be called from process or softirq context.
++ *
+ * Return values:
+ * %true - Uncompleted handshake request was canceled
+ * %false - Handshake request already completed or not found
+--
+2.53.0
+
--- /dev/null
+From cfeae8c251efba00e11719a40afda675842367c9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 22:45:24 +0800
+Subject: net: hibmcge: disable Relaxed Ordering to fix RX packet corruption
+
+From: Jijie Shao <shaojijie@huawei.com>
+
+[ Upstream commit 463a1271aa26eac992851b9d98cc75bc3cd4a1ed ]
+
+When SMMU is disabled, the hibmcge driver may receive corrupted packets.
+The hardware writes packet data and descriptors to the same page, but
+with Relaxed Ordering enabled, PCI write transactions may not be
+strictly ordered. This can cause the driver to observe a valid
+descriptor before the corresponding packet data is fully written.
+
+Fix this by clearing PCI_EXP_DEVCTL_RELAX_EN in the PCI bridge control
+register to ensure strict write ordering between packet data and
+descriptors.
+
+Fixes: f72e25594061 ("net: hibmcge: Implement rx_poll function to receive packets")
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Link: https://patch.msgid.link/20260525144525.94884-2-shaojijie@huawei.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
+index 068da2fd1fea83..f721e98938049e 100644
+--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
++++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
+@@ -420,6 +420,9 @@ static int hbg_pci_init(struct pci_dev *pdev)
+ return -ENOMEM;
+
+ pci_set_master(pdev);
++ pcie_capability_clear_word(pdev, PCI_EXP_DEVCTL,
++ PCI_EXP_DEVCTL_RELAX_EN);
++ pci_save_state(pdev);
+ return 0;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 1eef5b200c5a704fe170ed657d7149524f46cc1b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 22:45:25 +0800
+Subject: net: hibmcge: move dma_rmb() after dma_sync_single_for_cpu() in RX
+ path
+
+From: Jijie Shao <shaojijie@huawei.com>
+
+[ Upstream commit b545b6ea1802b32436fa97f1d2918718212cc831 ]
+
+The dma_rmb() barrier was placed before dma_sync_single_for_cpu(), which
+is incorrect. DMA sync must complete first to make the buffer accessible
+to the CPU, then the rmb barrier ensures subsequent descriptor reads
+observe the latest data written by the hardware.
+
+Reorder the operations so dma_sync_single_for_cpu() is called before
+dma_rmb() to guarantee the driver reads consistent data from the DMA
+buffer.
+
+Fixes: f72e25594061 ("net: hibmcge: Implement rx_poll function to receive packets")
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Link: https://patch.msgid.link/20260525144525.94884-3-shaojijie@huawei.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
+index a4ea92c31c2fea..0ae31499467693 100644
+--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
++++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_txrx.c
+@@ -452,12 +452,12 @@ static bool hbg_sync_data_from_hw(struct hbg_priv *priv,
+ {
+ struct hbg_rx_desc *rx_desc;
+
+- /* make sure HW write desc complete */
+- dma_rmb();
+-
+ dma_sync_single_for_cpu(&priv->pdev->dev, buffer->page_dma,
+ buffer->page_size, DMA_FROM_DEVICE);
+
++ /* make sure HW write desc complete */
++ dma_rmb();
++
+ rx_desc = (struct hbg_rx_desc *)buffer->page_addr;
+ return FIELD_GET(HBG_RX_DESC_W2_PKT_LEN_M, rx_desc->word2) != 0;
+ }
+--
+2.53.0
+
--- /dev/null
+From 46edc11fffee29f552edb03be622b536bfa94855 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 23 May 2026 15:03:30 +0200
+Subject: net: hsr: fix potential OOB access in supervision frame handling
+
+From: Luka Gejak <luka.gejak@linux.dev>
+
+[ Upstream commit f229426072fc865654a60978bb7fda790a051ff3 ]
+
+Ensure the entire TLV header is linearized before access by adding
+sizeof(struct hsr_sup_tlv) to the pskb_may_pull() calls. Without this,
+a truncated frame could cause an out-of-bounds access.
+
+Fixes: eafaa88b3eb7 ("net: hsr: Add support for redbox supervision frames")
+Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Link: https://patch.msgid.link/20260523130330.61880-1-luka.gejak@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/hsr/hsr_forward.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
+index aefc9b6936ba0c..299de290ddaa5c 100644
+--- a/net/hsr/hsr_forward.c
++++ b/net/hsr/hsr_forward.c
+@@ -84,7 +84,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
+
+ /* Get next tlv */
+ total_length += hsr_sup_tag->tlv.HSR_TLV_length;
+- if (!pskb_may_pull(skb, total_length))
++ if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
+ return false;
+ skb_pull(skb, total_length);
+ hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data;
+@@ -100,7 +100,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
+
+ /* make sure another tlv follows */
+ total_length += sizeof(struct hsr_sup_tlv) + hsr_sup_tlv->HSR_TLV_length;
+- if (!pskb_may_pull(skb, total_length))
++ if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
+ return false;
+
+ /* get next tlv */
+--
+2.53.0
+
--- /dev/null
+From bb7061e5395e889293daffb386f50a6838e46097 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:48 -0400
+Subject: net: Introduce skb tc depth field to track packet loops
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 98b34f3e8c3492cfc89ff943c9d92b4d52863d1d ]
+
+Add a 2-bit per-skb tc depth field to track packet loops across the stack.
+
+The previous per-CPU loop counters like MIRRED_NEST_LIMIT
+assume a single call stack and lose state in two cases:
+1) When a packet is queued and reprocessed later (e.g., egress->ingress
+ via backlog), the per-cpu state is gone by the time it is dequeued.
+2) With XPS/RPS a packet may arrive on one CPU and be processed on
+ another.
+
+A per-skb field solves both by travelling with the packet itself.
+
+The field fits in existing padding, using 2 bits that were previously a
+hole:
+
+pahole before(-) and after (+) diff looks like:
+ __u8 slow_gro:1; /* 132: 3 1 */
+ __u8 csum_not_inet:1; /* 132: 4 1 */
+ __u8 unreadable:1; /* 132: 5 1 */
+ + __u8 tc_depth:2; /* 132: 6 1 */
+
+ - /* XXX 2 bits hole, try to pack */
+ /* XXX 1 byte hole, try to pack */
+
+ __u16 tc_index; /* 134 2 */
+
+There used to be a ttl field which was removed as part of tc_verd in commit
+aec745e2c520 ("net-tc: remove unused tc_verd fields"). It was already
+unused by that time, due to remove earlier in commit c19ae86a510c ("tc: remove
+unused redirect ttl").
+
+The first user of this field is netem, which increments tc_depth on
+duplicated packets before re-enqueueing them at the root qdisc. On
+re-entry, netem skips duplication for any skb with tc_depth already set,
+bounding recursion to a single level regardless of tree topology.
+
+The other user is mirred which increments it on each pass
+and limits to depth to MIRRED_DEFER_LIMIT (3).
+
+The new field was called ttl in earlier versions of this patch
+but renamed to tc_depth to avoid confusion with IP ttl.
+
+Note (looking at you Sashiko! Dont ignore me and continue bringing this up):
+1. Since both mirred and netem utilize the same 2-bit tc_depth field it is
+ possible when netem and mirred are used together that netem qdisc to skip
+ the duplication step. This is a known trade-off, as a 2-bit field cannot
+ independently track both features' recursion depths and it is not considered
+ sane to have a setup that addresses both features on at the same time.
+
+2. skb_scrub_packet does not clear tc_depth. This means a packet's loop history
+ is preserved even across namespaces. While this might be restrictive for
+ some topologies, it is also design intent to provide robustness against loops
+ across namespaces.
+
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-2-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: db875221ab08 ("net/sched: Fix ethx:ingress -> ethy:egress -> ethx:ingress mirred loop")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/skbuff.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index 2f278ce376b7ed..a58ff8903e536e 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -821,6 +821,7 @@ enum skb_tstamp_type {
+ * @_sk_redir: socket redirection information for skmsg
+ * @_nfct: Associated connection, if any (with nfctinfo bits)
+ * @skb_iif: ifindex of device we arrived on
++ * @tc_depth: counter for packet duplication
+ * @tc_index: Traffic control index
+ * @hash: the packet hash
+ * @queue_mapping: Queue mapping for multiqueue devices
+@@ -1030,6 +1031,7 @@ struct sk_buff {
+ __u8 csum_not_inet:1;
+ #endif
+ __u8 unreadable:1;
++ __u8 tc_depth:2;
+ #if defined(CONFIG_NET_SCHED) || defined(CONFIG_NET_XGRESS)
+ __u16 tc_index; /* traffic control index */
+ #endif
+--
+2.53.0
+
--- /dev/null
+From b2ffd478825809dcaaacb0279519368df3385a11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 07:11:45 -0700
+Subject: net/iucv: fix locking in .getsockopt
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit 3589d20a666caf30ad100c960a2de7de390fce88 ]
+
+Mirror iucv_sock_setsockopt() and wrap the whole switch in
+lock_sock()/release_sock(). The pre-existing SO_MSGLIMIT-only lock
+becomes redundant and is removed.
+
+Any AF_IUCV HIPER user can potentially crash the kernel by racing
+recvmsg() with getsockopt(SO_MSGSIZE): the SO_MSGSIZE arm dereferences
+iucv->hs_dev->mtu after iucv_sock_close() (called from the racing
+recvmsg()) has set hs_dev to NULL, producing a NULL pointer dereference
+oops.
+
+Suggested-by: Stanislav Fomichev <sdf.kernel@gmail.com>
+Fixes: 51363b8751a6 ("af_iucv: allow retrieval of maximum message size")
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
+Tested-by: Alexandra Winter <wintera@linux.ibm.com>
+Link: https://patch.msgid.link/20260521-af_iucv_fix2-v1-1-f16b1c510aa9@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/iucv/af_iucv.c | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
+index 6554d2cffc1961..30cbd98f941a98 100644
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -1538,7 +1538,7 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+ struct sock *sk = sock->sk;
+ struct iucv_sock *iucv = iucv_sk(sk);
+ unsigned int val;
+- int len;
++ int len, rc;
+
+ if (level != SOL_IUCV)
+ return -ENOPROTOOPT;
+@@ -1551,26 +1551,34 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
+
+ len = min_t(unsigned int, len, sizeof(int));
+
++ rc = 0;
++
++ lock_sock(sk);
+ switch (optname) {
+ case SO_IPRMDATA_MSG:
+ val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0;
+ break;
+ case SO_MSGLIMIT:
+- lock_sock(sk);
+ val = (iucv->path != NULL) ? iucv->path->msglim /* connected */
+ : iucv->msglimit; /* default */
+- release_sock(sk);
+ break;
+ case SO_MSGSIZE:
+- if (sk->sk_state == IUCV_OPEN)
+- return -EBADFD;
++ if (sk->sk_state == IUCV_OPEN) {
++ rc = -EBADFD;
++ break;
++ }
+ val = (iucv->hs_dev) ? iucv->hs_dev->mtu -
+ sizeof(struct af_iucv_trans_hdr) - ETH_HLEN :
+ 0x7fffffff;
+ break;
+ default:
+- return -ENOPROTOOPT;
++ rc = -ENOPROTOOPT;
++ break;
+ }
++ release_sock(sk);
++
++ if (rc)
++ return rc;
+
+ if (put_user(len, optlen))
+ return -EFAULT;
+--
+2.53.0
+
--- /dev/null
+From ae0d68b335ffad3e1e24a238363c50cdc850204e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 01:08:24 -0700
+Subject: net: mana: Add NULL guards in teardown path to prevent panic on
+ attach failure
+
+From: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+
+[ Upstream commit 17bfe0a8c014ee1d542ad352cd6a0a505361664a ]
+
+When queue allocation fails partway through, the error cleanup frees
+and NULLs apc->tx_qp and apc->rxqs. Multiple teardown paths such as
+mana_remove(), mana_change_mtu() recovery, and internal error handling
+in mana_alloc_queues() can subsequently call into functions that
+dereference these pointers without NULL checks:
+
+- mana_chn_setxdp() dereferences apc->rxqs[0], causing a NULL pointer
+ dereference panic (CR2: 0000000000000000 at mana_chn_setxdp+0x26).
+- mana_destroy_vport() iterates apc->rxqs without a NULL check.
+- mana_fence_rqs() iterates apc->rxqs without a NULL check.
+- mana_dealloc_queues() iterates apc->tx_qp without a NULL check.
+
+Add NULL guards for apc->rxqs in mana_fence_rqs(),
+mana_destroy_vport(), and before the mana_chn_setxdp() call. Add a
+NULL guard for apc->tx_qp in mana_dealloc_queues() to skip TX queue
+draining when TX queues were never allocated or already freed.
+
+Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+Link: https://patch.msgid.link/20260525081129.1230035-2-dipayanroy@linux.microsoft.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 70 +++++++++++--------
+ 1 file changed, 41 insertions(+), 29 deletions(-)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 14d6f68eaa6958..3ddbf3b9a76501 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -1713,6 +1713,9 @@ static void mana_fence_rqs(struct mana_port_context *apc)
+ struct mana_rxq *rxq;
+ int err;
+
++ if (!apc->rxqs)
++ return;
++
+ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+ rxq = apc->rxqs[rxq_idx];
+ err = mana_fence_rq(apc, rxq);
+@@ -2821,13 +2824,16 @@ static void mana_destroy_vport(struct mana_port_context *apc)
+ struct mana_rxq *rxq;
+ u32 rxq_idx;
+
+- for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+- rxq = apc->rxqs[rxq_idx];
+- if (!rxq)
+- continue;
++ if (apc->rxqs) {
+
+- mana_destroy_rxq(apc, rxq, true);
+- apc->rxqs[rxq_idx] = NULL;
++ for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
++ rxq = apc->rxqs[rxq_idx];
++ if (!rxq)
++ continue;
++
++ mana_destroy_rxq(apc, rxq, true);
++ apc->rxqs[rxq_idx] = NULL;
++ }
+ }
+
+ mana_destroy_txq(apc);
+@@ -3232,7 +3238,8 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ if (apc->port_is_up)
+ return -EINVAL;
+
+- mana_chn_setxdp(apc, NULL);
++ if (apc->rxqs)
++ mana_chn_setxdp(apc, NULL);
+
+ if (gd->gdma_context->is_pf && !apc->ac->bm_hostmode)
+ mana_pf_deregister_filter(apc);
+@@ -3250,33 +3257,38 @@ static int mana_dealloc_queues(struct net_device *ndev)
+ * number of queues.
+ */
+
+- for (i = 0; i < apc->num_queues; i++) {
+- txq = &apc->tx_qp[i].txq;
+- tsleep = 1000;
+- while (atomic_read(&txq->pending_sends) > 0 &&
+- time_before(jiffies, timeout)) {
+- usleep_range(tsleep, tsleep + 1000);
+- tsleep <<= 1;
+- }
+- if (atomic_read(&txq->pending_sends)) {
+- err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
+- if (err) {
+- netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+- err, atomic_read(&txq->pending_sends),
+- txq->gdma_txq_id);
++ if (apc->tx_qp) {
++ for (i = 0; i < apc->num_queues; i++) {
++ txq = &apc->tx_qp[i].txq;
++ tsleep = 1000;
++ while (atomic_read(&txq->pending_sends) > 0 &&
++ time_before(jiffies, timeout)) {
++ usleep_range(tsleep, tsleep + 1000);
++ tsleep <<= 1;
++ }
++ if (atomic_read(&txq->pending_sends)) {
++ err =
++ pcie_flr(to_pci_dev(gd->gdma_context->dev));
++ if (err) {
++ netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
++ err,
++ atomic_read(&txq->pending_sends),
++ txq->gdma_txq_id);
++ }
++ break;
+ }
+- break;
+ }
+- }
+
+- for (i = 0; i < apc->num_queues; i++) {
+- txq = &apc->tx_qp[i].txq;
+- while ((skb = skb_dequeue(&txq->pending_skbs))) {
+- mana_unmap_skb(skb, apc);
+- dev_kfree_skb_any(skb);
++ for (i = 0; i < apc->num_queues; i++) {
++ txq = &apc->tx_qp[i].txq;
++ while ((skb = skb_dequeue(&txq->pending_skbs))) {
++ mana_unmap_skb(skb, apc);
++ dev_kfree_skb_any(skb);
++ }
++ atomic_set(&txq->pending_sends, 0);
+ }
+- atomic_set(&txq->pending_sends, 0);
+ }
++
+ /* We're 100% sure the queues can no longer be woken up, because
+ * we're sure now mana_poll_tx_cq() can't be running.
+ */
+--
+2.53.0
+
--- /dev/null
+From 4bdb09f16d22a76ac25db360d5cfbd8dcb341672 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 01:08:25 -0700
+Subject: net: mana: Skip redundant detach on already-detached port
+
+From: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+
+[ Upstream commit 5b05aa36ee24297d7296ca58dfd8c448d0e4cda3 ]
+
+When mana_per_port_queue_reset_work_handler() runs after a previous
+detach succeeded but attach failed, the port is left in a detached
+state with apc->tx_qp and apc->rxqs already freed. Calling
+mana_detach() again unconditionally leads to NULL pointer dereferences
+during queue teardown.
+
+Add an early exit in mana_detach() when the port is already in
+detached state (!netif_device_present) for non-close callers, making
+it safe to call idempotently. This allows the queue reset handler and
+other recovery paths to simply retry mana_attach() without redundant
+teardown.
+
+Fixes: 3b194343c250 ("net: mana: Implement ndo_tx_timeout and serialize queue resets per port.")
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Signed-off-by: Dipayaan Roy <dipayanroy@linux.microsoft.com>
+Link: https://patch.msgid.link/20260525081129.1230035-3-dipayanroy@linux.microsoft.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microsoft/mana/mana_en.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
+index 3ddbf3b9a76501..13a0af0456c9e3 100644
+--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
++++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
+@@ -3313,6 +3313,12 @@ int mana_detach(struct net_device *ndev, bool from_close)
+
+ ASSERT_RTNL();
+
++ /* If already detached (indicates detach succeeded but attach failed
++ * previously). Now skip mana detach and just retry mana_attach.
++ */
++ if (!from_close && !netif_device_present(ndev))
++ return 0;
++
+ apc->port_st_save = apc->port_is_up;
+ apc->port_is_up = false;
+
+--
+2.53.0
+
--- /dev/null
+From 29a39d1a8e1fa1b8d48f7beacafdc71bb4d79068 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 May 2026 01:00:31 +0100
+Subject: net/mlx5: HWS: Reject unsupported remove-header action
+
+From: Prathamesh Deshpande <prathameshdeshpande7@gmail.com>
+
+[ Upstream commit 86f1d0f063e423a5c1982db1e5e7a8eac511e603 ]
+
+mlx5_cmd_hws_packet_reformat_alloc() handles
+MLX5_REFORMAT_TYPE_REMOVE_HDR by looking up a matching HWS remove-header
+action.
+
+If mlx5_fs_get_action_remove_header_vlan() returns NULL, the code only
+logs an error and continues. The function then returns success with a NULL
+HWS action stored in the packet-reformat object.
+
+Return an error when no matching remove-header action is available.
+
+Fixes: aecd9d1020e3 ("net/mlx5: fs, add HWS packet reformat API function")
+Signed-off-by: Prathamesh Deshpande <prathameshdeshpande7@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
+Acked-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://patch.msgid.link/20260506000054.51797-1-prathameshdeshpande7@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c
+index aca77853abb81b..5a172c572a68f5 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/fs_hws.c
+@@ -1320,8 +1320,10 @@ mlx5_cmd_hws_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns,
+ break;
+ case MLX5_REFORMAT_TYPE_REMOVE_HDR:
+ hws_action = mlx5_fs_get_action_remove_header_vlan(fs_ctx, params);
+- if (!hws_action)
++ if (!hws_action) {
+ mlx5_core_err(dev, "Only vlan remove header supported\n");
++ return -EOPNOTSUPP;
++ }
+ break;
+ default:
+ mlx5_core_err(ns->dev, "Packet-reformat not supported(%d)\n",
+--
+2.53.0
+
--- /dev/null
+From c02be8ca232955dabaaefb486e7a15ee59720851 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:36 +0200
+Subject: net: netlink: don't set nsid on local notifications
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 88b126b39f9757e9debc322d4679239e9af089c7 ]
+
+In most cases, notifications on sockets with NETLINK_LISTEN_ALL_NSID
+do not contain NSID in their ancillary data in case the event is local
+to the listener.
+
+However, when a self-referential NSID is allocated for a namespace,
+every local notification starts sending this ID to the user space.
+
+This is problematic, because the listener cannot tell if those
+notifications are local or not anymore without making extra requests
+to figure out if the provided NSID is local or not. The listener
+can also not figure out the local NSID beforehand as it can be
+allocated at any point in time by other processes, changing the
+structure of the future notifications for everyone.
+
+The value is practically not useful, since it's the namespace's own
+ID that the application has to obtain from other sources in order to
+figure out if it's the same or not. So, for the application it's
+just an extra busy work with no benefits. Moreover, applications
+that do not know about this quirk may be mishandling notifications
+with NSID set as notifications from remote namespaces. This is the
+case for ovs-vswitchd and the iproute2's 'ip monitor' that stops
+printing 'current' and starts printing the nsid number mid-session.
+
+Lack of clear documentation for this behavior is also not helping.
+
+A search though open-source projects doesn't reveal any projects
+that use NETNSA_NSID_NOT_ASSIGNED and rely on metadata to contain
+self-referential NSIDs (expected, since the value is not useful).
+Quite the opposite, as already mentioned, there are few applications
+that rely on NSID to not be present in local events.
+
+Since the value is not useful and actively harmful in some cases,
+let's not report it for local events, making the notifications more
+consistent.
+
+Also adding some blank lines for readability.
+
+Fixes: 59324cf35aba ("netlink: allow to listen "all" netns")
+Reported-by: Matteo Perin <matteo.perin@canonical.com>
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-3-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 441c9852b25714..c47f530b9ff7d9 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1482,10 +1482,14 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++
+ NETLINK_CB(p->skb2).nsid_is_set = false;
+- NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+- if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+- NETLINK_CB(p->skb2).nsid_is_set = true;
++ if (!net_eq(sock_net(sk), p->net)) {
++ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
++ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
++ NETLINK_CB(p->skb2).nsid_is_set = true;
++ }
++
+ val = netlink_broadcast_deliver(sk, p->skb2);
+ if (val < 0) {
+ netlink_overrun(sk);
+--
+2.53.0
+
--- /dev/null
+From d7e12a472a7a13f826bf9f11ea71e8732568776e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 19:22:35 +0200
+Subject: net: netlink: fix sending unassigned nsid after assigned one
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 70f8592ee90585272018a725054b6eb2ab7e99ca ]
+
+If the current skb is not shared, it is re-used directly for all the
+sockets subscribed to the notification. If we have remote all-nsid
+socket receiving a message first, then the 'nsid_is_set' will be
+set to 'true'. If the nsid is NOT_ASSIGNED for the next socket in
+the list, the 'nsid_is_set' will remain 'true' and the negative value
+is be delivered to the user space. All subsequent nsid values will be
+delivered as well, since there is no code path that sets the flag
+back to 'false'.
+
+Fix that by always dropping the flag to 'false' first.
+
+Fixes: 7212462fa6fd ("netlink: don't send unknown nsid")
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Link: https://patch.msgid.link/20260520172317.175168-2-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netlink/af_netlink.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
+index 4d609d5cf40653..441c9852b25714 100644
+--- a/net/netlink/af_netlink.c
++++ b/net/netlink/af_netlink.c
+@@ -1482,6 +1482,7 @@ static void do_one_broadcast(struct sock *sk,
+ p->skb2 = NULL;
+ goto out;
+ }
++ NETLINK_CB(p->skb2).nsid_is_set = false;
+ NETLINK_CB(p->skb2).nsid = peernet2id(sock_net(sk), p->net);
+ if (NETLINK_CB(p->skb2).nsid != NETNSA_NSID_NOT_ASSIGNED)
+ NETLINK_CB(p->skb2).nsid_is_set = true;
+--
+2.53.0
+
--- /dev/null
+From 68d43e79c75d51bed77ed440241f848e044c5ae8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 May 2026 17:32:38 +0200
+Subject: net: pcs: pcs-mtk-lynxi: fix bpi-r3 serdes configuration
+
+From: Frank Wunderlich <frank-w@public-files.de>
+
+[ Upstream commit 422b5233b607476ac7176bfa2a101b9a103d7653 ]
+
+Commit 8871389da151 introduces common pcs dts properties which writes
+rx=normal,tx=normal polarity to register SGMSYS_QPHY_WRAP_CTRL of switch.
+This is initialized with tx-bit set and so change inverts polarity
+compared to before.
+
+It looks like mt7531 has tx polarity inverted in hardware and set tx-bit
+by default to restore the normal polarity.
+
+The MT7531 datasheet quite clearly states:
+Register 000050EC QPHY_WRAP_CTRL -- QPHY wrapper control
+Reset value: 0x00000501
+
+BIT 1 RX_BIT_POLARITY -- RX bit polarity control
+ 1'b0: normal
+ 1'b1: inverted
+
+BIT 0 TX_BIT_POLARITY -- TX bit polarity control (TX default inversed
+in MT7531)
+ 1'b0: normal
+ 1'b1: inverted
+
+Till this patch the register write was only called when mediatek,pnswap
+property was set which cannot be done for switch because the fw-node param
+was always NULL from switch driver in the mtk_pcs_lynxi_create call.
+
+Do not configure switch side like it's done before.
+
+Fixes: 8871389da151 ("net: pcs: pcs-mtk-lynxi: deprecate "mediatek,pnswap"")
+Signed-off-by: Frank Wunderlich <frank-w@public-files.de>
+Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Link: https://patch.msgid.link/20260526153239.30194-1-linux@fw-web.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/pcs/pcs-mtk-lynxi.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/pcs/pcs-mtk-lynxi.c b/drivers/net/pcs/pcs-mtk-lynxi.c
+index c12f8087af9be5..a753bd88cbc223 100644
+--- a/drivers/net/pcs/pcs-mtk-lynxi.c
++++ b/drivers/net/pcs/pcs-mtk-lynxi.c
+@@ -129,6 +129,9 @@ static int mtk_pcs_config_polarity(struct mtk_pcs_lynxi *mpcs,
+ unsigned int val = 0;
+ int ret;
+
++ if (!fwnode)
++ return 0;
++
+ if (fwnode_property_read_bool(fwnode, "mediatek,pnswap"))
+ default_pol = PHY_POL_INVERT;
+
+--
+2.53.0
+
--- /dev/null
+From 47d74a925129f0f80822a799be3a6404b4bf8be9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:53 -0400
+Subject: net/sched: act_mirred: Fix blockcast recursion bypass leading to
+ stack overflow
+
+From: Kito Xu (veritas501) <hxzene@gmail.com>
+
+[ Upstream commit a005fa5d7502eefec7ee6e1c01adadc06de2f9ad ]
+
+tcf_mirred_act() checks sched_mirred_nest against MIRRED_NEST_LIMIT (4)
+to prevent deep recursion. However, when the action uses blockcast
+(tcfm_blockid != 0), the function returns at the tcf_blockcast() call
+BEFORE reaching the counter increment. As a result, the recursion
+counter never advances and the limit check is entirely bypassed.
+
+When two devices share a TC egress block with a mirred blockcast rule,
+a packet egressing on device A is mirrored to device B via blockcast;
+device B's egress TC re-enters tcf_mirred_act() via blockcast and
+mirrors back to A, creating an unbounded recursion loop:
+
+ tcf_mirred_act -> tcf_blockcast -> tcf_mirred_to_dev -> dev_queue_xmit
+ -> sch_handle_egress -> tcf_classify -> tcf_mirred_act -> (repeat)
+
+This recursion continues until the kernel stack overflows.
+
+The bug is reachable from an unprivileged user via
+unshare(CLONE_NEWUSER | CLONE_NEWNET): user namespaces grant
+CAP_NET_ADMIN in the new network namespace, which is sufficient to
+create dummy devices, attach clsact qdiscs with shared blocks, and
+install mirred blockcast filters.
+
+ BUG: TASK stack guard page was hit at ffffc90000b7fff8
+ Oops: stack guard page: 0000 [#1] SMP KASAN NOPTI
+ CPU: 2 UID: 1000 PID: 169 Comm: poc Not tainted 7.0.0-rc7-next-20260410
+ RIP: 0010:xas_find+0x17/0x480
+ Call Trace:
+ xa_find+0x17b/0x1d0
+ tcf_mirred_act+0x640/0x1060
+ tcf_action_exec+0x400/0x530
+ basic_classify+0x128/0x1d0
+ tcf_classify+0xd83/0x1150
+ tc_run+0x328/0x620
+ __dev_queue_xmit+0x797/0x3100
+ tcf_mirred_to_dev+0x7b1/0xf70
+ tcf_mirred_act+0x68a/0x1060
+ [repeating ~30+ times until stack overflow]
+ Kernel panic - not syncing: Fatal exception in interrupt
+
+Fix this by incrementing sched_mirred_nest before calling
+tcf_blockcast() and decrementing it on return, mirroring the
+non-blockcast path. This ensures subsequent recursive entries see the
+updated counter and are correctly limited by MIRRED_NEST_LIMIT.
+
+Fixes: fe946a751d9b ("net/sched: act_mirred: add loop detection")
+Signed-off-by: Kito Xu (veritas501) <hxzene@gmail.com>
+Link: https://patch.msgid.link/20260525122556.973584-7-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_mirred.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
+index dd5e7ea7ef2652..dbe4a4ff3e08b8 100644
+--- a/net/sched/act_mirred.c
++++ b/net/sched/act_mirred.c
+@@ -396,14 +396,12 @@ static int tcf_blockcast_mirror(struct sk_buff *skb, struct tcf_mirred *m,
+
+ static int tcf_blockcast(struct sk_buff *skb, struct tcf_mirred *m,
+ const u32 blockid, struct tcf_result *res,
+- int retval)
++ int m_eaction, int retval)
+ {
+ const u32 exception_ifindex = skb->dev->ifindex;
+ struct tcf_block *block;
+ bool is_redirect;
+- int m_eaction;
+
+- m_eaction = READ_ONCE(m->tcfm_eaction);
+ is_redirect = tcf_mirred_is_act_redirect(m_eaction);
+
+ /* we are already under rcu protection, so can call block lookup
+@@ -453,8 +451,16 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ tcf_action_update_bstats(&m->common, skb);
+
+ blockid = READ_ONCE(m->tcfm_blockid);
+- if (blockid)
+- return tcf_blockcast(skb, m, blockid, res, retval);
++ m_eaction = READ_ONCE(m->tcfm_eaction);
++ want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
++ if (blockid) {
++ if (!want_ingress)
++ xmit->sched_mirred_dev[xmit->sched_mirred_nest++] = NULL;
++ retval = tcf_blockcast(skb, m, blockid, res, m_eaction, retval);
++ if (!want_ingress)
++ xmit->sched_mirred_nest--;
++ return retval;
++ }
+
+ dev = rcu_dereference_bh(m->tcfm_dev);
+ if (unlikely(!dev)) {
+@@ -463,8 +469,6 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ return retval;
+ }
+
+- m_eaction = READ_ONCE(m->tcfm_eaction);
+- want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
+ if (!want_ingress) {
+ for (i = 0; i < xmit->sched_mirred_nest; i++) {
+ if (xmit->sched_mirred_dev[i] != dev)
+--
+2.53.0
+
--- /dev/null
+From e2675e84594fb8dfef530667a43734a445885b56 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:54 -0400
+Subject: net/sched: act_mirred: Fix return code in early mirred redirect error
+ paths
+
+From: Victor Nogueira <victor@mojatatu.com>
+
+[ Upstream commit e80ad525fc7e8c933ad78478c5dda286cfd55c60 ]
+
+Since retval is set as TC_ACT_STOLEN in the mirred redirect case, returning
+retval in cases where redirect failed will make the callers not register
+the skb as being dropped.
+
+Fix this by returning TC_ACT_SHOT instead in such scenarios.
+
+Fixes: 16085e48cb48 ("net/sched: act_mirred: Create function tcf_mirred_to_dev and improve readability")
+Reported-by: Sashiko <sashiko-bot@kernel.org>
+Closes: https://sashiko.dev/#/patchset/20260413082027.2244884-1-hxzene%40gmail.com
+Signed-off-by: Victor Nogueira <victor@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-8-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_mirred.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
+index dbe4a4ff3e08b8..553342c55cf7c6 100644
+--- a/net/sched/act_mirred.c
++++ b/net/sched/act_mirred.c
+@@ -372,7 +372,8 @@ static int tcf_blockcast_redir(struct sk_buff *skb, struct tcf_mirred *m,
+ dev_is_mac_header_xmit(dev_prev),
+ m_eaction, retval);
+
+- return retval;
++ /* If the packet wasn't redirected, we have to register as a drop */
++ return TC_ACT_SHOT;
+ }
+
+ static int tcf_blockcast_mirror(struct sk_buff *skb, struct tcf_mirred *m,
+@@ -410,7 +411,7 @@ static int tcf_blockcast(struct sk_buff *skb, struct tcf_mirred *m,
+ block = tcf_block_lookup(dev_net(skb->dev), blockid);
+ if (!block || xa_empty(&block->ports)) {
+ tcf_action_inc_overlimit_qstats(&m->common);
+- return retval;
++ return is_redirect ? TC_ACT_SHOT : retval;
+ }
+
+ if (is_redirect)
+@@ -428,8 +429,8 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ {
+ struct tcf_mirred *m = to_mirred(a);
+ int retval = READ_ONCE(m->tcf_action);
++ bool m_mac_header_xmit, is_redirect;
+ struct netdev_xmit *xmit;
+- bool m_mac_header_xmit;
+ struct net_device *dev;
+ bool want_ingress;
+ int i, m_eaction;
+@@ -462,11 +463,13 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ return retval;
+ }
+
++ is_redirect = tcf_mirred_is_act_redirect(m_eaction);
++
+ dev = rcu_dereference_bh(m->tcfm_dev);
+ if (unlikely(!dev)) {
+ pr_notice_once("tc mirred: target device is gone\n");
+ tcf_action_inc_overlimit_qstats(&m->common);
+- return retval;
++ goto err_out;
+ }
+
+ if (!want_ingress) {
+@@ -476,7 +479,7 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ pr_notice_once("tc mirred: loop on device %s\n",
+ netdev_name(dev));
+ tcf_action_inc_overlimit_qstats(&m->common);
+- return retval;
++ goto err_out;
+ }
+ xmit->sched_mirred_dev[xmit->sched_mirred_nest++] = dev;
+ }
+@@ -489,6 +492,11 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ xmit->sched_mirred_nest--;
+
+ return retval;
++
++err_out:
++ if (is_redirect)
++ retval = TC_ACT_SHOT;
++ return retval;
+ }
+
+ static void tcf_stats_update(struct tc_action *a, u64 bytes, u64 packets,
+--
+2.53.0
+
--- /dev/null
+From f2941f2de613209607df02d329c266682fa59d59 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:52 -0400
+Subject: net/sched: Fix ethx:ingress -> ethy:egress -> ethx:ingress mirred
+ loop
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit db875221ab08d213a83bf30196ae8b64d55a3403 ]
+
+When mirred redirects to ingress (from either ingress or egress) the loop
+state from sched_mirred_dev array dev is lost because of 1) the packet
+deferral into the backlog and 2) the fact the sched_mirred_dev array is
+cleared. In such cases, if there was a loop we won't discover it.
+
+Here's a simple test to reproduce:
+ip a add dev port0 10.10.10.11/24
+
+tc qdisc add dev port0 clsact
+tc filter add dev port0 egress protocol ip \
+ prio 10 matchall action mirred ingress redirect dev port1
+
+tc qdisc add dev port1 clsact
+tc filter add dev port1 ingress protocol ip \
+ prio 10 matchall action mirred egress redirect dev port0
+
+ping -c 1 -W0.01 10.10.10.10
+
+Fixes: fe946a751d9b ("net/sched: act_mirred: add loop detection")
+Tested-by: Victor Nogueira <victor@mojatatu.com>
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-6-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_mirred.c | 47 +++++++++++++++++++++++++++---------------
+ 1 file changed, 30 insertions(+), 17 deletions(-)
+
+diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
+index 2c5a7a321a9438..dd5e7ea7ef2652 100644
+--- a/net/sched/act_mirred.c
++++ b/net/sched/act_mirred.c
+@@ -26,6 +26,10 @@
+ #include <net/tc_act/tc_mirred.h>
+ #include <net/tc_wrapper.h>
+
++#define MIRRED_DEFER_LIMIT 3
++_Static_assert(MIRRED_DEFER_LIMIT <= 3,
++ "MIRRED_DEFER_LIMIT exceeds tc_depth bitfield width");
++
+ static LIST_HEAD(mirred_list);
+ static DEFINE_SPINLOCK(mirred_list_lock);
+
+@@ -234,12 +238,15 @@ tcf_mirred_forward(bool at_ingress, bool want_ingress, struct sk_buff *skb)
+ {
+ int err;
+
+- if (!want_ingress)
++ if (!want_ingress) {
+ err = tcf_dev_queue_xmit(skb, dev_queue_xmit);
+- else if (!at_ingress)
+- err = netif_rx(skb);
+- else
+- err = netif_receive_skb(skb);
++ } else {
++ skb->tc_depth++;
++ if (!at_ingress)
++ err = netif_rx(skb);
++ else
++ err = netif_receive_skb(skb);
++ }
+
+ return err;
+ }
+@@ -426,6 +433,7 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ struct netdev_xmit *xmit;
+ bool m_mac_header_xmit;
+ struct net_device *dev;
++ bool want_ingress;
+ int i, m_eaction;
+ u32 blockid;
+
+@@ -434,7 +442,8 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ #else
+ xmit = this_cpu_ptr(&softnet_data.xmit);
+ #endif
+- if (unlikely(xmit->sched_mirred_nest >= MIRRED_NEST_LIMIT)) {
++ if (unlikely(xmit->sched_mirred_nest >= MIRRED_NEST_LIMIT ||
++ skb->tc_depth >= MIRRED_DEFER_LIMIT)) {
+ net_warn_ratelimited("Packet exceeded mirred recursion limit on dev %s\n",
+ netdev_name(skb->dev));
+ return TC_ACT_SHOT;
+@@ -453,23 +462,27 @@ TC_INDIRECT_SCOPE int tcf_mirred_act(struct sk_buff *skb,
+ tcf_action_inc_overlimit_qstats(&m->common);
+ return retval;
+ }
+- for (i = 0; i < xmit->sched_mirred_nest; i++) {
+- if (xmit->sched_mirred_dev[i] != dev)
+- continue;
+- pr_notice_once("tc mirred: loop on device %s\n",
+- netdev_name(dev));
+- tcf_action_inc_overlimit_qstats(&m->common);
+- return retval;
+- }
+
+- xmit->sched_mirred_dev[xmit->sched_mirred_nest++] = dev;
++ m_eaction = READ_ONCE(m->tcfm_eaction);
++ want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
++ if (!want_ingress) {
++ for (i = 0; i < xmit->sched_mirred_nest; i++) {
++ if (xmit->sched_mirred_dev[i] != dev)
++ continue;
++ pr_notice_once("tc mirred: loop on device %s\n",
++ netdev_name(dev));
++ tcf_action_inc_overlimit_qstats(&m->common);
++ return retval;
++ }
++ xmit->sched_mirred_dev[xmit->sched_mirred_nest++] = dev;
++ }
+
+ m_mac_header_xmit = READ_ONCE(m->tcfm_mac_header_xmit);
+- m_eaction = READ_ONCE(m->tcfm_eaction);
+
+ retval = tcf_mirred_to_dev(skb, m, dev, m_mac_header_xmit, m_eaction,
+ retval);
+- xmit->sched_mirred_nest--;
++ if (!want_ingress)
++ xmit->sched_mirred_nest--;
+
+ return retval;
+ }
+--
+2.53.0
+
--- /dev/null
+From c4011f23f07b6f676e2c8a8786db346fe0baf900 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:51 -0400
+Subject: net/sched: fix packet loop on netem when duplicate is on
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit 9552b11e3edabc97cfcd9f29103d5afbce7ae183 ]
+
+When netem duplicates a packet it re-enqueues the copy at the root qdisc.
+If another netem sits in the tree the copy can be duplicated
+again, recursing until the stack or memory is exhausted.
+
+The original duplication guard temporarily zeroed q->duplicate around
+the re-enqueue, but that does not cover all cases because it is
+per-qdisc state shared across all concurrent enqueue paths
+and is not safe without additional locking.
+
+Use the skb tc_depth field introduced in an earlier patch:
+ - increment it on the duplicate before re-enqueue
+ - skip duplication for any skb whose tc_depth is already non-zero.
+
+This marks the packet itself rather than mutating qdisc state,
+therefore it is safe regardless of tree topology or concurrency.
+
+Fixes: 0afb51e72855 ("[PKT_SCHED]: netem: reinsert for duplication")
+Reported-by: William Liu <will@willsroot.io>
+Reported-by: Savino Dicanosa <savy@syst3mfailure.io>
+Closes: https://lore.kernel.org/netdev/8DuRWwfqjoRDLDmBMlIfbrsZg9Gx50DHJc1ilxsEBNe2D6NMoigR_eIRIG0LOjMc3r10nUUZtArXx4oZBIdUfZQrwjcQhdinnMis_0G7VEk=@willsroot.io/
+Co-developed-by: Victor Nogueira <victor@mojatatu.com>
+Signed-off-by: Victor Nogueira <victor@mojatatu.com>
+Reviewed-by: William Liu <will@willsroot.io>
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-5-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_netem.c | 7 +++----
+ 1 file changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
+index d97acd2f392346..17a79fe2f0911d 100644
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -461,7 +461,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+ skb->prev = NULL;
+
+ /* Random duplication */
+- if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor, &q->prng))
++ if (q->duplicate && skb->tc_depth == 0 &&
++ q->duplicate >= get_crandom(&q->dup_cor, &q->prng))
+ ++count;
+
+ /* Drop packet? */
+@@ -540,11 +541,9 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
+ */
+ if (skb2) {
+ struct Qdisc *rootq = qdisc_root_bh(sch);
+- u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
+
+- q->duplicate = 0;
++ skb2->tc_depth++; /* prevent duplicating a dup... */
+ rootq->enqueue(skb2, rootq, to_free);
+- q->duplicate = dupsave;
+ skb2 = NULL;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 9e979a4d13b2b7675c50cff8ecd323d91f115356 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 08:25:49 -0400
+Subject: net/sched: Revert "net/sched: Restrict conditions for adding
+ duplicating netems to qdisc tree"
+
+From: Jamal Hadi Salim <jhs@mojatatu.com>
+
+[ Upstream commit eda0b7f203bb166c98d1418b204135bd566ac83b ]
+
+This reverts commit ec8e0e3d7adef940cdf9475e2352c0680189d14e.
+
+The original patch rejects any tree containing two netems when
+either has duplication set, even when they sit on unrelated classes
+of the same classful parent. That broke configurations that have
+worked since netem was introduced.
+
+The re-entrancy problem the original commit was trying to solve is
+handled by later patch using tc_depth flag.
+
+Doing this revert will (re)expose the original bug with multiple
+netem duplication. When this patch is backported make sure
+and get the full series.
+
+Fixes: ec8e0e3d7ade ("net/sched: Restrict conditions for adding duplicating netems to qdisc tree")
+Reported-by: Ji-Soo Chung <jschung2@proton.me>
+Reported-by: Gerlinde <lrGerlinde@mailfence.com>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220774
+Reported-by: zyc zyc <zyc199902@zohomail.cn>
+Closes: https://lore.kernel.org/all/19adda5a1e2.12410b78222774.9191120410578703463@zohomail.cn/
+Reported-by: Manas Ghandat <ghandatmanas@gmail.com>
+Closes: https://lore.kernel.org/netdev/f69b2c8f-8325-4c2e-a011-6dbc089f30e4@gmail.com/
+Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
+Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Link: https://patch.msgid.link/20260525122556.973584-3-jhs@mojatatu.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_netem.c | 40 ----------------------------------------
+ 1 file changed, 40 deletions(-)
+
+diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
+index bc18e1976b6e07..d97acd2f392346 100644
+--- a/net/sched/sch_netem.c
++++ b/net/sched/sch_netem.c
+@@ -1007,41 +1007,6 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
+ return 0;
+ }
+
+-static const struct Qdisc_class_ops netem_class_ops;
+-
+-static int check_netem_in_tree(struct Qdisc *sch, bool duplicates,
+- struct netlink_ext_ack *extack)
+-{
+- struct Qdisc *root, *q;
+- unsigned int i;
+-
+- root = qdisc_root_sleeping(sch);
+-
+- if (sch != root && root->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(root))->duplicate)
+- goto err;
+- }
+-
+- if (!qdisc_dev(root))
+- return 0;
+-
+- hash_for_each(qdisc_dev(root)->qdisc_hash, i, q, hash) {
+- if (sch != q && q->ops->cl_ops == &netem_class_ops) {
+- if (duplicates ||
+- ((struct netem_sched_data *)qdisc_priv(q))->duplicate)
+- goto err;
+- }
+- }
+-
+- return 0;
+-
+-err:
+- NL_SET_ERR_MSG(extack,
+- "netem: cannot mix duplicating netems with other netems in tree");
+- return -EINVAL;
+-}
+-
+ /* Parse netlink message to set options */
+ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ struct netlink_ext_ack *extack)
+@@ -1118,11 +1083,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
+ q->gap = qopt->gap;
+ q->counter = 0;
+ q->loss = qopt->loss;
+-
+- ret = check_netem_in_tree(sch, qopt->duplicate, extack);
+- if (ret)
+- goto unlock;
+-
+ q->duplicate = qopt->duplicate;
+
+ /* for compatibility with earlier versions.
+--
+2.53.0
+
--- /dev/null
+From 486561b89e9f97c15e8cd6e953d924fd86826871 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 May 2026 19:43:53 +0100
+Subject: net: skbuff: fix pskb_carve leaking zcopy pages
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit ff6e798c2eac3ebd0501ad7e796f583fab928de8 ]
+
+When SKBFL_MANAGED_FRAG_REFS is set, frag pages are not refcounted but
+their lifetime is controlled by the attached ubuf_info. To make a copy
+of the skb_shared_info, we either should clear the flag and reference
+the frags, or keep the flag and have frags unreferenced.
+
+pskb_carve_inside_header() and pskb_carve_inside_nonlinear() don't
+follow the rule and thus can leak page references. Let's clear
+SKBFL_MANAGED_FRAG_REFS from the original skb to fix it. It's the
+simplest way to address it, but there are more performant ways to do
+that if it ever becomes a problem.
+
+Link: https://lore.kernel.org/all/20260523085809.26331-1-nvminh232@clc.fitus.edu.vn/
+Fixes: 753f1ca4e1e50 ("net: introduce managed frags infrastructure")
+Reported-by: Minh Nguyen <minhnguyen.080505@gmail.com>
+Reported-by: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/1e2086aa69217d7f9c8da3d38f5be7160f1b4cd1.1779993185.git.asml.silence@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/skbuff.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 13af6f35428d52..95ef64fad657d3 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -6847,6 +6847,11 @@ static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off,
+ skb_copy_from_linear_data_offset(skb, off, data, new_hlen);
+ skb->len -= off;
+
++ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
++ * while refcounting frags below.
++ */
++ skb_zcopy_downgrade_managed(skb);
++
+ memcpy((struct skb_shared_info *)(data + size),
+ skb_shinfo(skb),
+ offsetof(struct skb_shared_info,
+@@ -6958,6 +6963,11 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,
+ return -ENOMEM;
+ size = SKB_WITH_OVERHEAD(size);
+
++ /* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
++ * while refcounting frags below.
++ */
++ skb_zcopy_downgrade_managed(skb);
++
+ memcpy((struct skb_shared_info *)(data + size),
+ skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0]));
+ if (skb_orphan_frags(skb, gfp_mask)) {
+--
+2.53.0
+
--- /dev/null
+From 6137ada3d0ec0ca3637d283839198f46d1936a01 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 16:56:39 +0200
+Subject: net/smc: Do not re-initialize smc hashtables
+
+From: Alexandra Winter <wintera@linux.ibm.com>
+
+[ Upstream commit 9e4389b0038781f19f97895186ed941ff8ac1678 ]
+
+INIT_HLIST_HEAD(&smc_v*_hashinfo.ht) are called after smc_nl_init(),
+proto_register() and sock_register(). This can lead to smc_v*_hashinfo.ht
+being reset even though hash entries already exist and are being used,
+possibly resulting in a corrupted list.
+
+Remove unnecessary and dangerous re-initialisation of smc_v*_hashinfo.ht in
+smc_init(); it is implicitly initialised to zero anyhow. Add
+HLIST_HEAD_INIT to the definitions for clarity.
+
+Fixes: f16a7dd5cf27 ("smc: netlink interface for SMC sockets")
+Suggested-by: Halil Pasic <pasic@linux.ibm.com>
+Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
+Acked-by: Halil Pasic <pasic@linux.ibm.com>
+Reviewed-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
+Link: https://patch.msgid.link/20260521145639.10317-1-wintera@linux.ibm.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/smc/af_smc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
+index f744f791121776..de034a3e5d801f 100644
+--- a/net/smc/af_smc.c
++++ b/net/smc/af_smc.c
+@@ -188,10 +188,12 @@ static bool smc_hs_congested(const struct sock *sk)
+
+ struct smc_hashinfo smc_v4_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v4_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ struct smc_hashinfo smc_v6_hashinfo = {
+ .lock = __RW_LOCK_UNLOCKED(smc_v6_hashinfo.lock),
++ .ht = HLIST_HEAD_INIT,
+ };
+
+ int smc_hash_sk(struct sock *sk)
+@@ -3522,8 +3524,6 @@ static int __init smc_init(void)
+ pr_err("%s: sock_register fails with %d\n", __func__, rc);
+ goto out_proto6;
+ }
+- INIT_HLIST_HEAD(&smc_v4_hashinfo.ht);
+- INIT_HLIST_HEAD(&smc_v6_hashinfo.ht);
+
+ rc = smc_ib_register_client();
+ if (rc) {
+--
+2.53.0
+
--- /dev/null
+From 0639455d3782e3bfd34565125f2225b8bfc5f607 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 22:52:07 +0200
+Subject: netfilter: ebtables: fix OOB read in compat_mtw_from_user
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit f438d1786d657d57790c5d138d6db3fc9fdac392 ]
+
+Luxiao Xu says:
+
+ The function compat_mtw_from_user() converts ebtables extensions from
+ 32-bit user structures to kernel native structures. However, it lacks
+ proper validation of the user-supplied match_size/target_size.
+
+ When certain extensions are processed, the kernel-side translation
+ logic may perform memory accesses based on the extension's expected
+ size. If the user provides a size smaller than what the extension
+ requires, it results in an out-of-bounds read as reported by KASAN.
+
+ This fix introduces a check to ensure match_size is at least as large
+ as the extension's required compatsize. This covers matches, watchers,
+ and targets, while maintaining compatibility with standard targets.
+
+AFAIU this is relevant for matches that need to go though
+match->compat_from_user() call. Those that use plain memcpy with the
+user-provided size are ok because the caller checks that size vs the
+start of the next rule entry offset (which itself is checked vs. total
+size copied from userspace).
+
+The ->compat_from_user() callbacks assume they can read compatsize bytes,
+so they need this extra check.
+
+Based on an earlier patch from Luxiao Xu.
+
+Fixes: 81e675c227ec ("netfilter: ebtables: add CONFIG_COMPAT support")
+Reported-by: Yuan Tan <yuantan098@gmail.com>
+Reported-by: Yifan Wu <yifanwucs@gmail.com>
+Reported-by: Juefei Pu <tomapufckgml@gmail.com>
+Reported-by: Xin Liu <bird@lzu.edu.cn>
+Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
+Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/netfilter/ebtables.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index b9f4daac09af36..8a6a069329d21d 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -1956,6 +1956,25 @@ enum compat_mwt {
+ EBT_COMPAT_TARGET,
+ };
+
++static bool match_size_ok(const struct xt_match *match, unsigned int match_size)
++{
++ u16 csize;
++
++ if (match->matchsize == -1) /* cannot validate ebt_among */
++ return true;
++
++ csize = match->compatsize ? : match->matchsize;
++
++ return match_size >= csize;
++}
++
++static bool tgt_size_ok(const struct xt_target *tgt, unsigned int tgt_size)
++{
++ u16 csize = tgt->compatsize ? : tgt->targetsize;
++
++ return tgt_size >= csize;
++}
++
+ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ enum compat_mwt compat_mwt,
+ struct ebt_entries_buf_state *state,
+@@ -1981,6 +2000,11 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ if (IS_ERR(match))
+ return PTR_ERR(match);
+
++ if (!match_size_ok(match, match_size)) {
++ module_put(match->me);
++ return -EINVAL;
++ }
++
+ off = ebt_compat_match_offset(match, match_size);
+ if (dst) {
+ if (match->compat_from_user)
+@@ -2000,6 +2024,12 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
+ mwt->u.revision);
+ if (IS_ERR(wt))
+ return PTR_ERR(wt);
++
++ if (!tgt_size_ok(wt, match_size)) {
++ module_put(wt->me);
++ return -EINVAL;
++ }
++
+ off = xt_compat_target_offset(wt);
+
+ if (dst) {
+--
+2.53.0
+
--- /dev/null
+From b0318bf07d4088b57acb7db0c691bb4f038eeeb9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 May 2026 16:37:56 +0200
+Subject: netfilter: nf_tables: fix dst corruption in same register operation
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 18014147d3ee7831dce53fe65d7fc8d428b02552 ]
+
+For lshift and rshift, the shift operations are performed in a loop over
+32-bit words. The loop calculates the shifted value and write it to dst,
+and then immediately reads from src to calculate the carry for the next
+iteration. Because src and dst could point to the same memory location,
+the carry is incorrectly calculated using the newly modified dst value
+instead of the original src value.
+
+Adding a temporary local variable to cache the original value before
+writing to dst and using it for the carry calculation solves the
+problem. In addition, partial overlap is rejected from control plane for
+all kind of operations including byteorder. This was tested with the
+following bytecode:
+
+table test_table ip flags 0 use 1 handle 1
+ip test_table test_chain use 3 type filter hook input prio 0 policy accept packets 0 bytes 0 flags 1
+ip test_table test_chain 2
+ [ immediate reg 1 0x44332211 0x88776655 ]
+ [ bitwise reg 1 = ( reg 1 << 0x08000000 ) ]
+ [ cmp eq reg 1 0x66443322 0x00887766 ]
+ [ counter pkts 0 bytes 0 ]
+ip test_table test_chain 4 3
+ [ immediate reg 1 0x44332211 0x88776655 ]
+ [ bitwise reg 1 = ( reg 1 << 0x08000000 ) ]
+ [ cmp eq reg 1 0x55443322 0x00887766 ]
+ [ counter pkts 21794 bytes 1917798 ]
+
+Fixes: 567d746b55bc ("netfilter: bitwise: add support for shifts.")
+Acked-by: Jeremy Sowden <jeremy@azazel.net>
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables.h | 7 +++++++
+ net/netfilter/nft_bitwise.c | 18 ++++++++++++++----
+ net/netfilter/nft_byteorder.c | 13 ++++++++++---
+ 3 files changed, 31 insertions(+), 7 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index 3ec41574af776c..668b401f5147b4 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -187,6 +187,13 @@ static inline u64 nft_reg_load64(const u32 *sreg)
+ return get_unaligned((u64 *)sreg);
+ }
+
++static inline bool nft_reg_overlap(u8 src, u8 dst, u32 len)
++{
++ unsigned int n = DIV_ROUND_UP(len, sizeof(u32));
++
++ return src != dst && src < dst + n && dst < src + n;
++}
++
+ static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
+ unsigned int len)
+ {
+diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
+index af990c600745be..1afb36fb5994db 100644
+--- a/net/netfilter/nft_bitwise.c
++++ b/net/netfilter/nft_bitwise.c
+@@ -43,8 +43,10 @@ static void nft_bitwise_eval_lshift(u32 *dst, const u32 *src,
+ u32 carry = 0;
+
+ for (i = DIV_ROUND_UP(priv->len, sizeof(u32)); i > 0; i--) {
+- dst[i - 1] = (src[i - 1] << shift) | carry;
+- carry = src[i - 1] >> (BITS_PER_TYPE(u32) - shift);
++ u32 tmp_src = src[i - 1];
++
++ dst[i - 1] = (tmp_src << shift) | carry;
++ carry = tmp_src >> (BITS_PER_TYPE(u32) - shift);
+ }
+ }
+
+@@ -56,8 +58,10 @@ static void nft_bitwise_eval_rshift(u32 *dst, const u32 *src,
+ u32 carry = 0;
+
+ for (i = 0; i < DIV_ROUND_UP(priv->len, sizeof(u32)); i++) {
+- dst[i] = carry | (src[i] >> shift);
+- carry = src[i] << (BITS_PER_TYPE(u32) - shift);
++ u32 tmp_src = src[i];
++
++ dst[i] = carry | (tmp_src >> shift);
++ carry = tmp_src << (BITS_PER_TYPE(u32) - shift);
+ }
+ }
+
+@@ -235,6 +239,9 @@ static int nft_bitwise_init_bool(const struct nft_ctx *ctx,
+ &priv->sreg2, priv->len);
+ if (err < 0)
+ return err;
++
++ if (nft_reg_overlap(priv->sreg2, priv->dreg, priv->len))
++ return -EINVAL;
+ }
+
+ return 0;
+@@ -265,6 +272,9 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
+ if (err < 0)
+ return err;
+
++ if (nft_reg_overlap(priv->sreg, priv->dreg, priv->len))
++ return -EINVAL;
++
+ if (tb[NFTA_BITWISE_OP]) {
+ priv->op = ntohl(nla_get_be32(tb[NFTA_BITWISE_OP]));
+ switch (priv->op) {
+diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
+index af9206a3afd181..5e7a7841b789b0 100644
+--- a/net/netfilter/nft_byteorder.c
++++ b/net/netfilter/nft_byteorder.c
+@@ -144,9 +144,16 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
+ if (err < 0)
+ return err;
+
+- return nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
+- &priv->dreg, NULL, NFT_DATA_VALUE,
+- priv->len);
++ err = nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
++ &priv->dreg, NULL, NFT_DATA_VALUE,
++ priv->len);
++ if (err < 0)
++ return err;
++
++ if (nft_reg_overlap(priv->sreg, priv->dreg, priv->len))
++ return -EINVAL;
++
++ return 0;
+ }
+
+ static int nft_byteorder_dump(struct sk_buff *skb,
+--
+2.53.0
+
--- /dev/null
+From 3785b183ff1f658fab7f65a5e55794ca86ec561a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 12:36:14 -0700
+Subject: netfilter: synproxy: refresh tcphdr after skb_ensure_writable
+
+From: Chris Mason <clm@meta.com>
+
+[ Upstream commit 92170e6afe927ab2792a3f71902845789c8e31b1 ]
+
+synproxy_tstamp_adjust() rewrites the TCP timestamp option in place
+and then patches the TCP checksum via inet_proto_csum_replace4() on
+the caller-supplied tcphdr pointer. Both ipv4_synproxy_hook() and
+ipv6_synproxy_hook() obtain that pointer with skb_header_pointer()
+before calling in, so it may either alias skb->head directly or
+point at the caller's on-stack _tcph buffer.
+
+Between obtaining the pointer and using it, the function calls
+skb_ensure_writable(skb, optend), which on a cloned or non-linear
+skb invokes pskb_expand_head() and frees the old skb->head. After
+that point the cached th is stale:
+
+ caller (ipv[46]_synproxy_hook)
+ th = skb_header_pointer(skb, ..., &_tcph)
+ synproxy_tstamp_adjust(skb, protoff, th, ...)
+ skb_ensure_writable(skb, optend)
+ pskb_expand_head() /* kfree(old skb->head) */
+ ...
+ inet_proto_csum_replace4(&th->check, ...)
+ /* writes into freed head, or
+ into the caller's stack copy
+ leaving the on-wire checksum
+ stale */
+
+The option bytes are written through skb->data and are fine; only
+the checksum update goes through th and so lands in the wrong
+place. The result is either a write into freed slab memory or a
+packet leaving with a checksum that does not match its payload.
+
+Fix by re-deriving th from skb->data + protoff immediately after
+skb_ensure_writable() succeeds, so the subsequent checksum update
+targets the linear, writable header.
+
+Fixes: 48b1de4c110a ("netfilter: add SYNPROXY core/target")
+Assisted-by: kres (claude-opus-4-7)
+Signed-off-by: Chris Mason <clm@meta.com>
+Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_synproxy_core.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
+index 57f57e2fc80a8f..036c8586f49b75 100644
+--- a/net/netfilter/nf_synproxy_core.c
++++ b/net/netfilter/nf_synproxy_core.c
+@@ -200,6 +200,8 @@ synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,
+ if (skb_ensure_writable(skb, optend))
+ return 0;
+
++ th = (struct tcphdr *)(skb->data + protoff);
++
+ while (optoff < optend) {
+ unsigned char *op = skb->data + optoff;
+
+--
+2.53.0
+
--- /dev/null
+From 64d259f9aff2371b33a3782e01d2a5a6db547288 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 20:10:08 +0200
+Subject: netfilter: xt_cpu: prefer raw_smp_processor_id
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit c376f07e16c02239ed44cabb97145d03f65b4d15 ]
+
+With PREEMPT_RCU we get splat:
+
+BUG: using smp_processor_id() in preemptible [..]
+caller is cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+CPU: 1 .. Comm: syz.3.1377 #0 PREEMPT(full)
+Call Trace:
+ <TASK>
+ dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
+ check_preemption_disabled+0xd3/0xe0 lib/smp_processor_id.c:47
+ cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37
+ [..]
+
+Just use raw version instead.
+This is similar to 14d14a5d2957 ("netfilter: nft_meta: use raw_smp_processor_id()").
+
+Fixes: 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
+Reported-by: syzbot+690d3e3ffa7335ac10eb@syzkaller.appspotmail.com
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/xt_cpu.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/xt_cpu.c b/net/netfilter/xt_cpu.c
+index 3bdc302a0f9137..9cb259902a586b 100644
+--- a/net/netfilter/xt_cpu.c
++++ b/net/netfilter/xt_cpu.c
+@@ -34,7 +34,7 @@ static bool cpu_mt(const struct sk_buff *skb, struct xt_action_param *par)
+ {
+ const struct xt_cpu_info *info = par->matchinfo;
+
+- return (info->cpu == smp_processor_id()) ^ info->invert;
++ return (info->cpu == raw_smp_processor_id()) ^ info->invert;
+ }
+
+ static struct xt_match cpu_mt_reg __read_mostly = {
+--
+2.53.0
+
--- /dev/null
+From 57f7005d37edd17fb90150d2bbe5146cdfc5a0a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:41 +0000
+Subject: nfc: llcp: Fix use-after-free in llcp_sock_release()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit f4268b466190dae95a7585f69b4f1f8ad097632c ]
+
+llcp_sock_release() unconditionally unlinks the socket from the local
+sockets list. However, if the socket is still in connecting state, it
+is on the connecting list.
+
+Fix this by checking the socket state and unlinking from the correct list.
+
+Fixes: b4011239a08e ("NFC: llcp: Fix non blocking sockets connections")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-1-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_sock.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
+index f1be1e84f66537..feab29fc62f44b 100644
+--- a/net/nfc/llcp_sock.c
++++ b/net/nfc/llcp_sock.c
+@@ -633,6 +633,8 @@ static int llcp_sock_release(struct socket *sock)
+
+ if (sock->type == SOCK_RAW)
+ nfc_llcp_sock_unlink(&local->raw_sockets, sk);
++ else if (sk->sk_state == LLCP_CONNECTING)
++ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ else
+ nfc_llcp_sock_unlink(&local->sockets, sk);
+
+--
+2.53.0
+
--- /dev/null
+From 6a7ed01eb4ecf4efdae29a44fd4ded9f6176a9dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Apr 2026 13:40:42 +0000
+Subject: nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()
+
+From: Lee Jones <lee@kernel.org>
+
+[ Upstream commit b493ea2765cc17cb8aa7e7544a4b6dcb05b6ed77 ]
+
+A race condition exists in the NFC LLCP connection state machine where
+the connection acceptance packet (CC) can be processed concurrently with
+socket release. This can lead to a use-after-free of the socket object.
+
+When nfc_llcp_recv_cc() moves the socket from the connecting_sockets
+list to the sockets list, it does so without holding the socket lock.
+If llcp_sock_release() is executing concurrently, it might have already
+unlinked the socket and dropped its references, which can result in
+nfc_llcp_recv_cc() linking a freed socket into the live list.
+
+Fix this by holding lock_sock() during the state transition and list
+movement in nfc_llcp_recv_cc(). After acquiring the lock, check if
+the socket is still hashed to ensure it hasn't already been unlinked
+and marked for destruction by the release path. This aligns the locking
+pattern with recv_hdlc() and recv_disc().
+
+Fixes: a69f32af86e3 ("NFC: Socket linked list")
+Signed-off-by: Lee Jones <lee@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20260429134115.3558604-2-lee@kernel.org
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/nfc/llcp_core.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
+index db5bc6a878ddb0..dc65c719f35f2e 100644
+--- a/net/nfc/llcp_core.c
++++ b/net/nfc/llcp_core.c
+@@ -1218,6 +1218,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+
+ sk = &llcp_sock->sk;
+
++ lock_sock(sk);
++
++ /* Check if socket was destroyed whilst waiting for the lock */
++ if (!sk_hashed(sk)) {
++ release_sock(sk);
++ nfc_llcp_sock_put(llcp_sock);
++ return;
++ }
++
+ /* Unlink from connecting and link to the client array */
+ nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
+ nfc_llcp_sock_link(&local->sockets, sk);
+@@ -1229,6 +1238,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
+ sk->sk_state = LLCP_CONNECTED;
+ sk->sk_state_change(sk);
+
++ release_sock(sk);
++
+ nfc_llcp_sock_put(llcp_sock);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 2ebff846067468486d15be8295548ed5de7caaa5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 May 2026 19:55:18 +0800
+Subject: nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems
+
+From: Carl Lee <carl.lee@amd.com>
+
+[ Upstream commit f23bf992d65a42007c517b060ca35cebdea3525a ]
+
+Some ACPI-based platforms report incorrect IRQ trigger types (e.g.
+IRQF_TRIGGER_HIGH), which can lead to interrupt storms.
+
+Use the historically working rising-edge trigger on ACPI systems to
+avoid this regression.
+
+Device Tree-based systems continue to use the firmware-provided
+trigger type.
+
+Fixes: 57be33f85e36 ("nfc: nxp-nci: remove interrupt trigger type")
+Signed-off-by: Carl Lee <carl.lee@amd.com>
+Tested-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
+Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
+Tested-by: Luca Stefani <luca.stefani.ge1@gmail.com>
+Link: https://patch.msgid.link/20260516-nfc-nxp-nci-i2c-restore-irq-trigger-fallback-v3-1-37ba4b6e9086@amd.com
+Signed-off-by: David Heidelberg <david@ixit.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/nxp-nci/i2c.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c
+index b3d34433bd14a0..a6c08175d9dd93 100644
+--- a/drivers/nfc/nxp-nci/i2c.c
++++ b/drivers/nfc/nxp-nci/i2c.c
+@@ -16,6 +16,7 @@
+ #include <linux/delay.h>
+ #include <linux/i2c.h>
+ #include <linux/interrupt.h>
++#include <linux/irq.h>
+ #include <linux/module.h>
+ #include <linux/nfc.h>
+ #include <linux/gpio/consumer.h>
+@@ -267,6 +268,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client)
+ {
+ struct device *dev = &client->dev;
+ struct nxp_nci_i2c_phy *phy;
++ unsigned long irqflags;
+ int r;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+@@ -303,9 +305,26 @@ static int nxp_nci_i2c_probe(struct i2c_client *client)
+ if (r < 0)
+ return r;
+
++ /*
++ * ACPI platforms may report incorrect IRQ trigger types
++ * (e.g. level-high), which can lead to interrupt storms.
++ *
++ * Use the historically stable rising-edge trigger for ACPI devices.
++ *
++ * On non-ACPI systems (e.g. Device Tree), prefer the firmware-
++ * provided trigger type, falling back to rising-edge if not set.
++ */
++ if (ACPI_COMPANION(dev)) {
++ irqflags = IRQF_TRIGGER_RISING;
++ } else {
++ irqflags = irq_get_trigger_type(client->irq);
++ if (!irqflags)
++ irqflags = IRQF_TRIGGER_RISING;
++ }
++
+ r = request_threaded_irq(client->irq, NULL,
+ nxp_nci_i2c_irq_thread_fn,
+- IRQF_ONESHOT,
++ irqflags | IRQF_ONESHOT,
+ NXP_NCI_I2C_DRIVER_NAME, phy);
+ if (r < 0)
+ nfc_err(&client->dev, "Unable to register IRQ handler\n");
+--
+2.53.0
+
--- /dev/null
+From 9ccafa4254a63ef89313fd285189fef0703166dc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 12:51:16 -0400
+Subject: nvme-tcp: store negative errno in queue->tls_err
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 9015985b5eb1a90eb86caf5bce1dfcf1aa38f8ad ]
+
+nvme_tcp_tls_done() assigns queue->tls_err in three branches. The
+ENOKEY lookup failure and the EOPNOTSUPP initializer both store
+negative errnos. The third branch, reached when the handshake
+layer reports a non-zero status, stores -status.
+
+The handshake layer delivers status to the consumer callback as a
+negative errno; the other in-tree consumers --
+xs_tls_handshake_done() and the nvmet target callback -- treat
+their status argument that way. The extra negation in
+nvme_tcp_tls_done() flips the sign, leaving tls_err as a positive
+value (for instance, +EIO), which nvme_tcp_start_tls() then
+returns to its caller.
+
+Drop the extra negation so queue->tls_err uniformly carries a
+negative errno on failure.
+
+Fixes: be8e82caa685 ("nvme-tcp: enable TLS handshake upcall")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Hannes Reinecke <hare@kernel.org>
+Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
+Link: https://patch.msgid.link/20260525-handshake-file-pin-v3-2-66c616906ead@oracle.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nvme/host/tcp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
+index 243dab830dc84f..29f9ba0bdd3f1e 100644
+--- a/drivers/nvme/host/tcp.c
++++ b/drivers/nvme/host/tcp.c
+@@ -1688,7 +1688,7 @@ static void nvme_tcp_tls_done(void *data, int status, key_serial_t pskid)
+ qid, pskid, status);
+
+ if (status) {
+- queue->tls_err = -status;
++ queue->tls_err = status;
+ goto out_complete;
+ }
+
+--
+2.53.0
+
--- /dev/null
+From 7f947d9ded5a08fd174b0011c86c6f8daa2afba8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 29 May 2026 13:23:57 +0200
+Subject: Revert "ipv6: preserve insertion order for same-scope addresses"
+
+From: Fernando Fernandez Mancera <fmancera@suse.de>
+
+[ Upstream commit 072aa0f5c3d8f11f3159037418ec45edce7440b8 ]
+
+Chris Adams reported that preserving insertion order for same-scope
+addresses is causing SSH connections to be dropped after stopping a VM
+while running NetworkManager.
+
+NetworkManager caches the IPv6 address configuration, when a RA arrives,
+it determines the list of addresses to configure and checks if the
+addresses are already in the right order in the kernel. If they aren't,
+NetworkManager removes and re-adds them to achieve the desired order.
+
+As the order changes, NetworkManager is confused and reconfigures the
+addresses on every update. In addition, this would also affect to cloud
+tooling that relies on IPv6 addresses order to identify primary and
+secondaries addresses.
+
+This reverts commit cb3de96eea66f5e4a580086c6a1be46e765f97f4.
+
+Fixes: cb3de96eea66 ("ipv6: preserve insertion order for same-scope addresses")
+Reported-by: Chris Adams <linux@cmadams.net>
+Closes: https://lore.kernel.org/netdev/20260521135310.GC977@cmadams.net/
+Signed-off-by: Fernando Fernandez Mancera <fmancera@suse.de>
+Link: https://patch.msgid.link/20260529112357.5079-1-fmancera@suse.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/addrconf.c | 2 +-
+ tools/testing/selftests/net/ioam6.sh | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index dd0b4d80e0f84d..e5276be71062a3 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -1012,7 +1012,7 @@ ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
+ list_for_each(p, &idev->addr_list) {
+ struct inet6_ifaddr *ifa
+ = list_entry(p, struct inet6_ifaddr, if_list);
+- if (ifp_scope > ipv6_addr_src_scope(&ifa->addr))
++ if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr))
+ break;
+ }
+
+diff --git a/tools/testing/selftests/net/ioam6.sh b/tools/testing/selftests/net/ioam6.sh
+index b2b99889942f75..845c26dd01a932 100755
+--- a/tools/testing/selftests/net/ioam6.sh
++++ b/tools/testing/selftests/net/ioam6.sh
+@@ -273,8 +273,8 @@ setup()
+ ip -netns $ioam_node_beta link set ioam-veth-betaR name veth1 &>/dev/null
+ ip -netns $ioam_node_gamma link set ioam-veth-gamma name veth0 &>/dev/null
+
+- ip -netns $ioam_node_alpha addr add 2001:db8:1::2/64 dev veth0 &>/dev/null
+ ip -netns $ioam_node_alpha addr add 2001:db8:1::50/64 dev veth0 &>/dev/null
++ ip -netns $ioam_node_alpha addr add 2001:db8:1::2/64 dev veth0 &>/dev/null
+ ip -netns $ioam_node_alpha link set veth0 up &>/dev/null
+ ip -netns $ioam_node_alpha link set lo up &>/dev/null
+ ip -netns $ioam_node_alpha route add 2001:db8:2::/64 \
+--
+2.53.0
+
--- /dev/null
+From ada4b76d8603ae226ddb79d6f868822cb9969dd2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 May 2026 14:09:41 -0400
+Subject: scsi: core: Run queues for all non-SDEV_DEL devices from
+ scsi_run_host_queues
+
+From: David Jeffery <djeffery@redhat.com>
+
+[ Upstream commit 7205b58702273baf21d6ba7992e6ba15852325f7 ]
+
+While a SCSI host is in a recovery state, scsi_mq_requeue_cmd() will not
+set the requeue list for a requeued command to be kicked in the future.
+The expectation is a call to scsi_run_host_queues() will kick all SCSI
+devices once the recovery state is cleared.
+
+However, scsi_run_host_queues() uses shost_for_each_device() which uses
+scsi_device_get() and so will ignore devices in a partially removed
+state like SDEV_CANCEL. But these devices may also have requeued
+requests, leaving their requests stuck from not being kicked and causing
+the removal process of the device to hang.
+
+scsi_run_host_queues() needs to run against more devices than the macro
+shost_for_each_device() allows. Instead of using the too limiting
+scsi_device_get() state checks, only ignore devices in SDEV_DEL state or
+when unable to acquire a reference. Attempt to run the queues for all
+other devices when scsi_run_host_queues() is called.
+
+Fixes: 8b566edbdbfb ("scsi: core: Only kick the requeue list if necessary")
+Signed-off-by: David Jeffery <djeffery@redhat.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://patch.msgid.link/20260515180941.9698-1-djeffery@redhat.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_lib.c | 27 +++++++++++++++++++++++++--
+ 1 file changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index d3a8cd4166f92f..1da52f07d299b5 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -574,10 +574,33 @@ void scsi_requeue_run_queue(struct work_struct *work)
+
+ void scsi_run_host_queues(struct Scsi_Host *shost)
+ {
+- struct scsi_device *sdev;
++ struct scsi_device *sdev, *prev = NULL;
++ unsigned long flags;
+
+- shost_for_each_device(sdev, shost)
++ spin_lock_irqsave(shost->host_lock, flags);
++ __shost_for_each_device(sdev, shost) {
++ /*
++ * Only skip devices so deep into removal they will never need
++ * another kick to their queues. Thus scsi_device_get() cannot
++ * be used as it would skip devices in SDEV_CANCEL state which
++ * may need a queue kick.
++ */
++ if (sdev->sdev_state == SDEV_DEL ||
++ !get_device(&sdev->sdev_gendev))
++ continue;
++ spin_unlock_irqrestore(shost->host_lock, flags);
++
++ if (prev)
++ put_device(&prev->sdev_gendev);
+ scsi_run_queue(sdev->request_queue);
++
++ prev = sdev;
++
++ spin_lock_irqsave(shost->host_lock, flags);
++ }
++ spin_unlock_irqrestore(shost->host_lock, flags);
++ if (prev)
++ put_device(&prev->sdev_gendev);
+ }
+
+ static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
+--
+2.53.0
+
--- /dev/null
+From 45613a00a0a2105166c48868e17596aa6ae4edbc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 May 2026 16:53:56 -0400
+Subject: scsi: scsi_debug: Add missing newline in scsi_debug_device_reset()
+
+From: Ewan D. Milne <emilne@redhat.com>
+
+[ Upstream commit e4bb73bf3ac11b4a93634660345b9d764a4a80df ]
+
+A "\n" at the end of the sdev_printk() string appears to have been
+inadvertently removed. Add it back for correct log message formatting.
+
+Fixes: a743b120227a ("scsi: scsi_debug: Stop printing extra function name in debug logs")
+Assisted-by: Claude:claude-opus-4-6
+Signed-off-by: Ewan D. Milne <emilne@redhat.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Link: https://patch.msgid.link/20260519205356.1040855-1-emilne@redhat.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_debug.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
+index 1515495fd9ea7e..040c5e1e713a2e 100644
+--- a/drivers/scsi/scsi_debug.c
++++ b/drivers/scsi/scsi_debug.c
+@@ -6953,7 +6953,7 @@ static int scsi_debug_device_reset(struct scsi_cmnd *SCpnt)
+ ++num_dev_resets;
+
+ if (SDEBUG_OPT_ALL_NOISE & sdebug_opts)
+- sdev_printk(KERN_INFO, sdp, "doing device reset");
++ sdev_printk(KERN_INFO, sdp, "doing device reset\n");
+
+ scsi_debug_stop_all_queued(sdp);
+ if (devip) {
+--
+2.53.0
+
--- /dev/null
+From 7946fa974b54dec0de9c545a2d82fbcde4b5abe7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 11:24:11 +0800
+Subject: sctp: fix race between sctp_wait_for_connect and peeloff
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Zhenghang Xiao <kipreyyy@gmail.com>
+
+[ Upstream commit f14fe6395a8b3d961a61e138ad7b36ba3626dd4e ]
+
+sctp_wait_for_connect() drops and re-acquires the socket lock while
+waiting for the association to reach ESTABLISHED state. During this
+window, another thread can peeloff the association to a new socket via
+getsockopt(SCTP_SOCKOPT_PEELOFF), changing asoc->base.sk. After
+re-acquiring the old socket lock, sctp_wait_for_connect() returns
+success without noticing the migration — the caller then accesses
+the association under the wrong lock in sctp_datamsg_from_user().
+
+Add the same sk != asoc->base.sk check that sctp_wait_for_sndbuf()
+already has, returning an error if the association was migrated while
+we slept.
+
+Fixes: 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
+Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
+Acked-by: Xin Long <lucien.xin@gmail.com>
+Link: https://patch.msgid.link/20260527032411.60959-1-kipreyyy@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sctp/socket.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index aeffa10ff2d34a..59e04788e1c760 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -9403,6 +9403,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
+ release_sock(sk);
+ current_timeo = schedule_timeout(current_timeo);
+ lock_sock(sk);
++ if (sk != asoc->base.sk)
++ goto do_error;
+
+ *timeo_p = current_timeo;
+ }
+--
+2.53.0
+
xfrm-move-policy_bydst-rcu-sync-from-per-netns-.exit.patch
net-sched-sch_sfb-replace-direct-dequeue-call-with-p.patch
bcache-fix-uninitialized-closure-object.patch
+nfc-llcp-fix-use-after-free-in-llcp_sock_release.patch
+nfc-llcp-fix-use-after-free-race-in-nfc_llcp_recv_cc.patch
+xfrm-check-for-underflow-in-xfrm_state_mtu.patch
+nfc-nxp-nci-i2c-use-rising-edge-irq-on-acpi-systems.patch
+tools-bootconfig-fix-buf-leaks-in-apply_xbc.patch
+hid-remove-duplicate-hid_warn_ratelimited-definition.patch
+kunit-fix-use-after-free-in-debugfs-when-using-kunit.patch
+accel-rocket-fix-uaf-via-dangling-gem-handle-in-crea.patch
+kernel-fork-validate-exit_signal-in-kernel_clone.patch
+esp-fix-page-frag-reference-leak-on-skb_to_sgvec-fai.patch
+netfilter-synproxy-refresh-tcphdr-after-skb_ensure_w.patch
+netfilter-xt_cpu-prefer-raw_smp_processor_id.patch
+netfilter-ebtables-fix-oob-read-in-compat_mtw_from_u.patch
+netfilter-nf_tables-fix-dst-corruption-in-same-regis.patch
+tun-free-page-on-short-frame-rejection-in-tun_xdp_on.patch
+tap-free-page-on-error-paths-in-tap_get_user_xdp.patch
+tun-free-page-on-build_skb-failure-in-tun_xdp_one.patch
+vsock-keep-poll-shutdown-state-consistent.patch
+net-netlink-fix-sending-unassigned-nsid-after-assign.patch
+net-netlink-don-t-set-nsid-on-local-notifications.patch
+net-smc-do-not-re-initialize-smc-hashtables.patch
+net-iucv-fix-locking-in-.getsockopt.patch
+scsi-core-run-queues-for-all-non-sdev_del-devices-fr.patch
+scsi-scsi_debug-add-missing-newline-in-scsi_debug_de.patch
+ipv4-free-net-ipv4.sysctl_local_reserved_ports-after.patch
+alsa-hda-cs35l56-fix-system-name-string-leaks.patch
+alsa-pcm-oss-fix-setup-list-uaf-on-proc-write-error.patch
+asoc-intel-bytcht_es8316-fix-mclk-leak-on-init-error.patch
+net-mlx5-hws-reject-unsupported-remove-header-action.patch
+net-hsr-fix-potential-oob-access-in-supervision-fram.patch
+accel-ivpu-prevent-uninitialized-data-bug-in-debugfs.patch
+gpio-mxc-fix-irq_high-handling.patch
+drm-i915-aux-use-polling-when-irqs-are-unavailable.patch
+net-avoid-checksumming-unreadable-skb-tail-on-trim.patch
+ethtool-rss-avoid-modifying-the-rss-context-response.patch
+ethtool-rss-add-missing-errno-on-rss-context-delete.patch
+ethtool-rss-fix-falsely-ignoring-indir-table-updates.patch
+ethtool-rss-fix-indir_table-and-hkey-leak-on-get_rxf.patch
+ethtool-rss-fix-hkey-leak-when-indir_size-is-0.patch
+ethtool-rss-avoid-device-context-leak-on-reply-build.patch
+ethtool-module-call-ethnl_ops_complete-on-module-fla.patch
+ethtool-module-avoid-leaking-a-netdev-ref-on-module-.patch
+ethtool-module-avoid-racy-updates-to-dev-ethtool-bit.patch
+ethtool-module-check-fw_flash_in_progress-under-rtnl.patch
+ethtool-module-fix-cleanup-if-socket-used-for-flashi.patch
+ethtool-cmis-require-exact-cdb-reply-length.patch
+ethtool-cmis-fix-u16-to-u8-truncation-of-msleep_pre_.patch
+ethtool-cmis-validate-start_cmd_payload_size-from-mo.patch
+ethtool-cmis-validate-fw-size-against-start_cmd_payl.patch
+cxl-test-update-mock-dev-array-before-calling-platfo.patch
+blk-mq-reinsert-cached-request-to-the-list.patch
+tunnels-load-network-headers-after-skb_cow-in-iptunn.patch
+vxlan-do-not-reuse-cached-ip_hdr-value-after-skb_tun.patch
+tunnels-do-not-assume-transport-header-in-iptunnel_p.patch
+ksmbd-fix-fsctl-permission-bypass-by-adding-a-permis.patch
+asoc-codecs-simple-mux-fix-enum-control-bounds-check.patch
+drm-xe-restore-idledly-regiter-on-engine-reset.patch
+bluetooth-6lowpan-check-skb_clone-return-value-in-se.patch
+bonding-refuse-to-enslave-can-devices.patch
+bridge-fix-sleep-in-atomic-context-in-netlink-path.patch
+bridge-fix-sleep-in-atomic-context-in-sysfs-path.patch
+ethtool-coalesce-cap-profile-updates-at-net_dim_para.patch
+ethtool-tsconfig-fix-reply-error-handling.patch
+ethtool-linkstate-fix-unbalanced-ethnl_ops_complete-.patch
+ethtool-pse-pd-fix-missing-ethnl_ops_complete.patch
+ethtool-tsconfig-fix-missing-ethnl_ops_complete.patch
+ethtool-tsinfo-fix-uninitialized-stats-on-the-by-phc.patch
+ethtool-tsinfo-don-t-pass-err_ptr-to-genlmsg_cancel-.patch
+ethtool-strset-fix-header-attribute-index-in-ethnl_r.patch
+ethtool-eeprom-add-missing-ethnl_ops_begin-_complete.patch
+ethtool-eeprom-add-more-safeties-to-eeprom-netlink-f.patch
+ipv6-rpl-fix-hdrlen-overflow-in-ipv6_rpl_srh_decompr.patch
+net-sched-revert-net-sched-restrict-conditions-for-a.patch
+net-sched-fix-packet-loop-on-netem-when-duplicate-is.patch
+net-introduce-skb-tc-depth-field-to-track-packet-loo.patch
+net-sched-fix-ethx-ingress-ethy-egress-ethx-ingress-.patch
+net-sched-act_mirred-fix-blockcast-recursion-bypass-.patch
+net-sched-act_mirred-fix-return-code-in-early-mirred.patch
+net-hibmcge-disable-relaxed-ordering-to-fix-rx-packe.patch
+net-hibmcge-move-dma_rmb-after-dma_sync_single_for_c.patch
+net-handshake-use-spin_lock_bh-for-hn_lock.patch
+nvme-tcp-store-negative-errno-in-queue-tls_err.patch
+net-handshake-pass-negative-errno-through-handshake_.patch
+net-handshake-hand-off-the-pinned-file-reference-to-.patch
+net-handshake-take-a-long-lived-file-reference-at-su.patch
+net-handshake-drain-pending-requests-at-net-namespac.patch
+dpll-zl3073x-detect-dpll-channel-count-from-chip-id-.patch
+dpll-zl3073x-add-die-temperature-reporting-for-suppo.patch
+dpll-export-__dpll_device_change_ntf-for-use-under-d.patch
+dpll-zl3073x-use-__dpll_device_change_ntf-and-remove.patch
+bluetooth-l2cap-clear-chan-ident-on-ecred-reconfigur.patch
+bluetooth-l2cap-fix-possible-crash-on-l2cap_ecred_co.patch
+bluetooth-hci_sync-set-hci_cmd_drain_workqueue-durin.patch
+bluetooth-hci_sync-reset-device-counters-in-hci_dev_.patch
+gpio-adnp-fix-flow-control-regression-caused-by-scop.patch
+gpio-virtuser-fix-uninitialized-data-bug-in-gpio_vir.patch
+gpio-rockchip-convert-bank-clk-to-devm_clk_get_enabl.patch
+gpio-rockchip-teardown-bugs-and-resource-leaks.patch
+net-mana-add-null-guards-in-teardown-path-to-prevent.patch
+net-mana-skip-redundant-detach-on-already-detached-p.patch
+sctp-fix-race-between-sctp_wait_for_connect-and-peel.patch
+net-pcs-pcs-mtk-lynxi-fix-bpi-r3-serdes-configuratio.patch
+vsock-virtio-bind-uarg-before-filling-zerocopy-skb.patch
+ipv6-fix-possible-infinite-loop-in-rt6_fill_node.patch
+ipv6-fix-possible-infinite-loop-in-fib6_select_path.patch
+net-skbuff-fix-pskb_carve-leaking-zcopy-pages.patch
+revert-ipv6-preserve-insertion-order-for-same-scope-.patch
--- /dev/null
+From 192848b7e150e475aa938b298842ebb047bb1441 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 09:32:31 -0700
+Subject: tap: free page on error paths in tap_get_user_xdp()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit 3bcf7aec6a9d16438f2cec29f5d7c8d5b8edf9b2 ]
+
+tap_get_user_xdp() rejects a frame shorter than ETH_HLEN with -EINVAL,
+and returns -ENOMEM when build_skb() fails. Both paths jump to the err
+label without freeing the page that vhost_net_build_xdp() allocated for
+the frame. tap_sendmsg() discards the per-buffer return value and always
+returns 0, so vhost_tx_batch() takes the success path and never frees
+the page; each rejected frame in a batch leaks one page-frag chunk.
+
+Free the page on both error paths, before the skb is built. This is the
+tap counterpart of the same leak in tun_xdp_one().
+
+Fixes: 0efac27791ee ("tap: accept an array of XDP buffs through sendmsg()")
+Fixes: ed7f2afdd0e0 ("tap: add missing verification for short frame")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260521163230.1478627-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tap.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/tap.c b/drivers/net/tap.c
+index a590e07ce0a98c..fae115915c8eff 100644
+--- a/drivers/net/tap.c
++++ b/drivers/net/tap.c
+@@ -1052,6 +1052,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
+ int err, depth;
+
+ if (unlikely(xdp->data_end - xdp->data < ETH_HLEN)) {
++ put_page(virt_to_head_page(xdp->data));
+ err = -EINVAL;
+ goto err;
+ }
+@@ -1061,6 +1062,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
+
+ skb = build_skb(xdp->data_hard_start, buflen);
+ if (!skb) {
++ put_page(virt_to_head_page(xdp->data));
+ err = -ENOMEM;
+ goto err;
+ }
+--
+2.53.0
+
--- /dev/null
+From ad672bdf9ef924e2b57c79efd27a32e823af81a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 11:01:26 +0800
+Subject: tools/bootconfig: Fix buf leaks in apply_xbc
+
+From: Hongtao Lee <lihongtao@kylinos.cn>
+
+[ Upstream commit f42d01aadcedd7bbf4f9a466cabe25c1781dedad ]
+
+If data calloc failed, free the buf before return.
+
+Link: https://lore.kernel.org/all/20260520030126.147782-1-lihongtao@kylinos.cn/
+
+Fixes: 950313ebf79c ("tools: bootconfig: Add bootconfig command")
+Signed-off-by: Hongtao Lee <lihongtao@kylinos.cn>
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/bootconfig/main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c
+index 643f707b8f1da1..ddabde20585f21 100644
+--- a/tools/bootconfig/main.c
++++ b/tools/bootconfig/main.c
+@@ -390,8 +390,10 @@ static int apply_xbc(const char *path, const char *xbc_path)
+
+ /* Backup the bootconfig data */
+ data = calloc(size + BOOTCONFIG_ALIGN + BOOTCONFIG_FOOTER_SIZE, 1);
+- if (!data)
++ if (!data) {
++ free(buf);
+ return -ENOMEM;
++ }
+ memcpy(data, buf, size);
+
+ /* Check the data format */
+--
+2.53.0
+
--- /dev/null
+From 460801af0941c4e69c20b9c35fc6cf3780737583 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 May 2026 09:33:13 -0700
+Subject: tun: free page on build_skb failure in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit aa8963fdce667a42fb7f0bdd2909fadcab02f9a8 ]
+
+When build_skb() fails in tun_xdp_one(), the function sets ret to
+-ENOMEM and jumps to the out label, which returns without freeing the
+page that vhost_net_build_xdp() allocated for the frame. As with the
+short-frame rejection path, tun_sendmsg() discards the per-buffer error
+and still returns total_len, so vhost_tx_batch() takes the success path
+and never frees the page. Each build_skb() failure in a batch leaks one
+page-frag chunk.
+
+Free the page before taking the error path, matching the put_page() the
+other error exits of tun_xdp_one() already perform.
+
+Fixes: 043d222f93ab ("tuntap: accept an array of XDP buffs through sendmsg()")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260521163312.1479805-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index 8154d18a2a235a..ca0ae5df73af78 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2437,6 +2437,7 @@ static int tun_xdp_one(struct tun_struct *tun,
+ build:
+ skb = build_skb(xdp->data_hard_start, buflen);
+ if (!skb) {
++ put_page(virt_to_head_page(xdp->data));
+ ret = -ENOMEM;
+ goto out;
+ }
+--
+2.53.0
+
--- /dev/null
+From f8ab9d7ffb13bb41e1dfb509ba278090aa062bd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 09:00:21 -0700
+Subject: tun: free page on short-frame rejection in tun_xdp_one()
+
+From: Weiming Shi <bestswngs@gmail.com>
+
+[ Upstream commit f4feb1e20058e407cb00f45aff47f5b7e19a6bbf ]
+
+tun_xdp_one() returns -EINVAL on a frame shorter than ETH_HLEN without
+freeing the page that vhost_net_build_xdp() allocated for it.
+tun_sendmsg() discards that -EINVAL and still returns total_len, so
+vhost_tx_batch() takes the success path and never frees the page; each
+short frame in a batch leaks one page-frag chunk.
+
+A local process that can open /dev/net/tun and /dev/vhost-net can hit
+this path: it attaches a tun/tap device as the vhost-net backend and
+feeds TX descriptors whose length minus the virtio-net header is below
+ETH_HLEN. Each kick leaks the page-frag chunks for that batch, and a
+tight submission loop exhausts host memory and triggers an OOM panic.
+Free the page before returning -EINVAL, matching the XDP-program error
+path in the same function.
+
+Fixes: 049584807f1d ("tun: add missing verification for short frame")
+Reported-by: Xiang Mei <xmei5@asu.edu>
+Signed-off-by: Weiming Shi <bestswngs@gmail.com>
+Reviewed-by: Dongli Zhang <dongli.zhang@oracle.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Link: https://patch.msgid.link/20260520160020.375349-2-bestswngs@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/tun.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/tun.c b/drivers/net/tun.c
+index c492fda6fc15a7..8154d18a2a235a 100644
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -2392,8 +2392,10 @@ static int tun_xdp_one(struct tun_struct *tun,
+ bool skb_xdp = false;
+ struct page *page;
+
+- if (unlikely(datasize < ETH_HLEN))
++ if (unlikely(datasize < ETH_HLEN)) {
++ put_page(virt_to_head_page(xdp->data));
+ return -EINVAL;
++ }
+
+ xdp_prog = rcu_dereference(tun->xdp_prog);
+ if (xdp_prog) {
+--
+2.53.0
+
--- /dev/null
+From 4e29eefbf913240fd13aba9d2b510f5b036e0950 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 May 2026 11:55:12 +0000
+Subject: tunnels: do not assume transport header in
+ iptunnel_pmtud_check_icmp()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 509323077ef79a26ba0c60bb556e45c12c398b2d ]
+
+In some cases, iptunnel_pmtud_check_icmp() can be called while
+skb transport header is not set.
+
+This triggers an out-of-bound access, because
+(typeof(skb->transport_header))~0U is 65535.
+
+Access the icmp header based on IPv4 network header,
+after making sure icmp->type is present in skb linear part.
+
+Note that iptunnel_pmtud_check_icmpv6()) is fine.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Reported-by: Damiano Melotti <melotti@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
+Link: https://patch.msgid.link/20260522115512.1519110-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index a52ba6f671fedf..fc993c78cbcc5e 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -280,7 +280,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct icmphdr *icmph = icmp_hdr(skb);
+ const struct iphdr *iph = ip_hdr(skb);
+
+ if (mtu < 576 || iph->frag_off != htons(IP_DF))
+@@ -291,9 +290,17 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ ipv4_is_lbcast(iph->saddr) || ipv4_is_multicast(iph->saddr))
+ return 0;
+
+- if (iph->protocol == IPPROTO_ICMP && icmp_is_err(icmph->type))
+- return 0;
++ if (iph->protocol == IPPROTO_ICMP) {
++ const struct icmphdr *icmph;
+
++ if (!pskb_network_may_pull(skb, iph->ihl * 4 +
++ offsetofend(struct icmphdr, type)))
++ return 0;
++ iph = ip_hdr(skb);
++ icmph = (void *)iph + iph->ihl * 4;
++ if (icmp_is_err(icmph->type))
++ return 0;
++ }
+ return iptunnel_pmtud_build_icmp(skb, mtu);
+ }
+
+--
+2.53.0
+
--- /dev/null
+From e02a263f36925bf91e85998209cad8cc1e2f6841 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:13:35 +0000
+Subject: tunnels: load network headers after skb_cow() in
+ iptunnel_pmtud_build_icmp[v6]()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit b4bc94353050b1fa7b702bd4c6600710dd926cff ]
+
+Sashiko found that iptunnel_pmtud_build_icmp() and
+iptunnel_pmtud_build_icmpv6() were caching ip_hdr() and ipv6_hdr()
+before an skb_cow() call which can reallocate skb->head.
+
+Fix this possible UAF by initializing the local variables
+after the skb_cow() call.
+
+Remove skb_reset_network_header() calls which were not needed.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525201335.2361845-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/ip_tunnel_core.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
+index f430d6f0463e7a..a52ba6f671fedf 100644
+--- a/net/ipv4/ip_tunnel_core.c
++++ b/net/ipv4/ip_tunnel_core.c
+@@ -212,7 +212,7 @@ EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);
+ */
+ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ {
+- const struct iphdr *iph = ip_hdr(skb);
++ const struct iphdr *iph;
+ struct icmphdr *icmph;
+ struct iphdr *niph;
+ struct ethhdr eh;
+@@ -226,7 +226,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, 576 - sizeof(*niph) - sizeof(*icmph));
+ if (err)
+@@ -236,7 +235,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)
+ err = skb_cow(skb, sizeof(*niph) + sizeof(*icmph) + ETH_HLEN);
+ if (err)
+ return err;
+-
++ iph = ip_hdr(skb);
+ icmph = skb_push(skb, sizeof(*icmph));
+ *icmph = (struct icmphdr) {
+ .type = ICMP_DEST_UNREACH,
+@@ -308,7 +307,7 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)
+ */
+ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ {
+- const struct ipv6hdr *ip6h = ipv6_hdr(skb);
++ const struct ipv6hdr *ip6h;
+ struct icmp6hdr *icmp6h;
+ struct ipv6hdr *nip6h;
+ struct ethhdr eh;
+@@ -323,7 +322,6 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+
+ skb_copy_bits(skb, skb_mac_offset(skb), &eh, ETH_HLEN);
+ pskb_pull(skb, ETH_HLEN);
+- skb_reset_network_header(skb);
+
+ err = pskb_trim(skb, IPV6_MIN_MTU - sizeof(*nip6h) - sizeof(*icmp6h));
+ if (err)
+@@ -334,6 +332,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)
+ if (err)
+ return err;
+
++ ip6h = ipv6_hdr(skb);
+ icmp6h = skb_push(skb, sizeof(*icmp6h));
+ *icmp6h = (struct icmp6hdr) {
+ .icmp6_type = ICMPV6_PKT_TOOBIG,
+--
+2.53.0
+
--- /dev/null
+From 908ca79c324a091b6705fdbb45748d215bcda089 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 May 2026 00:56:36 +0800
+Subject: vsock: keep poll shutdown state consistent
+
+From: Ziyu Zhang <ziyuzhang201@gmail.com>
+
+[ Upstream commit aae9d8a5528b8ee9ff8dc5d3558b8a9f852a724a ]
+
+vsock_poll() reads vsk->peer_shutdown before taking the socket lock
+to set EPOLLHUP and EPOLLRDHUP, then reads it again after taking
+the lock to report EOF readability. A shutdown packet can update
+peer_shutdown while poll is waiting for the lock, so one poll invocation
+can report EOF readability without the corresponding HUP/RDHUP bits.
+
+For connectible sockets, take one peer_shutdown snapshot after
+lock_sock() and use it for all peer-shutdown-derived poll bits. For
+datagram sockets, which do not take lock_sock() in poll(), take one
+lockless READ_ONCE() snapshot and pair it with WRITE_ONCE() on the
+writer side.
+
+This keeps the peer-shutdown-derived bits internally consistent for each
+poll pass.
+
+Fixes: d021c344051a ("VSOCK: Introduce VM Sockets")
+Signed-off-by: Ziyu Zhang <ziyuzhang201@gmail.com>
+Link: https://patch.msgid.link/20260519165636.62542-1-ziyuzhang201@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/vmw_vsock/af_vsock.c | 49 ++++++++++++++++---------
+ net/vmw_vsock/hyperv_transport.c | 9 +++--
+ net/vmw_vsock/virtio_transport_common.c | 14 ++++---
+ net/vmw_vsock/vmci_transport.c | 8 ++--
+ 4 files changed, 52 insertions(+), 28 deletions(-)
+
+diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
+index 08f4dfb9782c28..0a93873eb4672b 100644
+--- a/net/vmw_vsock/af_vsock.c
++++ b/net/vmw_vsock/af_vsock.c
+@@ -628,7 +628,7 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
+ */
+ sock_reset_flag(sk, SOCK_DONE);
+ sk->sk_state = TCP_CLOSE;
+- vsk->peer_shutdown = 0;
++ WRITE_ONCE(vsk->peer_shutdown, 0);
+ }
+
+ if (sk->sk_type == SOCK_SEQPACKET) {
+@@ -919,7 +919,7 @@ static struct sock *__vsock_create(struct net *net,
+ vsk->rejected = false;
+ vsk->sent_request = false;
+ vsk->ignore_connecting_rst = false;
+- vsk->peer_shutdown = 0;
++ WRITE_ONCE(vsk->peer_shutdown, 0);
+ INIT_DELAYED_WORK(&vsk->connect_work, vsock_connect_timeout);
+ INIT_DELAYED_WORK(&vsk->pending_work, vsock_pending_work);
+
+@@ -1227,6 +1227,25 @@ static int vsock_shutdown(struct socket *sock, int mode)
+ return err;
+ }
+
++static __poll_t vsock_poll_shutdown(struct sock *sk, u32 peer_shutdown)
++{
++ __poll_t mask = 0;
++
++ /* INET sockets treat local write shutdown and peer write shutdown as a
++ * case of EPOLLHUP set.
++ */
++ if (sk->sk_shutdown == SHUTDOWN_MASK ||
++ ((sk->sk_shutdown & SEND_SHUTDOWN) &&
++ (peer_shutdown & SEND_SHUTDOWN)))
++ mask |= EPOLLHUP;
++
++ if (sk->sk_shutdown & RCV_SHUTDOWN ||
++ peer_shutdown & SEND_SHUTDOWN)
++ mask |= EPOLLRDHUP;
++
++ return mask;
++}
++
+ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+ {
+@@ -1244,24 +1263,17 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ /* Signify that there has been an error on this socket. */
+ mask |= EPOLLERR;
+
+- /* INET sockets treat local write shutdown and peer write shutdown as a
+- * case of EPOLLHUP set.
+- */
+- if ((sk->sk_shutdown == SHUTDOWN_MASK) ||
+- ((sk->sk_shutdown & SEND_SHUTDOWN) &&
+- (vsk->peer_shutdown & SEND_SHUTDOWN))) {
+- mask |= EPOLLHUP;
+- }
+-
+- if (sk->sk_shutdown & RCV_SHUTDOWN ||
+- vsk->peer_shutdown & SEND_SHUTDOWN) {
+- mask |= EPOLLRDHUP;
+- }
+-
+ if (sk_is_readable(sk))
+ mask |= EPOLLIN | EPOLLRDNORM;
+
+ if (sock->type == SOCK_DGRAM) {
++ u32 peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++
++ /* DGRAM sockets do not take lock_sock() in poll(), so use one
++ * lockless snapshot for all shutdown-derived mask bits.
++ */
++ mask |= vsock_poll_shutdown(sk, peer_shutdown);
++
+ /* For datagram sockets we can read if there is something in
+ * the queue and write as long as the socket isn't shutdown for
+ * sending.
+@@ -1276,6 +1288,7 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+
+ } else if (sock_type_connectible(sk->sk_type)) {
+ const struct vsock_transport *transport;
++ u32 peer_shutdown;
+
+ lock_sock(sk);
+
+@@ -1308,8 +1321,10 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
+ * terminated should also be considered read, and we check the
+ * shutdown flag for that.
+ */
++ peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++ mask |= vsock_poll_shutdown(sk, peer_shutdown);
+ if (sk->sk_shutdown & RCV_SHUTDOWN ||
+- vsk->peer_shutdown & SEND_SHUTDOWN) {
++ peer_shutdown & SEND_SHUTDOWN) {
+ mask |= EPOLLIN | EPOLLRDNORM;
+ }
+
+diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
+index d5b0fd0a889723..842510f7dda2e3 100644
+--- a/net/vmw_vsock/hyperv_transport.c
++++ b/net/vmw_vsock/hyperv_transport.c
+@@ -264,7 +264,7 @@ static void hvs_do_close_lock_held(struct vsock_sock *vsk,
+ struct sock *sk = sk_vsock(vsk);
+
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+ sk->sk_state_change(sk);
+@@ -593,7 +593,9 @@ static int hvs_update_recv_data(struct hvsock *hvs)
+ return -EIO;
+
+ if (payload_len == 0)
+- hvs->vsk->peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(hvs->vsk->peer_shutdown,
++ READ_ONCE(hvs->vsk->peer_shutdown) |
++ SEND_SHUTDOWN);
+
+ hvs->recv_data_len = payload_len;
+ hvs->recv_data_off = 0;
+@@ -736,7 +738,8 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk)
+ return ret;
+ return hvs->recv_data_len;
+ case 0:
+- vsk->peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(vsk->peer_shutdown,
++ READ_ONCE(vsk->peer_shutdown) | SEND_SHUTDOWN);
+ ret = 0;
+ break;
+ default: /* -1 */
+diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
+index e8fb2e20db0f38..1c0f1e5c75dec8 100644
+--- a/net/vmw_vsock/virtio_transport_common.c
++++ b/net/vmw_vsock/virtio_transport_common.c
+@@ -1221,7 +1221,7 @@ static void virtio_transport_do_close(struct vsock_sock *vsk,
+ struct sock *sk = sk_vsock(vsk);
+
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+ sk->sk_state_change(sk);
+@@ -1424,12 +1424,15 @@ virtio_transport_recv_connected(struct sock *sk,
+ case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
+ sk->sk_write_space(sk);
+ break;
+- case VIRTIO_VSOCK_OP_SHUTDOWN:
++ case VIRTIO_VSOCK_OP_SHUTDOWN: {
++ u32 peer_shutdown = READ_ONCE(vsk->peer_shutdown);
++
+ if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_RCV)
+- vsk->peer_shutdown |= RCV_SHUTDOWN;
++ peer_shutdown |= RCV_SHUTDOWN;
+ if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_SEND)
+- vsk->peer_shutdown |= SEND_SHUTDOWN;
+- if (vsk->peer_shutdown == SHUTDOWN_MASK) {
++ peer_shutdown |= SEND_SHUTDOWN;
++ WRITE_ONCE(vsk->peer_shutdown, peer_shutdown);
++ if (peer_shutdown == SHUTDOWN_MASK) {
+ if (vsock_stream_has_data(vsk) <= 0 && !sock_flag(sk, SOCK_DONE)) {
+ (void)virtio_transport_reset(vsk, NULL);
+ virtio_transport_do_close(vsk, true);
+@@ -1444,6 +1447,7 @@ virtio_transport_recv_connected(struct sock *sk,
+ if (le32_to_cpu(virtio_vsock_hdr(skb)->flags))
+ sk->sk_state_change(sk);
+ break;
++ }
+ case VIRTIO_VSOCK_OP_RST:
+ virtio_transport_do_close(vsk, true);
+ break;
+diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c
+index d2579380f51e5d..5c1ecd5bfdbc21 100644
+--- a/net/vmw_vsock/vmci_transport.c
++++ b/net/vmw_vsock/vmci_transport.c
+@@ -819,7 +819,7 @@ static void vmci_transport_handle_detach(struct sock *sk)
+ /* On a detach the peer will not be sending or receiving
+ * anymore.
+ */
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+
+ /* We should not be sending anymore since the peer won't be
+ * there to receive, but we can still receive if there is data
+@@ -1542,7 +1542,9 @@ static int vmci_transport_recv_connected(struct sock *sk,
+ if (pkt->u.mode) {
+ vsk = vsock_sk(sk);
+
+- vsk->peer_shutdown |= pkt->u.mode;
++ WRITE_ONCE(vsk->peer_shutdown,
++ READ_ONCE(vsk->peer_shutdown) |
++ pkt->u.mode);
+ sk->sk_state_change(sk);
+ }
+ break;
+@@ -1559,7 +1561,7 @@ static int vmci_transport_recv_connected(struct sock *sk,
+ * a clean shutdown.
+ */
+ sock_set_flag(sk, SOCK_DONE);
+- vsk->peer_shutdown = SHUTDOWN_MASK;
++ WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
+ if (vsock_stream_has_data(vsk) <= 0)
+ sk->sk_state = TCP_CLOSING;
+
+--
+2.53.0
+
--- /dev/null
+From 76f701991ac26a578240a173e7b4ed3688f71c79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 27 May 2026 10:33:01 +0800
+Subject: vsock/virtio: bind uarg before filling zerocopy skb
+
+From: Jingguo Tan <tanjingguo@huawei.com>
+
+[ Upstream commit 1e584c304cfb94a759417130b1fc6d30b30c4cce ]
+
+virtio_transport_send_pkt_info() allocates or reuses the zerocopy uarg
+before entering the send loop, but virtio_transport_alloc_skb() still
+fills the skb before it inherits that uarg. When fixed-buffer vectored
+zerocopy hits MAX_SKB_FRAGS, io_sg_from_iter() may partially attach
+managed frags and return -EMSGSIZE. The rollback path call kfree_skb()
+to free an skb that carries SKBFL_MANAGED_FRAG_REFS but no uarg, so
+skb_release_data() falls through to ordinary frag unref.
+
+Pass the uarg into virtio_transport_alloc_skb() and bind it immediately
+before virtio_transport_fill_skb(). This keeps control or no-payload skbs
+untouched while ensuring success and rollback share one lifetime rule.
+
+Fixes: 581512a6dc93 ("vsock/virtio: MSG_ZEROCOPY flag support")
+Signed-off-by: Lin Ma <malin89@huawei.com>
+Signed-off-by: Rongzhen Cui <cuirongzhen@huawei.com>
+Signed-off-by: Jingguo Tan <tanjingguo@huawei.com>
+Acked-by: Arseniy Krasnov <avkrasnov@salutedevices.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
+Link: https://patch.msgid.link/20260527023301.1075581-1-malin89@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/vmw_vsock/virtio_transport_common.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c
+index 1c0f1e5c75dec8..abe7bfcedc5a6d 100644
+--- a/net/vmw_vsock/virtio_transport_common.c
++++ b/net/vmw_vsock/virtio_transport_common.c
+@@ -207,6 +207,7 @@ static u16 virtio_transport_get_type(struct sock *sk)
+ static struct sk_buff *virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *info,
+ size_t payload_len,
+ bool zcopy,
++ struct ubuf_info *uarg,
+ u32 src_cid,
+ u32 src_port,
+ u32 dst_cid,
+@@ -247,6 +248,12 @@ static struct sk_buff *virtio_transport_alloc_skb(struct virtio_vsock_pkt_info *
+ if (info->msg && payload_len > 0) {
+ int err;
+
++ /* Bind the zerocopy lifetime before filling frags so error
++ * rollback frees managed fixed-buffer pages through
++ * the uarg-aware path.
++ */
++ skb_zcopy_set(skb, uarg, NULL);
++
+ err = virtio_transport_fill_skb(skb, info, payload_len, zcopy);
+ if (err)
+ goto out;
+@@ -366,6 +373,7 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
+ skb_len = min(max_skb_len, rest_len);
+
+ skb = virtio_transport_alloc_skb(info, skb_len, can_zcopy,
++ uarg,
+ src_cid, src_port,
+ dst_cid, dst_port);
+ if (!skb) {
+@@ -373,8 +381,6 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
+ break;
+ }
+
+- skb_zcopy_set(skb, uarg, NULL);
+-
+ virtio_transport_inc_tx_pkt(vvs, skb);
+
+ ret = t_ops->send_pkt(skb, info->net);
+@@ -1176,7 +1182,7 @@ static int virtio_transport_reset_no_sock(const struct virtio_transport *t,
+ if (!t)
+ return -ENOTCONN;
+
+- reply = virtio_transport_alloc_skb(&info, 0, false,
++ reply = virtio_transport_alloc_skb(&info, 0, false, NULL,
+ le64_to_cpu(hdr->dst_cid),
+ le32_to_cpu(hdr->dst_port),
+ le64_to_cpu(hdr->src_cid),
+--
+2.53.0
+
--- /dev/null
+From b1f63588e7e767e9b17385d19ab49575780a7475 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 25 May 2026 20:36:42 +0000
+Subject: vxlan: do not reuse cached ip_hdr() value after
+ skb_tunnel_check_pmtu()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 7d9ef0cb271555d8cf39fefe6c981e1493b25ecf ]
+
+skb_tunnel_check_pmtu() can change skb->head.
+
+Reusing old_iph afer skb_tunnel_check_pmtu() can cause an UAF.
+
+Use instead ip_hdr(skb) as done in drivers/net/bareudp.c
+and drivers/net/geneve.c.
+
+Found by Sashiko.
+
+Fixes: 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
+Link: https://patch.msgid.link/20260525203642.2389723-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/vxlan/vxlan_core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
+index a94ac82a613649..0cc3b34add5eb4 100644
+--- a/drivers/net/vxlan/vxlan_core.c
++++ b/drivers/net/vxlan/vxlan_core.c
+@@ -2534,7 +2534,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
+ vni, md, flags, udp_sum);
+@@ -2608,7 +2608,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
+ goto out_unlock;
+ }
+
+- tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
++ tos = ip_tunnel_ecn_encap(tos, ip_hdr(skb), skb);
+ ttl = ttl ? : ip6_dst_hoplimit(ndst);
+ skb_scrub_packet(skb, xnet);
+ err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
+--
+2.53.0
+
--- /dev/null
+From 0275e38f18e7e32158919e688382b990eebb4c2f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 10:49:14 -0600
+Subject: xfrm: Check for underflow in xfrm_state_mtu
+
+From: David Ahern <dahern@nvidia.com>
+
+[ Upstream commit 742b04d0550b0ec89dcbc99537ec88653bd1ad90 ]
+
+Leo Lin reported OOB write issue in esp component:
+
+ xfrm_state_mtu() returns u32 but performs its arithmetic in unsigned
+ modulo-2^32 space using an attacker-influenced "header_len + authsize +
+ net_adj" subtracted from a small "mtu" argument. A nobody user can
+ install an IPv4 ESP tunnel SA with a large authentication key
+ (XFRMA_ALG_AUTH_TRUNC, e.g. hmac(sha512), 64-byte key, 64-byte trunc),
+ configure a small interface MTU (68 bytes), and set XFRMA_TFCPAD to a
+ large value. When a single UDP datagram is then sent through the
+ tunnel, xfrm_state_mtu() underflows to a near-2^32 value, and
+ esp_output() consumes it as a signed int via:
+
+ padto = min(x->tfcpad, xfrm_state_mtu(x, mtu_cached))
+ esp.tfclen = padto - skb->len (assigned to int)
+
+ esp.tfclen ends up negative (e.g. -207). It is sign-extended to size_t
+ when passed to memset() inside esp_output_fill_trailer(), producing a
+ ~16 EB write of zeroes at skb_tail_pointer(skb). KASAN logs it as
+ "Write of size 18446744073709551537 at addr ffff888...".
+
+Check for underflow and return 1. This causes the sendmsg attempt to
+fail with ENETUNREACH.
+
+Fixes: c5c252389374 ("[XFRM]: Optimize MTU calculation")
+Reported-by: Leo Lin <leo@depthfirst.com>
+Assisted-by: Codex:26.506.31004
+Signed-off-by: David Ahern <dahern@nvidia.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_state.c | 19 ++++++++++++++++---
+ 1 file changed, 16 insertions(+), 3 deletions(-)
+
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 686014d394298c..f597e4996bb28a 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -3114,10 +3114,14 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ const struct xfrm_type *type = READ_ONCE(x->type);
+ struct crypto_aead *aead;
+ u32 blksize, net_adj = 0;
++ u32 overhead, payload_mtu;
+
+ if (x->km.state != XFRM_STATE_VALID ||
+- !type || type->proto != IPPROTO_ESP)
++ !type || type->proto != IPPROTO_ESP) {
++ if (mtu <= x->props.header_len)
++ return 1;
+ return mtu - x->props.header_len;
++ }
+
+ aead = x->data;
+ blksize = ALIGN(crypto_aead_blocksize(aead), 4);
+@@ -3140,8 +3144,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ break;
+ }
+
+- return ((mtu - x->props.header_len - crypto_aead_authsize(aead) -
+- net_adj) & ~(blksize - 1)) + net_adj - 2;
++ overhead = x->props.header_len + crypto_aead_authsize(aead) + net_adj;
++ if (mtu <= overhead)
++ return 1;
++
++ payload_mtu = mtu - overhead;
++ payload_mtu &= ~(blksize - 1);
++ if (payload_mtu <= 2)
++ return 1;
++
++ return payload_mtu + net_adj - 2;
++
+ }
+ EXPORT_SYMBOL_GPL(xfrm_state_mtu);
+
+--
+2.53.0
+