From: Sasha Levin Date: Tue, 28 Jul 2026 18:17:47 +0000 (-0400) Subject: Fixes for all trees X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=aa662e2b9a453ec05bb4ed8f89b6313533721805;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch b/queue-5.10/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch new file mode 100644 index 0000000000..b70301c169 --- /dev/null +++ b/queue-5.10/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch @@ -0,0 +1,58 @@ +From 5860666a41d6b7cf441b90214d21055070212e5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 15:20:06 +0530 +Subject: amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN + +From: Prashanth Kumar KR + +[ Upstream commit 4bf22afe53a1de4b44b04cf677fd5199089cbdff ] + +MAC_AUTO_SW (VR_MII_DIG_CTRL1 bit 9) enables automatic XPCS speed +mode switching after CL37 auto-negotiation and is only meaningful in +SGMII MAC mode. The original code unconditionally set this bit on +every call to xgbe_an37_set(), including when called from +xgbe_an37_disable() with enable=false. This left MAC_AUTO_SW=1 after +AN was disabled, causing the XPCS to autonomously switch speed from +stale AN state during subsequent mode changes, breaking SGMII speed +negotiation on 1G copper SFP modules. + +Patrick: This was breaking negotiation for all 1G SFP modules, +not just copper modules. + +Fixes: 42fd432fe6d3 ("amd-xgbe: align CL37 AN sequence as per databook") +Reported-by: Patrick Oppenlander +Link: https://lore.kernel.org/netdev/CAEg67GmFS0Q4oSZkz8zWdOzckSth9_vBPiOy6a7-d697C2w2Xg@mail.gmail.com +Signed-off-by: Prashanth Kumar KR +Tested-by: Patrick Oppenlander +Link: https://patch.msgid.link/20260709095006.3683940-1-prashanthkumar.k.r@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index ebb8b3e5b9a882..01c37ffc9ceb81 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -364,9 +364,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, + + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); + +- reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); +- reg |= XGBE_VEND2_MAC_AUTO_SW; +- XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ if (pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) { ++ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); ++ if (enable) ++ reg |= XGBE_VEND2_MAC_AUTO_SW; ++ else ++ reg &= ~XGBE_VEND2_MAC_AUTO_SW; ++ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ } + } + + static void xgbe_an37_restart(struct xgbe_prv_data *pdata) +-- +2.53.0 + diff --git a/queue-5.10/asoc-bt-sco-fix-bt-sco-pcm-wb-dai-widget-don-t-conne.patch b/queue-5.10/asoc-bt-sco-fix-bt-sco-pcm-wb-dai-widget-don-t-conne.patch new file mode 100644 index 0000000000..f5b8a93fe5 --- /dev/null +++ b/queue-5.10/asoc-bt-sco-fix-bt-sco-pcm-wb-dai-widget-don-t-conne.patch @@ -0,0 +1,50 @@ +From d34e5a49e6d17a445276f95bfe5569da9d8fba10 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Mar 2022 09:35:33 +0800 +Subject: ASoC: bt-sco: fix bt-sco-pcm-wb dai widget don't connect to the + endpoint + +From: Jiaxin Yu + +[ Upstream commit 8f2b025abc31bc15d38657d1286d7470bbbd5efa ] + +This patch fix the second dai driver's dai widget can't connect to the +endpoint. Because "bt-sco-pcm" and "bt-sco-pcm-wb" dai driver have the +same stream_name, so it will cause they have the same widget name. +Therefor it will just create only one route when do snd_soc_dapm_add_route +that only find the widget through the widget name. + +Signed-off-by: Jiaxin Yu +Link: https://lore.kernel.org/r/20220302013533.29068-1-jiaxin.yu@mediatek.com +Signed-off-by: Mark Brown +Stable-dep-of: 0b604e886ece ("ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/bt-sco.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c +index 4d286844e3c832..cf17b9741bd832 100644 +--- a/sound/soc/codecs/bt-sco.c ++++ b/sound/soc/codecs/bt-sco.c +@@ -13,11 +13,15 @@ + static const struct snd_soc_dapm_widget bt_sco_widgets[] = { + SND_SOC_DAPM_INPUT("RX"), + SND_SOC_DAPM_OUTPUT("TX"), ++ SND_SOC_DAPM_AIF_IN("BT_SCO_RX", "Playback", 0, ++ SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0, ++ SND_SOC_NOPM, 0, 0), + }; + + static const struct snd_soc_dapm_route bt_sco_routes[] = { +- { "Capture", NULL, "RX" }, +- { "TX", NULL, "Playback" }, ++ { "BT_SCO_TX", NULL, "RX" }, ++ { "TX", NULL, "BT_SCO_RX" }, + }; + + static struct snd_soc_dai_driver bt_sco_dai[] = { +-- +2.53.0 + diff --git a/queue-5.10/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch b/queue-5.10/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch new file mode 100644 index 0000000000..612b24fa0d --- /dev/null +++ b/queue-5.10/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch @@ -0,0 +1,72 @@ +From 36821caf60bc39019ba24a3a4ff6283eb669cbfa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 18:06:20 +0800 +Subject: ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI + +From: Shengjiu Wang + +[ Upstream commit 0b604e886ece11b71c4daaeccc512c784b89b014 ] + +The bt-sco-pcm-wb DAI uses the same stream_name strings as bt-sco-pcm +("Playback" and "Capture"). This causes duplicate DAPM AIF widget +names within the same component, leading to debugfs warnings: + + debugfs: 'Playback' already exists in 'dapm' + debugfs: 'Capture' already exists in 'dapm' + +Give the wideband DAI distinct stream names ("WB Playback" and +"WB Capture") and add corresponding DAPM AIF widgets and routes for +them. + +Fixes: 5947e1b4992e ("ASoC: bt-sco: extend rate and add a general compatible string") +Assisted-by: VeroCoder:claude-sonnet-4-5 +Signed-off-by: Shengjiu Wang +Link: https://patch.msgid.link/20260715100620.1387159-1-shengjiu.wang@oss.nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/bt-sco.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c +index cf17b9741bd832..7c42fcdee27bb7 100644 +--- a/sound/soc/codecs/bt-sco.c ++++ b/sound/soc/codecs/bt-sco.c +@@ -17,11 +17,17 @@ static const struct snd_soc_dapm_widget bt_sco_widgets[] = { + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0, + SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_IN("BT_SCO_RX_WB", "WB Playback", 0, ++ SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("BT_SCO_TX_WB", "WB Capture", 0, ++ SND_SOC_NOPM, 0, 0), + }; + + static const struct snd_soc_dapm_route bt_sco_routes[] = { + { "BT_SCO_TX", NULL, "RX" }, + { "TX", NULL, "BT_SCO_RX" }, ++ { "BT_SCO_TX_WB", NULL, "RX" }, ++ { "TX", NULL, "BT_SCO_RX_WB" }, + }; + + static struct snd_soc_dai_driver bt_sco_dai[] = { +@@ -45,14 +51,14 @@ static struct snd_soc_dai_driver bt_sco_dai[] = { + { + .name = "bt-sco-pcm-wb", + .playback = { +- .stream_name = "Playback", ++ .stream_name = "WB Playback", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { +- .stream_name = "Capture", ++ .stream_name = "WB Capture", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, +-- +2.53.0 + diff --git a/queue-5.10/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch b/queue-5.10/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch new file mode 100644 index 0000000000..fde3fa46f1 --- /dev/null +++ b/queue-5.10/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch @@ -0,0 +1,79 @@ +From 048646aa307c7d159721d5c6b313c3057d57ba1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jul 2026 18:38:56 +0800 +Subject: bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() + +From: Chengfeng Ye + +[ Upstream commit 2d66a033864e27ab8d5e44cb36f31d9d2413bee4 ] + +tcp_bpf_sendmsg() keeps msg_tx across sk_stream_wait_memory(), which +drops and reacquires the socket lock. Its error path tries to decide +whether msg_tx names the local temporary message by comparing it with +the current value of psock->cork. + +This comparison is unsafe when two threads send on the same socket: + + Thread A Thread B + msg_tx = psock->cork + sk_msg_alloc() fails + sk_stream_wait_memory() + releases the socket lock acquires the socket lock + completes the cork + psock->cork = NULL + frees the cork + reacquires the socket lock + msg_tx != psock->cork + sk_msg_free(msg_tx) + +The stale cork is therefore mistaken for the local temporary message +and freed again. KASAN reported: + + BUG: KASAN: slab-use-after-free in sk_msg_free+0x49/0x50 + Read of size 4 at addr ffff88810c908800 by task poc/90 + Call Trace: + sk_msg_free+0x49/0x50 + tcp_bpf_sendmsg+0x14f5/0x1cc0 + __sys_sendto+0x32c/0x3a0 + __x64_sys_sendto+0xdb/0x1b0 + Allocated by task 89: + __kasan_kmalloc+0x8f/0xa0 + tcp_bpf_sendmsg+0x16b3/0x1cc0 + Freed by task 91: + __kasan_slab_free+0x43/0x70 + kfree+0x131/0x3c0 + tcp_bpf_sendmsg+0xec3/0x1cc0 + +msg_tx can only name the stack-local tmp or the shared cork. Check for +tmp directly so a changed psock->cork cannot turn a shared message into +an apparent local one. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Chengfeng Ye +Reviewed-by: Emil Tsalapatis +Reviewed-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/87fr18lmzo.fsf%40cloudflare.com/ +Link: https://lore.kernel.org/netdev/20260719161630.2901208-1-nicoyip.dev%40gmail.com/ [v1] +Link: https://patch.msgid.link/20260724103856.3399001-1-nicoyip.dev@gmail.com +Signed-off-by: Eduard Zingerman +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 76cd974887774d..f9eee18ef7323b 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -504,7 +504,7 @@ static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + wait_for_memory: + err = sk_stream_wait_memory(sk, &timeo); + if (err) { +- if (msg_tx && msg_tx != psock->cork) ++ if (msg_tx == &tmp) + sk_msg_free(sk, msg_tx); + goto out_err; + } +-- +2.53.0 + diff --git a/queue-5.10/firewire-net-fix-fragmented-datagram-reassembly.patch b/queue-5.10/firewire-net-fix-fragmented-datagram-reassembly.patch new file mode 100644 index 0000000000..8d6d1ecb33 --- /dev/null +++ b/queue-5.10/firewire-net-fix-fragmented-datagram-reassembly.patch @@ -0,0 +1,99 @@ +From cc4ea9413330efacf8e0bdec864bcd903cdd81fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 23:04:54 +0800 +Subject: firewire: net: Fix fragmented datagram reassembly + +From: Ruoyu Wang + +[ Upstream commit d52a13adbb8ccbab99cd3bad36804e87d8b5c052 ] + +fwnet_frag_new() keeps a sorted list of received fragments for a partial +datagram. When a new fragment is adjacent to an existing fragment, the +code checks whether the new fragment also closes the gap to the next or +previous list entry. + +Those neighbor lookups currently assume that the current fragment always +has a real next or previous fragment. At a list edge, the next or +previous entry is the list head, not a struct fwnet_fragment_info. + +The gap checks also compare against the old edge of the current fragment +instead of the edge after adding the new fragment. As a result, a +fragment that bridges two existing ranges may leave two adjacent ranges +unmerged, so fwnet_pd_is_complete() can miss a complete datagram. + +Check for the list head before looking up the neighboring fragment, and +compare the neighbor against the new fragment's far edge when deciding +whether to merge all three ranges. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: c76acec6d551 ("firewire: add IPv4 support") +Signed-off-by: Ruoyu Wang +Link: https://lore.kernel.org/r/20260707150454.2265951-1-ruoyuw560@gmail.com +Signed-off-by: Takashi Sakamoto +Signed-off-by: Sasha Levin +--- + drivers/firewire/net.c | 39 +++++++++++++++++++++------------------ + 1 file changed, 21 insertions(+), 18 deletions(-) + +diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c +index 715e491dfbc333..8678ded9360a63 100644 +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -306,31 +306,34 @@ static struct fwnet_fragment_info *fwnet_frag_new( + if (fi->offset + fi->len == offset) { + /* The new fragment can be tacked on to the end */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.next, +- struct fwnet_fragment_info, fi_link); +- if (fi->offset + fi->len == fi2->offset) { +- /* glue fragments together */ +- fi->len += len + fi2->len; +- list_del(&fi2->fi_link); +- kfree(fi2); +- } else { +- fi->len += len; ++ if (!list_is_last(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_next_entry(fi, fi_link); ++ if (offset + len == fi2->offset) { ++ /* glue fragments together */ ++ fi->len += len + fi2->len; ++ list_del(&fi2->fi_link); ++ kfree(fi2); ++ ++ return fi; ++ } + } ++ fi->len += len; + + return fi; + } + if (offset + len == fi->offset) { + /* The new fragment can be tacked on to the beginning */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.prev, +- struct fwnet_fragment_info, fi_link); +- if (fi2->offset + fi2->len == fi->offset) { +- /* glue fragments together */ +- fi2->len += fi->len + len; +- list_del(&fi->fi_link); +- kfree(fi); +- +- return fi2; ++ if (!list_is_first(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_prev_entry(fi, fi_link); ++ if (fi2->offset + fi2->len == offset) { ++ /* glue fragments together */ ++ fi2->len += fi->len + len; ++ list_del(&fi->fi_link); ++ kfree(fi); ++ ++ return fi2; ++ } + } + fi->offset = offset; + fi->len += len; +-- +2.53.0 + diff --git a/queue-5.10/hinic-remove-unused-ethtool-rss-user-configuration-b.patch b/queue-5.10/hinic-remove-unused-ethtool-rss-user-configuration-b.patch new file mode 100644 index 0000000000..1cd4456719 --- /dev/null +++ b/queue-5.10/hinic-remove-unused-ethtool-rss-user-configuration-b.patch @@ -0,0 +1,83 @@ +From 5f5eb12dd68efc022b7003ab006c47a332273fe1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:53:53 +0800 +Subject: hinic: remove unused ethtool RSS user configuration buffers + +From: Chenguang Zhao + +[ Upstream commit fe0c002928c6749b7f4a726f6f600f6dd70280ea ] + +rss_indir_user and rss_hkey_user are allocated and filled in +__set_rss_rxfh() when the user configures RSS via ethtool, but +nothing ever reads them. hinic_get_rxfh() fetches the state from +the device, and the hardware is programmed from the original +indir/key arguments. These buffers only leaked on driver unload. + +Drop the unused allocations, memcpys, and struct fields. + +Fixes: 4fdc51bb4e92 ("hinic: add support for rss parameters with ethtool") +Signed-off-by: Chenguang Zhao +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260722025353.328179-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/huawei/hinic/hinic_dev.h | 2 -- + .../net/ethernet/huawei/hinic/hinic_ethtool.c | 21 ------------------- + 2 files changed, 23 deletions(-) + +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +index a4fbf44f944cd3..46b24f3c5e168d 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h ++++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +@@ -100,8 +100,6 @@ struct hinic_dev { + u16 num_rss; + u16 rss_limit; + struct hinic_rss_type rss_type; +- u8 *rss_hkey_user; +- s32 *rss_indir_user; + struct hinic_intr_coal_info *rx_intr_coalesce; + struct hinic_intr_coal_info *tx_intr_coalesce; + struct hinic_sriov_info sriov_info; +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +index c340d9acba803f..4a1693c70582a8 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c ++++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +@@ -1061,17 +1061,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + int err; + + if (indir) { +- if (!nic_dev->rss_indir_user) { +- nic_dev->rss_indir_user = +- kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE, +- GFP_KERNEL); +- if (!nic_dev->rss_indir_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_indir_user, indir, +- sizeof(u32) * HINIC_RSS_INDIR_SIZE); +- + err = hinic_rss_set_indir_tbl(nic_dev, + nic_dev->rss_tmpl_idx, indir); + if (err) +@@ -1079,16 +1068,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + } + + if (key) { +- if (!nic_dev->rss_hkey_user) { +- nic_dev->rss_hkey_user = +- kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL); +- +- if (!nic_dev->rss_hkey_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE); +- + err = hinic_rss_set_template_tbl(nic_dev, + nic_dev->rss_tmpl_idx, key); + if (err) +-- +2.53.0 + diff --git a/queue-5.10/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch b/queue-5.10/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch new file mode 100644 index 0000000000..c499444fa4 --- /dev/null +++ b/queue-5.10/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch @@ -0,0 +1,41 @@ +From 09f23e38487333e0c065ded6a31e4d690d98ee03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 17:52:54 -0700 +Subject: hwmon: (corsair-cpro) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 94c87871b051d7ad758828a805215a2ec194512a ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 40c3a44542257 ("hwmon: add Corsair Commander Pro driver") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-cpro.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c +index 074f812332e89b..f117479096ef87 100644 +--- a/drivers/hwmon/corsair-cpro.c ++++ b/drivers/hwmon/corsair-cpro.c +@@ -557,6 +557,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) + + out_hw_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-5.10/iommu-amd-bound-the-early-acpi-hid-map.patch b/queue-5.10/iommu-amd-bound-the-early-acpi-hid-map.patch new file mode 100644 index 0000000000..61b7d769fe --- /dev/null +++ b/queue-5.10/iommu-amd-bound-the-early-acpi-hid-map.patch @@ -0,0 +1,45 @@ +From 1227172e939198ad47970e89631e879dbab76f1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:46:13 +0800 +Subject: iommu/amd: Bound the early ACPI HID map + +From: Pengpeng Hou + +[ Upstream commit fb80117fddb5b477218dc99bb53911b72c3847f8 ] + +The ivrs_acpihid command-line parser appends entries to a fixed +four-element early_acpihid_map array. Unlike the sibling IOAPIC and HPET +parsers, it does not reject a fifth entry before incrementing the map size. + +Check the capacity at the common found label before parsing the HID and +UID or writing the entry. + +Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter") +Signed-off-by: Pengpeng Hou +Reviewed-by: Ankit Soni +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/init.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index 1ba6adb5b91241..1b7a0fae423ce9 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -3227,6 +3227,12 @@ static int __init parse_ivrs_acpihid(char *str) + return 1; + + found: ++ if (early_acpihid_map_size == EARLY_MAP_SIZE) { ++ pr_err("Early ACPI HID map overflow - ignoring ivrs_acpihid%s\n", ++ str); ++ return 1; ++ } ++ + p = acpiid; + hid = strsep(&p, ":"); + uid = p; +-- +2.53.0 + diff --git a/queue-5.10/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch b/queue-5.10/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch new file mode 100644 index 0000000000..44be0acb65 --- /dev/null +++ b/queue-5.10/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch @@ -0,0 +1,88 @@ +From 873a0c6734d3df95ba6bd6fb03c912f7867b281d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:42:36 +0000 +Subject: ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup + +From: Eric Dumazet + +[ Upstream commit 853e164c2b321f0711361bc23505aaeb7dc432c3 ] + +When Linux forwards a packet and needs to generate an ICMP error, +icmp_route_lookup() performs a reverse-path relookup. For non-local +destinations, it performs a decoy lookup to find the expected egress +interface (rt2->dst.dev) before validating the path with ip_route_input(). + +Currently, the decoy flow structure (fl4_2) only sets .daddr = fl4_dec.saddr, +leaving .saddr, .flowi4_dscp, .flowi4_proto, .flowi4_mark, .flowi4_oif, +.fl4_sport, .fl4_dport, and .flowi4_uid zeroed out. + +When policy routing rules (such as ip rule add from $SRC lookup 100, or +dscp/fwmark/ipproto/port rules, or VRF bindings) are configured: +1. The decoy lookup fails to match the policy rule because saddr and other + key flow selectors are missing in fl4_2. +2. It resolves a route using the default table instead, returning an incorrect + egress netdev. +3. Passing the wrong netdev to ip_route_input() causes strict reverse-path + filtering (rp_filter=1) to fail, logging false-positive "martian source" + warnings and causing the relookup to fail. + +Fix this by initializing fl4_2 from fl4_dec and: +- Swapping source/destination IP addresses. +- Swapping L4 ports for transport protocols with ports (TCP, UDP, SCTP, DCCP) + so port-based policy routing matches correctly. Non-port protocols (such as + ICMP or GRE) leave the flowi_uli union fields intact to prevent corruption. +- Setting .flowi4_oif = l3mdev_master_ifindex(route_lookup_dev) to ensure + VRF routing tables are respected. +- Setting .flowi4_flags |= FLOWI_FLAG_ANYSRC to allow output route lookups + for non-local source IP addresses. +- Using __ip_route_output_key() instead of ip_route_output_key() for fl4_2 + so that raw FIB routing is used without triggering spurious XFRM policy + lookups on the decoy flow (the actual XFRM lookup is performed later using + fl4_dec). + +Fixes: 415b3334a21a ("icmp: Fix regression in nexthop resolution during replies.") +Reported-by: Muhammad Ziad +Closes: https://lore.kernel.org/netdev/CAOAwikA60AYKdFr_UDLyja3oU4hqyAE7uFZWqum5uRdaQsgRYg@mail.gmail.com/ +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260722104236.2938082-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index 3c74fecce2382c..e919d2a5169e79 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -533,11 +533,23 @@ static struct rtable *icmp_route_lookup(struct net *net, + if (IS_ERR(rt2)) + err = PTR_ERR(rt2); + } else { +- struct flowi4 fl4_2 = {}; ++ struct flowi4 fl4_2 = fl4_dec; + unsigned long orefdst; + +- fl4_2.daddr = fl4_dec.saddr; +- rt2 = ip_route_output_key(net, &fl4_2); ++ swap(fl4_2.daddr, fl4_2.saddr); ++ switch (fl4_2.flowi4_proto) { ++ case IPPROTO_TCP: ++ case IPPROTO_UDP: ++ case IPPROTO_SCTP: ++ case IPPROTO_DCCP: ++ swap(fl4_2.fl4_sport, fl4_2.fl4_dport); ++ break; ++ } ++ ++ fl4_2.flowi4_oif = l3mdev_master_ifindex(route_lookup_dev); ++ fl4_2.flowi4_flags |= FLOWI_FLAG_ANYSRC; ++ ++ rt2 = __ip_route_output_key(net, &fl4_2); + if (IS_ERR(rt2)) { + err = PTR_ERR(rt2); + goto relookup_failed; +-- +2.53.0 + diff --git a/queue-5.10/net-bridge-vlan-add-support-for-dumping-global-vlan-.patch b/queue-5.10/net-bridge-vlan-add-support-for-dumping-global-vlan-.patch new file mode 100644 index 0000000000..7650670a64 --- /dev/null +++ b/queue-5.10/net-bridge-vlan-add-support-for-dumping-global-vlan-.patch @@ -0,0 +1,177 @@ +From 43fb1e4721455d12e8e758bc059bba03b2eb8d52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Jul 2021 20:06:35 +0300 +Subject: net: bridge: vlan: add support for dumping global vlan options + +From: Nikolay Aleksandrov + +[ Upstream commit 743a53d9636aad83da63a8638e8365e817ef6365 ] + +Add a new vlan options dump flag which causes only global vlan options +to be dumped. The dumps are done only with bridge devices, ports are +ignored. They support vlan compression if the options in sequential +vlans are equal (currently always true). + +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Stable-dep-of: 43171c97e471 ("net: bridge: vlan: fix vlan range dumps starting with pvid") +Signed-off-by: Sasha Levin +--- + include/uapi/linux/if_bridge.h | 1 + + net/bridge/br_private.h | 4 ++++ + net/bridge/br_vlan.c | 41 +++++++++++++++++++++++++++------- + net/bridge/br_vlan_options.c | 31 +++++++++++++++++++++++++ + 4 files changed, 69 insertions(+), 8 deletions(-) + +diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h +index f56e9114558299..e4a94f5c3a147f 100644 +--- a/include/uapi/linux/if_bridge.h ++++ b/include/uapi/linux/if_bridge.h +@@ -354,6 +354,7 @@ enum { + + /* flags used in BRIDGE_VLANDB_DUMP_FLAGS attribute to affect dumps */ + #define BRIDGE_VLANDB_DUMPF_STATS (1 << 0) /* Include stats in the dump */ ++#define BRIDGE_VLANDB_DUMPF_GLOBAL (1 << 1) /* Dump global vlan options only */ + + /* Bridge vlan RTM attributes + * [BRIDGE_VLANDB_ENTRY] = { +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index bd68d049c5fd93..b3a98ae8fbd619 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1331,6 +1331,10 @@ int br_vlan_rtm_process_global_options(struct net_device *dev, + const struct nlattr *attr, + int cmd, + struct netlink_ext_ack *extack); ++bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr, ++ const struct net_bridge_vlan *r_end); ++bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range, ++ const struct net_bridge_vlan *v_opts); + + /* vlan state manipulation helpers using *_ONCE to annotate lock-free access */ + static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v) +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index 0bd5a168943fd1..258702134d9bfc 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1777,6 +1777,7 @@ static int br_vlan_dump_dev(const struct net_device *dev, + u32 dump_flags) + { + struct net_bridge_vlan *v, *range_start = NULL, *range_end = NULL; ++ bool dump_global = !!(dump_flags & BRIDGE_VLANDB_DUMPF_GLOBAL); + bool dump_stats = !!(dump_flags & BRIDGE_VLANDB_DUMPF_STATS); + struct net_bridge_vlan_group *vg; + int idx = 0, s_idx = cb->args[1]; +@@ -1795,6 +1796,10 @@ static int br_vlan_dump_dev(const struct net_device *dev, + vg = br_vlan_group_rcu(br); + p = NULL; + } else { ++ /* global options are dumped only for bridge devices */ ++ if (dump_global) ++ return 0; ++ + p = br_port_get_rcu(dev); + if (WARN_ON(!p)) + return -EINVAL; +@@ -1817,7 +1822,7 @@ static int br_vlan_dump_dev(const struct net_device *dev, + + /* idx must stay at range's beginning until it is filled in */ + list_for_each_entry_rcu(v, &vg->vlan_list, vlist) { +- if (!br_vlan_should_use(v)) ++ if (!dump_global && !br_vlan_should_use(v)) + continue; + if (idx < s_idx) { + idx++; +@@ -1830,8 +1835,21 @@ static int br_vlan_dump_dev(const struct net_device *dev, + continue; + } + +- if (dump_stats || v->vid == pvid || +- !br_vlan_can_enter_range(v, range_end)) { ++ if (dump_global) { ++ if (br_vlan_global_opts_can_enter_range(v, range_end)) ++ continue; ++ if (!br_vlan_global_opts_fill(skb, range_start->vid, ++ range_end->vid, ++ range_start)) { ++ err = -EMSGSIZE; ++ break; ++ } ++ /* advance number of filled vlans */ ++ idx += range_end->vid - range_start->vid + 1; ++ ++ range_start = v; ++ } else if (dump_stats || v->vid == pvid || ++ !br_vlan_can_enter_range(v, range_end)) { + u16 vlan_flags = br_vlan_flags(range_start, pvid); + + if (!br_vlan_fill_vids(skb, range_start->vid, +@@ -1853,11 +1871,18 @@ static int br_vlan_dump_dev(const struct net_device *dev, + * - last vlan (range_start == range_end, not in range) + * - last vlan range (range_start != range_end, in range) + */ +- if (!err && range_start && +- !br_vlan_fill_vids(skb, range_start->vid, range_end->vid, +- range_start, br_vlan_flags(range_start, pvid), +- dump_stats)) +- err = -EMSGSIZE; ++ if (!err && range_start) { ++ if (dump_global && ++ !br_vlan_global_opts_fill(skb, range_start->vid, ++ range_end->vid, range_start)) ++ err = -EMSGSIZE; ++ else if (!dump_global && ++ !br_vlan_fill_vids(skb, range_start->vid, ++ range_end->vid, range_start, ++ br_vlan_flags(range_start, pvid), ++ dump_stats)) ++ err = -EMSGSIZE; ++ } + + cb->args[1] = err ? idx : 0; + +diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c +index a7d5a233420732..f290f514054714 100644 +--- a/net/bridge/br_vlan_options.c ++++ b/net/bridge/br_vlan_options.c +@@ -259,6 +259,37 @@ int br_vlan_process_options(const struct net_bridge *br, + return err; + } + ++bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr, ++ const struct net_bridge_vlan *r_end) ++{ ++ return v_curr->vid - r_end->vid == 1; ++} ++ ++bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range, ++ const struct net_bridge_vlan *v_opts) ++{ ++ struct nlattr *nest; ++ ++ nest = nla_nest_start(skb, BRIDGE_VLANDB_GLOBAL_OPTIONS); ++ if (!nest) ++ return false; ++ ++ if (nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_ID, vid)) ++ goto out_err; ++ ++ if (vid_range && vid < vid_range && ++ nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_RANGE, vid_range)) ++ goto out_err; ++ ++ nla_nest_end(skb, nest); ++ ++ return true; ++ ++out_err: ++ nla_nest_cancel(skb, nest); ++ return false; ++} ++ + static int br_vlan_process_global_one_opts(const struct net_bridge *br, + struct net_bridge_vlan_group *vg, + struct net_bridge_vlan *v, +-- +2.53.0 + diff --git a/queue-5.10/net-bridge-vlan-add-support-for-global-options.patch b/queue-5.10/net-bridge-vlan-add-support-for-global-options.patch new file mode 100644 index 0000000000..cb28aa789c --- /dev/null +++ b/queue-5.10/net-bridge-vlan-add-support-for-global-options.patch @@ -0,0 +1,209 @@ +From 572fd59ba0929922122ddb7935d2f79261c6aedb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Jul 2021 20:06:34 +0300 +Subject: net: bridge: vlan: add support for global options + +From: Nikolay Aleksandrov + +[ Upstream commit 47ecd2dbd8ec43125ea75d7d2e73c888cda8663f ] + +We can have two types of vlan options depending on context: + - per-device vlan options (split in per-bridge and per-port) + - global vlan options + +The second type wasn't supported in the bridge until now, but we need +them for per-vlan multicast support, per-vlan STP support and other +options which require global vlan context. They are contained in the global +bridge vlan context even if the vlan is not configured on the bridge device +itself. This patch adds initial netlink attributes and support for setting +these global vlan options, they can only be set (RTM_NEWVLAN) and the +operation must use the bridge device. Since there are no such options yet +it shouldn't have any functional effect. + +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Stable-dep-of: 43171c97e471 ("net: bridge: vlan: fix vlan range dumps starting with pvid") +Signed-off-by: Sasha Levin +--- + include/uapi/linux/if_bridge.h | 13 ++++++ + net/bridge/br_private.h | 4 ++ + net/bridge/br_vlan.c | 16 +++++-- + net/bridge/br_vlan_options.c | 85 ++++++++++++++++++++++++++++++++++ + 4 files changed, 115 insertions(+), 3 deletions(-) + +diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h +index 4c687686aa8f73..f56e9114558299 100644 +--- a/include/uapi/linux/if_bridge.h ++++ b/include/uapi/linux/if_bridge.h +@@ -360,10 +360,15 @@ enum { + * [BRIDGE_VLANDB_ENTRY_INFO] + * ... + * } ++ * [BRIDGE_VLANDB_GLOBAL_OPTIONS] = { ++ * [BRIDGE_VLANDB_GOPTS_ID] ++ * ... ++ * } + */ + enum { + BRIDGE_VLANDB_UNSPEC, + BRIDGE_VLANDB_ENTRY, ++ BRIDGE_VLANDB_GLOBAL_OPTIONS, + __BRIDGE_VLANDB_MAX, + }; + #define BRIDGE_VLANDB_MAX (__BRIDGE_VLANDB_MAX - 1) +@@ -413,6 +418,14 @@ enum { + }; + #define BRIDGE_VLANDB_STATS_MAX (__BRIDGE_VLANDB_STATS_MAX - 1) + ++enum { ++ BRIDGE_VLANDB_GOPTS_UNSPEC, ++ BRIDGE_VLANDB_GOPTS_ID, ++ BRIDGE_VLANDB_GOPTS_RANGE, ++ __BRIDGE_VLANDB_GOPTS_MAX ++}; ++#define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1) ++ + /* Bridge multicast database attributes + * [MDBA_MDB] = { + * [MDBA_MDB_ENTRY] = { +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index 19d77a8721fafb..bd68d049c5fd93 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1327,6 +1327,10 @@ int br_vlan_process_options(const struct net_bridge *br, + struct net_bridge_vlan *range_end, + struct nlattr **tb, + struct netlink_ext_ack *extack); ++int br_vlan_rtm_process_global_options(struct net_device *dev, ++ const struct nlattr *attr, ++ int cmd, ++ struct netlink_ext_ack *extack); + + /* vlan state manipulation helpers using *_ONCE to annotate lock-free access */ + static inline u8 br_vlan_get_state(const struct net_bridge_vlan *v) +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index 1dc5db07650c9a..0bd5a168943fd1 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -2062,12 +2062,22 @@ static int br_vlan_rtm_process(struct sk_buff *skb, struct nlmsghdr *nlh, + } + + nlmsg_for_each_attr(attr, nlh, sizeof(*bvm), rem) { +- if (nla_type(attr) != BRIDGE_VLANDB_ENTRY) ++ switch (nla_type(attr)) { ++ case BRIDGE_VLANDB_ENTRY: ++ err = br_vlan_rtm_process_one(dev, attr, ++ nlh->nlmsg_type, ++ extack); ++ break; ++ case BRIDGE_VLANDB_GLOBAL_OPTIONS: ++ err = br_vlan_rtm_process_global_options(dev, attr, ++ nlh->nlmsg_type, ++ extack); ++ break; ++ default: + continue; ++ } + + vlans++; +- err = br_vlan_rtm_process_one(dev, attr, nlh->nlmsg_type, +- extack); + if (err) + break; + } +diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c +index b4add9ea8964a9..a7d5a233420732 100644 +--- a/net/bridge/br_vlan_options.c ++++ b/net/bridge/br_vlan_options.c +@@ -258,3 +258,88 @@ int br_vlan_process_options(const struct net_bridge *br, + + return err; + } ++ ++static int br_vlan_process_global_one_opts(const struct net_bridge *br, ++ struct net_bridge_vlan_group *vg, ++ struct net_bridge_vlan *v, ++ struct nlattr **tb, ++ bool *changed, ++ struct netlink_ext_ack *extack) ++{ ++ *changed = false; ++ return 0; ++} ++ ++static const struct nla_policy br_vlan_db_gpol[BRIDGE_VLANDB_GOPTS_MAX + 1] = { ++ [BRIDGE_VLANDB_GOPTS_ID] = { .type = NLA_U16 }, ++ [BRIDGE_VLANDB_GOPTS_RANGE] = { .type = NLA_U16 }, ++}; ++ ++int br_vlan_rtm_process_global_options(struct net_device *dev, ++ const struct nlattr *attr, ++ int cmd, ++ struct netlink_ext_ack *extack) ++{ ++ struct nlattr *tb[BRIDGE_VLANDB_GOPTS_MAX + 1]; ++ struct net_bridge_vlan_group *vg; ++ struct net_bridge_vlan *v; ++ u16 vid, vid_range = 0; ++ struct net_bridge *br; ++ int err = 0; ++ ++ if (cmd != RTM_NEWVLAN) { ++ NL_SET_ERR_MSG_MOD(extack, "Global vlan options support only set operation"); ++ return -EINVAL; ++ } ++ if (!netif_is_bridge_master(dev)) { ++ NL_SET_ERR_MSG_MOD(extack, "Global vlan options can only be set on bridge device"); ++ return -EINVAL; ++ } ++ br = netdev_priv(dev); ++ vg = br_vlan_group(br); ++ if (WARN_ON(!vg)) ++ return -ENODEV; ++ ++ err = nla_parse_nested(tb, BRIDGE_VLANDB_GOPTS_MAX, attr, ++ br_vlan_db_gpol, extack); ++ if (err) ++ return err; ++ ++ if (!tb[BRIDGE_VLANDB_GOPTS_ID]) { ++ NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry id"); ++ return -EINVAL; ++ } ++ vid = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_ID]); ++ if (!br_vlan_valid_id(vid, extack)) ++ return -EINVAL; ++ ++ if (tb[BRIDGE_VLANDB_GOPTS_RANGE]) { ++ vid_range = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_RANGE]); ++ if (!br_vlan_valid_id(vid_range, extack)) ++ return -EINVAL; ++ if (vid >= vid_range) { ++ NL_SET_ERR_MSG_MOD(extack, "End vlan id is less than or equal to start vlan id"); ++ return -EINVAL; ++ } ++ } else { ++ vid_range = vid; ++ } ++ ++ for (; vid <= vid_range; vid++) { ++ bool changed = false; ++ ++ v = br_vlan_find(vg, vid); ++ if (!v) { ++ NL_SET_ERR_MSG_MOD(extack, "Vlan in range doesn't exist, can't process global options"); ++ err = -ENOENT; ++ break; ++ } ++ ++ err = br_vlan_process_global_one_opts(br, vg, v, tb, &changed, ++ extack); ++ if (err) ++ break; ++ } ++ ++ return err; ++} +-- +2.53.0 + diff --git a/queue-5.10/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch b/queue-5.10/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch new file mode 100644 index 0000000000..51df8f9c67 --- /dev/null +++ b/queue-5.10/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch @@ -0,0 +1,149 @@ +From 6b75a67d001de62da1d44c241414e3828f4bc37e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:09:21 +0300 +Subject: net: bridge: vlan: fix vlan range dumps starting with pvid + +From: Nikolay Aleksandrov + +[ Upstream commit 43171c97e4714bf601b468401b37732244639c21 ] + +There is a bug in all range dumps that rely on br_vlan_can_enter_range() +when the PVID is a range starting VLAN, all following VLANs that match +its flags can enter the range, but when the range is filled in only the +PVID VLAN is dumped and the rest of the range is discarded because +br_vlan_fill_vids() checks for the PVID flag. Since the PVID VLAN can +be only one, we need to break ranges around it, the best way to do that +consistently for all is to alter br_vlan_can_enter_range() to take into +account the PVID and return false to break the range when it's matched. + +Before the fix: +$ ip l add br0 type bridge vlan_filtering 1 +$ ip l add dumdum type dummy +$ ip l set dumdum master br0 +$ ip l set br0 up +$ ip l set dumdum up +$ bridge vlan add dev dumdum vid 1 pvid untagged master +$ bridge vlan add dev dumdum vid 2 untagged master +$ bridge vlan show dev dumdum # use legacy dump to show all vlans +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged + +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + +VLAN 2 is missing, and if there are more matching VLANs afterwards +they'd be missing too. + +After the fix: +[ same setup steps ] +$ bridge vlan show dev dumdum +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + 2 Egress Untagged + state forwarding mcast_router 1 + +Fixes: 0ab558795184 ("net: bridge: vlan: add rtm range support") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260721140922.682265-2-razor@blackwall.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_netlink_tunnel.c | 3 ++- + net/bridge/br_private.h | 6 ++++-- + net/bridge/br_vlan.c | 10 ++++++---- + net/bridge/br_vlan_options.c | 3 +-- + 4 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/net/bridge/br_netlink_tunnel.c b/net/bridge/br_netlink_tunnel.c +index 8914290c75d480..e4aab077527011 100644 +--- a/net/bridge/br_netlink_tunnel.c ++++ b/net/bridge/br_netlink_tunnel.c +@@ -268,7 +268,8 @@ static void __vlan_tunnel_handle_range(const struct net_bridge_port *p, + if (!*v_start) + goto out_init; + +- if (v && curr_change && br_vlan_can_enter_range(v, *v_end)) { ++ if (v && curr_change && ++ br_vlan_can_enter_range(v, *v_end, br_get_pvid(vg))) { + *v_end = v; + return; + } +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index b3a98ae8fbd619..17327852c807d9 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1093,7 +1093,8 @@ void br_vlan_notify(const struct net_bridge *br, + u16 vid, u16 vid_range, + int cmd); + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end); ++ const struct net_bridge_vlan *range_end, ++ u16 pvid); + + static inline struct net_bridge_vlan_group *br_vlan_group( + const struct net_bridge *br) +@@ -1309,7 +1310,8 @@ static inline void br_vlan_notify(const struct net_bridge *br, + } + + static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { + return true; + } +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index 258702134d9bfc..2eb9e33130e604 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1764,9 +1764,11 @@ void br_vlan_notify(const struct net_bridge *br, + + /* check if v_curr can enter a range ending in range_end */ + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { +- return v_curr->vid - range_end->vid == 1 && ++ return v_curr->vid != pvid && range_end->vid != pvid && ++ v_curr->vid - range_end->vid == 1 && + range_end->flags == v_curr->flags && + br_vlan_opts_eq_range(v_curr, range_end); + } +@@ -1848,8 +1850,8 @@ static int br_vlan_dump_dev(const struct net_device *dev, + idx += range_end->vid - range_start->vid + 1; + + range_start = v; +- } else if (dump_stats || v->vid == pvid || +- !br_vlan_can_enter_range(v, range_end)) { ++ } else if (dump_stats || ++ !br_vlan_can_enter_range(v, range_end, pvid)) { + u16 vlan_flags = br_vlan_flags(range_start, pvid); + + if (!br_vlan_fill_vids(skb, range_start->vid, +diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c +index f290f514054714..29fb37e7046ad3 100644 +--- a/net/bridge/br_vlan_options.c ++++ b/net/bridge/br_vlan_options.c +@@ -234,8 +234,7 @@ int br_vlan_process_options(const struct net_bridge *br, + continue; + } + +- if (v->vid == pvid || +- !br_vlan_can_enter_range(v, curr_end)) { ++ if (!br_vlan_can_enter_range(v, curr_end, pvid)) { + br_vlan_notify(br, p, curr_start->vid, + curr_end->vid, RTM_NEWVLAN); + curr_start = v; +-- +2.53.0 + diff --git a/queue-5.10/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch b/queue-5.10/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch new file mode 100644 index 0000000000..201df0e567 --- /dev/null +++ b/queue-5.10/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch @@ -0,0 +1,48 @@ +From f8fb29ac81c78dec1cf99ebfd535a20f74fb7c06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 22:32:30 +0800 +Subject: net: ipv6: fix dif and sdif mismatch in raw6_icmp_error + +From: Li RongQing + +[ Upstream commit 440e274da4d1b93c7df2cb0ce893c3009dd4db55 ] + +In raw6_icmp_error(), raw_v6_match() is called with inet6_iif(skb) passed +to both the 'dif' and 'sdif' arguments. This is a copy-paste or typo error, +as the last argument should represent the secondary interface index (sdif). + +This mismatch breaks ICMPv6 error handling for IPv6 raw sockets in VRF +(Virtual Routing and Forwarding) environments. When a raw socket is bound +to a VRF master device, raw_v6_match() fails to find a match because it is +not given the correct sdif value, causing the socket to miss relevant +ICMPv6 error notifications. + +Fix this by properly passing inet6_sdif(skb) as the last argument to +raw_v6_match(). + +Fixes: 5108ab4bf446fa ("net: ipv6: add second dif to raw socket lookups") +Signed-off-by: Li RongQing +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260717143230.1836-1-lirongqing@baidu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/raw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 16ff46c4f300e1..719e1932363e90 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -351,7 +351,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + daddr = &ip6h->daddr; + + if (!raw_v6_match(net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr, +- inet6_iif(skb), inet6_iif(skb))) ++ inet6_iif(skb), inet6_sdif(skb))) + continue; + rawv6_err(sk, skb, NULL, type, code, inner_offset, info); + } +-- +2.53.0 + diff --git a/queue-5.10/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch b/queue-5.10/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch new file mode 100644 index 0000000000..e19ca6ad93 --- /dev/null +++ b/queue-5.10/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch @@ -0,0 +1,51 @@ +From 22d5b2d113a0a0612501689e2334f16773bb68ba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:33:06 +0300 +Subject: net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule + +From: Yael Chemla + +[ Upstream commit d12956d083eb70f2c6d72711aebaf8c2ce21e170 ] + +esw_egress_acl_vlan_create() hardcodes num_dest=0 in its +mlx5_add_flow_rules() call. When invoked from the non-bond path +fwd_dest is NULL and num_dest=0 is correct. When invoked from +esw_acl_egress_ofld_rules_create() during a bond event, fwd_dest is +non-NULL and flow_act.action carries MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, +but _mlx5_add_flow_rules() rejects a non-NULL dest pointer paired with +dest_num<=0 and returns -EINVAL. The error propagates as +"configure slave vport egress fwd, err(-22)". The passive vport's egress +ACL table ends up with its flow groups allocated but no FTEs, so +prio-tagged packets are not popped and bond failover is broken on +prio_tag_required devices. + +Fix by passing fwd_dest ? 1 : 0 as num_dest to match the actual number +of destinations supplied. + +Fixes: bf773dc0e6d5 ("net/mlx5: E-Switch, Introduce APIs to enable egress acl forward-to-vport rule") +Signed-off-by: Yael Chemla +Reviewed-by: Cosmin Ratiu +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20260717073306.1242399-1-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +index 22f4c1c280065f..e1d71e88fad4a3 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +@@ -67,7 +67,7 @@ int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw, + flow_act.action = flow_action; + vport->egress.allowed_vlan = + mlx5_add_flow_rules(vport->egress.acl, spec, +- &flow_act, fwd_dest, 0); ++ &flow_act, fwd_dest, fwd_dest ? 1 : 0); + if (IS_ERR(vport->egress.allowed_vlan)) { + err = PTR_ERR(vport->egress.allowed_vlan); + esw_warn(esw->dev, +-- +2.53.0 + diff --git a/queue-5.10/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch b/queue-5.10/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch new file mode 100644 index 0000000000..ed8f30a7df --- /dev/null +++ b/queue-5.10/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch @@ -0,0 +1,46 @@ +From 7f29dc96f18ae21439803467bf072b3a8a7f665e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:25 +0300 +Subject: net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation + +From: Alexei Lazar + +[ Upstream commit 9173e1d3c7c7d49a71eee813091f9e834ec7cee5 ] + +Credit Based (CB) TSA is not supported by the mlx5 driver, so reject +any configurations that specify it. + +Fixes: 08fb1dacdd76 ("net/mlx5e: Support DCBNL IEEE ETS") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-3-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index c1d1c21f41b4b1..6ea50a9ef1be56 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -309,6 +309,14 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev, + } + } + ++ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { ++ if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_CB_SHAPER) { ++ netdev_err(netdev, ++ "Failed to validate ETS: CB Shaper is not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ + /* Validate Bandwidth Sum */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { +-- +2.53.0 + diff --git a/queue-5.10/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch b/queue-5.10/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch new file mode 100644 index 0000000000..8510dcdefb --- /dev/null +++ b/queue-5.10/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch @@ -0,0 +1,53 @@ +From a78aa26eeb4494619277f533da0e6373e7880a74 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:24 +0300 +Subject: net/mlx5e: Report zero bandwidth for non-ETS traffic classes + +From: Alexei Lazar + +[ Upstream commit ffb1873b2df11945b8c395e859169248675c91c5 ] + +The IEEE 802.1Qaz standard defines that bandwidth allocation percentages +only apply to Enhanced Transmission Selection (ETS) traffic classes. +For STRICT and VENDOR transmission selection algorithms, bandwidth +percentage values are not applicable. + +Currently for non-ETS 100 bandwidth is being reported for all traffic +classes in the get operation due to hardware limitation, regardless of +their TSA type. + +Fix this by reporting 0 for non-ETS traffic classes. + +Fixes: 820c2c5e773d ("net/mlx5e: Read ETS settings directly from firmware") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-2-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 5d0be9703a48e1..c1d1c21f41b4b1 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -158,6 +158,13 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, + } + memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa)); + ++ /* Report 0 for non ETS TSA */ ++ for (i = 0; i < ets->ets_cap; i++) { ++ if (ets->tc_tx_bw[i] == MLX5E_MAX_BW_ALLOC && ++ priv->dcbx.tc_tsa[i] != IEEE_8021QAZ_TSA_ETS) ++ ets->tc_tx_bw[i] = 0; ++ } ++ + return err; + } + +-- +2.53.0 + diff --git a/queue-5.10/net-packet-avoid-fanout-hook-re-registration-after-u.patch b/queue-5.10/net-packet-avoid-fanout-hook-re-registration-after-u.patch new file mode 100644 index 0000000000..608af44c68 --- /dev/null +++ b/queue-5.10/net-packet-avoid-fanout-hook-re-registration-after-u.patch @@ -0,0 +1,61 @@ +From 587f09ff5a902b12252d7aa4a6f76e44228dd488 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:44:37 +0000 +Subject: net/packet: avoid fanout hook re-registration after unregister + +From: David Lee + +[ Upstream commit 50aff80475abd3533eef4320477037e6fcc6b56e ] + +packet_set_ring() temporarily detaches a socket from packet delivery while +reconfiguring its ring. It records the previous running state, clears +po->num, unregisters the protocol hook when needed, drops po->bind_lock, +and later restores po->num and re-registers the hook from the saved +was_running value. + +That unlocked window can race with NETDEV_UNREGISTER. The notifier can +observe the socket as not running, skip __unregister_prot_hook(), and +invalidate the per-socket binding by setting po->ifindex to -1 and clearing +po->prot_hook.dev. A one-member fanout group can still retain its shared +fanout hook device pointer. When packet_set_ring() resumes, re-registering +solely from the stale was_running state can re-add the fanout hook after +the device has been unregistered. + +Treat po->ifindex == -1 as an invalidated binding after reacquiring +po->bind_lock. This is distinct from ifindex 0, the normal +unbound/wildcard state: ifindex -1 marks an existing device binding that +was invalidated when the device was unregistered. Restore po->num as +before, but do not re-register the hook if device unregister already +detached the socket. + +Fixes: dc99f600698d ("packet: Add fanout support.") +Link: https://lore.kernel.org/netdev/20260701113947.23180-1-david.lee@trailofbits.com/ +Signed-off-by: David Lee +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260707104440.833129-1-david.lee@trailofbits.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 793720e506799c..b09d1bbddde937 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -4551,7 +4551,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + + spin_lock(&po->bind_lock); + WRITE_ONCE(po->num, num); +- if (was_running) ++ /* ++ * NETDEV_UNREGISTER may have invalidated the binding while bind_lock ++ * was dropped above. Do not re-add a fanout hook to a dead device. ++ */ ++ if (was_running && READ_ONCE(po->ifindex) != -1) + register_prot_hook(sk); + + spin_unlock(&po->bind_lock); +-- +2.53.0 + diff --git a/queue-5.10/net-qrtr-restrict-socket-creation-to-the-initial-net.patch b/queue-5.10/net-qrtr-restrict-socket-creation-to-the-initial-net.patch new file mode 100644 index 0000000000..0921ec57fa --- /dev/null +++ b/queue-5.10/net-qrtr-restrict-socket-creation-to-the-initial-net.patch @@ -0,0 +1,63 @@ +From 55fe73e00bde88ea02fdbc111c9bfeb1cd61694d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 12:43:19 -0300 +Subject: net: qrtr: restrict socket creation to the initial network namespace + +From: Aldo Ariel Panzardo + +[ Upstream commit 3b536db8fb32da9e9c62f2bb45e2e319331f0426 ] + +QRTR keeps its entire port and node state in module-global variables +that are not partitioned per network namespace: qrtr_local_nid is a +single global node id (always 1) and qrtr_ports is a single global +xarray. qrtr_port_lookup() and qrtr_local_enqueue() operate on that +global state with no network-namespace check, and qrtr_create() places +no restriction on the namespace a socket is created in. + +As a result an unprivileged process that creates an AF_QIPCRTR socket +in a separate network namespace, e.g. via +unshare(CLONE_NEWUSER | CLONE_NEWNET), can send QRTR datagrams - +including control-plane messages such as QRTR_TYPE_NEW_SERVER - to QRTR +sockets owned by another namespace, and vice versa. The receiving +socket sees such a message as coming from node id 1, indistinguishable +from a legitimate local client, breaking the isolation that network +namespaces are expected to provide. + +QRTR is a transport to global hardware endpoints (the modem and other +remote processors) and has no per-namespace semantics; its in-kernel +name service already creates its socket in init_net only. Confine the +socket family to the initial network namespace, as other +non-namespace-aware socket families do (see llc_ui_create() and the +ieee802154 socket code). + +Fixes: bdabad3e363d ("net: Add Qualcomm IPC router") +Signed-off-by: Aldo Ariel Panzardo +Link: https://patch.msgid.link/20260716154319.3297699-1-qwe.aldo@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/qrtr/af_qrtr.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c +index 0018a9b32241b9..31371f3c1a57b2 100644 +--- a/net/qrtr/af_qrtr.c ++++ b/net/qrtr/af_qrtr.c +@@ -1257,6 +1257,14 @@ static int qrtr_create(struct net *net, struct socket *sock, + if (sock->type != SOCK_DGRAM) + return -EPROTOTYPE; + ++ /* QRTR keeps its port and node state in module-global variables that ++ * are not partitioned per network namespace, and the in-kernel name ++ * service only operates in init_net. Confine the family to init_net so ++ * a socket in another namespace cannot reach the global control plane. ++ */ ++ if (!net_eq(net, &init_net)) ++ return -EAFNOSUPPORT; ++ + sk = sk_alloc(net, AF_QIPCRTR, GFP_KERNEL, &qrtr_proto, kern); + if (!sk) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-5.10/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch b/queue-5.10/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch new file mode 100644 index 0000000000..cd507af425 --- /dev/null +++ b/queue-5.10/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch @@ -0,0 +1,43 @@ +From 2b2602ff3474af90889cf664d3061b174e9b059f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:16 -0700 +Subject: net: stmmac: reset residual action in L3L4 filters on delete + +From: Nazim Amirul + +[ Upstream commit a448f821289934b961dd9d8d0beb006cc8937ba2 ] + +When deleting an L3/L4 flower filter entry, the action field is not +reset. If a filter was previously configured with a drop action, that +action may persist and affect subsequent filter configurations +unintentionally. + +Clear the action field when the filter entry is deleted. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-5-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 3539c1542eb8c6..f5977539129cfd 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -603,6 +603,7 @@ static int tc_del_flow(struct stmmac_priv *priv, + entry->in_use = false; + entry->cookie = 0; + entry->is_l4 = false; ++ entry->action = 0; + return ret; + } + +-- +2.53.0 + diff --git a/queue-5.10/nfp-check-resource-mutex-allocation.patch b/queue-5.10/nfp-check-resource-mutex-allocation.patch new file mode 100644 index 0000000000..32216df11c --- /dev/null +++ b/queue-5.10/nfp-check-resource-mutex-allocation.patch @@ -0,0 +1,52 @@ +From 6ff6df183941c1ee8c55456a5f700f35d1e4c710 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:08 +0800 +Subject: nfp: Check resource mutex allocation + +From: Ruoyu Wang + +[ Upstream commit a61b4db34a753bdf5c9e77a7f3d3dddd41dcfacc ] + +nfp_cpp_resource_find() allocates a CPP mutex handle for the matching +resource-table entry and then reports success. nfp_resource_try_acquire() +immediately passes that handle to nfp_cpp_mutex_trylock(). + +However, nfp_cpp_mutex_alloc() returns NULL on failure. If that happens +for a matching table entry, the resource lookup still returns success and +the following trylock dereferences a NULL mutex pointer while opening the +resource. + +nfp_resource_acquire() already treats failure to allocate the table mutex +as -ENOMEM. Do the same for the resource mutex and fail the lookup before +publishing the rest of the resource handle. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: f01a2161577d ("nfp: add support for resources") +Signed-off-by: Ruoyu Wang +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708143408.3168425-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +index ce7492a6a98fad..908d99f398b819 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c ++++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +@@ -96,6 +96,9 @@ static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res) + res->mutex = + nfp_cpp_mutex_alloc(cpp, + NFP_RESOURCE_TBL_TARGET, addr, key); ++ if (!res->mutex) ++ return -ENOMEM; ++ + res->cpp_id = NFP_CPP_ID(entry.region.cpp_target, + entry.region.cpp_action, + entry.region.cpp_token); +-- +2.53.0 + diff --git a/queue-5.10/raw-use-more-conventional-iterators.patch b/queue-5.10/raw-use-more-conventional-iterators.patch new file mode 100644 index 0000000000..9e0f6c209d --- /dev/null +++ b/queue-5.10/raw-use-more-conventional-iterators.patch @@ -0,0 +1,451 @@ +From 548de93286222b110183e05b5c6d051f0b6ac9fa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jun 2022 20:47:04 -0700 +Subject: raw: use more conventional iterators + +From: Eric Dumazet + +[ Upstream commit ba44f8182ec299c5d1c8a72fc0fde4ec127b5a6d ] + +In order to prepare the following patch, +I change raw v4 & v6 code to use more conventional +iterators. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Stable-dep-of: 440e274da4d1 ("net: ipv6: fix dif and sdif mismatch in raw6_icmp_error") +Signed-off-by: Sasha Levin +--- + include/net/raw.h | 5 +-- + include/net/rawv6.h | 6 +-- + net/ipv4/raw.c | 93 ++++++++++++++------------------------- + net/ipv4/raw_diag.c | 33 +++++++------- + net/ipv6/raw.c | 105 ++++++++++++++++---------------------------- + 5 files changed, 92 insertions(+), 150 deletions(-) + +diff --git a/include/net/raw.h b/include/net/raw.h +index c51a635671a73d..6324965779ec6a 100644 +--- a/include/net/raw.h ++++ b/include/net/raw.h +@@ -20,9 +20,8 @@ + extern struct proto raw_prot; + + extern struct raw_hashinfo raw_v4_hashinfo; +-struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, +- unsigned short num, __be32 raddr, +- __be32 laddr, int dif, int sdif); ++bool raw_v4_match(struct net *net, struct sock *sk, unsigned short num, ++ __be32 raddr, __be32 laddr, int dif, int sdif); + + int raw_abort(struct sock *sk, int err); + void raw_icmp_error(struct sk_buff *, int, u32); +diff --git a/include/net/rawv6.h b/include/net/rawv6.h +index 53d86b6055e8cc..c48c1298699a04 100644 +--- a/include/net/rawv6.h ++++ b/include/net/rawv6.h +@@ -5,9 +5,9 @@ + #include + + extern struct raw_hashinfo raw_v6_hashinfo; +-struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, +- unsigned short num, const struct in6_addr *loc_addr, +- const struct in6_addr *rmt_addr, int dif, int sdif); ++bool raw_v6_match(struct net *net, struct sock *sk, unsigned short num, ++ const struct in6_addr *loc_addr, ++ const struct in6_addr *rmt_addr, int dif, int sdif); + + int raw_abort(struct sock *sk, int err); + +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index 2d14d9aabc0b3b..3ce0ff77ef3a61 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -117,24 +117,19 @@ void raw_unhash_sk(struct sock *sk) + } + EXPORT_SYMBOL_GPL(raw_unhash_sk); + +-struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, +- unsigned short num, __be32 raddr, __be32 laddr, +- int dif, int sdif) ++bool raw_v4_match(struct net *net, struct sock *sk, unsigned short num, ++ __be32 raddr, __be32 laddr, int dif, int sdif) + { +- sk_for_each_from(sk) { +- struct inet_sock *inet = inet_sk(sk); +- +- if (net_eq(sock_net(sk), net) && inet->inet_num == num && +- !(inet->inet_daddr && inet->inet_daddr != raddr) && +- !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && +- raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif)) +- goto found; /* gotcha */ +- } +- sk = NULL; +-found: +- return sk; ++ struct inet_sock *inet = inet_sk(sk); ++ ++ if (net_eq(sock_net(sk), net) && inet->inet_num == num && ++ !(inet->inet_daddr && inet->inet_daddr != raddr) && ++ !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && ++ raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif)) ++ return true; ++ return false; + } +-EXPORT_SYMBOL_GPL(__raw_v4_lookup); ++EXPORT_SYMBOL_GPL(raw_v4_match); + + /* + * 0 - deliver +@@ -168,23 +163,21 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb) + */ + static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) + { ++ struct net *net = dev_net(skb->dev); + int sdif = inet_sdif(skb); + int dif = inet_iif(skb); +- struct sock *sk; + struct hlist_head *head; + int delivered = 0; +- struct net *net; ++ struct sock *sk; + +- read_lock(&raw_v4_hashinfo.lock); + head = &raw_v4_hashinfo.ht[hash]; + if (hlist_empty(head)) +- goto out; +- +- net = dev_net(skb->dev); +- sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol, +- iph->saddr, iph->daddr, dif, sdif); +- +- while (sk) { ++ return 0; ++ read_lock(&raw_v4_hashinfo.lock); ++ sk_for_each(sk, head) { ++ if (!raw_v4_match(net, sk, iph->protocol, ++ iph->saddr, iph->daddr, dif, sdif)) ++ continue; + delivered = 1; + if ((iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) && + ip_mc_sf_allow(sk, iph->daddr, iph->saddr, +@@ -195,31 +188,16 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) + if (clone) + raw_rcv(sk, clone); + } +- sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol, +- iph->saddr, iph->daddr, +- dif, sdif); + } +-out: + read_unlock(&raw_v4_hashinfo.lock); + return delivered; + } + + int raw_local_deliver(struct sk_buff *skb, int protocol) + { +- int hash; +- struct sock *raw_sk; +- +- hash = protocol & (RAW_HTABLE_SIZE - 1); +- raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); +- +- /* If there maybe a raw socket we must check - if not we +- * don't care less +- */ +- if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash)) +- raw_sk = NULL; +- +- return raw_sk != NULL; ++ int hash = protocol & (RAW_HTABLE_SIZE - 1); + ++ return raw_v4_input(skb, ip_hdr(skb), hash); + } + + static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) +@@ -286,29 +264,24 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) + + void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) + { +- int hash; +- struct sock *raw_sk; ++ struct net *net = dev_net(skb->dev);; ++ int dif = skb->dev->ifindex; ++ int sdif = inet_sdif(skb); ++ struct hlist_head *head; + const struct iphdr *iph; +- struct net *net; ++ struct sock *sk; ++ int hash; + + hash = protocol & (RAW_HTABLE_SIZE - 1); ++ head = &raw_v4_hashinfo.ht[hash]; + + read_lock(&raw_v4_hashinfo.lock); +- raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); +- if (raw_sk) { +- int dif = skb->dev->ifindex; +- int sdif = inet_sdif(skb); +- ++ sk_for_each(sk, head) { + iph = (const struct iphdr *)skb->data; +- net = dev_net(skb->dev); +- +- while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, +- iph->daddr, iph->saddr, +- dif, sdif)) != NULL) { +- raw_err(raw_sk, skb, info); +- raw_sk = sk_next(raw_sk); +- iph = (const struct iphdr *)skb->data; +- } ++ if (!raw_v4_match(net, sk, iph->protocol, ++ iph->saddr, iph->daddr, dif, sdif)) ++ continue; ++ raw_err(sk, skb, info); + } + read_unlock(&raw_v4_hashinfo.lock); + } +diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c +index ccacbde30a2c50..b6d92dc7b051d1 100644 +--- a/net/ipv4/raw_diag.c ++++ b/net/ipv4/raw_diag.c +@@ -34,31 +34,30 @@ raw_get_hashinfo(const struct inet_diag_req_v2 *r) + * use helper to figure it out. + */ + +-static struct sock *raw_lookup(struct net *net, struct sock *from, +- const struct inet_diag_req_v2 *req) ++static bool raw_lookup(struct net *net, struct sock *sk, ++ const struct inet_diag_req_v2 *req) + { + struct inet_diag_req_raw *r = (void *)req; +- struct sock *sk = NULL; + + if (r->sdiag_family == AF_INET) +- sk = __raw_v4_lookup(net, from, r->sdiag_raw_protocol, +- r->id.idiag_dst[0], +- r->id.idiag_src[0], +- r->id.idiag_if, 0); ++ return raw_v4_match(net, sk, r->sdiag_raw_protocol, ++ r->id.idiag_dst[0], ++ r->id.idiag_src[0], ++ r->id.idiag_if, 0); + #if IS_ENABLED(CONFIG_IPV6) + else +- sk = __raw_v6_lookup(net, from, r->sdiag_raw_protocol, +- (const struct in6_addr *)r->id.idiag_src, +- (const struct in6_addr *)r->id.idiag_dst, +- r->id.idiag_if, 0); ++ return raw_v6_match(net, sk, r->sdiag_raw_protocol, ++ (const struct in6_addr *)r->id.idiag_src, ++ (const struct in6_addr *)r->id.idiag_dst, ++ r->id.idiag_if, 0); + #endif +- return sk; ++ return false; + } + + static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 *r) + { + struct raw_hashinfo *hashinfo = raw_get_hashinfo(r); +- struct sock *sk = NULL, *s; ++ struct sock *sk; + int slot; + + if (IS_ERR(hashinfo)) +@@ -66,9 +65,8 @@ static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 + + read_lock(&hashinfo->lock); + for (slot = 0; slot < RAW_HTABLE_SIZE; slot++) { +- sk_for_each(s, &hashinfo->ht[slot]) { +- sk = raw_lookup(net, s, r); +- if (sk) { ++ sk_for_each(sk, &hashinfo->ht[slot]) { ++ if (raw_lookup(net, sk, r)) { + /* + * Grab it and keep until we fill + * diag meaage to be reported, so +@@ -81,10 +79,11 @@ static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 + } + } + } ++ sk = ERR_PTR(-ENOENT); + out_unlock: + read_unlock(&hashinfo->lock); + +- return sk ? sk : ERR_PTR(-ENOENT); ++ return sk; + } + + static int raw_diag_dump_one(struct netlink_callback *cb, +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 3308b9a4d52378..16ff46c4f300e1 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -66,41 +66,27 @@ struct raw_hashinfo raw_v6_hashinfo = { + }; + EXPORT_SYMBOL_GPL(raw_v6_hashinfo); + +-struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, +- unsigned short num, const struct in6_addr *loc_addr, +- const struct in6_addr *rmt_addr, int dif, int sdif) ++bool raw_v6_match(struct net *net, struct sock *sk, unsigned short num, ++ const struct in6_addr *loc_addr, ++ const struct in6_addr *rmt_addr, int dif, int sdif) + { +- bool is_multicast = ipv6_addr_is_multicast(loc_addr); +- +- sk_for_each_from(sk) +- if (inet_sk(sk)->inet_num == num) { +- +- if (!net_eq(sock_net(sk), net)) +- continue; +- +- if (!ipv6_addr_any(&sk->sk_v6_daddr) && +- !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) +- continue; +- +- if (!raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, +- dif, sdif)) +- continue; +- +- if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { +- if (ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)) +- goto found; +- if (is_multicast && +- inet6_mc_check(sk, loc_addr, rmt_addr)) +- goto found; +- continue; +- } +- goto found; +- } +- sk = NULL; +-found: +- return sk; ++ if (inet_sk(sk)->inet_num != num || ++ !net_eq(sock_net(sk), net) || ++ (!ipv6_addr_any(&sk->sk_v6_daddr) && ++ !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) || ++ !raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, ++ dif, sdif)) ++ return false; ++ ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr) || ++ ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr) || ++ (ipv6_addr_is_multicast(loc_addr) && ++ inet6_mc_check(sk, loc_addr, rmt_addr))) ++ return true; ++ ++ return false; + } +-EXPORT_SYMBOL_GPL(__raw_v6_lookup); ++EXPORT_SYMBOL_GPL(raw_v6_match); + + /* + * 0 - deliver +@@ -156,31 +142,28 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister); + */ + static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) + { ++ struct net *net = dev_net(skb->dev); + const struct in6_addr *saddr; + const struct in6_addr *daddr; ++ struct hlist_head *head; + struct sock *sk; + bool delivered = false; + __u8 hash; +- struct net *net; + + saddr = &ipv6_hdr(skb)->saddr; + daddr = saddr + 1; + + hash = nexthdr & (RAW_HTABLE_SIZE - 1); +- ++ head = &raw_v6_hashinfo.ht[hash]; ++ if (hlist_empty(head)) ++ return false; + read_lock(&raw_v6_hashinfo.lock); +- sk = sk_head(&raw_v6_hashinfo.ht[hash]); +- +- if (!sk) +- goto out; +- +- net = dev_net(skb->dev); +- sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, +- inet6_iif(skb), inet6_sdif(skb)); +- +- while (sk) { ++ sk_for_each(sk, head) { + int filtered; + ++ if (!raw_v6_match(net, sk, nexthdr, daddr, saddr, ++ inet6_iif(skb), inet6_sdif(skb))) ++ continue; + delivered = true; + switch (nexthdr) { + case IPPROTO_ICMPV6: +@@ -219,23 +202,14 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) + rawv6_rcv(sk, clone); + } + } +- sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr, +- inet6_iif(skb), inet6_sdif(skb)); + } +-out: + read_unlock(&raw_v6_hashinfo.lock); + return delivered; + } + + bool raw6_local_deliver(struct sk_buff *skb, int nexthdr) + { +- struct sock *raw_sk; +- +- raw_sk = sk_head(&raw_v6_hashinfo.ht[nexthdr & (RAW_HTABLE_SIZE - 1)]); +- if (raw_sk && !ipv6_raw_deliver(skb, nexthdr)) +- raw_sk = NULL; +- +- return raw_sk != NULL; ++ return ipv6_raw_deliver(skb, nexthdr); + } + + /* This cleans up af_inet6 a bit. -DaveM */ +@@ -361,28 +335,25 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb, + void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + u8 type, u8 code, int inner_offset, __be32 info) + { ++ const struct in6_addr *saddr, *daddr; ++ struct net *net = dev_net(skb->dev); ++ struct hlist_head *head; + struct sock *sk; + int hash; +- const struct in6_addr *saddr, *daddr; +- struct net *net; + + hash = nexthdr & (RAW_HTABLE_SIZE - 1); +- ++ head = &raw_v6_hashinfo.ht[hash]; + read_lock(&raw_v6_hashinfo.lock); +- sk = sk_head(&raw_v6_hashinfo.ht[hash]); +- if (sk) { ++ sk_for_each(sk, head) { + /* Note: ipv6_hdr(skb) != skb->data */ + const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data; + saddr = &ip6h->saddr; + daddr = &ip6h->daddr; +- net = dev_net(skb->dev); + +- while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, +- inet6_iif(skb), inet6_iif(skb)))) { +- rawv6_err(sk, skb, NULL, type, code, +- inner_offset, info); +- sk = sk_next(sk); +- } ++ if (!raw_v6_match(net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr, ++ inet6_iif(skb), inet6_iif(skb))) ++ continue; ++ rawv6_err(sk, skb, NULL, type, code, inner_offset, info); + } + read_unlock(&raw_v6_hashinfo.lock); + } +-- +2.53.0 + diff --git a/queue-5.10/rds-drop-incoming-messages-that-cross-network-namesp.patch b/queue-5.10/rds-drop-incoming-messages-that-cross-network-namesp.patch new file mode 100644 index 0000000000..63eaa6eb30 --- /dev/null +++ b/queue-5.10/rds-drop-incoming-messages-that-cross-network-namesp.patch @@ -0,0 +1,78 @@ +From 9e50741536935a905729e885c3d1914e7817d46b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 19:43:14 -0700 +Subject: rds: drop incoming messages that cross network namespace boundaries + +From: Aldo Ariel Panzardo + +[ Upstream commit 5521ae71e32a8069ed4ca6e792179dc57bc43ab2 ] + +rds_find_bound() looks up the destination socket using a global +rhashtable keyed solely on (addr, port, scope_id). Network namespaces +are not part of the key, so a sender in netns A can deliver an incoming +message (inc) to a socket that lives in a different netns B. + +When this happens, inc->i_conn points to an rds_connection whose c_net +is netns A, but the receiving rs lives in netns B. Once the child +process that created netns A exits, cleanup_net() calls +rds_loop_exit_net() -> rds_loop_kill_conns() -> rds_conn_destroy(), +freeing that connection. If the survivor socket in netns B still holds +the inc, any subsequent dereference of inc->i_conn is a use-after-free. + +There are two dangerous sites in rds_clear_recv_queue(): + 1. inc->i_conn->c_lcong (offset 88 of freed rds_connection, size 200) + read via rds_recv_rcvbuf_delta() -- confirmed by KASAN. + 2. inc->i_conn->c_trans->inc_free(inc) (function pointer at offset 80) + called via rds_inc_put() when the inc refcount reaches zero -- same + race window, potential call-through-freed-object primitive. + +The bug is reachable from unprivileged user namespaces +(CLONE_NEWUSER + CLONE_NEWNET), available since Linux 3.8. + +Fix this by rejecting the delivery in rds_recv_incoming() when the +socket returned by rds_find_bound() belongs to a different network +namespace than the connection that carried the message. Use the +existing rds_conn_net() / sock_net() helpers and net_eq() for the +comparison. + +Fixes: c809195f5523 ("rds: clean up loopback rds_connections on netns deletion") +Signed-off-by: Aldo Ariel Panzardo +Reviewed-by: Allison Henderson +Tested-by: Allison Henderson +Signed-off-by: Allison Henderson +Link: https://patch.msgid.link/20260708024314.601139-1-achender@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/rds/recv.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/net/rds/recv.c b/net/rds/recv.c +index f570d64367a410..24a82e335d5a62 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -365,6 +365,21 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr, + goto out; + } + ++ /* ++ * rds_find_bound() uses a global (netns-agnostic) hash table. ++ * An RDS connection created in netns A can match a socket bound ++ * in the init netns, delivering inc cross-netns with inc->i_conn ++ * pointing into netns A. When cleanup_net() then frees that conn, ++ * any subsequent dereference of inc->i_conn is a use-after-free. ++ * Drop the inc if the receiving socket lives in a different netns. ++ */ ++ if (!net_eq(sock_net(rds_rs_to_sk(rs)), rds_conn_net(conn))) { ++ rds_stats_inc(s_recv_drop_no_sock); ++ rds_sock_put(rs); ++ rs = NULL; ++ goto out; ++ } ++ + /* Process extension headers */ + rds_recv_incoming_exthdrs(inc, rs); + +-- +2.53.0 + diff --git a/queue-5.10/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch b/queue-5.10/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch new file mode 100644 index 0000000000..34ea351cb7 --- /dev/null +++ b/queue-5.10/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch @@ -0,0 +1,51 @@ +From 0f431e5bf719b1aafd0cae2139c3d02e470ea2be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 09:55:32 +0800 +Subject: sctp: auth: verify auth requirement when auth_chunk is NULL + +From: Qing Luo + +[ Upstream commit 8e04823c120b376ef7dab14b60ebf6823aa16c14 ] + +sctp_auth_chunk_verify() returns true unconditionally when +chunk->auth_chunk is NULL, silently skipping authentication. +This is incorrect when: + +1. skb_clone() failed in the BH receive path, leaving auth_chunk + NULL. In sctp_endpoint_bh_rcv() asoc is NULL for new + connections, so the early sctp_auth_recv_cid() check cannot + catch this. + +2. No AUTH chunk precedes COOKIE-ECHO, so skb_clone() is never + called and auth_chunk remains NULL. + +Fix by checking sctp_auth_recv_cid() when auth_chunk is NULL: +if authentication is required, return false to drop the chunk; +otherwise continue normally. + +Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk") +Signed-off-by: Qing Luo +Acked-by: Xin Long +Link: https://patch.msgid.link/20260721015532.120157-2-l1138897701@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/sm_statefuns.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 17b9deb0cc758b..4ffb45aea51d7a 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -632,7 +632,7 @@ static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, + struct sctp_chunk auth; + + if (!chunk->auth_chunk) +- return true; ++ return !sctp_auth_recv_cid(chunk->chunk_hdr->type, asoc); + + /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo + * is supposed to be authenticated and we have to do delayed +-- +2.53.0 + diff --git a/queue-5.10/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch b/queue-5.10/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch new file mode 100644 index 0000000000..5d07445ad3 --- /dev/null +++ b/queue-5.10/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch @@ -0,0 +1,46 @@ +From 6ce464d497416400ac985733ffcc486f0813ae63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 03:20:21 +0000 +Subject: sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid + +From: HanQuan + +[ Upstream commit ff04b26794a16a8a879eb4fd2c02c2d6b03850e9 ] + +sctp_auth_ep_add_chunkid() uses SCTP_NUM_CHUNK_TYPES (20) as the +capacity limit for ep->auth_chunk_list, allowing it to hold up to +20 chunk entries (param_hdr.length up to 24). However, the copy +destination asoc->c.auth_chunks in struct sctp_cookie is only +SCTP_AUTH_MAX_CHUNKS (16) entries (20 bytes). When more than 16 +chunks are added, sctp_association_init() memcpy overflows the +destination by up to 4 bytes. + +Fix by using SCTP_AUTH_MAX_CHUNKS as the capacity limit, matching +the destination capacity. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Signed-off-by: HanQuan +Acked-by: Xin Long +Link: https://patch.msgid.link/20260713032021.3491702-1-zhoujian.zja@antgroup.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/auth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index 34964145514e6d..a983f96bb0c395 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -766,7 +766,7 @@ int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) + /* Check if we can add this chunk to the array */ + param_len = ntohs(p->param_hdr.length); + nchunks = param_len - sizeof(struct sctp_paramhdr); +- if (nchunks == SCTP_NUM_CHUNK_TYPES) ++ if (nchunks == SCTP_AUTH_MAX_CHUNKS) + return -EINVAL; + + p->chunks[nchunks] = chunk_id; +-- +2.53.0 + diff --git a/queue-5.10/sctp-validate-stream-count-in-sctp_process_strreset_.patch b/queue-5.10/sctp-validate-stream-count-in-sctp_process_strreset_.patch new file mode 100644 index 0000000000..e82db9f3c0 --- /dev/null +++ b/queue-5.10/sctp-validate-stream-count-in-sctp_process_strreset_.patch @@ -0,0 +1,80 @@ +From 56145aab6626132aa4b2dce7c52f2565ee634c57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 21:07:18 -0400 +Subject: sctp: validate stream count in sctp_process_strreset_inreq() + +From: Cen Zhang (Microsoft) + +[ Upstream commit 18ae07691d43183d270de8be9dc8e027906015d9 ] + +When processing a RESET_IN_REQUEST from a peer, +sctp_process_strreset_inreq() derives the stream count from the +parameter length but does not check whether the resulting +RESET_OUT_REQUEST would exceed SCTP_MAX_CHUNK_LEN. + +The OUT request header (sctp_strreset_outreq, 16 bytes) is 8 bytes +larger than the IN request header (sctp_strreset_inreq, 8 bytes). +Generally, the IP payload is bounded to 65535 bytes, so the stream +list cannot be large enough to trigger the overflow. However, on +interfaces with MTU > 65535 (e.g., loopback with IPv6 jumbograms), a +stream list that fits within the incoming IN parameter can cause a +__u16 overflow in sctp_make_strreset_req() when computing the OUT +request size, leading to an undersized skb allocation and a kernel +BUG: + + net/core/skbuff.c:207 skb_panic + net/core/skbuff.c:2625 skb_put + net/sctp/sm_make_chunk.c:1535 sctp_addto_chunk + net/sctp/sm_make_chunk.c:3695 sctp_make_strreset_req + net/sctp/stream.c:655 sctp_process_strreset_inreq + +The local setsockopt path validates the generated reset request size. +However, for an incoming-only reset, it accounts for the smaller IN +request even though the peer must generate an OUT request with the same +stream list. Such a request cannot be completed successfully by the +peer. + +Reject peer IN requests whose corresponding OUT request would exceed +SCTP_MAX_CHUNK_LEN. Also tighten the local check so it does not send an +IN request that would require an oversized OUT request from the peer. + +Fixes: 7f9d68ac944e ("sctp: implement sender-side procedures for SSN Reset Request Parameter") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/20260707203215.2752-1-blbllhy@gmail.com/ +Suggested-by: Xin Long +Signed-off-by: Cen Zhang (Microsoft) +Acked-by: Xin Long +Link: https://patch.msgid.link/20260710010718.20318-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/stream.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/stream.c b/net/sctp/stream.c +index d38e5431f359dc..34754ba23198ae 100644 +--- a/net/sctp/stream.c ++++ b/net/sctp/stream.c +@@ -308,7 +308,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc, + goto out; + + param_len += str_nums * sizeof(__u16) + +- sizeof(struct sctp_strreset_inreq); ++ (out ? sizeof(struct sctp_strreset_inreq) ++ : sizeof(struct sctp_strreset_outreq)); + } + + if (param_len > SCTP_MAX_CHUNK_LEN - +@@ -639,6 +640,9 @@ struct sctp_chunk *sctp_process_strreset_inreq( + + nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16); + str_p = inreq->list_of_streams; ++ if (nums * sizeof(__u16) + sizeof(struct sctp_strreset_outreq) > ++ SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_reconf_chunk)) ++ goto out; + for (i = 0; i < nums; i++) { + if (ntohs(str_p[i]) >= stream->outcnt) { + result = SCTP_STRRESET_ERR_WRONG_SSN; +-- +2.53.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 4304ed3faa..aa4b53e215 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -59,3 +59,44 @@ posix-cpu-timers-prevent-uaf-caused-by-non-leader-ex.patch crypto-rsa-pkcs1pad-don-t-warn-on-an-empty-digest.patch bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch +wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch +hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch +watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch +wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch +firewire-net-fix-fragmented-datagram-reassembly.patch +wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch +wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch +wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch +wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch +wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch +asoc-bt-sco-fix-bt-sco-pcm-wb-dai-widget-don-t-conne.patch +asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch +usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch +net-packet-avoid-fanout-hook-re-registration-after-u.patch +rds-drop-incoming-messages-that-cross-network-namesp.patch +nfp-check-resource-mutex-allocation.patch +wan-wanxl-only-reset-hardware-after-bar-mapping.patch +wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch +iommu-amd-bound-the-early-acpi-hid-map.patch +wifi-mac80211-recalculate-tim-when-a-station-enters-.patch +amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch +sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch +sctp-validate-stream-count-in-sctp_process_strreset_.patch +tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch +wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch +net-bridge-vlan-add-support-for-global-options.patch +net-bridge-vlan-add-support-for-dumping-global-vlan-.patch +net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch +sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch +vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch +tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch +net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch +ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch +hinic-remove-unused-ethtool-rss-user-configuration-b.patch +net-qrtr-restrict-socket-creation-to-the-initial-net.patch +net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch +net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch +net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch +raw-use-more-conventional-iterators.patch +net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch +bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch diff --git a/queue-5.10/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch b/queue-5.10/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch new file mode 100644 index 0000000000..0c8b3c8c7e --- /dev/null +++ b/queue-5.10/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch @@ -0,0 +1,47 @@ +From f90fdf77347b4ecb800f8473bc0c90ecfd3587bb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:49:35 -0300 +Subject: tipc: fix infinite loop in __tipc_nl_compat_dumpit + +From: Helen Koike + +[ Upstream commit 22f8aa35964e8f2ab026578f45befc9605fd1b28 ] + +cmd->dumpit callback can return a negative errno, causing an infinite +loop due to the while(len) condition. As the loop never terminates, +genl_mutex is never released, and other tasks waiting on it starve in D +state. + +Check dumpit's return value, propagate it and jump to err_out on error. + +Reported-by: syzbot+85d0bec020d805014a3a@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=85d0bec020d805014a3a +Fixes: d0796d1ef63d ("tipc: convert legacy nl bearer dump to nl compat") +Signed-off-by: Helen Koike +Reviewed-by: Tung Nguyen +Link: https://patch.msgid.link/20260713204940.647668-1-koike@igalia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/netlink_compat.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c +index 6f0c09b6a15315..e94c9ca2924f45 100644 +--- a/net/tipc/netlink_compat.c ++++ b/net/tipc/netlink_compat.c +@@ -223,6 +223,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, + int rem; + + len = (*cmd->dumpit)(buf, &cb); ++ if (len < 0) { ++ err = len; ++ goto err_out; ++ } + + nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) { + err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN, +-- +2.53.0 + diff --git a/queue-5.10/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch b/queue-5.10/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch new file mode 100644 index 0000000000..e0ff457a3b --- /dev/null +++ b/queue-5.10/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch @@ -0,0 +1,72 @@ +From c03c78eeb09d6a411d3263d1472c6584c2e17d41 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 00:15:41 -0400 +Subject: tipc: fix u16 MTU truncation in media and bearer MTU validation + +From: Cen Zhang (Microsoft) + +[ Upstream commit 9f29cd8a8e7901a2617c8064ce9f50fc67b97cb8 ] + +Both TIPC_NL_MEDIA_SET and TIPC_NL_BEARER_SET accept user-supplied +MTU values but only enforce a minimum bound, not a maximum. When a user +sets the MTU to a value exceeding U16_MAX (65535), it passes validation +but is silently truncated when assigned to u16 fields l->mtu and +l->advertised_mtu in tipc_link_create(). Values like 65536 (0x10000) +truncate to 0, causing a division by zero in tipc_link_set_queue_limits() +which computes TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE). Other overflowing +values (e.g. 65537-131071) produce small incorrect MTU values, resulting +in link malfunction behaviors. + +Crash stack (triggered as unprivileged user via user namespace): + + tipc_link_set_queue_limits net/tipc/link.c:2531 + tipc_link_create net/tipc/link.c:520 + tipc_node_check_dest net/tipc/node.c:1279 + tipc_disc_rcv net/tipc/discover.c:252 + tipc_rcv net/tipc/node.c:2129 + tipc_udp_recv net/tipc/udp_media.c:392 + +Two independent paths lack the upper bound check: +1. tipc_udp_mtu_bad() -- called from __tipc_nl_media_set() (MEDIA_SET) +2. inline check in __tipc_nl_bearer_set() at bearer.c:1160 (BEARER_SET) + +Fix both by rejecting MTU values above U16_MAX. + +Fixes: 901271e0403a ("tipc: implement configuration of UDP media MTU") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/CAB8m9WgETt0AjmFwE=F-CKjGXsK6_WDv0=kbYRcC8-noo+amnA@mail.gmail.com +Reviewed-by: Vadim Fedorenko +Signed-off-by: Cen Zhang (Microsoft) +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260714041541.307702-1-blbllhy@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tipc/netlink.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c +index 35e167de0fcf78..3fb31857de6b5e 100644 +--- a/net/tipc/netlink.c ++++ b/net/tipc/netlink.c +@@ -113,12 +113,16 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { + }; + + /* Properties valid for media, bearer and link */ ++static const struct netlink_range_validation tipc_nl_mtu_range = { ++ .max = U16_MAX, ++}; ++ + const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { + [TIPC_NLA_PROP_UNSPEC] = { .type = NLA_UNSPEC }, + [TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 }, +- [TIPC_NLA_PROP_MTU] = { .type = NLA_U32 }, ++ [TIPC_NLA_PROP_MTU] = NLA_POLICY_FULL_RANGE(NLA_U32, &tipc_nl_mtu_range), + [TIPC_NLA_PROP_BROADCAST] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_BROADCAST_RATIO] = { .type = NLA_U32 } + }; +-- +2.53.0 + diff --git a/queue-5.10/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch b/queue-5.10/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch new file mode 100644 index 0000000000..2fc58c1e1c --- /dev/null +++ b/queue-5.10/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch @@ -0,0 +1,93 @@ +From 099cb64a99f68b92b610d786db1e1dc5ea767641 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 02:07:04 -0600 +Subject: usb: atm: ueagle-atm: reject descriptors that confuse probe and + disconnect + +From: Diego Fernando Mancera Gomez + +[ Upstream commit 71132cedd1ecbc4032d76e9928c18a10f7e39b80 ] + +uea_probe() distinguishes a pre-firmware device from a post-firmware one +using the USB id (UEA_IS_PREFIRM()), and stores a different object as the +interface data in each case: a 'struct completion' for a pre-firmware +device (to be waited on in .disconnect()), or a 'struct usbatm_data' for a +post-firmware one. + +uea_disconnect() instead tells the two apart by the number of interfaces +of the active configuration (a pre-firmware device exposes a single +interface, ADI930 has 2 and eagle has 3), and casts the interface data +accordingly. + +Because the two handlers use different criteria, a crafted device that +advertises a pre-firmware id together with a multi-interface descriptor +(or a post-firmware id with a single interface) makes them disagree: the +small 'struct completion' stored by uea_probe() is then passed to +usbatm_usb_disconnect(), which casts it to 'struct usbatm_data' and takes +instance->serialize, reading past the end of the allocation: + + BUG: KASAN: slab-out-of-bounds in __mutex_lock+0x152a/0x1b80 + Read of size 8 at addr ffff8880470e2c60 by task kworker/1:2/982 + ... + __mutex_lock+0x152a/0x1b80 + usbatm_usb_disconnect+0x70/0x820 + uea_disconnect+0x133/0x2c0 + usb_unbind_interface+0x1dd/0x9e0 + ... + which belongs to the cache kmalloc-96 of size 96 + The buggy address is located 0 bytes to the right of + allocated 96-byte region [ffff8880470e2c00, ffff8880470e2c60) + +Reject such inconsistent descriptors in uea_probe() so that both handlers +always make the same pre/post-firmware decision. + +Reported-by: syzbot+e62a973f8322b3bbe3ac@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e62a973f8322b3bbe3ac +Fixes: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()") +Signed-off-by: Diego Fernando Mancera Gomez +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260717080704.1264-1-diegomancera.dev@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/atm/ueagle-atm.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c +index 661820041ca70d..6a282400027d68 100644 +--- a/drivers/usb/atm/ueagle-atm.c ++++ b/drivers/usb/atm/ueagle-atm.c +@@ -2591,6 +2591,7 @@ static struct usbatm_driver uea_usbatm_driver = { + static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + { + struct usb_device *usb = interface_to_usbdev(intf); ++ bool single_iface = usb->config->desc.bNumInterfaces == 1; + int ret; + + uea_enters(usb); +@@ -2600,6 +2601,22 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + le16_to_cpu(usb->descriptor.bcdDevice), + chip_name[UEA_CHIP_VERSION(id)]); + ++ /* ++ * uea_probe() decides between the pre-firmware and post-firmware case ++ * from the USB id and stores a different object as interface data in ++ * each case: a struct completion for a pre-firmware device, a struct ++ * usbatm_data for a post-firmware one. uea_disconnect() instead tells ++ * the two apart by the number of interfaces (a pre-firmware device ++ * exposes a single interface, ADI930 has 2 and eagle has 3). A crafted ++ * device advertising a pre-firmware id together with a multi-interface ++ * descriptor (or the other way around) makes the two disagree, so that ++ * usbatm_usb_disconnect() treats the small completion object as a ++ * struct usbatm_data and reads out of bounds. Reject such inconsistent ++ * descriptors so both paths make the same decision. ++ */ ++ if (UEA_IS_PREFIRM(id) != single_iface) ++ return -ENODEV; ++ + usb_reset_device(usb); + + if (UEA_IS_PREFIRM(id)) { +-- +2.53.0 + diff --git a/queue-5.10/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch b/queue-5.10/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch new file mode 100644 index 0000000000..326d052825 --- /dev/null +++ b/queue-5.10/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch @@ -0,0 +1,84 @@ +From 02bf2022d5a0fd7d1a199f492a716a0c4101c61d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 07:09:15 -0700 +Subject: vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets + +From: Harshaka Narayana + +[ Upstream commit 34a71f5361fc3adb5b7138da78750b0d535a8252 ] + +vmxnet3_get_hdr_len() assumes gdesc->rcd.v4/v6/tcp always describe the +outer header, but for a Geneve-encapsulated packet the device can set +them based on the inner header instead, signalled by the +VMXNET3_RCD_HDR_INNER_SHIFT bit in the completion descriptor. Since the +function never skips the outer encapsulation, this mismatch triggers: + +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP), because the outer + protocol is UDP (Geneve), not TCP. +- BUG_ON(hdr.eth->h_proto != ...), when the tunnel's outer and inner + IP versions differ (e.g. outer IPv6/inner IPv4 or vice versa). + +Check VMXNET3_RCD_HDR_INNER_SHIFT up front and bail out, since the +function cannot locate the inner header it would need to parse. Also +convert the remaining BUG_ON()s in this function to return 0 +defensively. + +Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)") +Signed-off-by: Harshaka Narayana +Reviewed-by: Ronak Doshi +Reviewed-by: Sankararaman Jayaraman +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260713140915.3381715-1-harshaka.narayana@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c +index f3c628a64b9545..b670259d9393d3 100644 +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -1313,7 +1313,11 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + struct ipv6hdr *ipv6; + struct tcphdr *tcp; + } hdr; +- BUG_ON(gdesc->rcd.tcp == 0); ++ ++ /* v4/v6/tcp then describe the inner header, which we can't locate. */ ++ if ((le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT)) || ++ gdesc->rcd.tcp == 0) ++ return 0; + + maplen = skb_headlen(skb); + if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen)) +@@ -1327,15 +1331,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + + hdr.eth = eth_hdr(skb); + if (gdesc->rcd.v4) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)); ++ if (hdr.eth->h_proto != htons(ETH_P_IP) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)) ++ return 0; ++ + hdr.ptr += hlen; +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP); ++ if (hdr.ipv4->protocol != IPPROTO_TCP) ++ return 0; ++ + hlen = hdr.ipv4->ihl << 2; + hdr.ptr += hdr.ipv4->ihl << 2; + } else if (gdesc->rcd.v6) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)); ++ if (hdr.eth->h_proto != htons(ETH_P_IPV6) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)) ++ return 0; ++ + hdr.ptr += hlen; + /* Use an estimated value, since we also need to handle + * TSO case. +-- +2.53.0 + diff --git a/queue-5.10/wan-wanxl-only-reset-hardware-after-bar-mapping.patch b/queue-5.10/wan-wanxl-only-reset-hardware-after-bar-mapping.patch new file mode 100644 index 0000000000..26d785c7e2 --- /dev/null +++ b/queue-5.10/wan-wanxl-only-reset-hardware-after-bar-mapping.patch @@ -0,0 +1,51 @@ +From 87e02cab4b39125868232b5bf38e468a22202d04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:15 +0800 +Subject: wan: wanxl: Only reset hardware after BAR mapping + +From: Ruoyu Wang + +[ Upstream commit 91957b89da995607cb654b1f9a3c126ddbaee10f ] + +wanxl_pci_init_one() stores the freshly allocated card in driver data +before the PLX BAR is mapped. Several early probe failures then unwind +through wanxl_pci_remove_one(), including failure to allocate the coherent +status area or to restore the DMA mask. + +wanxl_pci_remove_one() unconditionally calls wanxl_reset(), and +wanxl_reset() dereferences card->plx. On those early failures card->plx +is still NULL, so the error path can dereference a NULL MMIO pointer. + +Only issue the hardware reset once the BAR mapping exists. The remaining +cleanup in wanxl_pci_remove_one() already checks whether later resources +were allocated. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ruoyu Wang +Link: https://patch.msgid.link/20260708143415.3169358-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/wan/wanxl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c +index a83133388de919..006862688e7d83 100644 +--- a/drivers/net/wan/wanxl.c ++++ b/drivers/net/wan/wanxl.c +@@ -521,7 +521,8 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) + if (card->irq) + free_irq(card->irq, card); + +- wanxl_reset(card); ++ if (card->plx) ++ wanxl_reset(card); + + for (i = 0; i < RX_QUEUE_LENGTH; i++) + if (card->rx_skbs[i]) { +-- +2.53.0 + diff --git a/queue-5.10/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch b/queue-5.10/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch new file mode 100644 index 0000000000..fcc393df1d --- /dev/null +++ b/queue-5.10/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch @@ -0,0 +1,48 @@ +From 837c93e9bf65be919a2e921436a0b7c9ecefdbf5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:18:03 +0000 +Subject: watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() + +From: Tzung-Bi Shih + +[ Upstream commit 7362ba0f9c96ac3ad6a2ca3995bd9fc9a28a8661 ] + +When a watchdog governor is unregistered, it updates existing watchdog +devices that were using this governor by falling back to `default_gov`. + +If the governor being unregistered is currently set as `default_gov`, +the `default_gov` is never cleared. This leads to 2 use-after-free +issues: +1. New watchdog devices registered after this point will inherit the + dangling `default_gov`. +2. Existing watchdog devices using the unregistered governor will have + their `wdd->gov` reassigned to the dangling `default_gov`. + +Fix the UAF by clearing `default_gov` if it matches the governor being +unregistered. + +Fixes: da0d12ff2b82 ("watchdog: pretimeout: add panic pretimeout governor") +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20260707101803.3598173-1-tzungbi@kernel.org +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/watchdog_pretimeout.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c +index 01ca84be240f6c..fe4c8ace9a4276 100644 +--- a/drivers/watchdog/watchdog_pretimeout.c ++++ b/drivers/watchdog/watchdog_pretimeout.c +@@ -164,6 +164,8 @@ void watchdog_unregister_governor(struct watchdog_governor *gov) + } + + spin_lock_irq(&pretimeout_lock); ++ if (default_gov == gov) ++ default_gov = NULL; + list_for_each_entry(p, &pretimeout_list, entry) + if (p->wdd->gov == gov) + p->wdd->gov = default_gov; +-- +2.53.0 + diff --git a/queue-5.10/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch b/queue-5.10/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch new file mode 100644 index 0000000000..0adfa0fad2 --- /dev/null +++ b/queue-5.10/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch @@ -0,0 +1,48 @@ +From 776d0a602a13dd42fabb6c4b26f1832027a1fba7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 May 2026 11:42:52 +0000 +Subject: wifi: ath11k: fix potential buffer underflow in + ath11k_hal_rx_msdu_list_get() + +From: Dmitry Morgun + +[ Upstream commit 7f11e70629650ff6ea140984e5ce188b775b2683 ] + +When the first entry in msdu_details has a zero buffer address, +the code accesses msdu_details[i - 1] with i == 0, causing a +buffer underflow. + +Fix similarly to ath12k_wifi7_hal_rx_msdu_list_get() by adding +a separate check for i == 0 before the main condition to prevent +the out-of-bounds access. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Dmitry Morgun +Reviewed-by: Rameshkumar Sundaram +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20260530114252.42615-1-d.morgun@ispras.ru +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 720c94806e1a18..54edf4a61c61aa 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -4441,6 +4441,9 @@ static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar, + msdu_details = &msdu_link->msdu_link[0]; + + for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) { ++ if (!i && FIELD_GET(BUFFER_ADDR_INFO0_ADDR, ++ msdu_details[i].buf_addr_info.info0) == 0) ++ break; + if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR, + msdu_details[i].buf_addr_info.info0) == 0) { + msdu_desc_info = &msdu_details[i - 1].rx_msdu_info; +-- +2.53.0 + diff --git a/queue-5.10/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch b/queue-5.10/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch new file mode 100644 index 0000000000..197be77c2c --- /dev/null +++ b/queue-5.10/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch @@ -0,0 +1,49 @@ +From c10c1b098c1d8dffddf8838c738cfa8dd01bc981 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:50:08 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware IE lengths in connect event + +From: Tristan Madani + +[ Upstream commit 6b47b29730de3232b919d8362749f6814c5f2a33 ] + +The firmware-controlled beacon_ie_len, assoc_req_len, and assoc_resp_len +fields in ath6kl_wmi_connect_event_rx() are not validated against the +buffer length. Their sum (up to 765) can exceed the actual WMI event +data, causing out-of-bounds reads during IE parsing and state corruption +of wmi->is_wmm_enabled. + +Add a check that the total IE length fits within the buffer. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20260421135009.348084-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index b64e0034d69f01..7aa4de770f6637 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -874,6 +874,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, + + ev = (struct wmi_connect_event *) datap; + ++ if (len < sizeof(*ev) + ev->beacon_ie_len + ++ ev->assoc_req_len + ev->assoc_resp_len) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, ++ "connect event: IE lengths %u+%u+%u exceed buffer %d\n", ++ ev->beacon_ie_len, ev->assoc_req_len, ++ ev->assoc_resp_len, len); ++ return -EINVAL; ++ } + if (vif->nw_type == AP_NETWORK) { + /* AP mode start/STA connected event */ + struct net_device *dev = vif->ndev; +-- +2.53.0 + diff --git a/queue-5.10/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch b/queue-5.10/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch new file mode 100644 index 0000000000..3e7a4a1ed3 --- /dev/null +++ b/queue-5.10/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch @@ -0,0 +1,53 @@ +From a040da3b5db594ca53c164f8d681aef543e08b54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jun 2026 23:29:07 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware num_msg in TX complete + handler + +From: Tristan Madani + +[ Upstream commit 3a21c89215cc18f1a97c5e5bfd1da6d4f3d44495 ] + +The firmware-controlled num_msg field (u8, 0-255) drives the loop in +ath6kl_wmi_tx_complete_event_rx() without validation against the buffer +length. This allows out-of-bounds reads of up to 1020 bytes past the +WMI event buffer when the firmware sends an inflated num_msg. + +Add a check that the buffer is large enough to hold the fixed struct +and the num_msg variable-length entries. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Link: https://patch.msgid.link/20260625232907.3620746-1-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index 5bacddee834491..b64e0034d69f01 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -484,6 +484,18 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) + + evt = (struct wmi_tx_complete_event *) datap; + ++ if (len < sizeof(*evt)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d\n", ++ len); ++ return -EINVAL; ++ } ++ ++ if (len < sizeof(*evt) + evt->num_msg * sizeof(struct tx_complete_msg_v1)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d for %u msgs\n", ++ len, evt->num_msg); ++ return -EINVAL; ++ } ++ + ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", + evt->num_msg, evt->msg_len, evt->msg_type); + +-- +2.53.0 + diff --git a/queue-5.10/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch b/queue-5.10/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch new file mode 100644 index 0000000000..8d21dbbedb --- /dev/null +++ b/queue-5.10/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch @@ -0,0 +1,90 @@ +From d26daa1315513245e8fae1fe668c51a73d426b24 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 08:32:10 -0700 +Subject: wifi: ath9k: hif_usb: don't dereference hif_dev after re-arming + firmware request +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Cheng Yongkang + +[ Upstream commit dad9f96945d77ecd4708f730c06ef54dcd8cc057 ] + +ath9k_hif_request_firmware() re-arms an asynchronous firmware load via +request_firmware_nowait(), passing hif_dev as the completion context, and +then still dereferences hif_dev: + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", + hif_dev->fw_name); + +The re-armed callback ath9k_hif_usb_firmware_cb() runs on the "events" +workqueue and, when the firmware is missing, walks the retry chain into +ath9k_hif_usb_firmware_fail() -> complete_all(&hif_dev->fw_done). That +releases the wait_for_completion(&hif_dev->fw_done) in a concurrent +ath9k_hif_usb_disconnect(), which then kfree()s hif_dev. The trailing +dev_info() in the frame that re-armed the request can therefore read freed +memory (hif_dev->udev, the first field of struct hif_device_usb): + + BUG: KASAN: slab-use-after-free in ath9k_hif_request_firmware + Read of size 8 ... by task kworker/... + ath9k_hif_request_firmware + ath9k_hif_usb_firmware_cb drivers/net/wireless/ath/ath9k/hif_usb.c:1247 + request_firmware_work_func + Allocated by ...: + ath9k_hif_usb_probe drivers/net/wireless/ath/ath9k/hif_usb.c + Freed by ...: + ath9k_hif_usb_disconnect -> kfree drivers/net/wireless/ath/ath9k/hif_usb.c + +The fw_done barrier only makes disconnect wait for the firmware chain to +*terminate*; it does not protect the outer ath9k_hif_request_firmware() +frame that re-armed the request and keeps touching hif_dev afterwards. + +Drop the post-request dev_info(): it is the only use of hif_dev after the +async request is armed, and it is purely informational (the dev_err() on the +failure path runs only when request_firmware_nowait() did not arm a callback, +so hif_dev is still alive there). + +This was first reported by syzbot as a single, non-reproduced crash that was +later auto-obsoleted, and was independently rediscovered by the reFuzz fuzzer, +which produced a C reproducer (USB-gadget connect/disconnect of an ath9k_htc +device whose firmware download fails). The vulnerable code is unchanged and +still present in v7.1-rc6, where the slab-use-after-free reproduces under KASAN +once the (sub-microsecond) race window is widened. + +Fixes: e904cf6fe230 ("ath9k_htc: introduce support for different fw versions") +Reported-by: syzbot+50122cbc2874b1eb25b0@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=50122cbc2874b1eb25b0 +Signed-off-by: Cheng Yongkang +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260605153210.20471-1-1020691186@qq.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index 6c73c0c0b82a99..7650f14dca8dad 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -1227,15 +1227,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, + ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, + &hif_dev->udev->dev, GFP_KERNEL, + hif_dev, ath9k_hif_usb_firmware_cb); +- if (ret) { ++ if (ret) + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Async request for firmware %s failed\n", + hif_dev->fw_name); +- return ret; +- } +- +- dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", +- hif_dev->fw_name); + + return ret; + } +-- +2.53.0 + diff --git a/queue-5.10/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch b/queue-5.10/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch new file mode 100644 index 0000000000..d353f26f98 --- /dev/null +++ b/queue-5.10/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch @@ -0,0 +1,69 @@ +From 10da4272eb92d4a4a9b21753979e97e923087101 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 May 2026 16:38:59 +0800 +Subject: wifi: brcmfmac: fix 802.1X-SHA256 call trace warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Shelley Yang + +[ Upstream commit 7cb34f6c4fe8a68af621d870abe63bfca2275dd6 ] + +Based on wpa_auth as 1x_256 mode, need to set up +"use_fwsup" with BRCMF_PROFILE_FWSUP_1X. +Or it will happen trace warning when call brcmf_cfg80211_set_pmk(). + +[ 4481.831101] ------------[ cut here ]------------ +[ 4481.831102] WARNING: CPU: 1 PID: 2997 at +drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:7242 brcmf_cfg80211_set_pmk+0x77/0xd0 [brcmfmac] +[...] +[ 4481.831202] Call Trace: +[ 4481.831204]   +[ 4481.831205]  nl80211_set_pmk+0x183/0x250 [cfg80211] +[ 4481.831233]  genl_family_rcv_msg_doit+0xea/0x150 +[ 4481.831237]  genl_rcv_msg+0x104/0x240 +[ 4481.831239]  ? cfg80211_probe_status+0x2c0/0x2c0 [cfg80211] +[ 4481.831257]  ? genl_family_rcv_msg_doit+0x150/0x150 +[ 4481.831259]  netlink_rcv_skb+0x4e/0x100 +[ 4481.831261]  genl_rcv+0x24/0x40 +[ 4481.831262]  netlink_unicast+0x236/0x380 +[ 4481.831264]  netlink_sendmsg+0x250/0x4b0 +[ 4481.831266]  sock_sendmsg+0x5c/0x70 +[ 4481.831269]  ____sys_sendmsg+0x236/0x2b0 +[ 4481.831271]  ? copy_msghdr_from_user+0x6d/0xa0 +[ 4481.831272]  ___sys_sendmsg+0x86/0xd0 +[ 4481.831274]  ? avc_has_perm+0x8c/0x1a0 +[ 4481.831276]  ? preempt_count_add+0x6a/0xa0 +[ 4481.831279]  ? sock_has_perm+0x82/0xa0 +[ 4481.831280]  __sys_sendmsg+0x57/0xa0 +[ 4481.831282]  do_syscall_64+0x38/0x90 +[ 4481.831284]  entry_SYSCALL_64_after_hwframe+0x63/0xcd +[ 4481.831286] RIP: 0033:0x7fd270d369b4 + +Fixes: 2526ff21aa77 ("brcmfmac: support 4-way handshake offloading for 802.1X") +Signed-off-by: Shelley Yang +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260525083859.581246-1-shelley.yang@infineon.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 4434e9a7eba055..3f6d4299965b26 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -1790,7 +1790,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) + sme->crypto.cipher_group); + return -EINVAL; + } +- } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { ++ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_1X_SHA256)) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + val = WPA2_AUTH_UNSPECIFIED; +-- +2.53.0 + diff --git a/queue-5.10/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch b/queue-5.10/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch new file mode 100644 index 0000000000..f208461988 --- /dev/null +++ b/queue-5.10/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch @@ -0,0 +1,48 @@ +From 37c4bffffe03c87e70f3d642cc377224704ef5fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:26 +0000 +Subject: wifi: carl9170: bound memcpy length in cmd callback to prevent OOB + read + +From: Tristan Madani + +[ Upstream commit 4cde55b2feff9504d1f993ab80e84e7ccb62791c ] + +When the firmware sends a command response with a length mismatch, +carl9170_cmd_callback() logs the mismatch and calls carl9170_restart() +but then falls through to memcpy(ar->readbuf, buffer + 4, len - 4). +Since len comes from the firmware and can exceed ar->readlen, this +copies more data than the readbuf was allocated for. + +Bound the memcpy to min(len - 4, ar->readlen) so that the response +is still completed -- avoiding repeated restarts from queued garbage -- +while preventing an overread past the response buffer. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-2-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 908c4c8b7f8256..9a25c2a540b95f 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -150,7 +150,8 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) + spin_lock(&ar->cmd_lock); + if (ar->readbuf) { + if (len >= 4) +- memcpy(ar->readbuf, buffer + 4, len - 4); ++ memcpy(ar->readbuf, buffer + 4, ++ min_t(u32, len - 4, ar->readlen)); + + ar->readbuf = NULL; + } +-- +2.53.0 + diff --git a/queue-5.10/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch b/queue-5.10/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch new file mode 100644 index 0000000000..0240e3a719 --- /dev/null +++ b/queue-5.10/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch @@ -0,0 +1,46 @@ +From c952539e53cb7f422e99fe9d5a9a258d3cf7b5d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:28 +0000 +Subject: wifi: carl9170: fix buffer overflow in rx_stream failover path + +From: Tristan Madani + +[ Upstream commit a1a21995c2e1cc2ca6b2226cfe4f5f018370182a ] + +The failover continuation in carl9170_rx_stream() copies the full tlen +from the second USB transfer instead of capping at rx_failover_missing +bytes. When both transfers are near maximum size, the total exceeds the +65535-byte failover SKB, triggering skb_over_panic. + +Limit the copy size to the missing byte count. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-4-tristmd@gmail.com +[Fix checkpatch CHECK:PARENTHESIS_ALIGNMENT] +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 9a25c2a540b95f..bda30b1f940459 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -918,7 +918,9 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) + } + } + +- skb_put_data(ar->rx_failover, tbuf, tlen); ++ skb_put_data(ar->rx_failover, tbuf, ++ min_t(unsigned int, tlen, ++ ar->rx_failover_missing)); + ar->rx_failover_missing -= tlen; + + if (ar->rx_failover_missing <= 0) { +-- +2.53.0 + diff --git a/queue-5.10/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch b/queue-5.10/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch new file mode 100644 index 0000000000..852d1be09f --- /dev/null +++ b/queue-5.10/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch @@ -0,0 +1,42 @@ +From 733332effe4062dd209f3dfa049ce23be9607fa9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:27 +0000 +Subject: wifi: carl9170: fix OOB read from off-by-two in TX status handler + +From: Tristan Madani + +[ Upstream commit a3f42f1049ad80c65560d2b078ad426c3134f78d ] + +The bounds check in carl9170_tx_process_status() uses +`i > ((cmd->hdr.len / 2) + 1)` which is off by two, allowing +2 extra iterations past valid _tx_status entries when the firmware- +controlled hdr.ext exceeds hdr.len/2. Fix by using the correct +comparison `i >= (cmd->hdr.len / 2)`. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c +index 43050dc7b98dfd..743c088dffb098 100644 +--- a/drivers/net/wireless/ath/carl9170/tx.c ++++ b/drivers/net/wireless/ath/carl9170/tx.c +@@ -692,7 +692,7 @@ void carl9170_tx_process_status(struct ar9170 *ar, + unsigned int i; + + for (i = 0; i < cmd->hdr.ext; i++) { +- if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) { ++ if (WARN_ON(i >= (cmd->hdr.len / 2))) { + print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE, + (void *) cmd, cmd->hdr.len + 4); + break; +-- +2.53.0 + diff --git a/queue-5.10/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch b/queue-5.10/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch new file mode 100644 index 0000000000..3bd20c02c3 --- /dev/null +++ b/queue-5.10/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch @@ -0,0 +1,56 @@ +From 27e6ee1343c953ba6fe7ed4054be761386f5a13d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:17:51 +1000 +Subject: wifi: mac80211: recalculate TIM when a station enters power save + +From: Andrew Pope + +[ Upstream commit a007a384c9eb17610f53a53e2f59944c31f1565a ] + +When an AP buffers frames for a station on its per-station TXQs and the +station subsequently enters power save, sta_ps_start() records the +buffered TIDs in txq_buffered_tids but does not update the TIM. The +station's TIM bit is only ever set when a further frame is buffered +while the station is already asleep +(ieee80211_tx_h_unicast_ps_buf() -> sta_info_recalc_tim()). + +If no further downlink frame arrives for that station the beacon +TIM never advertises the buffered traffic. A station relying on the +TIM then remains in doze indefinitely on top of a non-empty queue. Its +TXQs were removed from the scheduler's active list at PS entry, nothing +pages it, and the flow deadlocks until an unrelated event wakes the +station. + +Recalculate the TIM at the end of sta_ps_start(), so traffic +already buffered at PS entry is advertised immediately. +sta_info_recalc_tim() already consults txq_buffered_tids, which is +updated above, and is safe in this context (it is already called +from equivalent paths such as the tx handlers and +ieee80211_handle_filtered_frame()). + +Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation") +Signed-off-by: Andrew Pope +Link: https://patch.msgid.link/20260717011751.79524-1-andrew.pope@morsemicro.com +[add wifi: subject prefix] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 8f497fe234edb2..8ec630a4d069e3 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1585,6 +1585,8 @@ static void sta_ps_start(struct sta_info *sta) + else + clear_bit(tid, &sta->txq_buffered_tids); + } ++ ++ sta_info_recalc_tim(sta); + } + + static void sta_ps_end(struct sta_info *sta) +-- +2.53.0 + diff --git a/queue-5.10/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch b/queue-5.10/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch new file mode 100644 index 0000000000..fd9ea04e3e --- /dev/null +++ b/queue-5.10/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch @@ -0,0 +1,104 @@ +From 30b92dc53ee14286008d1085458a59a22d07861b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 22:57:11 +0900 +Subject: wifi: mwifiex: bound uAP association event IEs to the event buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit f0858bfc7d3cab411a447b88e3ef970e575032c9 ] + +mwifiex_process_uap_event() handles EVENT_UAP_STA_ASSOC by exposing the +(re)association request IEs that the firmware copies into the event: + + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - (u8 *)&event->frame_control; + sinfo->assoc_req_ies_len = le16_to_cpu(event->len) - (u16)len; + +event->len is supplied by the device firmware and is never validated, +and the subtraction is unchecked. assoc_req_ies points into +adapter->event_body[MAX_EVENT_SIZE], a fixed-size array embedded in the +kmalloc()'d struct mwifiex_adapter. + +On the ap_11n_enabled path mwifiex_set_sta_ht_cap() walks these IEs with +cfg80211_find_ie(), whose for_each_element() loop dereferences each +element header. A firmware-reported event->len larger than the bytes +actually received makes assoc_req_ies_len describe IEs that extend past +event_body, so the walk reads out of the adapter slab object, a +slab-out-of-bounds read (KASAN: slab-out-of-bounds in cfg80211_find_ie). +An event->len smaller than the header instead makes the int subtraction +negative, which wraps to a huge size_t when stored in assoc_req_ies_len. +The same length is handed to cfg80211_new_sta(), so a more modest +over-claim can also copy stale event_body bytes into the +NL80211_CMD_NEW_STATION notification. + +A malicious or malfunctioning mwifiex device (USB/SDIO/PCIe) can deliver +such an event while the interface is in AP/uAP mode. + +Validate event->len before use: reject a length that underflows the +header or that would place the IEs outside the event_body[] buffer the +event was copied into. event->len here is struct mwifiex_assoc_event.len, +a payload field internal to this event, not the transport frame length, +so it is validated in this handler rather than at the generic +MWIFIEX_TYPE_EVENT receive path, which only sees the event cause and the +transport frame length. The bound is against event_body[MAX_EVENT_SIZE] +rather than the actually-received length because the transports store the +event differently (USB and SDIO leave the 4-byte event header in +event_skb, PCIe strips it via skb_pull), whereas event_body is the single +fixed buffer all of them copy the event into. This is the event-path +analogue of the receive-path bounds checks added in commit 119585281617 +("wifi: mwifiex: Fix OOB and integer underflow when rx packets"). + +Fixes: e568634ae7ac ("mwifiex: add AP event handling framework") +Signed-off-by: HE WEI (ギカク) +Reviewed-by: Francesco Dolcini +Link: https://patch.msgid.link/20260715135711.34688-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + .../net/wireless/marvell/mwifiex/uap_event.c | 24 +++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c +index 9121447e270184..eebfc0eaf9056f 100644 +--- a/drivers/net/wireless/marvell/mwifiex/uap_event.c ++++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c +@@ -135,11 +135,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) + len = ETH_ALEN; + + if (len != -1) { ++ u16 evt_len = le16_to_cpu(event->len); ++ + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - + (u8 *)&event->frame_control; +- sinfo->assoc_req_ies_len = +- le16_to_cpu(event->len) - (u16)len; ++ ++ /* ++ * event->len is reported by the device firmware ++ * and is not otherwise validated. Reject a ++ * length that underflows the header, or that ++ * would place the association request IEs ++ * outside the fixed-size event_body[] buffer the ++ * event was copied into; otherwise the IE walk ++ * in mwifiex_set_sta_ht_cap() reads past ++ * event_body and out of the adapter slab object. ++ */ ++ if (evt_len < len || ++ (u8 *)&event->frame_control + evt_len > ++ adapter->event_body + MAX_EVENT_SIZE) { ++ mwifiex_dbg(adapter, ERROR, ++ "invalid STA assoc event length\n"); ++ kfree(sinfo); ++ return -1; ++ } ++ sinfo->assoc_req_ies_len = evt_len - (u16)len; + } + } + cfg80211_new_sta(priv->netdev, event->sta_addr, sinfo, +-- +2.53.0 + diff --git a/queue-5.15/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch b/queue-5.15/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch new file mode 100644 index 0000000000..5c369e7bf9 --- /dev/null +++ b/queue-5.15/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch @@ -0,0 +1,58 @@ +From f9a80b4ea51553aab02673d63a30937cc40432e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 15:20:06 +0530 +Subject: amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN + +From: Prashanth Kumar KR + +[ Upstream commit 4bf22afe53a1de4b44b04cf677fd5199089cbdff ] + +MAC_AUTO_SW (VR_MII_DIG_CTRL1 bit 9) enables automatic XPCS speed +mode switching after CL37 auto-negotiation and is only meaningful in +SGMII MAC mode. The original code unconditionally set this bit on +every call to xgbe_an37_set(), including when called from +xgbe_an37_disable() with enable=false. This left MAC_AUTO_SW=1 after +AN was disabled, causing the XPCS to autonomously switch speed from +stale AN state during subsequent mode changes, breaking SGMII speed +negotiation on 1G copper SFP modules. + +Patrick: This was breaking negotiation for all 1G SFP modules, +not just copper modules. + +Fixes: 42fd432fe6d3 ("amd-xgbe: align CL37 AN sequence as per databook") +Reported-by: Patrick Oppenlander +Link: https://lore.kernel.org/netdev/CAEg67GmFS0Q4oSZkz8zWdOzckSth9_vBPiOy6a7-d697C2w2Xg@mail.gmail.com +Signed-off-by: Prashanth Kumar KR +Tested-by: Patrick Oppenlander +Link: https://patch.msgid.link/20260709095006.3683940-1-prashanthkumar.k.r@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index ebb8b3e5b9a882..01c37ffc9ceb81 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -364,9 +364,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, + + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); + +- reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); +- reg |= XGBE_VEND2_MAC_AUTO_SW; +- XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ if (pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) { ++ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); ++ if (enable) ++ reg |= XGBE_VEND2_MAC_AUTO_SW; ++ else ++ reg &= ~XGBE_VEND2_MAC_AUTO_SW; ++ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ } + } + + static void xgbe_an37_restart(struct xgbe_prv_data *pdata) +-- +2.53.0 + diff --git a/queue-5.15/asoc-bt-sco-fix-bt-sco-pcm-wb-dai-widget-don-t-conne.patch b/queue-5.15/asoc-bt-sco-fix-bt-sco-pcm-wb-dai-widget-don-t-conne.patch new file mode 100644 index 0000000000..345580d9c0 --- /dev/null +++ b/queue-5.15/asoc-bt-sco-fix-bt-sco-pcm-wb-dai-widget-don-t-conne.patch @@ -0,0 +1,50 @@ +From d092dc624e01c838db97ea3abfabfc6bb1754421 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Mar 2022 09:35:33 +0800 +Subject: ASoC: bt-sco: fix bt-sco-pcm-wb dai widget don't connect to the + endpoint + +From: Jiaxin Yu + +[ Upstream commit 8f2b025abc31bc15d38657d1286d7470bbbd5efa ] + +This patch fix the second dai driver's dai widget can't connect to the +endpoint. Because "bt-sco-pcm" and "bt-sco-pcm-wb" dai driver have the +same stream_name, so it will cause they have the same widget name. +Therefor it will just create only one route when do snd_soc_dapm_add_route +that only find the widget through the widget name. + +Signed-off-by: Jiaxin Yu +Link: https://lore.kernel.org/r/20220302013533.29068-1-jiaxin.yu@mediatek.com +Signed-off-by: Mark Brown +Stable-dep-of: 0b604e886ece ("ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/bt-sco.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c +index 4d286844e3c832..cf17b9741bd832 100644 +--- a/sound/soc/codecs/bt-sco.c ++++ b/sound/soc/codecs/bt-sco.c +@@ -13,11 +13,15 @@ + static const struct snd_soc_dapm_widget bt_sco_widgets[] = { + SND_SOC_DAPM_INPUT("RX"), + SND_SOC_DAPM_OUTPUT("TX"), ++ SND_SOC_DAPM_AIF_IN("BT_SCO_RX", "Playback", 0, ++ SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0, ++ SND_SOC_NOPM, 0, 0), + }; + + static const struct snd_soc_dapm_route bt_sco_routes[] = { +- { "Capture", NULL, "RX" }, +- { "TX", NULL, "Playback" }, ++ { "BT_SCO_TX", NULL, "RX" }, ++ { "TX", NULL, "BT_SCO_RX" }, + }; + + static struct snd_soc_dai_driver bt_sco_dai[] = { +-- +2.53.0 + diff --git a/queue-5.15/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch b/queue-5.15/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch new file mode 100644 index 0000000000..ecb3352218 --- /dev/null +++ b/queue-5.15/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch @@ -0,0 +1,72 @@ +From 9dbf92f715cb6e484ee787d0c660572c5b2dd75e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 18:06:20 +0800 +Subject: ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI + +From: Shengjiu Wang + +[ Upstream commit 0b604e886ece11b71c4daaeccc512c784b89b014 ] + +The bt-sco-pcm-wb DAI uses the same stream_name strings as bt-sco-pcm +("Playback" and "Capture"). This causes duplicate DAPM AIF widget +names within the same component, leading to debugfs warnings: + + debugfs: 'Playback' already exists in 'dapm' + debugfs: 'Capture' already exists in 'dapm' + +Give the wideband DAI distinct stream names ("WB Playback" and +"WB Capture") and add corresponding DAPM AIF widgets and routes for +them. + +Fixes: 5947e1b4992e ("ASoC: bt-sco: extend rate and add a general compatible string") +Assisted-by: VeroCoder:claude-sonnet-4-5 +Signed-off-by: Shengjiu Wang +Link: https://patch.msgid.link/20260715100620.1387159-1-shengjiu.wang@oss.nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/bt-sco.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c +index cf17b9741bd832..7c42fcdee27bb7 100644 +--- a/sound/soc/codecs/bt-sco.c ++++ b/sound/soc/codecs/bt-sco.c +@@ -17,11 +17,17 @@ static const struct snd_soc_dapm_widget bt_sco_widgets[] = { + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0, + SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_IN("BT_SCO_RX_WB", "WB Playback", 0, ++ SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("BT_SCO_TX_WB", "WB Capture", 0, ++ SND_SOC_NOPM, 0, 0), + }; + + static const struct snd_soc_dapm_route bt_sco_routes[] = { + { "BT_SCO_TX", NULL, "RX" }, + { "TX", NULL, "BT_SCO_RX" }, ++ { "BT_SCO_TX_WB", NULL, "RX" }, ++ { "TX", NULL, "BT_SCO_RX_WB" }, + }; + + static struct snd_soc_dai_driver bt_sco_dai[] = { +@@ -45,14 +51,14 @@ static struct snd_soc_dai_driver bt_sco_dai[] = { + { + .name = "bt-sco-pcm-wb", + .playback = { +- .stream_name = "Playback", ++ .stream_name = "WB Playback", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { +- .stream_name = "Capture", ++ .stream_name = "WB Capture", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, +-- +2.53.0 + diff --git a/queue-5.15/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch b/queue-5.15/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch new file mode 100644 index 0000000000..4e290b918e --- /dev/null +++ b/queue-5.15/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch @@ -0,0 +1,79 @@ +From ce8dd4c0ef6cf27fb42aaa6f15c42b6d7e4b5e7d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jul 2026 18:38:56 +0800 +Subject: bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() + +From: Chengfeng Ye + +[ Upstream commit 2d66a033864e27ab8d5e44cb36f31d9d2413bee4 ] + +tcp_bpf_sendmsg() keeps msg_tx across sk_stream_wait_memory(), which +drops and reacquires the socket lock. Its error path tries to decide +whether msg_tx names the local temporary message by comparing it with +the current value of psock->cork. + +This comparison is unsafe when two threads send on the same socket: + + Thread A Thread B + msg_tx = psock->cork + sk_msg_alloc() fails + sk_stream_wait_memory() + releases the socket lock acquires the socket lock + completes the cork + psock->cork = NULL + frees the cork + reacquires the socket lock + msg_tx != psock->cork + sk_msg_free(msg_tx) + +The stale cork is therefore mistaken for the local temporary message +and freed again. KASAN reported: + + BUG: KASAN: slab-use-after-free in sk_msg_free+0x49/0x50 + Read of size 4 at addr ffff88810c908800 by task poc/90 + Call Trace: + sk_msg_free+0x49/0x50 + tcp_bpf_sendmsg+0x14f5/0x1cc0 + __sys_sendto+0x32c/0x3a0 + __x64_sys_sendto+0xdb/0x1b0 + Allocated by task 89: + __kasan_kmalloc+0x8f/0xa0 + tcp_bpf_sendmsg+0x16b3/0x1cc0 + Freed by task 91: + __kasan_slab_free+0x43/0x70 + kfree+0x131/0x3c0 + tcp_bpf_sendmsg+0xec3/0x1cc0 + +msg_tx can only name the stack-local tmp or the shared cork. Check for +tmp directly so a changed psock->cork cannot turn a shared message into +an apparent local one. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Chengfeng Ye +Reviewed-by: Emil Tsalapatis +Reviewed-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/87fr18lmzo.fsf%40cloudflare.com/ +Link: https://lore.kernel.org/netdev/20260719161630.2901208-1-nicoyip.dev%40gmail.com/ [v1] +Link: https://patch.msgid.link/20260724103856.3399001-1-nicoyip.dev@gmail.com +Signed-off-by: Eduard Zingerman +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 11cb3a353cc6dd..f94b8d4ba23a36 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -525,7 +525,7 @@ static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + wait_for_memory: + err = sk_stream_wait_memory(sk, &timeo); + if (err) { +- if (msg_tx && msg_tx != psock->cork) ++ if (msg_tx == &tmp) + sk_msg_free(sk, msg_tx); + goto out_err; + } +-- +2.53.0 + diff --git a/queue-5.15/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch b/queue-5.15/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch new file mode 100644 index 0000000000..6a210b8544 --- /dev/null +++ b/queue-5.15/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch @@ -0,0 +1,47 @@ +From 588d1150f8f8f766d98a0154f541ddbb33d73c7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 03:17:28 +0000 +Subject: btrfs: free mapping node on duplicate reloc root insert + +From: Guanghui Yang <3497809730@qq.com> + +[ Upstream commit 6a8269b6459ed870a8156c106a0f597383907872 ] + +__add_reloc_root() allocates a mapping_node before inserting it into +rc->reloc_root_tree. If rb_simple_insert() finds an existing entry, it +returns the existing rb_node and leaves the newly allocated node unlinked. + +The error path then returns -EEXIST without freeing the new node. Since +the node was never inserted into reloc_root_tree, the later cleanup in +put_reloc_control() cannot find it either. + +Free the newly allocated node before returning -EEXIST. + +The callers currently assert that -EEXIST should not happen, so this is a +defensive cleanup for an unexpected duplicate insert path. If the path is +ever reached, the local allocation should still be released. + +Fixes: 57a304cfd43b ("btrfs: do not panic in __add_reloc_root") +Reviewed-by: Qu Wenruo +Signed-off-by: Guanghui Yang <3497809730@qq.com> +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 2c4130c3120175..06cf9468340176 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -642,6 +642,7 @@ static int __must_check __add_reloc_root(struct btrfs_root *root) + btrfs_err(fs_info, + "Duplicate root found for start=%llu while inserting into relocation tree", + node->bytenr); ++ kfree(node); + return -EEXIST; + } + +-- +2.53.0 + diff --git a/queue-5.15/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch b/queue-5.15/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..31c6733025 --- /dev/null +++ b/queue-5.15/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,48 @@ +From b15b91facf411b72ee0b11498a555d98600868eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:17:37 +0800 +Subject: dpaa2-eth: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit b4b201cc93ff70150853aba03e14d314d1980ca0 ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The Ethernet connect path stores that +device in mac->mc_dev and keeps it for the lifetime of the connected MAC +object. + +However, the disconnect path only disconnects and closes the MAC before +freeing the dpaa2_mac object. It does not drop the endpoint device +reference stored in mac->mc_dev, so every successful connect leaks that +device reference when the MAC is later disconnected. + +Drop the endpoint device reference after closing the MAC and before +freeing the dpaa2_mac object. + +Fixes: 719479230893 ("dpaa2-eth: add MAC/PHY support through phylink") +Signed-off-by: Guangshuo Li +Reviewed-by: Ioana Ciornei +Reviewed-by: Ioana Ciornei +Link: https://patch.msgid.link/20260708111738.750391-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index c6f20ceadede31..b21be20dcf8513 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -4284,6 +4284,7 @@ static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-5.15/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch b/queue-5.15/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..9fe2e8f3bd --- /dev/null +++ b/queue-5.15/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,46 @@ +From 7fe601f8f8de927457a65567babf30f189e9ef5f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:10:25 +0800 +Subject: dpaa2-switch: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit 4c1eabbef7a1707635652e956e39db1269c3af2b ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The switch port connect path stores +that device in mac->mc_dev and keeps it for the lifetime of the connected +MAC object. + +However, the disconnect path only closes the MAC and frees the dpaa2_mac +object. It does not drop the endpoint device reference stored in +mac->mc_dev, so every successful connect leaks that device reference when +the MAC is later disconnected. + +Drop the endpoint device reference before freeing the dpaa2_mac object. + +Fixes: 84cba72956fd ("dpaa2-switch: integrate the MAC endpoint support") +Signed-off-by: Guangshuo Li +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708111025.749311-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +index ea93144d24931b..4d596af27dc0f1 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +@@ -1510,6 +1510,7 @@ static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-5.15/firewire-net-fix-fragmented-datagram-reassembly.patch b/queue-5.15/firewire-net-fix-fragmented-datagram-reassembly.patch new file mode 100644 index 0000000000..99b7c83077 --- /dev/null +++ b/queue-5.15/firewire-net-fix-fragmented-datagram-reassembly.patch @@ -0,0 +1,99 @@ +From 65409c1a1f29b5f0dc0d864720681b39bfc21c76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 23:04:54 +0800 +Subject: firewire: net: Fix fragmented datagram reassembly + +From: Ruoyu Wang + +[ Upstream commit d52a13adbb8ccbab99cd3bad36804e87d8b5c052 ] + +fwnet_frag_new() keeps a sorted list of received fragments for a partial +datagram. When a new fragment is adjacent to an existing fragment, the +code checks whether the new fragment also closes the gap to the next or +previous list entry. + +Those neighbor lookups currently assume that the current fragment always +has a real next or previous fragment. At a list edge, the next or +previous entry is the list head, not a struct fwnet_fragment_info. + +The gap checks also compare against the old edge of the current fragment +instead of the edge after adding the new fragment. As a result, a +fragment that bridges two existing ranges may leave two adjacent ranges +unmerged, so fwnet_pd_is_complete() can miss a complete datagram. + +Check for the list head before looking up the neighboring fragment, and +compare the neighbor against the new fragment's far edge when deciding +whether to merge all three ranges. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: c76acec6d551 ("firewire: add IPv4 support") +Signed-off-by: Ruoyu Wang +Link: https://lore.kernel.org/r/20260707150454.2265951-1-ruoyuw560@gmail.com +Signed-off-by: Takashi Sakamoto +Signed-off-by: Sasha Levin +--- + drivers/firewire/net.c | 39 +++++++++++++++++++++------------------ + 1 file changed, 21 insertions(+), 18 deletions(-) + +diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c +index beba0a56bb9aea..b9bbfd308dc51d 100644 +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -306,31 +306,34 @@ static struct fwnet_fragment_info *fwnet_frag_new( + if (fi->offset + fi->len == offset) { + /* The new fragment can be tacked on to the end */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.next, +- struct fwnet_fragment_info, fi_link); +- if (fi->offset + fi->len == fi2->offset) { +- /* glue fragments together */ +- fi->len += len + fi2->len; +- list_del(&fi2->fi_link); +- kfree(fi2); +- } else { +- fi->len += len; ++ if (!list_is_last(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_next_entry(fi, fi_link); ++ if (offset + len == fi2->offset) { ++ /* glue fragments together */ ++ fi->len += len + fi2->len; ++ list_del(&fi2->fi_link); ++ kfree(fi2); ++ ++ return fi; ++ } + } ++ fi->len += len; + + return fi; + } + if (offset + len == fi->offset) { + /* The new fragment can be tacked on to the beginning */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.prev, +- struct fwnet_fragment_info, fi_link); +- if (fi2->offset + fi2->len == fi->offset) { +- /* glue fragments together */ +- fi2->len += fi->len + len; +- list_del(&fi->fi_link); +- kfree(fi); +- +- return fi2; ++ if (!list_is_first(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_prev_entry(fi, fi_link); ++ if (fi2->offset + fi2->len == offset) { ++ /* glue fragments together */ ++ fi2->len += fi->len + len; ++ list_del(&fi->fi_link); ++ kfree(fi); ++ ++ return fi2; ++ } + } + fi->offset = offset; + fi->len += len; +-- +2.53.0 + diff --git a/queue-5.15/hinic-remove-unused-ethtool-rss-user-configuration-b.patch b/queue-5.15/hinic-remove-unused-ethtool-rss-user-configuration-b.patch new file mode 100644 index 0000000000..35799a753d --- /dev/null +++ b/queue-5.15/hinic-remove-unused-ethtool-rss-user-configuration-b.patch @@ -0,0 +1,83 @@ +From 317b92d9a1fb5492467c78d028823dea61ab63d1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:53:53 +0800 +Subject: hinic: remove unused ethtool RSS user configuration buffers + +From: Chenguang Zhao + +[ Upstream commit fe0c002928c6749b7f4a726f6f600f6dd70280ea ] + +rss_indir_user and rss_hkey_user are allocated and filled in +__set_rss_rxfh() when the user configures RSS via ethtool, but +nothing ever reads them. hinic_get_rxfh() fetches the state from +the device, and the hardware is programmed from the original +indir/key arguments. These buffers only leaked on driver unload. + +Drop the unused allocations, memcpys, and struct fields. + +Fixes: 4fdc51bb4e92 ("hinic: add support for rss parameters with ethtool") +Signed-off-by: Chenguang Zhao +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260722025353.328179-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/huawei/hinic/hinic_dev.h | 2 -- + .../net/ethernet/huawei/hinic/hinic_ethtool.c | 21 ------------------- + 2 files changed, 23 deletions(-) + +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +index a4fbf44f944cd3..46b24f3c5e168d 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h ++++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +@@ -100,8 +100,6 @@ struct hinic_dev { + u16 num_rss; + u16 rss_limit; + struct hinic_rss_type rss_type; +- u8 *rss_hkey_user; +- s32 *rss_indir_user; + struct hinic_intr_coal_info *rx_intr_coalesce; + struct hinic_intr_coal_info *tx_intr_coalesce; + struct hinic_sriov_info sriov_info; +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +index b431c300ef1b9d..2ed258558b2bd1 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c ++++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +@@ -1060,17 +1060,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + int err; + + if (indir) { +- if (!nic_dev->rss_indir_user) { +- nic_dev->rss_indir_user = +- kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE, +- GFP_KERNEL); +- if (!nic_dev->rss_indir_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_indir_user, indir, +- sizeof(u32) * HINIC_RSS_INDIR_SIZE); +- + err = hinic_rss_set_indir_tbl(nic_dev, + nic_dev->rss_tmpl_idx, indir); + if (err) +@@ -1078,16 +1067,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + } + + if (key) { +- if (!nic_dev->rss_hkey_user) { +- nic_dev->rss_hkey_user = +- kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL); +- +- if (!nic_dev->rss_hkey_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE); +- + err = hinic_rss_set_template_tbl(nic_dev, + nic_dev->rss_tmpl_idx, key); + if (err) +-- +2.53.0 + diff --git a/queue-5.15/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch b/queue-5.15/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch new file mode 100644 index 0000000000..3b96a80c3d --- /dev/null +++ b/queue-5.15/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch @@ -0,0 +1,41 @@ +From 06fb419be674e5e3cc3cb1367b8134c9d00aa2a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 17:52:54 -0700 +Subject: hwmon: (corsair-cpro) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 94c87871b051d7ad758828a805215a2ec194512a ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 40c3a44542257 ("hwmon: add Corsair Commander Pro driver") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-cpro.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c +index 18da3e013c20b7..62f9372f2d3551 100644 +--- a/drivers/hwmon/corsair-cpro.c ++++ b/drivers/hwmon/corsair-cpro.c +@@ -558,6 +558,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) + + out_hw_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-5.15/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch b/queue-5.15/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..baddbc5f20 --- /dev/null +++ b/queue-5.15/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,89 @@ +From acaa81d329a1fc1d52b5b67ce7d8b4c0852a4dd1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Apr 2026 12:12:26 +0800 +Subject: hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop + +From: Edward Adam Davis + +[ Upstream commit 9ab8656548cd737b98d0b19c4253aff8d68e97f4 ] + +hid_hw_stop() does not stop the device IO. + +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +corsairpsu_probe(). If the probe operation fails after "io start" has +been initiated, this race condition will result in a uaf vulnerability +[1]. + +CPU0 CPU1 +==== ==== +corsairpsu_probe() + hid_device_io_start() + ... unlock driver_input_lock + hid_hw_stop() + kfree(hidraw) __hid_input_report() + ... acquire driver_input_lock + hid_report_raw_event() + hidraw_report_event() + ... access hidraw's list_lock // trigger uaf + +Consequently, when corsairpsu_probe() fails and hid_hw_stop() needs to +be executed, the io_started flag is first cleared while holding the +driver_input_lock to prevent potential race conditions involving input +reports. + +[1] +BUG: KASAN: slab-use-after-free in rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56 +Call Trace: + hidraw_report_event+0x5d/0x3a0 drivers/hid/hidraw.c:577 + hid_report_raw_event+0x311/0x1730 drivers/hid/hid-core.c:2076 + __hid_input_report drivers/hid/hid-core.c:2152 [inline] + hid_input_report+0x44e/0x580 drivers/hid/hid-core.c:2174 + hid_irq_in+0x47e/0x6d0 drivers/hid/usbhid/hid-core.c:286 + __usb_hcd_giveback_urb+0x3b3/0x5e0 drivers/usb/core/hcd.c:1657 + dummy_timer+0x8a9/0x47d0 drivers/usb/gadget/udc/dummy_hcd.c:2005 + +Allocated by task 10: + hidraw_connect+0x57/0x430 drivers/hid/hidraw.c:606 + hid_connect+0x5bf/0x19d0 drivers/hid/hid-core.c:2277 + hid_hw_start+0xa8/0x120 drivers/hid/hid-core.c:2387 + corsairpsu_probe+0xd9/0x3c0 drivers/hwmon/corsair-psu.c:782 + +Freed by task 10: + hidraw_disconnect+0x4f/0x60 drivers/hid/hidraw.c:662 + hid_disconnect drivers/hid/hid-core.c:2362 [inline] + hid_hw_stop+0x101/0x1e0 drivers/hid/hid-core.c:2407 + corsairpsu_probe+0x327/0x3c0 drivers/hwmon/corsair-psu.c:826 + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Fixes: d115b51e0e56 ("hwmon: add Corsair PSU HID controller driver") +Reported-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9eebf5f6544c5e873858 +Tested-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Link: https://lore.kernel.org/r/tencent_BB7C33EB9EA41B7B4B5F1B8B25C0BA13BB08@qq.com +[groeck: Updated subject and description; + call hid_device_io_stop() only if IO has been started] +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-psu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c +index e3a46e5369c46e..e9518221efc4c9 100644 +--- a/drivers/hwmon/corsair-psu.c ++++ b/drivers/hwmon/corsair-psu.c +@@ -742,6 +742,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id + + fail_and_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + fail_and_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-5.15/hwmon-occ-add-sysfs-entries-for-additional-extended-.patch b/queue-5.15/hwmon-occ-add-sysfs-entries-for-additional-extended-.patch new file mode 100644 index 0000000000..bb8d015351 --- /dev/null +++ b/queue-5.15/hwmon-occ-add-sysfs-entries-for-additional-extended-.patch @@ -0,0 +1,89 @@ +From 125c9633b37907f3bc08ec3fac7b7e20ca6242ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Feb 2022 09:10:21 -0600 +Subject: hwmon: (occ) Add sysfs entries for additional extended status bits + +From: Eddie James + +[ Upstream commit a03d8969887325167d5fe47ead99d280bbbc6b06 ] + +Add sysfs entries for DVFS due to a VRM Vdd over-temperature condition, +and add the GPU throttling condition bits (such that if bit 1 is set, +GPU1 is throttling). + +Signed-off-by: Eddie James +Reviewed-by: Joel Stanley +Link: https://lore.kernel.org/r/20220215151022.7498-4-eajames@linux.ibm.com +Signed-off-by: Guenter Roeck +Stable-dep-of: 70e76e700fc6 ("hwmon: occ: validate poll response sensor blocks") +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/sysfs.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/drivers/hwmon/occ/sysfs.c b/drivers/hwmon/occ/sysfs.c +index 88f655887c958d..b2f788a7774693 100644 +--- a/drivers/hwmon/occ/sysfs.c ++++ b/drivers/hwmon/occ/sysfs.c +@@ -19,6 +19,8 @@ + #define OCC_EXT_STAT_DVFS_POWER BIT(6) + #define OCC_EXT_STAT_MEM_THROTTLE BIT(5) + #define OCC_EXT_STAT_QUICK_DROP BIT(4) ++#define OCC_EXT_STAT_DVFS_VDD BIT(3) ++#define OCC_EXT_STAT_GPU_THROTTLE GENMASK(2, 0) + + static ssize_t occ_sysfs_show(struct device *dev, + struct device_attribute *attr, char *buf) +@@ -69,6 +71,12 @@ static ssize_t occ_sysfs_show(struct device *dev, + case 9: + val = header->mode; + break; ++ case 10: ++ val = !!(header->ext_status & OCC_EXT_STAT_DVFS_VDD); ++ break; ++ case 11: ++ val = header->ext_status & OCC_EXT_STAT_GPU_THROTTLE; ++ break; + default: + return -EINVAL; + } +@@ -96,6 +104,8 @@ static SENSOR_DEVICE_ATTR(occ_state, 0444, occ_sysfs_show, NULL, 6); + static SENSOR_DEVICE_ATTR(occs_present, 0444, occ_sysfs_show, NULL, 7); + static SENSOR_DEVICE_ATTR(occ_ips_status, 0444, occ_sysfs_show, NULL, 8); + static SENSOR_DEVICE_ATTR(occ_mode, 0444, occ_sysfs_show, NULL, 9); ++static SENSOR_DEVICE_ATTR(occ_dvfs_vdd, 0444, occ_sysfs_show, NULL, 10); ++static SENSOR_DEVICE_ATTR(occ_gpu_throttle, 0444, occ_sysfs_show, NULL, 11); + static DEVICE_ATTR_RO(occ_error); + + static struct attribute *occ_attributes[] = { +@@ -109,6 +119,8 @@ static struct attribute *occ_attributes[] = { + &sensor_dev_attr_occs_present.dev_attr.attr, + &sensor_dev_attr_occ_ips_status.dev_attr.attr, + &sensor_dev_attr_occ_mode.dev_attr.attr, ++ &sensor_dev_attr_occ_dvfs_vdd.dev_attr.attr, ++ &sensor_dev_attr_occ_gpu_throttle.dev_attr.attr, + &dev_attr_occ_error.attr, + NULL + }; +@@ -166,6 +178,18 @@ void occ_sysfs_poll_done(struct occ *occ) + sysfs_notify(&occ->bus_dev->kobj, NULL, name); + } + ++ if ((header->ext_status & OCC_EXT_STAT_DVFS_VDD) != ++ (occ->prev_ext_stat & OCC_EXT_STAT_DVFS_VDD)) { ++ name = sensor_dev_attr_occ_dvfs_vdd.dev_attr.attr.name; ++ sysfs_notify(&occ->bus_dev->kobj, NULL, name); ++ } ++ ++ if ((header->ext_status & OCC_EXT_STAT_GPU_THROTTLE) != ++ (occ->prev_ext_stat & OCC_EXT_STAT_GPU_THROTTLE)) { ++ name = sensor_dev_attr_occ_gpu_throttle.dev_attr.attr.name; ++ sysfs_notify(&occ->bus_dev->kobj, NULL, name); ++ } ++ + if ((header->status & OCC_STAT_MASTER) && + header->occs_present != occ->prev_occs_present) { + name = sensor_dev_attr_occs_present.dev_attr.attr.name; +-- +2.53.0 + diff --git a/queue-5.15/hwmon-occ-add-sysfs-entry-for-ips-idle-power-saver-s.patch b/queue-5.15/hwmon-occ-add-sysfs-entry-for-ips-idle-power-saver-s.patch new file mode 100644 index 0000000000..ec1cc17461 --- /dev/null +++ b/queue-5.15/hwmon-occ-add-sysfs-entry-for-ips-idle-power-saver-s.patch @@ -0,0 +1,89 @@ +From 0f020a75d22bd0d1eb5688d840aee665baafba91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Feb 2022 09:10:19 -0600 +Subject: hwmon: (occ) Add sysfs entry for IPS (Idle Power Saver) status + +From: Eddie James + +[ Upstream commit 6109c3e1905c3f8d0a3909c5f6a9ad5186822b2b ] + +BMC control applications need to check the Idle Power Saver status +byte returned by the OCC poll response, so export it in sysfs with +the other OCC-specific data. + +Signed-off-by: Eddie James +Reviewed-by: Joel Stanley +Link: https://lore.kernel.org/r/20220215151022.7498-2-eajames@linux.ibm.com +Signed-off-by: Guenter Roeck +Stable-dep-of: 70e76e700fc6 ("hwmon: occ: validate poll response sensor blocks") +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/common.h | 1 + + drivers/hwmon/occ/sysfs.c | 11 +++++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h +index 7abf191020628e..ad7d169b517cf3 100644 +--- a/drivers/hwmon/occ/common.h ++++ b/drivers/hwmon/occ/common.h +@@ -120,6 +120,7 @@ struct occ { + u8 prev_stat; + u8 prev_ext_stat; + u8 prev_occs_present; ++ u8 prev_ips_status; + }; + + int occ_setup(struct occ *occ, const char *name); +diff --git a/drivers/hwmon/occ/sysfs.c b/drivers/hwmon/occ/sysfs.c +index 03b16abef67fd3..6dc69c9aa4c290 100644 +--- a/drivers/hwmon/occ/sysfs.c ++++ b/drivers/hwmon/occ/sysfs.c +@@ -63,6 +63,9 @@ static ssize_t occ_sysfs_show(struct device *dev, + else + val = 1; + break; ++ case 8: ++ val = header->ips_status; ++ break; + default: + return -EINVAL; + } +@@ -88,6 +91,7 @@ static SENSOR_DEVICE_ATTR(occ_mem_throttle, 0444, occ_sysfs_show, NULL, 4); + static SENSOR_DEVICE_ATTR(occ_quick_pwr_drop, 0444, occ_sysfs_show, NULL, 5); + static SENSOR_DEVICE_ATTR(occ_state, 0444, occ_sysfs_show, NULL, 6); + static SENSOR_DEVICE_ATTR(occs_present, 0444, occ_sysfs_show, NULL, 7); ++static SENSOR_DEVICE_ATTR(occ_ips_status, 0444, occ_sysfs_show, NULL, 8); + static DEVICE_ATTR_RO(occ_error); + + static struct attribute *occ_attributes[] = { +@@ -99,6 +103,7 @@ static struct attribute *occ_attributes[] = { + &sensor_dev_attr_occ_quick_pwr_drop.dev_attr.attr, + &sensor_dev_attr_occ_state.dev_attr.attr, + &sensor_dev_attr_occs_present.dev_attr.attr, ++ &sensor_dev_attr_occ_ips_status.dev_attr.attr, + &dev_attr_occ_error.attr, + NULL + }; +@@ -162,6 +167,11 @@ void occ_sysfs_poll_done(struct occ *occ) + sysfs_notify(&occ->bus_dev->kobj, NULL, name); + } + ++ if (header->ips_status != occ->prev_ips_status) { ++ name = sensor_dev_attr_occ_ips_status.dev_attr.attr.name; ++ sysfs_notify(&occ->bus_dev->kobj, NULL, name); ++ } ++ + if (occ->error && occ->error != occ->prev_error) { + name = dev_attr_occ_error.attr.name; + sysfs_notify(&occ->bus_dev->kobj, NULL, name); +@@ -174,6 +184,7 @@ void occ_sysfs_poll_done(struct occ *occ) + occ->prev_stat = header->status; + occ->prev_ext_stat = header->ext_status; + occ->prev_occs_present = header->occs_present; ++ occ->prev_ips_status = header->ips_status; + } + + int occ_setup_sysfs(struct occ *occ) +-- +2.53.0 + diff --git a/queue-5.15/hwmon-occ-add-sysfs-entry-for-occ-mode.patch b/queue-5.15/hwmon-occ-add-sysfs-entry-for-occ-mode.patch new file mode 100644 index 0000000000..c539075c61 --- /dev/null +++ b/queue-5.15/hwmon-occ-add-sysfs-entry-for-occ-mode.patch @@ -0,0 +1,89 @@ +From a2d0da7f80fcec1d95643b78f61eda35ae9e0bfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 15 Feb 2022 09:10:20 -0600 +Subject: hwmon: (occ) Add sysfs entry for OCC mode + +From: Eddie James + +[ Upstream commit a25126fc32890a2a03ba5ddd1189aa8a4bcf4591 ] + +BMC control applications need to check the OCC mode returned by the +OCC poll response, so export it in sysfs with the other OCC-specific +data. + +Signed-off-by: Eddie James +Reviewed-by: Joel Stanley +Link: https://lore.kernel.org/r/20220215151022.7498-3-eajames@linux.ibm.com +Signed-off-by: Guenter Roeck +Stable-dep-of: 70e76e700fc6 ("hwmon: occ: validate poll response sensor blocks") +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/common.h | 1 + + drivers/hwmon/occ/sysfs.c | 11 +++++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h +index ad7d169b517cf3..726943af9a077e 100644 +--- a/drivers/hwmon/occ/common.h ++++ b/drivers/hwmon/occ/common.h +@@ -121,6 +121,7 @@ struct occ { + u8 prev_ext_stat; + u8 prev_occs_present; + u8 prev_ips_status; ++ u8 prev_mode; + }; + + int occ_setup(struct occ *occ, const char *name); +diff --git a/drivers/hwmon/occ/sysfs.c b/drivers/hwmon/occ/sysfs.c +index 6dc69c9aa4c290..88f655887c958d 100644 +--- a/drivers/hwmon/occ/sysfs.c ++++ b/drivers/hwmon/occ/sysfs.c +@@ -66,6 +66,9 @@ static ssize_t occ_sysfs_show(struct device *dev, + case 8: + val = header->ips_status; + break; ++ case 9: ++ val = header->mode; ++ break; + default: + return -EINVAL; + } +@@ -92,6 +95,7 @@ static SENSOR_DEVICE_ATTR(occ_quick_pwr_drop, 0444, occ_sysfs_show, NULL, 5); + static SENSOR_DEVICE_ATTR(occ_state, 0444, occ_sysfs_show, NULL, 6); + static SENSOR_DEVICE_ATTR(occs_present, 0444, occ_sysfs_show, NULL, 7); + static SENSOR_DEVICE_ATTR(occ_ips_status, 0444, occ_sysfs_show, NULL, 8); ++static SENSOR_DEVICE_ATTR(occ_mode, 0444, occ_sysfs_show, NULL, 9); + static DEVICE_ATTR_RO(occ_error); + + static struct attribute *occ_attributes[] = { +@@ -104,6 +108,7 @@ static struct attribute *occ_attributes[] = { + &sensor_dev_attr_occ_state.dev_attr.attr, + &sensor_dev_attr_occs_present.dev_attr.attr, + &sensor_dev_attr_occ_ips_status.dev_attr.attr, ++ &sensor_dev_attr_occ_mode.dev_attr.attr, + &dev_attr_occ_error.attr, + NULL + }; +@@ -172,6 +177,11 @@ void occ_sysfs_poll_done(struct occ *occ) + sysfs_notify(&occ->bus_dev->kobj, NULL, name); + } + ++ if (header->mode != occ->prev_mode) { ++ name = sensor_dev_attr_occ_mode.dev_attr.attr.name; ++ sysfs_notify(&occ->bus_dev->kobj, NULL, name); ++ } ++ + if (occ->error && occ->error != occ->prev_error) { + name = dev_attr_occ_error.attr.name; + sysfs_notify(&occ->bus_dev->kobj, NULL, name); +@@ -185,6 +195,7 @@ void occ_sysfs_poll_done(struct occ *occ) + occ->prev_ext_stat = header->ext_status; + occ->prev_occs_present = header->occs_present; + occ->prev_ips_status = header->ips_status; ++ occ->prev_mode = header->mode; + } + + int occ_setup_sysfs(struct occ *occ) +-- +2.53.0 + diff --git a/queue-5.15/hwmon-occ-delay-hwmon-registration-until-user-reques.patch b/queue-5.15/hwmon-occ-delay-hwmon-registration-until-user-reques.patch new file mode 100644 index 0000000000..69ae78544a --- /dev/null +++ b/queue-5.15/hwmon-occ-delay-hwmon-registration-until-user-reques.patch @@ -0,0 +1,408 @@ +From bc5453f1135c909368a0a5ecae710363a9981680 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Apr 2022 09:04:43 -0500 +Subject: hwmon: (occ) Delay hwmon registration until user request + +From: Eddie James + +[ Upstream commit 849b0156d9960da628a06756bb920d9571c15e66 ] + +Instead of registering the hwmon device at probe time, use the +existing "occ_active" sysfs file to control when the driver polls +the OCC for sensor data and registers with hwmon. The reason for +this change is that the SBE, which is the device by which the +driver communicates with the OCC, cannot handle communications +during certain system state transitions, resulting in +unrecoverable system errors. + +Signed-off-by: Eddie James +Link: https://lore.kernel.org/r/20220427140443.11428-1-eajames@linux.ibm.com +Signed-off-by: Guenter Roeck +Stable-dep-of: 70e76e700fc6 ("hwmon: occ: validate poll response sensor blocks") +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/common.c | 100 +++++++++++++++++++-------- + drivers/hwmon/occ/common.h | 5 +- + drivers/hwmon/occ/p8_i2c.c | 2 +- + drivers/hwmon/occ/p9_sbe.c | 2 +- + drivers/hwmon/occ/sysfs.c | 137 ++++++++++++++++++++++--------------- + 5 files changed, 156 insertions(+), 90 deletions(-) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index dff19885851220..e0ab04b1d92ca5 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -1106,44 +1106,75 @@ static void occ_parse_poll_response(struct occ *occ) + sizeof(*header), size + sizeof(*header)); + } + +-int occ_setup(struct occ *occ, const char *name) ++int occ_active(struct occ *occ, bool active) + { +- int rc; +- +- mutex_init(&occ->lock); +- occ->groups[0] = &occ->group; ++ int rc = mutex_lock_interruptible(&occ->lock); + +- /* no need to lock */ +- rc = occ_poll(occ); +- if (rc == -ESHUTDOWN) { +- dev_info(occ->bus_dev, "host is not ready\n"); +- return rc; +- } else if (rc < 0) { +- dev_err(occ->bus_dev, +- "failed to get OCC poll response=%02x: %d\n", +- occ->resp.return_status, rc); ++ if (rc) + return rc; +- } + +- occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; +- occ_parse_poll_response(occ); ++ if (active) { ++ if (occ->active) { ++ rc = -EALREADY; ++ goto unlock; ++ } + +- rc = occ_setup_sensor_attrs(occ); +- if (rc) { +- dev_err(occ->bus_dev, "failed to setup sensor attrs: %d\n", +- rc); +- return rc; +- } ++ occ->error_count = 0; ++ occ->last_safe = 0; + +- occ->hwmon = devm_hwmon_device_register_with_groups(occ->bus_dev, name, +- occ, occ->groups); +- if (IS_ERR(occ->hwmon)) { +- rc = PTR_ERR(occ->hwmon); +- dev_err(occ->bus_dev, "failed to register hwmon device: %d\n", +- rc); +- return rc; ++ rc = occ_poll(occ); ++ if (rc < 0) { ++ dev_err(occ->bus_dev, ++ "failed to get OCC poll response=%02x: %d\n", ++ occ->resp.return_status, rc); ++ goto unlock; ++ } ++ ++ occ->active = true; ++ occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; ++ occ_parse_poll_response(occ); ++ ++ rc = occ_setup_sensor_attrs(occ); ++ if (rc) { ++ dev_err(occ->bus_dev, ++ "failed to setup sensor attrs: %d\n", rc); ++ goto unlock; ++ } ++ ++ occ->hwmon = hwmon_device_register_with_groups(occ->bus_dev, ++ "occ", occ, ++ occ->groups); ++ if (IS_ERR(occ->hwmon)) { ++ rc = PTR_ERR(occ->hwmon); ++ occ->hwmon = NULL; ++ dev_err(occ->bus_dev, ++ "failed to register hwmon device: %d\n", rc); ++ goto unlock; ++ } ++ } else { ++ if (!occ->active) { ++ rc = -EALREADY; ++ goto unlock; ++ } ++ ++ if (occ->hwmon) ++ hwmon_device_unregister(occ->hwmon); ++ occ->active = false; ++ occ->hwmon = NULL; + } + ++unlock: ++ mutex_unlock(&occ->lock); ++ return rc; ++} ++ ++int occ_setup(struct occ *occ) ++{ ++ int rc; ++ ++ mutex_init(&occ->lock); ++ occ->groups[0] = &occ->group; ++ + rc = occ_setup_sysfs(occ); + if (rc) + dev_err(occ->bus_dev, "failed to setup sysfs: %d\n", rc); +@@ -1152,6 +1183,15 @@ int occ_setup(struct occ *occ, const char *name) + } + EXPORT_SYMBOL_GPL(occ_setup); + ++void occ_shutdown(struct occ *occ) ++{ ++ occ_shutdown_sysfs(occ); ++ ++ if (occ->hwmon) ++ hwmon_device_unregister(occ->hwmon); ++} ++EXPORT_SYMBOL_GPL(occ_shutdown); ++ + MODULE_AUTHOR("Eddie James "); + MODULE_DESCRIPTION("Common OCC hwmon code"); + MODULE_LICENSE("GPL"); +diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h +index 726943af9a077e..7ac4b2febce65f 100644 +--- a/drivers/hwmon/occ/common.h ++++ b/drivers/hwmon/occ/common.h +@@ -107,6 +107,7 @@ struct occ { + struct attribute_group group; + const struct attribute_group *groups[2]; + ++ bool active; + int error; /* final transfer error after retry */ + int last_error; /* latest transfer error */ + unsigned int error_count; /* number of xfr errors observed */ +@@ -124,9 +125,11 @@ struct occ { + u8 prev_mode; + }; + +-int occ_setup(struct occ *occ, const char *name); ++int occ_active(struct occ *occ, bool active); ++int occ_setup(struct occ *occ); + int occ_setup_sysfs(struct occ *occ); + void occ_shutdown(struct occ *occ); ++void occ_shutdown_sysfs(struct occ *occ); + void occ_sysfs_poll_done(struct occ *occ); + int occ_update_response(struct occ *occ); + +diff --git a/drivers/hwmon/occ/p8_i2c.c b/drivers/hwmon/occ/p8_i2c.c +index c35c07964d856c..b221be1f35f31e 100644 +--- a/drivers/hwmon/occ/p8_i2c.c ++++ b/drivers/hwmon/occ/p8_i2c.c +@@ -224,7 +224,7 @@ static int p8_i2c_occ_probe(struct i2c_client *client) + occ->poll_cmd_data = 0x10; /* P8 OCC poll data */ + occ->send_cmd = p8_i2c_occ_send_cmd; + +- return occ_setup(occ, "p8_occ"); ++ return occ_setup(occ); + } + + static int p8_i2c_occ_remove(struct i2c_client *client) +diff --git a/drivers/hwmon/occ/p9_sbe.c b/drivers/hwmon/occ/p9_sbe.c +index 14923e78e1f324..3c3d887fcc1e04 100644 +--- a/drivers/hwmon/occ/p9_sbe.c ++++ b/drivers/hwmon/occ/p9_sbe.c +@@ -73,7 +73,7 @@ static int p9_sbe_occ_probe(struct platform_device *pdev) + occ->poll_cmd_data = 0x20; /* P9 OCC poll data */ + occ->send_cmd = p9_sbe_occ_send_cmd; + +- rc = occ_setup(occ, "p9_occ"); ++ rc = occ_setup(occ); + if (rc == -ESHUTDOWN) + rc = -ENODEV; /* Host is shutdown, don't spew errors */ + +diff --git a/drivers/hwmon/occ/sysfs.c b/drivers/hwmon/occ/sysfs.c +index b2f788a7774693..2317301fc1e9f6 100644 +--- a/drivers/hwmon/occ/sysfs.c ++++ b/drivers/hwmon/occ/sysfs.c +@@ -6,13 +6,13 @@ + #include + #include + #include ++#include + #include + + #include "common.h" + + /* OCC status register */ + #define OCC_STAT_MASTER BIT(7) +-#define OCC_STAT_ACTIVE BIT(0) + + /* OCC extended status register */ + #define OCC_EXT_STAT_DVFS_OT BIT(7) +@@ -22,6 +22,25 @@ + #define OCC_EXT_STAT_DVFS_VDD BIT(3) + #define OCC_EXT_STAT_GPU_THROTTLE GENMASK(2, 0) + ++static ssize_t occ_active_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ int rc; ++ bool active; ++ struct occ *occ = dev_get_drvdata(dev); ++ ++ rc = kstrtobool(buf, &active); ++ if (rc) ++ return rc; ++ ++ rc = occ_active(occ, active); ++ if (rc) ++ return rc; ++ ++ return count; ++} ++ + static ssize_t occ_sysfs_show(struct device *dev, + struct device_attribute *attr, char *buf) + { +@@ -31,54 +50,64 @@ static ssize_t occ_sysfs_show(struct device *dev, + struct occ_poll_response_header *header; + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + +- rc = occ_update_response(occ); +- if (rc) +- return rc; ++ if (occ->active) { ++ rc = occ_update_response(occ); ++ if (rc) ++ return rc; + +- header = (struct occ_poll_response_header *)occ->resp.data; +- +- switch (sattr->index) { +- case 0: +- val = !!(header->status & OCC_STAT_MASTER); +- break; +- case 1: +- val = !!(header->status & OCC_STAT_ACTIVE); +- break; +- case 2: +- val = !!(header->ext_status & OCC_EXT_STAT_DVFS_OT); +- break; +- case 3: +- val = !!(header->ext_status & OCC_EXT_STAT_DVFS_POWER); +- break; +- case 4: +- val = !!(header->ext_status & OCC_EXT_STAT_MEM_THROTTLE); +- break; +- case 5: +- val = !!(header->ext_status & OCC_EXT_STAT_QUICK_DROP); +- break; +- case 6: +- val = header->occ_state; +- break; +- case 7: +- if (header->status & OCC_STAT_MASTER) +- val = hweight8(header->occs_present); +- else ++ header = (struct occ_poll_response_header *)occ->resp.data; ++ ++ switch (sattr->index) { ++ case 0: ++ val = !!(header->status & OCC_STAT_MASTER); ++ break; ++ case 1: + val = 1; +- break; +- case 8: +- val = header->ips_status; +- break; +- case 9: +- val = header->mode; +- break; +- case 10: +- val = !!(header->ext_status & OCC_EXT_STAT_DVFS_VDD); +- break; +- case 11: +- val = header->ext_status & OCC_EXT_STAT_GPU_THROTTLE; +- break; +- default: +- return -EINVAL; ++ break; ++ case 2: ++ val = !!(header->ext_status & OCC_EXT_STAT_DVFS_OT); ++ break; ++ case 3: ++ val = !!(header->ext_status & OCC_EXT_STAT_DVFS_POWER); ++ break; ++ case 4: ++ val = !!(header->ext_status & ++ OCC_EXT_STAT_MEM_THROTTLE); ++ break; ++ case 5: ++ val = !!(header->ext_status & OCC_EXT_STAT_QUICK_DROP); ++ break; ++ case 6: ++ val = header->occ_state; ++ break; ++ case 7: ++ if (header->status & OCC_STAT_MASTER) ++ val = hweight8(header->occs_present); ++ else ++ val = 1; ++ break; ++ case 8: ++ val = header->ips_status; ++ break; ++ case 9: ++ val = header->mode; ++ break; ++ case 10: ++ val = !!(header->ext_status & OCC_EXT_STAT_DVFS_VDD); ++ break; ++ case 11: ++ val = header->ext_status & OCC_EXT_STAT_GPU_THROTTLE; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } else { ++ if (sattr->index == 1) ++ val = 0; ++ else if (sattr->index <= 11) ++ val = -ENODATA; ++ else ++ return -EINVAL; + } + + return sysfs_emit(buf, "%d\n", val); +@@ -95,7 +124,8 @@ static ssize_t occ_error_show(struct device *dev, + } + + static SENSOR_DEVICE_ATTR(occ_master, 0444, occ_sysfs_show, NULL, 0); +-static SENSOR_DEVICE_ATTR(occ_active, 0444, occ_sysfs_show, NULL, 1); ++static SENSOR_DEVICE_ATTR(occ_active, 0644, occ_sysfs_show, occ_active_store, ++ 1); + static SENSOR_DEVICE_ATTR(occ_dvfs_overtemp, 0444, occ_sysfs_show, NULL, 2); + static SENSOR_DEVICE_ATTR(occ_dvfs_power, 0444, occ_sysfs_show, NULL, 3); + static SENSOR_DEVICE_ATTR(occ_mem_throttle, 0444, occ_sysfs_show, NULL, 4); +@@ -139,7 +169,7 @@ void occ_sysfs_poll_done(struct occ *occ) + * On the first poll response, we haven't yet created the sysfs + * attributes, so don't make any notify calls. + */ +- if (!occ->hwmon) ++ if (!occ->active) + goto done; + + if ((header->status & OCC_STAT_MASTER) != +@@ -148,12 +178,6 @@ void occ_sysfs_poll_done(struct occ *occ) + sysfs_notify(&occ->bus_dev->kobj, NULL, name); + } + +- if ((header->status & OCC_STAT_ACTIVE) != +- (occ->prev_stat & OCC_STAT_ACTIVE)) { +- name = sensor_dev_attr_occ_active.dev_attr.attr.name; +- sysfs_notify(&occ->bus_dev->kobj, NULL, name); +- } +- + if ((header->ext_status & OCC_EXT_STAT_DVFS_OT) != + (occ->prev_ext_stat & OCC_EXT_STAT_DVFS_OT)) { + name = sensor_dev_attr_occ_dvfs_overtemp.dev_attr.attr.name; +@@ -227,8 +251,7 @@ int occ_setup_sysfs(struct occ *occ) + return sysfs_create_group(&occ->bus_dev->kobj, &occ_sysfs); + } + +-void occ_shutdown(struct occ *occ) ++void occ_shutdown_sysfs(struct occ *occ) + { + sysfs_remove_group(&occ->bus_dev->kobj, &occ_sysfs); + } +-EXPORT_SYMBOL_GPL(occ_shutdown); +-- +2.53.0 + diff --git a/queue-5.15/hwmon-occ-validate-poll-response-sensor-blocks.patch b/queue-5.15/hwmon-occ-validate-poll-response-sensor-blocks.patch new file mode 100644 index 0000000000..66cfc683a2 --- /dev/null +++ b/queue-5.15/hwmon-occ-validate-poll-response-sensor-blocks.patch @@ -0,0 +1,118 @@ +From af8c759749bb629438bf9f2848ad23e9c4fd6c96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:58:26 +0800 +Subject: hwmon: occ: validate poll response sensor blocks + +From: Pengpeng Hou + +[ Upstream commit 70e76e700fc6c46afb4e17aec099a1ea089b4a22 ] + +The OCC poll response parser walks a counted list of sensor data blocks. +It used the static backing-array capacity as the parse boundary, but a +transport response makes only data_length bytes current and valid. A +truncated response can therefore make the parser consume a block header or +block extent outside the current response. + +Use data_length as the parent boundary, prove the fixed poll header and +each current block header before reading them, and prove the complete block +before advancing. Keep parsed sensor metadata local until the complete +response has passed validation, then publish it. Propagate +malformed-response errors before publishing the OCC as active. + +Fixes: aa195fe49b03 ("hwmon (occ): Parse OCC poll response") +Signed-off-by: Pengpeng Hou +Link: https://lore.kernel.org/r/20260720115826.14813-1-pengpeng@iscas.ac.cn +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/common.c | 38 ++++++++++++++++++++++++++++++-------- + 1 file changed, 30 insertions(+), 8 deletions(-) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index e0ab04b1d92ca5..86c54b36b7dbf8 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -1049,32 +1049,49 @@ static int occ_setup_sensor_attrs(struct occ *occ) + } + + /* only need to do this once at startup, as OCC won't change sensors on us */ +-static void occ_parse_poll_response(struct occ *occ) ++static int occ_parse_poll_response(struct occ *occ) + { + unsigned int i, old_offset, offset = 0, size = 0; ++ u16 data_length; + struct occ_sensor *sensor; +- struct occ_sensors *sensors = &occ->sensors; ++ struct occ_sensors parsed = {}; ++ struct occ_sensors *sensors = &parsed; + struct occ_response *resp = &occ->resp; + struct occ_poll_response *poll = + (struct occ_poll_response *)&resp->data[0]; + struct occ_poll_response_header *header = &poll->header; + struct occ_sensor_data_block *block = &poll->block; + ++ data_length = get_unaligned_be16(&resp->data_length); ++ if (data_length < sizeof(*header) || data_length > OCC_RESP_DATA_BYTES) { ++ dev_err(occ->bus_dev, "invalid OCC poll response length %u\n", ++ data_length); ++ return -EMSGSIZE; ++ } ++ + dev_info(occ->bus_dev, "OCC found, code level: %.16s\n", + header->occ_code_level); + + for (i = 0; i < header->num_sensor_data_blocks; ++i) { + block = (struct occ_sensor_data_block *)((u8 *)block + offset); ++ if (size + sizeof(*header) + sizeof(block->header) > ++ data_length) { ++ dev_err(occ->bus_dev, ++ "truncated OCC sensor block header\n"); ++ return -EMSGSIZE; ++ } ++ + old_offset = offset; + offset = (block->header.num_sensors * + block->header.sensor_length) + sizeof(block->header); +- size += offset; + + /* validate all the length/size fields */ +- if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) { +- dev_warn(occ->bus_dev, "exceeded response buffer\n"); +- return; ++ if (size + sizeof(*header) + offset > data_length) { ++ dev_err(occ->bus_dev, ++ "exceeded OCC poll response length\n"); ++ return -EMSGSIZE; + } ++ size += offset; + + dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n", + old_offset, offset - 1, block->header.eye_catcher, +@@ -1104,6 +1121,9 @@ static void occ_parse_poll_response(struct occ *occ) + + dev_dbg(occ->bus_dev, "Max resp size: %u+%zd=%zd\n", size, + sizeof(*header), size + sizeof(*header)); ++ occ->sensors = parsed; ++ ++ return 0; + } + + int occ_active(struct occ *occ, bool active) +@@ -1130,10 +1150,12 @@ int occ_active(struct occ *occ, bool active) + goto unlock; + } + +- occ->active = true; + occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; +- occ_parse_poll_response(occ); ++ rc = occ_parse_poll_response(occ); ++ if (rc) ++ goto unlock; + ++ occ->active = true; + rc = occ_setup_sensor_attrs(occ); + if (rc) { + dev_err(occ->bus_dev, +-- +2.53.0 + diff --git a/queue-5.15/iommu-amd-bound-the-early-acpi-hid-map.patch b/queue-5.15/iommu-amd-bound-the-early-acpi-hid-map.patch new file mode 100644 index 0000000000..5657fc5049 --- /dev/null +++ b/queue-5.15/iommu-amd-bound-the-early-acpi-hid-map.patch @@ -0,0 +1,45 @@ +From 6216a48ba82a6f675a4aeb8a3e41042ec9312d43 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:46:13 +0800 +Subject: iommu/amd: Bound the early ACPI HID map + +From: Pengpeng Hou + +[ Upstream commit fb80117fddb5b477218dc99bb53911b72c3847f8 ] + +The ivrs_acpihid command-line parser appends entries to a fixed +four-element early_acpihid_map array. Unlike the sibling IOAPIC and HPET +parsers, it does not reject a fifth entry before incrementing the map size. + +Check the capacity at the common found label before parsing the HID and +UID or writing the entry. + +Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter") +Signed-off-by: Pengpeng Hou +Reviewed-by: Ankit Soni +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/init.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index 065d626d590505..b9754219e5d9df 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -3327,6 +3327,12 @@ static int __init parse_ivrs_acpihid(char *str) + return 1; + + found: ++ if (early_acpihid_map_size == EARLY_MAP_SIZE) { ++ pr_err("Early ACPI HID map overflow - ignoring ivrs_acpihid%s\n", ++ str); ++ return 1; ++ } ++ + p = acpiid; + hid = strsep(&p, ":"); + uid = p; +-- +2.53.0 + diff --git a/queue-5.15/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch b/queue-5.15/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch new file mode 100644 index 0000000000..c79c0e7ba6 --- /dev/null +++ b/queue-5.15/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch @@ -0,0 +1,43 @@ +From 477770aa9c172a01b257f4555b24328ed57f8813 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:34:10 +0800 +Subject: iommu/intel: Fix out-of-bounds memset in dmar_latency_disable() + +From: Li RongQing + +[ Upstream commit 754f8efe45f87e3a9c6871b645b2f9d46d1b407b ] + +dmar_latency_disable() intends to zero out only the single +latency_statistic entry for the given type, but the memset size was +computed as sizeof(*lstat) * DMAR_LATENCY_NUM, which clears the entire +array starting from &lstat[type]. + +When type > 0, this writes beyond the end of the allocated array, +corrupting adjacent memory. + +Fix by using sizeof(*lstat) to clear only the target entry. + +Fixes: 55ee5e67a59a ("iommu/vt-d: Add common code for dmar latency performance monitors") +Signed-off-by: Li RongQing +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/perf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/intel/perf.c b/drivers/iommu/intel/perf.c +index 700eeb07bda0a0..d7b2818649b818 100644 +--- a/drivers/iommu/intel/perf.c ++++ b/drivers/iommu/intel/perf.c +@@ -63,7 +63,7 @@ void dmar_latency_disable(struct intel_iommu *iommu, enum latency_type type) + return; + + spin_lock_irqsave(&latency_lock, flags); +- memset(&lstat[type], 0, sizeof(*lstat) * DMAR_LATENCY_NUM); ++ memset(&lstat[type], 0, sizeof(*lstat)); + spin_unlock_irqrestore(&latency_lock, flags); + } + +-- +2.53.0 + diff --git a/queue-5.15/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch b/queue-5.15/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch new file mode 100644 index 0000000000..b649671a08 --- /dev/null +++ b/queue-5.15/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch @@ -0,0 +1,88 @@ +From 00627a669848b7c114f807de707cdc42541f0f3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:42:36 +0000 +Subject: ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup + +From: Eric Dumazet + +[ Upstream commit 853e164c2b321f0711361bc23505aaeb7dc432c3 ] + +When Linux forwards a packet and needs to generate an ICMP error, +icmp_route_lookup() performs a reverse-path relookup. For non-local +destinations, it performs a decoy lookup to find the expected egress +interface (rt2->dst.dev) before validating the path with ip_route_input(). + +Currently, the decoy flow structure (fl4_2) only sets .daddr = fl4_dec.saddr, +leaving .saddr, .flowi4_dscp, .flowi4_proto, .flowi4_mark, .flowi4_oif, +.fl4_sport, .fl4_dport, and .flowi4_uid zeroed out. + +When policy routing rules (such as ip rule add from $SRC lookup 100, or +dscp/fwmark/ipproto/port rules, or VRF bindings) are configured: +1. The decoy lookup fails to match the policy rule because saddr and other + key flow selectors are missing in fl4_2. +2. It resolves a route using the default table instead, returning an incorrect + egress netdev. +3. Passing the wrong netdev to ip_route_input() causes strict reverse-path + filtering (rp_filter=1) to fail, logging false-positive "martian source" + warnings and causing the relookup to fail. + +Fix this by initializing fl4_2 from fl4_dec and: +- Swapping source/destination IP addresses. +- Swapping L4 ports for transport protocols with ports (TCP, UDP, SCTP, DCCP) + so port-based policy routing matches correctly. Non-port protocols (such as + ICMP or GRE) leave the flowi_uli union fields intact to prevent corruption. +- Setting .flowi4_oif = l3mdev_master_ifindex(route_lookup_dev) to ensure + VRF routing tables are respected. +- Setting .flowi4_flags |= FLOWI_FLAG_ANYSRC to allow output route lookups + for non-local source IP addresses. +- Using __ip_route_output_key() instead of ip_route_output_key() for fl4_2 + so that raw FIB routing is used without triggering spurious XFRM policy + lookups on the decoy flow (the actual XFRM lookup is performed later using + fl4_dec). + +Fixes: 415b3334a21a ("icmp: Fix regression in nexthop resolution during replies.") +Reported-by: Muhammad Ziad +Closes: https://lore.kernel.org/netdev/CAOAwikA60AYKdFr_UDLyja3oU4hqyAE7uFZWqum5uRdaQsgRYg@mail.gmail.com/ +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260722104236.2938082-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index ab631e665e9892..9c363f44a694cd 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -537,11 +537,23 @@ static struct rtable *icmp_route_lookup(struct net *net, + if (IS_ERR(rt2)) + err = PTR_ERR(rt2); + } else { +- struct flowi4 fl4_2 = {}; ++ struct flowi4 fl4_2 = fl4_dec; + unsigned long orefdst; + +- fl4_2.daddr = fl4_dec.saddr; +- rt2 = ip_route_output_key(net, &fl4_2); ++ swap(fl4_2.daddr, fl4_2.saddr); ++ switch (fl4_2.flowi4_proto) { ++ case IPPROTO_TCP: ++ case IPPROTO_UDP: ++ case IPPROTO_SCTP: ++ case IPPROTO_DCCP: ++ swap(fl4_2.fl4_sport, fl4_2.fl4_dport); ++ break; ++ } ++ ++ fl4_2.flowi4_oif = l3mdev_master_ifindex(route_lookup_dev); ++ fl4_2.flowi4_flags |= FLOWI_FLAG_ANYSRC; ++ ++ rt2 = __ip_route_output_key(net, &fl4_2); + if (IS_ERR(rt2)) { + err = PTR_ERR(rt2); + goto relookup_failed; +-- +2.53.0 + diff --git a/queue-5.15/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch b/queue-5.15/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch new file mode 100644 index 0000000000..25df9c6b56 --- /dev/null +++ b/queue-5.15/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch @@ -0,0 +1,149 @@ +From 81ca321417fcff77cb7af23b58b42950c3d92f78 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:09:21 +0300 +Subject: net: bridge: vlan: fix vlan range dumps starting with pvid + +From: Nikolay Aleksandrov + +[ Upstream commit 43171c97e4714bf601b468401b37732244639c21 ] + +There is a bug in all range dumps that rely on br_vlan_can_enter_range() +when the PVID is a range starting VLAN, all following VLANs that match +its flags can enter the range, but when the range is filled in only the +PVID VLAN is dumped and the rest of the range is discarded because +br_vlan_fill_vids() checks for the PVID flag. Since the PVID VLAN can +be only one, we need to break ranges around it, the best way to do that +consistently for all is to alter br_vlan_can_enter_range() to take into +account the PVID and return false to break the range when it's matched. + +Before the fix: +$ ip l add br0 type bridge vlan_filtering 1 +$ ip l add dumdum type dummy +$ ip l set dumdum master br0 +$ ip l set br0 up +$ ip l set dumdum up +$ bridge vlan add dev dumdum vid 1 pvid untagged master +$ bridge vlan add dev dumdum vid 2 untagged master +$ bridge vlan show dev dumdum # use legacy dump to show all vlans +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged + +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + +VLAN 2 is missing, and if there are more matching VLANs afterwards +they'd be missing too. + +After the fix: +[ same setup steps ] +$ bridge vlan show dev dumdum +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + 2 Egress Untagged + state forwarding mcast_router 1 + +Fixes: 0ab558795184 ("net: bridge: vlan: add rtm range support") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260721140922.682265-2-razor@blackwall.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_netlink_tunnel.c | 3 ++- + net/bridge/br_private.h | 6 ++++-- + net/bridge/br_vlan.c | 10 ++++++---- + net/bridge/br_vlan_options.c | 3 +-- + 4 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/net/bridge/br_netlink_tunnel.c b/net/bridge/br_netlink_tunnel.c +index 8914290c75d480..e4aab077527011 100644 +--- a/net/bridge/br_netlink_tunnel.c ++++ b/net/bridge/br_netlink_tunnel.c +@@ -268,7 +268,8 @@ static void __vlan_tunnel_handle_range(const struct net_bridge_port *p, + if (!*v_start) + goto out_init; + +- if (v && curr_change && br_vlan_can_enter_range(v, *v_end)) { ++ if (v && curr_change && ++ br_vlan_can_enter_range(v, *v_end, br_get_pvid(vg))) { + *v_end = v; + return; + } +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index 9a5479868489e9..62fdafbcc7e720 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1475,7 +1475,8 @@ int br_vlan_replay(struct net_device *br_dev, struct net_device *dev, + const void *ctx, bool adding, struct notifier_block *nb, + struct netlink_ext_ack *extack); + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end); ++ const struct net_bridge_vlan *range_end, ++ u16 pvid); + + void br_vlan_fill_forward_path_pvid(struct net_bridge *br, + struct net_device_path_ctx *ctx, +@@ -1715,7 +1716,8 @@ static inline void br_vlan_notify(const struct net_bridge *br, + } + + static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { + return true; + } +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index 055d988d280cd6..5c41c6d00942d4 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1958,9 +1958,11 @@ int br_vlan_replay(struct net_device *br_dev, struct net_device *dev, + + /* check if v_curr can enter a range ending in range_end */ + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { +- return v_curr->vid - range_end->vid == 1 && ++ return v_curr->vid != pvid && range_end->vid != pvid && ++ v_curr->vid - range_end->vid == 1 && + range_end->flags == v_curr->flags && + br_vlan_opts_eq_range(v_curr, range_end); + } +@@ -2042,8 +2044,8 @@ static int br_vlan_dump_dev(const struct net_device *dev, + idx += range_end->vid - range_start->vid + 1; + + range_start = v; +- } else if (dump_stats || v->vid == pvid || +- !br_vlan_can_enter_range(v, range_end)) { ++ } else if (dump_stats || ++ !br_vlan_can_enter_range(v, range_end, pvid)) { + u16 vlan_flags = br_vlan_flags(range_start, pvid); + + if (!br_vlan_fill_vids(skb, range_start->vid, +diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c +index a6382973b3e701..87fe159efcf76e 100644 +--- a/net/bridge/br_vlan_options.c ++++ b/net/bridge/br_vlan_options.c +@@ -262,8 +262,7 @@ int br_vlan_process_options(const struct net_bridge *br, + continue; + } + +- if (v->vid == pvid || +- !br_vlan_can_enter_range(v, curr_end)) { ++ if (!br_vlan_can_enter_range(v, curr_end, pvid)) { + br_vlan_notify(br, p, curr_start->vid, + curr_end->vid, RTM_NEWVLAN); + curr_start = v; +-- +2.53.0 + diff --git a/queue-5.15/net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch b/queue-5.15/net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch new file mode 100644 index 0000000000..54493361ed --- /dev/null +++ b/queue-5.15/net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch @@ -0,0 +1,111 @@ +From 1fdb47dc21f16ea1a86ffc38cd212b0cb86a3b1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 16:12:14 +0200 +Subject: net: dpaa2-eth: assign priv->mac after dpaa2_mac_connect() call + +From: Vladimir Oltean + +[ Upstream commit 02d61948e8daf3844d0af41ba5d563ef03cc7c4f ] + +There are 2 requirements for correct code: + +- Any time the driver accesses the priv->mac pointer at runtime, it + either holds NULL to indicate a DPNI-DPNI connection (or unconnected + DPNI), or a struct dpaa2_mac whose phylink instance was fully + initialized (created and connected to the PHY). No changes are made to + priv->mac while it is being used. Currently, rtnl_lock() watches over + the call to dpaa2_eth_connect_mac(), so it serves the purpose of + serializing this with all readers of priv->mac. + +- dpaa2_mac_connect() should run unlocked, because inside it are 2 + phylink calls with incompatible locking requirements: phylink_create() + requires that the rtnl_mutex isn't held, and phylink_fwnode_phy_connect() + requires that the rtnl_mutex is held. The only way to solve those + contradictory requirements is to let dpaa2_mac_connect() take + rtnl_lock() when it needs to. + +To solve both requirements, we need to identify the writer side of the +priv->mac pointer, which can be wrapped in a mutex private to the driver +in a future patch. The dpaa2_mac_connect() cannot be part of the writer +side critical section, because of an AB/BA deadlock with rtnl_lock(). + +So the strategy needs to be that where we prepare the DPMAC by calling +dpaa2_mac_connect(), and only make priv->mac point to it once it's fully +prepared. This ensures that the writer side critical section has the +absolute minimum surface it can. + +The reverse strategy is adopted in the dpaa2_eth_disconnect_mac() code +path. This makes sure that priv->mac is NULL when we start tearing down +the DPMAC that we disconnected from, and concurrent code will simply not +see it. + +No locking changes in this patch (concurrent code is still blocked by +the rtnl_mutex). + +Signed-off-by: Vladimir Oltean +Reviewed-by: Ioana Ciornei +Tested-by: Ioana Ciornei +Signed-off-by: Paolo Abeni +Stable-dep-of: b4b201cc93ff ("dpaa2-eth: put MAC endpoint device on disconnect") +Signed-off-by: Sasha Levin +--- + .../net/ethernet/freescale/dpaa2/dpaa2-eth.c | 21 +++++++++++-------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index 0439bf465fa5bd..c6f20ceadede31 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -4248,9 +4248,8 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv) + err = dpaa2_mac_open(mac); + if (err) + goto err_free_mac; +- priv->mac = mac; + +- if (dpaa2_eth_is_type_phy(priv)) { ++ if (dpaa2_mac_is_type_phy(mac)) { + err = dpaa2_mac_connect(mac); + if (err && err != -EPROBE_DEFER) + netdev_err(priv->net_dev, "Error connecting to the MAC endpoint: %pe", +@@ -4259,11 +4258,12 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv) + goto err_close_mac; + } + ++ priv->mac = mac; ++ + return 0; + + err_close_mac: + dpaa2_mac_close(mac); +- priv->mac = NULL; + err_free_mac: + kfree(mac); + out_put_device: +@@ -4273,15 +4273,18 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv) + + static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) + { +- if (dpaa2_eth_is_type_phy(priv)) +- dpaa2_mac_disconnect(priv->mac); ++ struct dpaa2_mac *mac = priv->mac; + +- if (!dpaa2_eth_has_mac(priv)) ++ priv->mac = NULL; ++ ++ if (!mac) + return; + +- dpaa2_mac_close(priv->mac); +- kfree(priv->mac); +- priv->mac = NULL; ++ if (dpaa2_mac_is_type_phy(mac)) ++ dpaa2_mac_disconnect(mac); ++ ++ dpaa2_mac_close(mac); ++ kfree(mac); + } + + static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg) +-- +2.53.0 + diff --git a/queue-5.15/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch b/queue-5.15/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch new file mode 100644 index 0000000000..50ed36a635 --- /dev/null +++ b/queue-5.15/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch @@ -0,0 +1,56 @@ +From 4bdc08bf14e3c2a8806b0610f69a038fa8a42a58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 10:12:40 +0000 +Subject: net: hsr: fix memory leak on slave unregistration by removing synced + VLANs + +From: Eric Dumazet + +[ Upstream commit dcf15eaf5641812f1cfc5e96537380132a7da89d ] + +When an HSR master device is brought UP, it auto-adds VLAN 0 via +vlan_vid0_add(), which propagates VID 0 to its slave devices (slave A and B). + +If a slave device is later unregistered while HSR is active (e.g., during +netns cleanup or interface destruction), hsr_del_port() is called to +detach the slave port from the HSR master. However, hsr_del_port() currently +does not delete the VLAN IDs that were synced to the slave device by HSR. + +As a result, the slave device retains a refcount on VID 0 (and any other +synced VLANs). When the slave device is destroyed, its vlan_info / +vlan_vid_info structure remains allocated, leading to a memory leak. + +Fix this by calling vlan_vids_del_by_dev(port->dev, master->dev) in +hsr_del_port() before unlinking slave A or slave B ports, matching the +propagation logic in hsr_ndo_vlan_rx_add_vid() / hsr_ndo_vlan_rx_kill_vid() +and the cleanup behavior in bonding and team drivers. + +Fixes: 1a8a63a5305e ("net: hsr: Add VLAN CTAG filter support") +Reported-by: syzbot+456957213f32970c0762@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/6a4cb6ca.57639fcc.86d58.000b.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Fernando Fernandez Mancera +Reviewed-by: Felix Maurer +Link: https://patch.msgid.link/20260721101240.995597-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_slave.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c +index b8230faa567f77..58e757dc555461 100644 +--- a/net/hsr/hsr_slave.c ++++ b/net/hsr/hsr_slave.c +@@ -228,6 +228,8 @@ void hsr_del_port(struct hsr_port *port) + netdev_rx_handler_unregister(port->dev); + if (!port->hsr->fwd_offloaded) + dev_set_promiscuity(port->dev, -1); ++ if (port->type == HSR_PT_SLAVE_A || port->type == HSR_PT_SLAVE_B) ++ vlan_vids_del_by_dev(port->dev, master->dev); + netdev_upper_dev_unlink(port->dev, master->dev); + } + +-- +2.53.0 + diff --git a/queue-5.15/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch b/queue-5.15/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch new file mode 100644 index 0000000000..516621828e --- /dev/null +++ b/queue-5.15/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch @@ -0,0 +1,48 @@ +From cf2bb08f5cff10212660a47eda3b6eb8692ff672 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 22:32:30 +0800 +Subject: net: ipv6: fix dif and sdif mismatch in raw6_icmp_error + +From: Li RongQing + +[ Upstream commit 440e274da4d1b93c7df2cb0ce893c3009dd4db55 ] + +In raw6_icmp_error(), raw_v6_match() is called with inet6_iif(skb) passed +to both the 'dif' and 'sdif' arguments. This is a copy-paste or typo error, +as the last argument should represent the secondary interface index (sdif). + +This mismatch breaks ICMPv6 error handling for IPv6 raw sockets in VRF +(Virtual Routing and Forwarding) environments. When a raw socket is bound +to a VRF master device, raw_v6_match() fails to find a match because it is +not given the correct sdif value, causing the socket to miss relevant +ICMPv6 error notifications. + +Fix this by properly passing inet6_sdif(skb) as the last argument to +raw_v6_match(). + +Fixes: 5108ab4bf446fa ("net: ipv6: add second dif to raw socket lookups") +Signed-off-by: Li RongQing +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260717143230.1836-1-lirongqing@baidu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/raw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 7e816853cd1cd4..f6b7a637df053c 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -351,7 +351,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + daddr = &ip6h->daddr; + + if (!raw_v6_match(net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr, +- inet6_iif(skb), inet6_iif(skb))) ++ inet6_iif(skb), inet6_sdif(skb))) + continue; + rawv6_err(sk, skb, NULL, type, code, inner_offset, info); + } +-- +2.53.0 + diff --git a/queue-5.15/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch b/queue-5.15/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch new file mode 100644 index 0000000000..8ffba1614d --- /dev/null +++ b/queue-5.15/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch @@ -0,0 +1,51 @@ +From 07c654d4e81e10c70d6c8f8ea3fa3a3dce104ac4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:33:06 +0300 +Subject: net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule + +From: Yael Chemla + +[ Upstream commit d12956d083eb70f2c6d72711aebaf8c2ce21e170 ] + +esw_egress_acl_vlan_create() hardcodes num_dest=0 in its +mlx5_add_flow_rules() call. When invoked from the non-bond path +fwd_dest is NULL and num_dest=0 is correct. When invoked from +esw_acl_egress_ofld_rules_create() during a bond event, fwd_dest is +non-NULL and flow_act.action carries MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, +but _mlx5_add_flow_rules() rejects a non-NULL dest pointer paired with +dest_num<=0 and returns -EINVAL. The error propagates as +"configure slave vport egress fwd, err(-22)". The passive vport's egress +ACL table ends up with its flow groups allocated but no FTEs, so +prio-tagged packets are not popped and bond failover is broken on +prio_tag_required devices. + +Fix by passing fwd_dest ? 1 : 0 as num_dest to match the actual number +of destinations supplied. + +Fixes: bf773dc0e6d5 ("net/mlx5: E-Switch, Introduce APIs to enable egress acl forward-to-vport rule") +Signed-off-by: Yael Chemla +Reviewed-by: Cosmin Ratiu +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20260717073306.1242399-1-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +index 45b839116212df..61d299f8ca25ce 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +@@ -70,7 +70,7 @@ int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw, + flow_act.action = flow_action; + vport->egress.allowed_vlan = + mlx5_add_flow_rules(vport->egress.acl, spec, +- &flow_act, fwd_dest, 0); ++ &flow_act, fwd_dest, fwd_dest ? 1 : 0); + if (IS_ERR(vport->egress.allowed_vlan)) { + err = PTR_ERR(vport->egress.allowed_vlan); + esw_warn(esw->dev, +-- +2.53.0 + diff --git a/queue-5.15/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch b/queue-5.15/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch new file mode 100644 index 0000000000..1e7eb2fcf8 --- /dev/null +++ b/queue-5.15/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch @@ -0,0 +1,46 @@ +From ea6fcd4cd20df483d648e1eeb3577008317ad828 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:25 +0300 +Subject: net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation + +From: Alexei Lazar + +[ Upstream commit 9173e1d3c7c7d49a71eee813091f9e834ec7cee5 ] + +Credit Based (CB) TSA is not supported by the mlx5 driver, so reject +any configurations that specify it. + +Fixes: 08fb1dacdd76 ("net/mlx5e: Support DCBNL IEEE ETS") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-3-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index bb1dd223ecf5ed..4be89f0d020ea4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -309,6 +309,14 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev, + } + } + ++ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { ++ if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_CB_SHAPER) { ++ netdev_err(netdev, ++ "Failed to validate ETS: CB Shaper is not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ + /* Validate Bandwidth Sum */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { +-- +2.53.0 + diff --git a/queue-5.15/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch b/queue-5.15/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch new file mode 100644 index 0000000000..2602adf4a6 --- /dev/null +++ b/queue-5.15/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch @@ -0,0 +1,53 @@ +From 94d59b7235c68f0e5d5d94e6fb6d3b2b634765c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:24 +0300 +Subject: net/mlx5e: Report zero bandwidth for non-ETS traffic classes + +From: Alexei Lazar + +[ Upstream commit ffb1873b2df11945b8c395e859169248675c91c5 ] + +The IEEE 802.1Qaz standard defines that bandwidth allocation percentages +only apply to Enhanced Transmission Selection (ETS) traffic classes. +For STRICT and VENDOR transmission selection algorithms, bandwidth +percentage values are not applicable. + +Currently for non-ETS 100 bandwidth is being reported for all traffic +classes in the get operation due to hardware limitation, regardless of +their TSA type. + +Fix this by reporting 0 for non-ETS traffic classes. + +Fixes: 820c2c5e773d ("net/mlx5e: Read ETS settings directly from firmware") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-2-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index dae944d28ee26d..bb1dd223ecf5ed 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -158,6 +158,13 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, + } + memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa)); + ++ /* Report 0 for non ETS TSA */ ++ for (i = 0; i < ets->ets_cap; i++) { ++ if (ets->tc_tx_bw[i] == MLX5E_MAX_BW_ALLOC && ++ priv->dcbx.tc_tsa[i] != IEEE_8021QAZ_TSA_ETS) ++ ets->tc_tx_bw[i] = 0; ++ } ++ + return err; + } + +-- +2.53.0 + diff --git a/queue-5.15/net-packet-avoid-fanout-hook-re-registration-after-u.patch b/queue-5.15/net-packet-avoid-fanout-hook-re-registration-after-u.patch new file mode 100644 index 0000000000..67449c4abf --- /dev/null +++ b/queue-5.15/net-packet-avoid-fanout-hook-re-registration-after-u.patch @@ -0,0 +1,61 @@ +From 6c57fbabb04f60130bfc0a5eb9f0f6c91fdcedec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:44:37 +0000 +Subject: net/packet: avoid fanout hook re-registration after unregister + +From: David Lee + +[ Upstream commit 50aff80475abd3533eef4320477037e6fcc6b56e ] + +packet_set_ring() temporarily detaches a socket from packet delivery while +reconfiguring its ring. It records the previous running state, clears +po->num, unregisters the protocol hook when needed, drops po->bind_lock, +and later restores po->num and re-registers the hook from the saved +was_running value. + +That unlocked window can race with NETDEV_UNREGISTER. The notifier can +observe the socket as not running, skip __unregister_prot_hook(), and +invalidate the per-socket binding by setting po->ifindex to -1 and clearing +po->prot_hook.dev. A one-member fanout group can still retain its shared +fanout hook device pointer. When packet_set_ring() resumes, re-registering +solely from the stale was_running state can re-add the fanout hook after +the device has been unregistered. + +Treat po->ifindex == -1 as an invalidated binding after reacquiring +po->bind_lock. This is distinct from ifindex 0, the normal +unbound/wildcard state: ifindex -1 marks an existing device binding that +was invalidated when the device was unregistered. Restore po->num as +before, but do not re-register the hook if device unregister already +detached the socket. + +Fixes: dc99f600698d ("packet: Add fanout support.") +Link: https://lore.kernel.org/netdev/20260701113947.23180-1-david.lee@trailofbits.com/ +Signed-off-by: David Lee +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260707104440.833129-1-david.lee@trailofbits.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index e0ea02e86b38e8..1e2c47a4be34c9 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -4548,7 +4548,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + + spin_lock(&po->bind_lock); + WRITE_ONCE(po->num, num); +- if (was_running) ++ /* ++ * NETDEV_UNREGISTER may have invalidated the binding while bind_lock ++ * was dropped above. Do not re-add a fanout hook to a dead device. ++ */ ++ if (was_running && READ_ONCE(po->ifindex) != -1) + register_prot_hook(sk); + + spin_unlock(&po->bind_lock); +-- +2.53.0 + diff --git a/queue-5.15/net-qrtr-restrict-socket-creation-to-the-initial-net.patch b/queue-5.15/net-qrtr-restrict-socket-creation-to-the-initial-net.patch new file mode 100644 index 0000000000..f96d1ef937 --- /dev/null +++ b/queue-5.15/net-qrtr-restrict-socket-creation-to-the-initial-net.patch @@ -0,0 +1,63 @@ +From 22211dd2d1e4f04763045bd4f1f7595f864f0a32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 12:43:19 -0300 +Subject: net: qrtr: restrict socket creation to the initial network namespace + +From: Aldo Ariel Panzardo + +[ Upstream commit 3b536db8fb32da9e9c62f2bb45e2e319331f0426 ] + +QRTR keeps its entire port and node state in module-global variables +that are not partitioned per network namespace: qrtr_local_nid is a +single global node id (always 1) and qrtr_ports is a single global +xarray. qrtr_port_lookup() and qrtr_local_enqueue() operate on that +global state with no network-namespace check, and qrtr_create() places +no restriction on the namespace a socket is created in. + +As a result an unprivileged process that creates an AF_QIPCRTR socket +in a separate network namespace, e.g. via +unshare(CLONE_NEWUSER | CLONE_NEWNET), can send QRTR datagrams - +including control-plane messages such as QRTR_TYPE_NEW_SERVER - to QRTR +sockets owned by another namespace, and vice versa. The receiving +socket sees such a message as coming from node id 1, indistinguishable +from a legitimate local client, breaking the isolation that network +namespaces are expected to provide. + +QRTR is a transport to global hardware endpoints (the modem and other +remote processors) and has no per-namespace semantics; its in-kernel +name service already creates its socket in init_net only. Confine the +socket family to the initial network namespace, as other +non-namespace-aware socket families do (see llc_ui_create() and the +ieee802154 socket code). + +Fixes: bdabad3e363d ("net: Add Qualcomm IPC router") +Signed-off-by: Aldo Ariel Panzardo +Link: https://patch.msgid.link/20260716154319.3297699-1-qwe.aldo@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/qrtr/af_qrtr.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c +index 27a7d1ff7f24da..94bfb0397e5d31 100644 +--- a/net/qrtr/af_qrtr.c ++++ b/net/qrtr/af_qrtr.c +@@ -1258,6 +1258,14 @@ static int qrtr_create(struct net *net, struct socket *sock, + if (sock->type != SOCK_DGRAM) + return -EPROTOTYPE; + ++ /* QRTR keeps its port and node state in module-global variables that ++ * are not partitioned per network namespace, and the in-kernel name ++ * service only operates in init_net. Confine the family to init_net so ++ * a socket in another namespace cannot reach the global control plane. ++ */ ++ if (!net_eq(net, &init_net)) ++ return -EAFNOSUPPORT; ++ + sk = sk_alloc(net, AF_QIPCRTR, GFP_KERNEL, &qrtr_proto, kern); + if (!sk) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-5.15/net-stmmac-add-tc-flower-filter-for-ethertype-matchi.patch b/queue-5.15/net-stmmac-add-tc-flower-filter-for-ethertype-matchi.patch new file mode 100644 index 0000000000..953f16fe99 --- /dev/null +++ b/queue-5.15/net-stmmac-add-tc-flower-filter-for-ethertype-matchi.patch @@ -0,0 +1,236 @@ +From d7f395b14fbd1a28948ad83e18e7616d6dc84048 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Dec 2021 22:43:10 +0800 +Subject: net: stmmac: add tc flower filter for EtherType matching + +From: Ong Boon Leong + +[ Upstream commit e48cb313fde3e6f9434bb41c858d5c791d83f2d0 ] + +This patch adds basic support for EtherType RX frame steering for +LLDP and PTP using the hardware offload capabilities. + +Example steps for setting up RX frame steering for LLDP and PTP: +$ IFDEVNAME=eth0 +$ tc qdisc add dev $IFDEVNAME ingress +$ tc qdisc add dev $IFDEVNAME root mqprio num_tc 8 \ + map 0 1 2 3 4 5 6 7 0 0 0 0 0 0 0 0 \ + queues 1@0 1@1 1@2 1@3 1@4 1@5 1@6 1@7 hw 0 + +For LLDP +$ tc filter add dev $IFDEVNAME parent ffff: protocol 0x88cc \ + flower hw_tc 5 +OR +$ tc filter add dev $IFDEVNAME parent ffff: protocol LLDP \ + flower hw_tc 5 + +For PTP +$ tc filter add dev $IFDEVNAME parent ffff: protocol 0x88f7 \ + flower hw_tc 6 + +Show tc ingress filter +$ tc filter show dev $IFDEVNAME ingress + +v1->v2: + Thanks to Kurt's and Sebastian's suggestion. + - change from __be16 to u16 etype + - change ETHER_TYPE_FULL_MASK to use cpu_to_be16() macro + +Signed-off-by: Ong Boon Leong +Signed-off-by: David S. Miller +Stable-dep-of: 5536d7c84363 ("net: stmmac: fix l3l4 filter rejecting unsupported offload requests") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac.h | 3 + + .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 121 ++++++++++++++++++ + 2 files changed, 124 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +index 1a74437787c030..5946e1decd9cc8 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h +@@ -175,11 +175,14 @@ struct stmmac_flow_entry { + /* Rx Frame Steering */ + enum stmmac_rfs_type { + STMMAC_RFS_T_VLAN, ++ STMMAC_RFS_T_LLDP, ++ STMMAC_RFS_T_1588, + STMMAC_RFS_T_MAX, + }; + + struct stmmac_rfs_entry { + unsigned long cookie; ++ u16 etype; + int in_use; + int type; + int tc; +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 5520f5a5391cff..62aef01b48f1e0 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -237,6 +237,8 @@ static int tc_rfs_init(struct stmmac_priv *priv) + int i; + + priv->rfs_entries_max[STMMAC_RFS_T_VLAN] = 8; ++ priv->rfs_entries_max[STMMAC_RFS_T_LLDP] = 1; ++ priv->rfs_entries_max[STMMAC_RFS_T_1588] = 1; + + for (i = 0; i < STMMAC_RFS_T_MAX; i++) + priv->rfs_entries_total += priv->rfs_entries_max[i]; +@@ -453,6 +455,8 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv, + return 0; + } + ++#define ETHER_TYPE_FULL_MASK cpu_to_be16(~0) ++ + static int tc_add_basic_flow(struct stmmac_priv *priv, + struct flow_cls_offload *cls, + struct stmmac_flow_entry *entry) +@@ -466,6 +470,7 @@ static int tc_add_basic_flow(struct stmmac_priv *priv, + return -EINVAL; + + flow_rule_match_basic(rule, &match); ++ + entry->ip_proto = match.key->ip_proto; + return 0; + } +@@ -726,6 +731,114 @@ static int tc_del_vlan_flow(struct stmmac_priv *priv, + return 0; + } + ++static int tc_add_ethtype_flow(struct stmmac_priv *priv, ++ struct flow_cls_offload *cls) ++{ ++ struct stmmac_rfs_entry *entry = tc_find_rfs(priv, cls, false); ++ struct flow_rule *rule = flow_cls_offload_flow_rule(cls); ++ struct flow_dissector *dissector = rule->match.dissector; ++ int tc = tc_classid_to_hwtc(priv->dev, cls->classid); ++ struct flow_match_basic match; ++ ++ if (!entry) { ++ entry = tc_find_rfs(priv, cls, true); ++ if (!entry) ++ return -ENOENT; ++ } ++ ++ /* Nothing to do here */ ++ if (!dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_BASIC)) ++ return -EINVAL; ++ ++ if (tc < 0) { ++ netdev_err(priv->dev, "Invalid traffic class\n"); ++ return -EINVAL; ++ } ++ ++ flow_rule_match_basic(rule, &match); ++ ++ if (match.mask->n_proto) { ++ u16 etype = ntohs(match.key->n_proto); ++ ++ if (match.mask->n_proto != ETHER_TYPE_FULL_MASK) { ++ netdev_err(priv->dev, "Only full mask is supported for EthType filter"); ++ return -EINVAL; ++ } ++ switch (etype) { ++ case ETH_P_LLDP: ++ if (priv->rfs_entries_cnt[STMMAC_RFS_T_LLDP] >= ++ priv->rfs_entries_max[STMMAC_RFS_T_LLDP]) ++ return -ENOENT; ++ ++ entry->type = STMMAC_RFS_T_LLDP; ++ priv->rfs_entries_cnt[STMMAC_RFS_T_LLDP]++; ++ ++ stmmac_rx_queue_routing(priv, priv->hw, ++ PACKET_DCBCPQ, tc); ++ break; ++ case ETH_P_1588: ++ if (priv->rfs_entries_cnt[STMMAC_RFS_T_1588] >= ++ priv->rfs_entries_max[STMMAC_RFS_T_1588]) ++ return -ENOENT; ++ ++ entry->type = STMMAC_RFS_T_1588; ++ priv->rfs_entries_cnt[STMMAC_RFS_T_1588]++; ++ ++ stmmac_rx_queue_routing(priv, priv->hw, ++ PACKET_PTPQ, tc); ++ break; ++ default: ++ netdev_err(priv->dev, "EthType(0x%x) is not supported", etype); ++ return -EINVAL; ++ } ++ ++ entry->in_use = true; ++ entry->cookie = cls->cookie; ++ entry->tc = tc; ++ entry->etype = etype; ++ ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static int tc_del_ethtype_flow(struct stmmac_priv *priv, ++ struct flow_cls_offload *cls) ++{ ++ struct stmmac_rfs_entry *entry = tc_find_rfs(priv, cls, false); ++ ++ if (!entry || !entry->in_use || ++ entry->type < STMMAC_RFS_T_LLDP || ++ entry->type > STMMAC_RFS_T_1588) ++ return -ENOENT; ++ ++ switch (entry->etype) { ++ case ETH_P_LLDP: ++ stmmac_rx_queue_routing(priv, priv->hw, ++ PACKET_DCBCPQ, 0); ++ priv->rfs_entries_cnt[STMMAC_RFS_T_LLDP]--; ++ break; ++ case ETH_P_1588: ++ stmmac_rx_queue_routing(priv, priv->hw, ++ PACKET_PTPQ, 0); ++ priv->rfs_entries_cnt[STMMAC_RFS_T_1588]--; ++ break; ++ default: ++ netdev_err(priv->dev, "EthType(0x%x) is not supported", ++ entry->etype); ++ return -EINVAL; ++ } ++ ++ entry->in_use = false; ++ entry->cookie = 0; ++ entry->tc = 0; ++ entry->etype = 0; ++ entry->type = 0; ++ ++ return 0; ++} ++ + static int tc_add_flow_cls(struct stmmac_priv *priv, + struct flow_cls_offload *cls) + { +@@ -735,6 +848,10 @@ static int tc_add_flow_cls(struct stmmac_priv *priv, + if (!ret) + return ret; + ++ ret = tc_add_ethtype_flow(priv, cls); ++ if (!ret) ++ return ret; ++ + return tc_add_vlan_flow(priv, cls); + } + +@@ -747,6 +864,10 @@ static int tc_del_flow_cls(struct stmmac_priv *priv, + if (!ret) + return ret; + ++ ret = tc_del_ethtype_flow(priv, cls); ++ if (!ret) ++ return ret; ++ + return tc_del_vlan_flow(priv, cls); + } + +-- +2.53.0 + diff --git a/queue-5.15/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch b/queue-5.15/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch new file mode 100644 index 0000000000..5e5d672021 --- /dev/null +++ b/queue-5.15/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch @@ -0,0 +1,103 @@ +From 370074c977699cf26e58f1b21d2e4626b49eae16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:15 -0700 +Subject: net: stmmac: fix l3l4 filter rejecting unsupported offload requests + +From: Nazim Amirul + +[ Upstream commit 5536d7c843637e9430279b94935fcf7df98babb3 ] + +The basic flow parser in tc_add_basic_flow() does not validate match +keys before proceeding. Unsupported offload configurations such as +partial protocol masks, non-IPv4 network proto, or non-TCP/UDP transport +proto are silently accepted instead of returning -EOPNOTSUPP. + +Add validation to return -EOPNOTSUPP early for: +- No network or transport proto present in the key +- Partial protocol mask (only full mask supported) +- Network proto is not IPv4 +- Transport proto is not TCP or UDP + +Each rejection includes an extack message so the user knows which part +of the match is unsupported. + +Also propagate -EOPNOTSUPP from tc_add_basic_flow() in tc_add_flow() +by returning it directly rather than using break. The break was silently +discarding the error for FLOW_CLS_REPLACE operations where entry->in_use +is already true, causing tc_add_flow() to return 0 (success) for +unsupported replace requests. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-4-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 34 +++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 62aef01b48f1e0..6d971a5db00bda 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -456,6 +456,7 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv, + } + + #define ETHER_TYPE_FULL_MASK cpu_to_be16(~0) ++#define IP_PROTO_FULL_MASK 0xFF + + static int tc_add_basic_flow(struct stmmac_priv *priv, + struct flow_cls_offload *cls, +@@ -471,6 +472,37 @@ static int tc_add_basic_flow(struct stmmac_priv *priv, + + flow_rule_match_basic(rule, &match); + ++ /* Both network proto and transport proto not present in the key */ ++ if (!match.mask || !(match.mask->n_proto || match.mask->ip_proto)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "filter must specify network or transport protocol"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* If the proto is present in the key and is not full mask */ ++ if ((match.mask->n_proto && match.mask->n_proto != ETHER_TYPE_FULL_MASK) || ++ (match.mask->ip_proto && match.mask->ip_proto != IP_PROTO_FULL_MASK)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only full protocol mask is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Network proto is present in the key and is not IPv4 */ ++ if (match.mask->n_proto && match.key->n_proto != cpu_to_be16(ETH_P_IP)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only IPv4 network protocol is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Transport proto is present in the key and is not TCP or UDP */ ++ if (match.mask->ip_proto && ++ match.key->ip_proto != IPPROTO_TCP && ++ match.key->ip_proto != IPPROTO_UDP) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only TCP and UDP transport protocols are supported"); ++ return -EOPNOTSUPP; ++ } ++ + entry->ip_proto = match.key->ip_proto; + return 0; + } +@@ -608,6 +640,8 @@ static int tc_add_flow(struct stmmac_priv *priv, + ret = tc_flow_parsers[i].fn(priv, cls, entry); + if (!ret) + entry->in_use = true; ++ else if (ret == -EOPNOTSUPP) ++ return ret; + } + + if (!entry->in_use) +-- +2.53.0 + diff --git a/queue-5.15/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch b/queue-5.15/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch new file mode 100644 index 0000000000..fe66f219be --- /dev/null +++ b/queue-5.15/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch @@ -0,0 +1,43 @@ +From 688cebcb4ce0d5dc93c45e73863dd38b3bc264f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:16 -0700 +Subject: net: stmmac: reset residual action in L3L4 filters on delete + +From: Nazim Amirul + +[ Upstream commit a448f821289934b961dd9d8d0beb006cc8937ba2 ] + +When deleting an L3/L4 flower filter entry, the action field is not +reset. If a filter was previously configured with a drop action, that +action may persist and affect subsequent filter configurations +unintentionally. + +Clear the action field when the filter entry is deleted. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-5-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 6d971a5db00bda..b31d2a86057a55 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -671,6 +671,7 @@ static int tc_del_flow(struct stmmac_priv *priv, + entry->in_use = false; + entry->cookie = 0; + entry->is_l4 = false; ++ entry->action = 0; + return ret; + } + +-- +2.53.0 + diff --git a/queue-5.15/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch b/queue-5.15/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch new file mode 100644 index 0000000000..096500cd80 --- /dev/null +++ b/queue-5.15/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch @@ -0,0 +1,59 @@ +From ad686311325530415e28d2faad9701480804269e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 22:15:51 +0000 +Subject: nexthop: initialize extack in nh_res_bucket_migrate() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 6347c5314cee49f364aaf2e40ff15415a57a116e ] + +nh_res_bucket_migrate() passes an uninitialized netlink_ext_ack to +call_nexthop_res_bucket_notifiers(). When +nh_notifier_res_bucket_info_init() fails (e.g. the kzalloc returns +-ENOMEM), the error is propagated back before any notifier sets +extack._msg, and the error path formats the stale pointer with +pr_err_ratelimited("%s\n", extack._msg). With CONFIG_INIT_STACK_NONE +this dereferences uninitialized stack memory: + + Oops: general protection fault, probably for non-canonical address ... + KASAN: maybe wild-memory-access in range [...] + RIP: 0010:string (lib/vsprintf.c:730) + vsnprintf (lib/vsprintf.c:2945) + _printk (kernel/printk/printk.c:2504) + nh_res_bucket_migrate (net/ipv4/nexthop.c:1816) + nh_res_table_upkeep (net/ipv4/nexthop.c:1866) + rtm_new_nexthop (net/ipv4/nexthop.c:3323) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7076) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + Kernel panic - not syncing: Fatal exception + +Zero-initialize extack so _msg is NULL on error paths that never set it. + +Fixes: 7c37c7e00411 ("nexthop: Implement notifiers for resilient nexthop groups") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260713221551.3344650-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/nexthop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c +index 8cd148be09c6b4..9257a63b9ffd94 100644 +--- a/net/ipv4/nexthop.c ++++ b/net/ipv4/nexthop.c +@@ -1503,8 +1503,8 @@ static bool nh_res_bucket_migrate(struct nh_res_table *res_table, + bool notify_nl, bool force) + { + struct nh_res_bucket *bucket = &res_table->nh_buckets[bucket_index]; ++ struct netlink_ext_ack extack = {}; + struct nh_grp_entry *new_nhge; +- struct netlink_ext_ack extack; + int err; + + new_nhge = list_first_entry_or_null(&res_table->uw_nh_entries, +-- +2.53.0 + diff --git a/queue-5.15/nfp-check-resource-mutex-allocation.patch b/queue-5.15/nfp-check-resource-mutex-allocation.patch new file mode 100644 index 0000000000..2295628036 --- /dev/null +++ b/queue-5.15/nfp-check-resource-mutex-allocation.patch @@ -0,0 +1,52 @@ +From bd1b45a0e62107d5fae470bc3d0bbedbe0ac48db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:08 +0800 +Subject: nfp: Check resource mutex allocation + +From: Ruoyu Wang + +[ Upstream commit a61b4db34a753bdf5c9e77a7f3d3dddd41dcfacc ] + +nfp_cpp_resource_find() allocates a CPP mutex handle for the matching +resource-table entry and then reports success. nfp_resource_try_acquire() +immediately passes that handle to nfp_cpp_mutex_trylock(). + +However, nfp_cpp_mutex_alloc() returns NULL on failure. If that happens +for a matching table entry, the resource lookup still returns success and +the following trylock dereferences a NULL mutex pointer while opening the +resource. + +nfp_resource_acquire() already treats failure to allocate the table mutex +as -ENOMEM. Do the same for the resource mutex and fail the lookup before +publishing the rest of the resource handle. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: f01a2161577d ("nfp: add support for resources") +Signed-off-by: Ruoyu Wang +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708143408.3168425-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +index ce7492a6a98fad..908d99f398b819 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c ++++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +@@ -96,6 +96,9 @@ static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res) + res->mutex = + nfp_cpp_mutex_alloc(cpp, + NFP_RESOURCE_TBL_TARGET, addr, key); ++ if (!res->mutex) ++ return -ENOMEM; ++ + res->cpp_id = NFP_CPP_ID(entry.region.cpp_target, + entry.region.cpp_action, + entry.region.cpp_token); +-- +2.53.0 + diff --git a/queue-5.15/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch b/queue-5.15/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch new file mode 100644 index 0000000000..7d4d1b43e3 --- /dev/null +++ b/queue-5.15/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch @@ -0,0 +1,40 @@ +From 9108446983da70d9ade1626c1fe12a7d401fbca9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 10:50:07 +0530 +Subject: octeontx2-vf: set TC flower flag on MCAM entry allocation + +From: Suman Ghosh + +[ Upstream commit 0d4d31e3cc5dd6204fa1495c4107f5075acce5ed ] + +When MCAM entries are allocated for a VF netdev via the devlink +mcam_count parameter, only OTX2_FLAG_NTUPLE_SUPPORT was set. That +enabled ethtool ntuple filters but not tc flower offload. Also set +OTX2_FLAG_TC_FLOWER_SUPPORT when entries are successfully allocated. + +Fixes: 2da489432747 ("octeontx2-pf: devlink params support to set mcam entry count") +Signed-off-by: Suman Ghosh +Signed-off-by: Ratheesh Kannoth +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260715052007.2099851-1-rkannoth@marvell.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +index 87e41b9a0ce63d..b7d528cf34328a 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +@@ -151,6 +151,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count) + if (allocated) { + pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC; + pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT; ++ pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT; + } + + if (allocated != count) +-- +2.53.0 + diff --git a/queue-5.15/raw-use-more-conventional-iterators.patch b/queue-5.15/raw-use-more-conventional-iterators.patch new file mode 100644 index 0000000000..0268aa908b --- /dev/null +++ b/queue-5.15/raw-use-more-conventional-iterators.patch @@ -0,0 +1,451 @@ +From c5b4171e913bded41acb1ee5beee3e985084b8b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jun 2022 20:47:04 -0700 +Subject: raw: use more conventional iterators + +From: Eric Dumazet + +[ Upstream commit ba44f8182ec299c5d1c8a72fc0fde4ec127b5a6d ] + +In order to prepare the following patch, +I change raw v4 & v6 code to use more conventional +iterators. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Stable-dep-of: 440e274da4d1 ("net: ipv6: fix dif and sdif mismatch in raw6_icmp_error") +Signed-off-by: Sasha Levin +--- + include/net/raw.h | 5 +-- + include/net/rawv6.h | 6 +-- + net/ipv4/raw.c | 93 ++++++++++++++------------------------- + net/ipv4/raw_diag.c | 33 +++++++------- + net/ipv6/raw.c | 105 ++++++++++++++++---------------------------- + 5 files changed, 92 insertions(+), 150 deletions(-) + +diff --git a/include/net/raw.h b/include/net/raw.h +index c51a635671a73d..6324965779ec6a 100644 +--- a/include/net/raw.h ++++ b/include/net/raw.h +@@ -20,9 +20,8 @@ + extern struct proto raw_prot; + + extern struct raw_hashinfo raw_v4_hashinfo; +-struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, +- unsigned short num, __be32 raddr, +- __be32 laddr, int dif, int sdif); ++bool raw_v4_match(struct net *net, struct sock *sk, unsigned short num, ++ __be32 raddr, __be32 laddr, int dif, int sdif); + + int raw_abort(struct sock *sk, int err); + void raw_icmp_error(struct sk_buff *, int, u32); +diff --git a/include/net/rawv6.h b/include/net/rawv6.h +index 53d86b6055e8cc..c48c1298699a04 100644 +--- a/include/net/rawv6.h ++++ b/include/net/rawv6.h +@@ -5,9 +5,9 @@ + #include + + extern struct raw_hashinfo raw_v6_hashinfo; +-struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, +- unsigned short num, const struct in6_addr *loc_addr, +- const struct in6_addr *rmt_addr, int dif, int sdif); ++bool raw_v6_match(struct net *net, struct sock *sk, unsigned short num, ++ const struct in6_addr *loc_addr, ++ const struct in6_addr *rmt_addr, int dif, int sdif); + + int raw_abort(struct sock *sk, int err); + +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index e6cb76ecbf2d9f..2271f679265c4d 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -117,24 +117,19 @@ void raw_unhash_sk(struct sock *sk) + } + EXPORT_SYMBOL_GPL(raw_unhash_sk); + +-struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, +- unsigned short num, __be32 raddr, __be32 laddr, +- int dif, int sdif) ++bool raw_v4_match(struct net *net, struct sock *sk, unsigned short num, ++ __be32 raddr, __be32 laddr, int dif, int sdif) + { +- sk_for_each_from(sk) { +- struct inet_sock *inet = inet_sk(sk); +- +- if (net_eq(sock_net(sk), net) && inet->inet_num == num && +- !(inet->inet_daddr && inet->inet_daddr != raddr) && +- !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && +- raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif)) +- goto found; /* gotcha */ +- } +- sk = NULL; +-found: +- return sk; ++ struct inet_sock *inet = inet_sk(sk); ++ ++ if (net_eq(sock_net(sk), net) && inet->inet_num == num && ++ !(inet->inet_daddr && inet->inet_daddr != raddr) && ++ !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && ++ raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif)) ++ return true; ++ return false; + } +-EXPORT_SYMBOL_GPL(__raw_v4_lookup); ++EXPORT_SYMBOL_GPL(raw_v4_match); + + /* + * 0 - deliver +@@ -168,23 +163,21 @@ static int icmp_filter(const struct sock *sk, const struct sk_buff *skb) + */ + static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) + { ++ struct net *net = dev_net(skb->dev); + int sdif = inet_sdif(skb); + int dif = inet_iif(skb); +- struct sock *sk; + struct hlist_head *head; + int delivered = 0; +- struct net *net; ++ struct sock *sk; + +- read_lock(&raw_v4_hashinfo.lock); + head = &raw_v4_hashinfo.ht[hash]; + if (hlist_empty(head)) +- goto out; +- +- net = dev_net(skb->dev); +- sk = __raw_v4_lookup(net, __sk_head(head), iph->protocol, +- iph->saddr, iph->daddr, dif, sdif); +- +- while (sk) { ++ return 0; ++ read_lock(&raw_v4_hashinfo.lock); ++ sk_for_each(sk, head) { ++ if (!raw_v4_match(net, sk, iph->protocol, ++ iph->saddr, iph->daddr, dif, sdif)) ++ continue; + delivered = 1; + if ((iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) && + ip_mc_sf_allow(sk, iph->daddr, iph->saddr, +@@ -195,31 +188,16 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) + if (clone) + raw_rcv(sk, clone); + } +- sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol, +- iph->saddr, iph->daddr, +- dif, sdif); + } +-out: + read_unlock(&raw_v4_hashinfo.lock); + return delivered; + } + + int raw_local_deliver(struct sk_buff *skb, int protocol) + { +- int hash; +- struct sock *raw_sk; +- +- hash = protocol & (RAW_HTABLE_SIZE - 1); +- raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); +- +- /* If there maybe a raw socket we must check - if not we +- * don't care less +- */ +- if (raw_sk && !raw_v4_input(skb, ip_hdr(skb), hash)) +- raw_sk = NULL; +- +- return raw_sk != NULL; ++ int hash = protocol & (RAW_HTABLE_SIZE - 1); + ++ return raw_v4_input(skb, ip_hdr(skb), hash); + } + + static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) +@@ -286,29 +264,24 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) + + void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) + { +- int hash; +- struct sock *raw_sk; ++ struct net *net = dev_net(skb->dev);; ++ int dif = skb->dev->ifindex; ++ int sdif = inet_sdif(skb); ++ struct hlist_head *head; + const struct iphdr *iph; +- struct net *net; ++ struct sock *sk; ++ int hash; + + hash = protocol & (RAW_HTABLE_SIZE - 1); ++ head = &raw_v4_hashinfo.ht[hash]; + + read_lock(&raw_v4_hashinfo.lock); +- raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); +- if (raw_sk) { +- int dif = skb->dev->ifindex; +- int sdif = inet_sdif(skb); +- ++ sk_for_each(sk, head) { + iph = (const struct iphdr *)skb->data; +- net = dev_net(skb->dev); +- +- while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, +- iph->daddr, iph->saddr, +- dif, sdif)) != NULL) { +- raw_err(raw_sk, skb, info); +- raw_sk = sk_next(raw_sk); +- iph = (const struct iphdr *)skb->data; +- } ++ if (!raw_v4_match(net, sk, iph->protocol, ++ iph->saddr, iph->daddr, dif, sdif)) ++ continue; ++ raw_err(sk, skb, info); + } + read_unlock(&raw_v4_hashinfo.lock); + } +diff --git a/net/ipv4/raw_diag.c b/net/ipv4/raw_diag.c +index ccacbde30a2c50..b6d92dc7b051d1 100644 +--- a/net/ipv4/raw_diag.c ++++ b/net/ipv4/raw_diag.c +@@ -34,31 +34,30 @@ raw_get_hashinfo(const struct inet_diag_req_v2 *r) + * use helper to figure it out. + */ + +-static struct sock *raw_lookup(struct net *net, struct sock *from, +- const struct inet_diag_req_v2 *req) ++static bool raw_lookup(struct net *net, struct sock *sk, ++ const struct inet_diag_req_v2 *req) + { + struct inet_diag_req_raw *r = (void *)req; +- struct sock *sk = NULL; + + if (r->sdiag_family == AF_INET) +- sk = __raw_v4_lookup(net, from, r->sdiag_raw_protocol, +- r->id.idiag_dst[0], +- r->id.idiag_src[0], +- r->id.idiag_if, 0); ++ return raw_v4_match(net, sk, r->sdiag_raw_protocol, ++ r->id.idiag_dst[0], ++ r->id.idiag_src[0], ++ r->id.idiag_if, 0); + #if IS_ENABLED(CONFIG_IPV6) + else +- sk = __raw_v6_lookup(net, from, r->sdiag_raw_protocol, +- (const struct in6_addr *)r->id.idiag_src, +- (const struct in6_addr *)r->id.idiag_dst, +- r->id.idiag_if, 0); ++ return raw_v6_match(net, sk, r->sdiag_raw_protocol, ++ (const struct in6_addr *)r->id.idiag_src, ++ (const struct in6_addr *)r->id.idiag_dst, ++ r->id.idiag_if, 0); + #endif +- return sk; ++ return false; + } + + static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 *r) + { + struct raw_hashinfo *hashinfo = raw_get_hashinfo(r); +- struct sock *sk = NULL, *s; ++ struct sock *sk; + int slot; + + if (IS_ERR(hashinfo)) +@@ -66,9 +65,8 @@ static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 + + read_lock(&hashinfo->lock); + for (slot = 0; slot < RAW_HTABLE_SIZE; slot++) { +- sk_for_each(s, &hashinfo->ht[slot]) { +- sk = raw_lookup(net, s, r); +- if (sk) { ++ sk_for_each(sk, &hashinfo->ht[slot]) { ++ if (raw_lookup(net, sk, r)) { + /* + * Grab it and keep until we fill + * diag meaage to be reported, so +@@ -81,10 +79,11 @@ static struct sock *raw_sock_get(struct net *net, const struct inet_diag_req_v2 + } + } + } ++ sk = ERR_PTR(-ENOENT); + out_unlock: + read_unlock(&hashinfo->lock); + +- return sk ? sk : ERR_PTR(-ENOENT); ++ return sk; + } + + static int raw_diag_dump_one(struct netlink_callback *cb, +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 586e972cbcd53c..7e816853cd1cd4 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -66,41 +66,27 @@ struct raw_hashinfo raw_v6_hashinfo = { + }; + EXPORT_SYMBOL_GPL(raw_v6_hashinfo); + +-struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, +- unsigned short num, const struct in6_addr *loc_addr, +- const struct in6_addr *rmt_addr, int dif, int sdif) ++bool raw_v6_match(struct net *net, struct sock *sk, unsigned short num, ++ const struct in6_addr *loc_addr, ++ const struct in6_addr *rmt_addr, int dif, int sdif) + { +- bool is_multicast = ipv6_addr_is_multicast(loc_addr); +- +- sk_for_each_from(sk) +- if (inet_sk(sk)->inet_num == num) { +- +- if (!net_eq(sock_net(sk), net)) +- continue; +- +- if (!ipv6_addr_any(&sk->sk_v6_daddr) && +- !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) +- continue; +- +- if (!raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, +- dif, sdif)) +- continue; +- +- if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { +- if (ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)) +- goto found; +- if (is_multicast && +- inet6_mc_check(sk, loc_addr, rmt_addr)) +- goto found; +- continue; +- } +- goto found; +- } +- sk = NULL; +-found: +- return sk; ++ if (inet_sk(sk)->inet_num != num || ++ !net_eq(sock_net(sk), net) || ++ (!ipv6_addr_any(&sk->sk_v6_daddr) && ++ !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) || ++ !raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, ++ dif, sdif)) ++ return false; ++ ++ if (ipv6_addr_any(&sk->sk_v6_rcv_saddr) || ++ ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr) || ++ (ipv6_addr_is_multicast(loc_addr) && ++ inet6_mc_check(sk, loc_addr, rmt_addr))) ++ return true; ++ ++ return false; + } +-EXPORT_SYMBOL_GPL(__raw_v6_lookup); ++EXPORT_SYMBOL_GPL(raw_v6_match); + + /* + * 0 - deliver +@@ -156,31 +142,28 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister); + */ + static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) + { ++ struct net *net = dev_net(skb->dev); + const struct in6_addr *saddr; + const struct in6_addr *daddr; ++ struct hlist_head *head; + struct sock *sk; + bool delivered = false; + __u8 hash; +- struct net *net; + + saddr = &ipv6_hdr(skb)->saddr; + daddr = saddr + 1; + + hash = nexthdr & (RAW_HTABLE_SIZE - 1); +- ++ head = &raw_v6_hashinfo.ht[hash]; ++ if (hlist_empty(head)) ++ return false; + read_lock(&raw_v6_hashinfo.lock); +- sk = sk_head(&raw_v6_hashinfo.ht[hash]); +- +- if (!sk) +- goto out; +- +- net = dev_net(skb->dev); +- sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, +- inet6_iif(skb), inet6_sdif(skb)); +- +- while (sk) { ++ sk_for_each(sk, head) { + int filtered; + ++ if (!raw_v6_match(net, sk, nexthdr, daddr, saddr, ++ inet6_iif(skb), inet6_sdif(skb))) ++ continue; + delivered = true; + switch (nexthdr) { + case IPPROTO_ICMPV6: +@@ -219,23 +202,14 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) + rawv6_rcv(sk, clone); + } + } +- sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr, +- inet6_iif(skb), inet6_sdif(skb)); + } +-out: + read_unlock(&raw_v6_hashinfo.lock); + return delivered; + } + + bool raw6_local_deliver(struct sk_buff *skb, int nexthdr) + { +- struct sock *raw_sk; +- +- raw_sk = sk_head(&raw_v6_hashinfo.ht[nexthdr & (RAW_HTABLE_SIZE - 1)]); +- if (raw_sk && !ipv6_raw_deliver(skb, nexthdr)) +- raw_sk = NULL; +- +- return raw_sk != NULL; ++ return ipv6_raw_deliver(skb, nexthdr); + } + + /* This cleans up af_inet6 a bit. -DaveM */ +@@ -361,28 +335,25 @@ static void rawv6_err(struct sock *sk, struct sk_buff *skb, + void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + u8 type, u8 code, int inner_offset, __be32 info) + { ++ const struct in6_addr *saddr, *daddr; ++ struct net *net = dev_net(skb->dev); ++ struct hlist_head *head; + struct sock *sk; + int hash; +- const struct in6_addr *saddr, *daddr; +- struct net *net; + + hash = nexthdr & (RAW_HTABLE_SIZE - 1); +- ++ head = &raw_v6_hashinfo.ht[hash]; + read_lock(&raw_v6_hashinfo.lock); +- sk = sk_head(&raw_v6_hashinfo.ht[hash]); +- if (sk) { ++ sk_for_each(sk, head) { + /* Note: ipv6_hdr(skb) != skb->data */ + const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data; + saddr = &ip6h->saddr; + daddr = &ip6h->daddr; +- net = dev_net(skb->dev); + +- while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, +- inet6_iif(skb), inet6_iif(skb)))) { +- rawv6_err(sk, skb, NULL, type, code, +- inner_offset, info); +- sk = sk_next(sk); +- } ++ if (!raw_v6_match(net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr, ++ inet6_iif(skb), inet6_iif(skb))) ++ continue; ++ rawv6_err(sk, skb, NULL, type, code, inner_offset, info); + } + read_unlock(&raw_v6_hashinfo.lock); + } +-- +2.53.0 + diff --git a/queue-5.15/rds-drop-incoming-messages-that-cross-network-namesp.patch b/queue-5.15/rds-drop-incoming-messages-that-cross-network-namesp.patch new file mode 100644 index 0000000000..32c227e2a0 --- /dev/null +++ b/queue-5.15/rds-drop-incoming-messages-that-cross-network-namesp.patch @@ -0,0 +1,78 @@ +From 85fc1beb5eded9c37059569c7cca1e0394063342 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 19:43:14 -0700 +Subject: rds: drop incoming messages that cross network namespace boundaries + +From: Aldo Ariel Panzardo + +[ Upstream commit 5521ae71e32a8069ed4ca6e792179dc57bc43ab2 ] + +rds_find_bound() looks up the destination socket using a global +rhashtable keyed solely on (addr, port, scope_id). Network namespaces +are not part of the key, so a sender in netns A can deliver an incoming +message (inc) to a socket that lives in a different netns B. + +When this happens, inc->i_conn points to an rds_connection whose c_net +is netns A, but the receiving rs lives in netns B. Once the child +process that created netns A exits, cleanup_net() calls +rds_loop_exit_net() -> rds_loop_kill_conns() -> rds_conn_destroy(), +freeing that connection. If the survivor socket in netns B still holds +the inc, any subsequent dereference of inc->i_conn is a use-after-free. + +There are two dangerous sites in rds_clear_recv_queue(): + 1. inc->i_conn->c_lcong (offset 88 of freed rds_connection, size 200) + read via rds_recv_rcvbuf_delta() -- confirmed by KASAN. + 2. inc->i_conn->c_trans->inc_free(inc) (function pointer at offset 80) + called via rds_inc_put() when the inc refcount reaches zero -- same + race window, potential call-through-freed-object primitive. + +The bug is reachable from unprivileged user namespaces +(CLONE_NEWUSER + CLONE_NEWNET), available since Linux 3.8. + +Fix this by rejecting the delivery in rds_recv_incoming() when the +socket returned by rds_find_bound() belongs to a different network +namespace than the connection that carried the message. Use the +existing rds_conn_net() / sock_net() helpers and net_eq() for the +comparison. + +Fixes: c809195f5523 ("rds: clean up loopback rds_connections on netns deletion") +Signed-off-by: Aldo Ariel Panzardo +Reviewed-by: Allison Henderson +Tested-by: Allison Henderson +Signed-off-by: Allison Henderson +Link: https://patch.msgid.link/20260708024314.601139-1-achender@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/rds/recv.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/net/rds/recv.c b/net/rds/recv.c +index a316180d3c32ec..7fd77e1b4fe71c 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -365,6 +365,21 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr, + goto out; + } + ++ /* ++ * rds_find_bound() uses a global (netns-agnostic) hash table. ++ * An RDS connection created in netns A can match a socket bound ++ * in the init netns, delivering inc cross-netns with inc->i_conn ++ * pointing into netns A. When cleanup_net() then frees that conn, ++ * any subsequent dereference of inc->i_conn is a use-after-free. ++ * Drop the inc if the receiving socket lives in a different netns. ++ */ ++ if (!net_eq(sock_net(rds_rs_to_sk(rs)), rds_conn_net(conn))) { ++ rds_stats_inc(s_recv_drop_no_sock); ++ rds_sock_put(rs); ++ rs = NULL; ++ goto out; ++ } ++ + /* Process extension headers */ + rds_recv_incoming_exthdrs(inc, rs); + +-- +2.53.0 + diff --git a/queue-5.15/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch b/queue-5.15/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch new file mode 100644 index 0000000000..f085ec86c9 --- /dev/null +++ b/queue-5.15/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch @@ -0,0 +1,51 @@ +From 5a115cc9775f564f835a4260c86768fd2ec406c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 09:55:32 +0800 +Subject: sctp: auth: verify auth requirement when auth_chunk is NULL + +From: Qing Luo + +[ Upstream commit 8e04823c120b376ef7dab14b60ebf6823aa16c14 ] + +sctp_auth_chunk_verify() returns true unconditionally when +chunk->auth_chunk is NULL, silently skipping authentication. +This is incorrect when: + +1. skb_clone() failed in the BH receive path, leaving auth_chunk + NULL. In sctp_endpoint_bh_rcv() asoc is NULL for new + connections, so the early sctp_auth_recv_cid() check cannot + catch this. + +2. No AUTH chunk precedes COOKIE-ECHO, so skb_clone() is never + called and auth_chunk remains NULL. + +Fix by checking sctp_auth_recv_cid() when auth_chunk is NULL: +if authentication is required, return false to drop the chunk; +otherwise continue normally. + +Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk") +Signed-off-by: Qing Luo +Acked-by: Xin Long +Link: https://patch.msgid.link/20260721015532.120157-2-l1138897701@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/sm_statefuns.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 572055ee129f86..d57ec436775059 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -639,7 +639,7 @@ static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, + struct sctp_chunk auth; + + if (!chunk->auth_chunk) +- return true; ++ return !sctp_auth_recv_cid(chunk->chunk_hdr->type, asoc); + + /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo + * is supposed to be authenticated and we have to do delayed +-- +2.53.0 + diff --git a/queue-5.15/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch b/queue-5.15/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch new file mode 100644 index 0000000000..9cef5c4f65 --- /dev/null +++ b/queue-5.15/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch @@ -0,0 +1,46 @@ +From 3f9f047dc1184a0684ce69a6e12f54ebe3cf9672 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 03:20:21 +0000 +Subject: sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid + +From: HanQuan + +[ Upstream commit ff04b26794a16a8a879eb4fd2c02c2d6b03850e9 ] + +sctp_auth_ep_add_chunkid() uses SCTP_NUM_CHUNK_TYPES (20) as the +capacity limit for ep->auth_chunk_list, allowing it to hold up to +20 chunk entries (param_hdr.length up to 24). However, the copy +destination asoc->c.auth_chunks in struct sctp_cookie is only +SCTP_AUTH_MAX_CHUNKS (16) entries (20 bytes). When more than 16 +chunks are added, sctp_association_init() memcpy overflows the +destination by up to 4 bytes. + +Fix by using SCTP_AUTH_MAX_CHUNKS as the capacity limit, matching +the destination capacity. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Signed-off-by: HanQuan +Acked-by: Xin Long +Link: https://patch.msgid.link/20260713032021.3491702-1-zhoujian.zja@antgroup.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/auth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index 34964145514e6d..a983f96bb0c395 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -766,7 +766,7 @@ int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) + /* Check if we can add this chunk to the array */ + param_len = ntohs(p->param_hdr.length); + nchunks = param_len - sizeof(struct sctp_paramhdr); +- if (nchunks == SCTP_NUM_CHUNK_TYPES) ++ if (nchunks == SCTP_AUTH_MAX_CHUNKS) + return -EINVAL; + + p->chunks[nchunks] = chunk_id; +-- +2.53.0 + diff --git a/queue-5.15/sctp-validate-stream-count-in-sctp_process_strreset_.patch b/queue-5.15/sctp-validate-stream-count-in-sctp_process_strreset_.patch new file mode 100644 index 0000000000..2a5101498d --- /dev/null +++ b/queue-5.15/sctp-validate-stream-count-in-sctp_process_strreset_.patch @@ -0,0 +1,80 @@ +From 18b5b337f883b4c188b8a05db102ed0b03c09597 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 21:07:18 -0400 +Subject: sctp: validate stream count in sctp_process_strreset_inreq() + +From: Cen Zhang (Microsoft) + +[ Upstream commit 18ae07691d43183d270de8be9dc8e027906015d9 ] + +When processing a RESET_IN_REQUEST from a peer, +sctp_process_strreset_inreq() derives the stream count from the +parameter length but does not check whether the resulting +RESET_OUT_REQUEST would exceed SCTP_MAX_CHUNK_LEN. + +The OUT request header (sctp_strreset_outreq, 16 bytes) is 8 bytes +larger than the IN request header (sctp_strreset_inreq, 8 bytes). +Generally, the IP payload is bounded to 65535 bytes, so the stream +list cannot be large enough to trigger the overflow. However, on +interfaces with MTU > 65535 (e.g., loopback with IPv6 jumbograms), a +stream list that fits within the incoming IN parameter can cause a +__u16 overflow in sctp_make_strreset_req() when computing the OUT +request size, leading to an undersized skb allocation and a kernel +BUG: + + net/core/skbuff.c:207 skb_panic + net/core/skbuff.c:2625 skb_put + net/sctp/sm_make_chunk.c:1535 sctp_addto_chunk + net/sctp/sm_make_chunk.c:3695 sctp_make_strreset_req + net/sctp/stream.c:655 sctp_process_strreset_inreq + +The local setsockopt path validates the generated reset request size. +However, for an incoming-only reset, it accounts for the smaller IN +request even though the peer must generate an OUT request with the same +stream list. Such a request cannot be completed successfully by the +peer. + +Reject peer IN requests whose corresponding OUT request would exceed +SCTP_MAX_CHUNK_LEN. Also tighten the local check so it does not send an +IN request that would require an oversized OUT request from the peer. + +Fixes: 7f9d68ac944e ("sctp: implement sender-side procedures for SSN Reset Request Parameter") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/20260707203215.2752-1-blbllhy@gmail.com/ +Suggested-by: Xin Long +Signed-off-by: Cen Zhang (Microsoft) +Acked-by: Xin Long +Link: https://patch.msgid.link/20260710010718.20318-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/stream.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/stream.c b/net/sctp/stream.c +index d38e5431f359dc..34754ba23198ae 100644 +--- a/net/sctp/stream.c ++++ b/net/sctp/stream.c +@@ -308,7 +308,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc, + goto out; + + param_len += str_nums * sizeof(__u16) + +- sizeof(struct sctp_strreset_inreq); ++ (out ? sizeof(struct sctp_strreset_inreq) ++ : sizeof(struct sctp_strreset_outreq)); + } + + if (param_len > SCTP_MAX_CHUNK_LEN - +@@ -639,6 +640,9 @@ struct sctp_chunk *sctp_process_strreset_inreq( + + nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16); + str_p = inreq->list_of_streams; ++ if (nums * sizeof(__u16) + sizeof(struct sctp_strreset_outreq) > ++ SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_reconf_chunk)) ++ goto out; + for (i = 0; i < nums; i++) { + if (ntohs(str_p[i]) >= stream->outcnt) { + result = SCTP_STRRESET_ERR_WRONG_SSN; +-- +2.53.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 9b8c9fc633..bea4f987a3 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -76,3 +76,59 @@ crypto-rsa-pkcs1pad-don-t-warn-on-an-empty-digest.patch revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch +wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch +hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch +hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch +watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch +wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch +firewire-net-fix-fragmented-datagram-reassembly.patch +wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch +wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch +wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch +wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch +wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch +btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch +asoc-bt-sco-fix-bt-sco-pcm-wb-dai-widget-don-t-conne.patch +asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch +usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch +hwmon-occ-add-sysfs-entry-for-ips-idle-power-saver-s.patch +hwmon-occ-add-sysfs-entry-for-occ-mode.patch +hwmon-occ-add-sysfs-entries-for-additional-extended-.patch +hwmon-occ-delay-hwmon-registration-until-user-reques.patch +hwmon-occ-validate-poll-response-sensor-blocks.patch +net-packet-avoid-fanout-hook-re-registration-after-u.patch +rds-drop-incoming-messages-that-cross-network-namesp.patch +dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch +net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch +dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch +nfp-check-resource-mutex-allocation.patch +wan-wanxl-only-reset-hardware-after-bar-mapping.patch +wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch +iommu-amd-bound-the-early-acpi-hid-map.patch +iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch +wifi-mac80211-recalculate-tim-when-a-station-enters-.patch +amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch +sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch +sctp-validate-stream-count-in-sctp_process_strreset_.patch +nexthop-initialize-extack-in-nh_res_bucket_migrate.patch +tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch +wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch +wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch +net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch +net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch +sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch +vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch +tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch +net-stmmac-add-tc-flower-filter-for-ethertype-matchi.patch +net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch +net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch +octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch +ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch +hinic-remove-unused-ethtool-rss-user-configuration-b.patch +net-qrtr-restrict-socket-creation-to-the-initial-net.patch +net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch +net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch +net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch +raw-use-more-conventional-iterators.patch +net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch +bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch diff --git a/queue-5.15/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch b/queue-5.15/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch new file mode 100644 index 0000000000..fb2c5149cc --- /dev/null +++ b/queue-5.15/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch @@ -0,0 +1,47 @@ +From 6806ef3731531f610fe42fcf1595c6b60c55e3f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:49:35 -0300 +Subject: tipc: fix infinite loop in __tipc_nl_compat_dumpit + +From: Helen Koike + +[ Upstream commit 22f8aa35964e8f2ab026578f45befc9605fd1b28 ] + +cmd->dumpit callback can return a negative errno, causing an infinite +loop due to the while(len) condition. As the loop never terminates, +genl_mutex is never released, and other tasks waiting on it starve in D +state. + +Check dumpit's return value, propagate it and jump to err_out on error. + +Reported-by: syzbot+85d0bec020d805014a3a@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=85d0bec020d805014a3a +Fixes: d0796d1ef63d ("tipc: convert legacy nl bearer dump to nl compat") +Signed-off-by: Helen Koike +Reviewed-by: Tung Nguyen +Link: https://patch.msgid.link/20260713204940.647668-1-koike@igalia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/netlink_compat.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c +index 116a97e301443a..a8aef355bedc67 100644 +--- a/net/tipc/netlink_compat.c ++++ b/net/tipc/netlink_compat.c +@@ -226,6 +226,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, + int rem; + + len = (*cmd->dumpit)(buf, &cb); ++ if (len < 0) { ++ err = len; ++ goto err_out; ++ } + + nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) { + err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN, +-- +2.53.0 + diff --git a/queue-5.15/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch b/queue-5.15/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch new file mode 100644 index 0000000000..ed2a6c80a6 --- /dev/null +++ b/queue-5.15/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch @@ -0,0 +1,72 @@ +From 59efd9e886f783b940e37532309b0f5f4bea3e76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 00:15:41 -0400 +Subject: tipc: fix u16 MTU truncation in media and bearer MTU validation + +From: Cen Zhang (Microsoft) + +[ Upstream commit 9f29cd8a8e7901a2617c8064ce9f50fc67b97cb8 ] + +Both TIPC_NL_MEDIA_SET and TIPC_NL_BEARER_SET accept user-supplied +MTU values but only enforce a minimum bound, not a maximum. When a user +sets the MTU to a value exceeding U16_MAX (65535), it passes validation +but is silently truncated when assigned to u16 fields l->mtu and +l->advertised_mtu in tipc_link_create(). Values like 65536 (0x10000) +truncate to 0, causing a division by zero in tipc_link_set_queue_limits() +which computes TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE). Other overflowing +values (e.g. 65537-131071) produce small incorrect MTU values, resulting +in link malfunction behaviors. + +Crash stack (triggered as unprivileged user via user namespace): + + tipc_link_set_queue_limits net/tipc/link.c:2531 + tipc_link_create net/tipc/link.c:520 + tipc_node_check_dest net/tipc/node.c:1279 + tipc_disc_rcv net/tipc/discover.c:252 + tipc_rcv net/tipc/node.c:2129 + tipc_udp_recv net/tipc/udp_media.c:392 + +Two independent paths lack the upper bound check: +1. tipc_udp_mtu_bad() -- called from __tipc_nl_media_set() (MEDIA_SET) +2. inline check in __tipc_nl_bearer_set() at bearer.c:1160 (BEARER_SET) + +Fix both by rejecting MTU values above U16_MAX. + +Fixes: 901271e0403a ("tipc: implement configuration of UDP media MTU") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/CAB8m9WgETt0AjmFwE=F-CKjGXsK6_WDv0=kbYRcC8-noo+amnA@mail.gmail.com +Reviewed-by: Vadim Fedorenko +Signed-off-by: Cen Zhang (Microsoft) +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260714041541.307702-1-blbllhy@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tipc/netlink.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c +index 35e167de0fcf78..3fb31857de6b5e 100644 +--- a/net/tipc/netlink.c ++++ b/net/tipc/netlink.c +@@ -113,12 +113,16 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { + }; + + /* Properties valid for media, bearer and link */ ++static const struct netlink_range_validation tipc_nl_mtu_range = { ++ .max = U16_MAX, ++}; ++ + const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { + [TIPC_NLA_PROP_UNSPEC] = { .type = NLA_UNSPEC }, + [TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 }, +- [TIPC_NLA_PROP_MTU] = { .type = NLA_U32 }, ++ [TIPC_NLA_PROP_MTU] = NLA_POLICY_FULL_RANGE(NLA_U32, &tipc_nl_mtu_range), + [TIPC_NLA_PROP_BROADCAST] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_BROADCAST_RATIO] = { .type = NLA_U32 } + }; +-- +2.53.0 + diff --git a/queue-5.15/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch b/queue-5.15/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch new file mode 100644 index 0000000000..b6e3d679b6 --- /dev/null +++ b/queue-5.15/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch @@ -0,0 +1,93 @@ +From ae81c6ef9f4aaf5d6b47e30e307a1f74f9b08cf9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 02:07:04 -0600 +Subject: usb: atm: ueagle-atm: reject descriptors that confuse probe and + disconnect + +From: Diego Fernando Mancera Gomez + +[ Upstream commit 71132cedd1ecbc4032d76e9928c18a10f7e39b80 ] + +uea_probe() distinguishes a pre-firmware device from a post-firmware one +using the USB id (UEA_IS_PREFIRM()), and stores a different object as the +interface data in each case: a 'struct completion' for a pre-firmware +device (to be waited on in .disconnect()), or a 'struct usbatm_data' for a +post-firmware one. + +uea_disconnect() instead tells the two apart by the number of interfaces +of the active configuration (a pre-firmware device exposes a single +interface, ADI930 has 2 and eagle has 3), and casts the interface data +accordingly. + +Because the two handlers use different criteria, a crafted device that +advertises a pre-firmware id together with a multi-interface descriptor +(or a post-firmware id with a single interface) makes them disagree: the +small 'struct completion' stored by uea_probe() is then passed to +usbatm_usb_disconnect(), which casts it to 'struct usbatm_data' and takes +instance->serialize, reading past the end of the allocation: + + BUG: KASAN: slab-out-of-bounds in __mutex_lock+0x152a/0x1b80 + Read of size 8 at addr ffff8880470e2c60 by task kworker/1:2/982 + ... + __mutex_lock+0x152a/0x1b80 + usbatm_usb_disconnect+0x70/0x820 + uea_disconnect+0x133/0x2c0 + usb_unbind_interface+0x1dd/0x9e0 + ... + which belongs to the cache kmalloc-96 of size 96 + The buggy address is located 0 bytes to the right of + allocated 96-byte region [ffff8880470e2c00, ffff8880470e2c60) + +Reject such inconsistent descriptors in uea_probe() so that both handlers +always make the same pre/post-firmware decision. + +Reported-by: syzbot+e62a973f8322b3bbe3ac@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e62a973f8322b3bbe3ac +Fixes: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()") +Signed-off-by: Diego Fernando Mancera Gomez +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260717080704.1264-1-diegomancera.dev@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/atm/ueagle-atm.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c +index 661820041ca70d..6a282400027d68 100644 +--- a/drivers/usb/atm/ueagle-atm.c ++++ b/drivers/usb/atm/ueagle-atm.c +@@ -2591,6 +2591,7 @@ static struct usbatm_driver uea_usbatm_driver = { + static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + { + struct usb_device *usb = interface_to_usbdev(intf); ++ bool single_iface = usb->config->desc.bNumInterfaces == 1; + int ret; + + uea_enters(usb); +@@ -2600,6 +2601,22 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + le16_to_cpu(usb->descriptor.bcdDevice), + chip_name[UEA_CHIP_VERSION(id)]); + ++ /* ++ * uea_probe() decides between the pre-firmware and post-firmware case ++ * from the USB id and stores a different object as interface data in ++ * each case: a struct completion for a pre-firmware device, a struct ++ * usbatm_data for a post-firmware one. uea_disconnect() instead tells ++ * the two apart by the number of interfaces (a pre-firmware device ++ * exposes a single interface, ADI930 has 2 and eagle has 3). A crafted ++ * device advertising a pre-firmware id together with a multi-interface ++ * descriptor (or the other way around) makes the two disagree, so that ++ * usbatm_usb_disconnect() treats the small completion object as a ++ * struct usbatm_data and reads out of bounds. Reject such inconsistent ++ * descriptors so both paths make the same decision. ++ */ ++ if (UEA_IS_PREFIRM(id) != single_iface) ++ return -ENODEV; ++ + usb_reset_device(usb); + + if (UEA_IS_PREFIRM(id)) { +-- +2.53.0 + diff --git a/queue-5.15/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch b/queue-5.15/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch new file mode 100644 index 0000000000..a47882e065 --- /dev/null +++ b/queue-5.15/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch @@ -0,0 +1,84 @@ +From b393218fa2e3253166021abca087574a8025cd8c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 07:09:15 -0700 +Subject: vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets + +From: Harshaka Narayana + +[ Upstream commit 34a71f5361fc3adb5b7138da78750b0d535a8252 ] + +vmxnet3_get_hdr_len() assumes gdesc->rcd.v4/v6/tcp always describe the +outer header, but for a Geneve-encapsulated packet the device can set +them based on the inner header instead, signalled by the +VMXNET3_RCD_HDR_INNER_SHIFT bit in the completion descriptor. Since the +function never skips the outer encapsulation, this mismatch triggers: + +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP), because the outer + protocol is UDP (Geneve), not TCP. +- BUG_ON(hdr.eth->h_proto != ...), when the tunnel's outer and inner + IP versions differ (e.g. outer IPv6/inner IPv4 or vice versa). + +Check VMXNET3_RCD_HDR_INNER_SHIFT up front and bail out, since the +function cannot locate the inner header it would need to parse. Also +convert the remaining BUG_ON()s in this function to return 0 +defensively. + +Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)") +Signed-off-by: Harshaka Narayana +Reviewed-by: Ronak Doshi +Reviewed-by: Sankararaman Jayaraman +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260713140915.3381715-1-harshaka.narayana@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c +index 269e0bf1301a70..ce8d10a754084d 100644 +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -1319,7 +1319,11 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + struct ipv6hdr *ipv6; + struct tcphdr *tcp; + } hdr; +- BUG_ON(gdesc->rcd.tcp == 0); ++ ++ /* v4/v6/tcp then describe the inner header, which we can't locate. */ ++ if ((le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT)) || ++ gdesc->rcd.tcp == 0) ++ return 0; + + maplen = skb_headlen(skb); + if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen)) +@@ -1333,15 +1337,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + + hdr.eth = eth_hdr(skb); + if (gdesc->rcd.v4) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)); ++ if (hdr.eth->h_proto != htons(ETH_P_IP) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)) ++ return 0; ++ + hdr.ptr += hlen; +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP); ++ if (hdr.ipv4->protocol != IPPROTO_TCP) ++ return 0; ++ + hlen = hdr.ipv4->ihl << 2; + hdr.ptr += hdr.ipv4->ihl << 2; + } else if (gdesc->rcd.v6) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)); ++ if (hdr.eth->h_proto != htons(ETH_P_IPV6) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)) ++ return 0; ++ + hdr.ptr += hlen; + /* Use an estimated value, since we also need to handle + * TSO case. +-- +2.53.0 + diff --git a/queue-5.15/wan-wanxl-only-reset-hardware-after-bar-mapping.patch b/queue-5.15/wan-wanxl-only-reset-hardware-after-bar-mapping.patch new file mode 100644 index 0000000000..a4a2cd898b --- /dev/null +++ b/queue-5.15/wan-wanxl-only-reset-hardware-after-bar-mapping.patch @@ -0,0 +1,51 @@ +From 209bf777b50989ec6dea3f2d79cdd6a4ef668c2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:15 +0800 +Subject: wan: wanxl: Only reset hardware after BAR mapping + +From: Ruoyu Wang + +[ Upstream commit 91957b89da995607cb654b1f9a3c126ddbaee10f ] + +wanxl_pci_init_one() stores the freshly allocated card in driver data +before the PLX BAR is mapped. Several early probe failures then unwind +through wanxl_pci_remove_one(), including failure to allocate the coherent +status area or to restore the DMA mask. + +wanxl_pci_remove_one() unconditionally calls wanxl_reset(), and +wanxl_reset() dereferences card->plx. On those early failures card->plx +is still NULL, so the error path can dereference a NULL MMIO pointer. + +Only issue the hardware reset once the BAR mapping exists. The remaining +cleanup in wanxl_pci_remove_one() already checks whether later resources +were allocated. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ruoyu Wang +Link: https://patch.msgid.link/20260708143415.3169358-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/wan/wanxl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c +index 5a9e262188efe1..c38dd741401e13 100644 +--- a/drivers/net/wan/wanxl.c ++++ b/drivers/net/wan/wanxl.c +@@ -514,7 +514,8 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) + if (card->irq) + free_irq(card->irq, card); + +- wanxl_reset(card); ++ if (card->plx) ++ wanxl_reset(card); + + for (i = 0; i < RX_QUEUE_LENGTH; i++) + if (card->rx_skbs[i]) { +-- +2.53.0 + diff --git a/queue-5.15/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch b/queue-5.15/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch new file mode 100644 index 0000000000..57f4ed3f4c --- /dev/null +++ b/queue-5.15/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch @@ -0,0 +1,48 @@ +From e333b47b9d5dcfcee709fa5329d28450801a3659 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:18:03 +0000 +Subject: watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() + +From: Tzung-Bi Shih + +[ Upstream commit 7362ba0f9c96ac3ad6a2ca3995bd9fc9a28a8661 ] + +When a watchdog governor is unregistered, it updates existing watchdog +devices that were using this governor by falling back to `default_gov`. + +If the governor being unregistered is currently set as `default_gov`, +the `default_gov` is never cleared. This leads to 2 use-after-free +issues: +1. New watchdog devices registered after this point will inherit the + dangling `default_gov`. +2. Existing watchdog devices using the unregistered governor will have + their `wdd->gov` reassigned to the dangling `default_gov`. + +Fix the UAF by clearing `default_gov` if it matches the governor being +unregistered. + +Fixes: da0d12ff2b82 ("watchdog: pretimeout: add panic pretimeout governor") +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20260707101803.3598173-1-tzungbi@kernel.org +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/watchdog_pretimeout.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c +index 376a495ab80c49..3c109f1db8f0e5 100644 +--- a/drivers/watchdog/watchdog_pretimeout.c ++++ b/drivers/watchdog/watchdog_pretimeout.c +@@ -165,6 +165,8 @@ void watchdog_unregister_governor(struct watchdog_governor *gov) + } + + spin_lock_irq(&pretimeout_lock); ++ if (default_gov == gov) ++ default_gov = NULL; + list_for_each_entry(p, &pretimeout_list, entry) + if (p->wdd->gov == gov) + p->wdd->gov = default_gov; +-- +2.53.0 + diff --git a/queue-5.15/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch b/queue-5.15/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch new file mode 100644 index 0000000000..c93b55b93c --- /dev/null +++ b/queue-5.15/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch @@ -0,0 +1,48 @@ +From 36573d19632a583dda33311c1bc1db95335d4a1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 May 2026 11:42:52 +0000 +Subject: wifi: ath11k: fix potential buffer underflow in + ath11k_hal_rx_msdu_list_get() + +From: Dmitry Morgun + +[ Upstream commit 7f11e70629650ff6ea140984e5ce188b775b2683 ] + +When the first entry in msdu_details has a zero buffer address, +the code accesses msdu_details[i - 1] with i == 0, causing a +buffer underflow. + +Fix similarly to ath12k_wifi7_hal_rx_msdu_list_get() by adding +a separate check for i == 0 before the main condition to prevent +the out-of-bounds access. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Dmitry Morgun +Reviewed-by: Rameshkumar Sundaram +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20260530114252.42615-1-d.morgun@ispras.ru +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 318c3bfd45fdd2..c075ab49345643 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -4470,6 +4470,9 @@ static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar, + msdu_details = &msdu_link->msdu_link[0]; + + for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) { ++ if (!i && FIELD_GET(BUFFER_ADDR_INFO0_ADDR, ++ msdu_details[i].buf_addr_info.info0) == 0) ++ break; + if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR, + msdu_details[i].buf_addr_info.info0) == 0) { + msdu_desc_info = &msdu_details[i - 1].rx_msdu_info; +-- +2.53.0 + diff --git a/queue-5.15/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch b/queue-5.15/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch new file mode 100644 index 0000000000..15199b66cd --- /dev/null +++ b/queue-5.15/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch @@ -0,0 +1,49 @@ +From 781c6a3cc1b897d3fa3b113b28ee19016d8f7ab2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:50:08 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware IE lengths in connect event + +From: Tristan Madani + +[ Upstream commit 6b47b29730de3232b919d8362749f6814c5f2a33 ] + +The firmware-controlled beacon_ie_len, assoc_req_len, and assoc_resp_len +fields in ath6kl_wmi_connect_event_rx() are not validated against the +buffer length. Their sum (up to 765) can exceed the actual WMI event +data, causing out-of-bounds reads during IE parsing and state corruption +of wmi->is_wmm_enabled. + +Add a check that the total IE length fits within the buffer. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20260421135009.348084-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index 55607e3adacb24..bae12143eebb69 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -874,6 +874,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, + + ev = (struct wmi_connect_event *) datap; + ++ if (len < sizeof(*ev) + ev->beacon_ie_len + ++ ev->assoc_req_len + ev->assoc_resp_len) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, ++ "connect event: IE lengths %u+%u+%u exceed buffer %d\n", ++ ev->beacon_ie_len, ev->assoc_req_len, ++ ev->assoc_resp_len, len); ++ return -EINVAL; ++ } + if (vif->nw_type == AP_NETWORK) { + /* AP mode start/STA connected event */ + struct net_device *dev = vif->ndev; +-- +2.53.0 + diff --git a/queue-5.15/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch b/queue-5.15/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch new file mode 100644 index 0000000000..3c1914bec2 --- /dev/null +++ b/queue-5.15/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch @@ -0,0 +1,53 @@ +From 5b5a0f7725ff3fccbc427cc963bd8b536bf2736b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jun 2026 23:29:07 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware num_msg in TX complete + handler + +From: Tristan Madani + +[ Upstream commit 3a21c89215cc18f1a97c5e5bfd1da6d4f3d44495 ] + +The firmware-controlled num_msg field (u8, 0-255) drives the loop in +ath6kl_wmi_tx_complete_event_rx() without validation against the buffer +length. This allows out-of-bounds reads of up to 1020 bytes past the +WMI event buffer when the firmware sends an inflated num_msg. + +Add a check that the buffer is large enough to hold the fixed struct +and the num_msg variable-length entries. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Link: https://patch.msgid.link/20260625232907.3620746-1-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index bd1ef633499780..55607e3adacb24 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -484,6 +484,18 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) + + evt = (struct wmi_tx_complete_event *) datap; + ++ if (len < sizeof(*evt)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d\n", ++ len); ++ return -EINVAL; ++ } ++ ++ if (len < sizeof(*evt) + evt->num_msg * sizeof(struct tx_complete_msg_v1)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d for %u msgs\n", ++ len, evt->num_msg); ++ return -EINVAL; ++ } ++ + ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", + evt->num_msg, evt->msg_len, evt->msg_type); + +-- +2.53.0 + diff --git a/queue-5.15/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch b/queue-5.15/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch new file mode 100644 index 0000000000..9b0c16d70e --- /dev/null +++ b/queue-5.15/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch @@ -0,0 +1,90 @@ +From 3555f7a1450c1d81bd7b5f0da585afe9ca97d50f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 08:32:10 -0700 +Subject: wifi: ath9k: hif_usb: don't dereference hif_dev after re-arming + firmware request +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Cheng Yongkang + +[ Upstream commit dad9f96945d77ecd4708f730c06ef54dcd8cc057 ] + +ath9k_hif_request_firmware() re-arms an asynchronous firmware load via +request_firmware_nowait(), passing hif_dev as the completion context, and +then still dereferences hif_dev: + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", + hif_dev->fw_name); + +The re-armed callback ath9k_hif_usb_firmware_cb() runs on the "events" +workqueue and, when the firmware is missing, walks the retry chain into +ath9k_hif_usb_firmware_fail() -> complete_all(&hif_dev->fw_done). That +releases the wait_for_completion(&hif_dev->fw_done) in a concurrent +ath9k_hif_usb_disconnect(), which then kfree()s hif_dev. The trailing +dev_info() in the frame that re-armed the request can therefore read freed +memory (hif_dev->udev, the first field of struct hif_device_usb): + + BUG: KASAN: slab-use-after-free in ath9k_hif_request_firmware + Read of size 8 ... by task kworker/... + ath9k_hif_request_firmware + ath9k_hif_usb_firmware_cb drivers/net/wireless/ath/ath9k/hif_usb.c:1247 + request_firmware_work_func + Allocated by ...: + ath9k_hif_usb_probe drivers/net/wireless/ath/ath9k/hif_usb.c + Freed by ...: + ath9k_hif_usb_disconnect -> kfree drivers/net/wireless/ath/ath9k/hif_usb.c + +The fw_done barrier only makes disconnect wait for the firmware chain to +*terminate*; it does not protect the outer ath9k_hif_request_firmware() +frame that re-armed the request and keeps touching hif_dev afterwards. + +Drop the post-request dev_info(): it is the only use of hif_dev after the +async request is armed, and it is purely informational (the dev_err() on the +failure path runs only when request_firmware_nowait() did not arm a callback, +so hif_dev is still alive there). + +This was first reported by syzbot as a single, non-reproduced crash that was +later auto-obsoleted, and was independently rediscovered by the reFuzz fuzzer, +which produced a C reproducer (USB-gadget connect/disconnect of an ath9k_htc +device whose firmware download fails). The vulnerable code is unchanged and +still present in v7.1-rc6, where the slab-use-after-free reproduces under KASAN +once the (sub-microsecond) race window is widened. + +Fixes: e904cf6fe230 ("ath9k_htc: introduce support for different fw versions") +Reported-by: syzbot+50122cbc2874b1eb25b0@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=50122cbc2874b1eb25b0 +Signed-off-by: Cheng Yongkang +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260605153210.20471-1-1020691186@qq.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index 6c73c0c0b82a99..7650f14dca8dad 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -1227,15 +1227,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, + ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, + &hif_dev->udev->dev, GFP_KERNEL, + hif_dev, ath9k_hif_usb_firmware_cb); +- if (ret) { ++ if (ret) + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Async request for firmware %s failed\n", + hif_dev->fw_name); +- return ret; +- } +- +- dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", +- hif_dev->fw_name); + + return ret; + } +-- +2.53.0 + diff --git a/queue-5.15/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch b/queue-5.15/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch new file mode 100644 index 0000000000..d385325100 --- /dev/null +++ b/queue-5.15/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch @@ -0,0 +1,69 @@ +From bf96423d82191266eb39afa4b60b470a7fda69ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 May 2026 16:38:59 +0800 +Subject: wifi: brcmfmac: fix 802.1X-SHA256 call trace warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Shelley Yang + +[ Upstream commit 7cb34f6c4fe8a68af621d870abe63bfca2275dd6 ] + +Based on wpa_auth as 1x_256 mode, need to set up +"use_fwsup" with BRCMF_PROFILE_FWSUP_1X. +Or it will happen trace warning when call brcmf_cfg80211_set_pmk(). + +[ 4481.831101] ------------[ cut here ]------------ +[ 4481.831102] WARNING: CPU: 1 PID: 2997 at +drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:7242 brcmf_cfg80211_set_pmk+0x77/0xd0 [brcmfmac] +[...] +[ 4481.831202] Call Trace: +[ 4481.831204]   +[ 4481.831205]  nl80211_set_pmk+0x183/0x250 [cfg80211] +[ 4481.831233]  genl_family_rcv_msg_doit+0xea/0x150 +[ 4481.831237]  genl_rcv_msg+0x104/0x240 +[ 4481.831239]  ? cfg80211_probe_status+0x2c0/0x2c0 [cfg80211] +[ 4481.831257]  ? genl_family_rcv_msg_doit+0x150/0x150 +[ 4481.831259]  netlink_rcv_skb+0x4e/0x100 +[ 4481.831261]  genl_rcv+0x24/0x40 +[ 4481.831262]  netlink_unicast+0x236/0x380 +[ 4481.831264]  netlink_sendmsg+0x250/0x4b0 +[ 4481.831266]  sock_sendmsg+0x5c/0x70 +[ 4481.831269]  ____sys_sendmsg+0x236/0x2b0 +[ 4481.831271]  ? copy_msghdr_from_user+0x6d/0xa0 +[ 4481.831272]  ___sys_sendmsg+0x86/0xd0 +[ 4481.831274]  ? avc_has_perm+0x8c/0x1a0 +[ 4481.831276]  ? preempt_count_add+0x6a/0xa0 +[ 4481.831279]  ? sock_has_perm+0x82/0xa0 +[ 4481.831280]  __sys_sendmsg+0x57/0xa0 +[ 4481.831282]  do_syscall_64+0x38/0x90 +[ 4481.831284]  entry_SYSCALL_64_after_hwframe+0x63/0xcd +[ 4481.831286] RIP: 0033:0x7fd270d369b4 + +Fixes: 2526ff21aa77 ("brcmfmac: support 4-way handshake offloading for 802.1X") +Signed-off-by: Shelley Yang +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260525083859.581246-1-shelley.yang@infineon.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index ff101ee5c364c3..13ea5f0c8e1e1e 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -1790,7 +1790,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) + sme->crypto.cipher_group); + return -EINVAL; + } +- } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { ++ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_1X_SHA256)) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + val = WPA2_AUTH_UNSPECIFIED; +-- +2.53.0 + diff --git a/queue-5.15/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch b/queue-5.15/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch new file mode 100644 index 0000000000..914e7da00f --- /dev/null +++ b/queue-5.15/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch @@ -0,0 +1,48 @@ +From 784564af0656b296ae0a233d2a313efea3c976be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:26 +0000 +Subject: wifi: carl9170: bound memcpy length in cmd callback to prevent OOB + read + +From: Tristan Madani + +[ Upstream commit 4cde55b2feff9504d1f993ab80e84e7ccb62791c ] + +When the firmware sends a command response with a length mismatch, +carl9170_cmd_callback() logs the mismatch and calls carl9170_restart() +but then falls through to memcpy(ar->readbuf, buffer + 4, len - 4). +Since len comes from the firmware and can exceed ar->readlen, this +copies more data than the readbuf was allocated for. + +Bound the memcpy to min(len - 4, ar->readlen) so that the response +is still completed -- avoiding repeated restarts from queued garbage -- +while preventing an overread past the response buffer. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-2-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 908c4c8b7f8256..9a25c2a540b95f 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -150,7 +150,8 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) + spin_lock(&ar->cmd_lock); + if (ar->readbuf) { + if (len >= 4) +- memcpy(ar->readbuf, buffer + 4, len - 4); ++ memcpy(ar->readbuf, buffer + 4, ++ min_t(u32, len - 4, ar->readlen)); + + ar->readbuf = NULL; + } +-- +2.53.0 + diff --git a/queue-5.15/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch b/queue-5.15/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch new file mode 100644 index 0000000000..049d0a6558 --- /dev/null +++ b/queue-5.15/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch @@ -0,0 +1,46 @@ +From 5ecc0c3b0ee445627e24b654f4390fb2a276b9d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:28 +0000 +Subject: wifi: carl9170: fix buffer overflow in rx_stream failover path + +From: Tristan Madani + +[ Upstream commit a1a21995c2e1cc2ca6b2226cfe4f5f018370182a ] + +The failover continuation in carl9170_rx_stream() copies the full tlen +from the second USB transfer instead of capping at rx_failover_missing +bytes. When both transfers are near maximum size, the total exceeds the +65535-byte failover SKB, triggering skb_over_panic. + +Limit the copy size to the missing byte count. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-4-tristmd@gmail.com +[Fix checkpatch CHECK:PARENTHESIS_ALIGNMENT] +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 9a25c2a540b95f..bda30b1f940459 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -918,7 +918,9 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) + } + } + +- skb_put_data(ar->rx_failover, tbuf, tlen); ++ skb_put_data(ar->rx_failover, tbuf, ++ min_t(unsigned int, tlen, ++ ar->rx_failover_missing)); + ar->rx_failover_missing -= tlen; + + if (ar->rx_failover_missing <= 0) { +-- +2.53.0 + diff --git a/queue-5.15/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch b/queue-5.15/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch new file mode 100644 index 0000000000..ca258ad7e0 --- /dev/null +++ b/queue-5.15/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch @@ -0,0 +1,42 @@ +From 694350d434300b364e4fcc1028468305253629c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:27 +0000 +Subject: wifi: carl9170: fix OOB read from off-by-two in TX status handler + +From: Tristan Madani + +[ Upstream commit a3f42f1049ad80c65560d2b078ad426c3134f78d ] + +The bounds check in carl9170_tx_process_status() uses +`i > ((cmd->hdr.len / 2) + 1)` which is off by two, allowing +2 extra iterations past valid _tx_status entries when the firmware- +controlled hdr.ext exceeds hdr.len/2. Fix by using the correct +comparison `i >= (cmd->hdr.len / 2)`. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c +index f9e1306ac74fe3..db49f334e52e2d 100644 +--- a/drivers/net/wireless/ath/carl9170/tx.c ++++ b/drivers/net/wireless/ath/carl9170/tx.c +@@ -692,7 +692,7 @@ void carl9170_tx_process_status(struct ar9170 *ar, + unsigned int i; + + for (i = 0; i < cmd->hdr.ext; i++) { +- if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) { ++ if (WARN_ON(i >= (cmd->hdr.len / 2))) { + print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE, + (void *) cmd, cmd->hdr.len + 4); + break; +-- +2.53.0 + diff --git a/queue-5.15/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch b/queue-5.15/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch new file mode 100644 index 0000000000..441d5d4f59 --- /dev/null +++ b/queue-5.15/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch @@ -0,0 +1,56 @@ +From e446d675d4665178ffb8849af41dc67976cb0a1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:17:51 +1000 +Subject: wifi: mac80211: recalculate TIM when a station enters power save + +From: Andrew Pope + +[ Upstream commit a007a384c9eb17610f53a53e2f59944c31f1565a ] + +When an AP buffers frames for a station on its per-station TXQs and the +station subsequently enters power save, sta_ps_start() records the +buffered TIDs in txq_buffered_tids but does not update the TIM. The +station's TIM bit is only ever set when a further frame is buffered +while the station is already asleep +(ieee80211_tx_h_unicast_ps_buf() -> sta_info_recalc_tim()). + +If no further downlink frame arrives for that station the beacon +TIM never advertises the buffered traffic. A station relying on the +TIM then remains in doze indefinitely on top of a non-empty queue. Its +TXQs were removed from the scheduler's active list at PS entry, nothing +pages it, and the flow deadlocks until an unrelated event wakes the +station. + +Recalculate the TIM at the end of sta_ps_start(), so traffic +already buffered at PS entry is advertised immediately. +sta_info_recalc_tim() already consults txq_buffered_tids, which is +updated above, and is safe in this context (it is already called +from equivalent paths such as the tx handlers and +ieee80211_handle_filtered_frame()). + +Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation") +Signed-off-by: Andrew Pope +Link: https://patch.msgid.link/20260717011751.79524-1-andrew.pope@morsemicro.com +[add wifi: subject prefix] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 15933e9abc9b9e..dda1ee11f8a8cb 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1591,6 +1591,8 @@ static void sta_ps_start(struct sta_info *sta) + else + clear_bit(tid, &sta->txq_buffered_tids); + } ++ ++ sta_info_recalc_tim(sta); + } + + static void sta_ps_end(struct sta_info *sta) +-- +2.53.0 + diff --git a/queue-5.15/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch b/queue-5.15/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..61ace2aa4d --- /dev/null +++ b/queue-5.15/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,38 @@ +From 7c97fc7e81ebb478bf76b785b7fd2c9a6a3915ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:24:59 +0200 +Subject: wifi: mt76: connac: fix possible NULL-pointer deref in + mt76_connac_mcu_uni_bss_he_tlv() + +From: Lorenzo Bianconi + +[ Upstream commit 2c1fb2335f5e3afb34f91bc07ecb63517c328090 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: d0e274af2f2e4 ("mt76: mt76_connac: create mcu library") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-1-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index a5dda20f39f3a3..3143b3f2ba6ad9 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -1191,6 +1191,8 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct bss_info_uni_he *he; + + cap = mt76_connac_get_he_phy_cap(phy, vif); ++ if (!cap) ++ return; + + he = (struct bss_info_uni_he *)tlv; + he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; +-- +2.53.0 + diff --git a/queue-5.15/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch b/queue-5.15/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch new file mode 100644 index 0000000000..537ea113c6 --- /dev/null +++ b/queue-5.15/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch @@ -0,0 +1,104 @@ +From 68dfe609a067af41bd3c852c8c9218fde63a2bce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 22:57:11 +0900 +Subject: wifi: mwifiex: bound uAP association event IEs to the event buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit f0858bfc7d3cab411a447b88e3ef970e575032c9 ] + +mwifiex_process_uap_event() handles EVENT_UAP_STA_ASSOC by exposing the +(re)association request IEs that the firmware copies into the event: + + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - (u8 *)&event->frame_control; + sinfo->assoc_req_ies_len = le16_to_cpu(event->len) - (u16)len; + +event->len is supplied by the device firmware and is never validated, +and the subtraction is unchecked. assoc_req_ies points into +adapter->event_body[MAX_EVENT_SIZE], a fixed-size array embedded in the +kmalloc()'d struct mwifiex_adapter. + +On the ap_11n_enabled path mwifiex_set_sta_ht_cap() walks these IEs with +cfg80211_find_ie(), whose for_each_element() loop dereferences each +element header. A firmware-reported event->len larger than the bytes +actually received makes assoc_req_ies_len describe IEs that extend past +event_body, so the walk reads out of the adapter slab object, a +slab-out-of-bounds read (KASAN: slab-out-of-bounds in cfg80211_find_ie). +An event->len smaller than the header instead makes the int subtraction +negative, which wraps to a huge size_t when stored in assoc_req_ies_len. +The same length is handed to cfg80211_new_sta(), so a more modest +over-claim can also copy stale event_body bytes into the +NL80211_CMD_NEW_STATION notification. + +A malicious or malfunctioning mwifiex device (USB/SDIO/PCIe) can deliver +such an event while the interface is in AP/uAP mode. + +Validate event->len before use: reject a length that underflows the +header or that would place the IEs outside the event_body[] buffer the +event was copied into. event->len here is struct mwifiex_assoc_event.len, +a payload field internal to this event, not the transport frame length, +so it is validated in this handler rather than at the generic +MWIFIEX_TYPE_EVENT receive path, which only sees the event cause and the +transport frame length. The bound is against event_body[MAX_EVENT_SIZE] +rather than the actually-received length because the transports store the +event differently (USB and SDIO leave the 4-byte event header in +event_skb, PCIe strips it via skb_pull), whereas event_body is the single +fixed buffer all of them copy the event into. This is the event-path +analogue of the receive-path bounds checks added in commit 119585281617 +("wifi: mwifiex: Fix OOB and integer underflow when rx packets"). + +Fixes: e568634ae7ac ("mwifiex: add AP event handling framework") +Signed-off-by: HE WEI (ギカク) +Reviewed-by: Francesco Dolcini +Link: https://patch.msgid.link/20260715135711.34688-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + .../net/wireless/marvell/mwifiex/uap_event.c | 24 +++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c +index 9121447e270184..eebfc0eaf9056f 100644 +--- a/drivers/net/wireless/marvell/mwifiex/uap_event.c ++++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c +@@ -135,11 +135,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) + len = ETH_ALEN; + + if (len != -1) { ++ u16 evt_len = le16_to_cpu(event->len); ++ + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - + (u8 *)&event->frame_control; +- sinfo->assoc_req_ies_len = +- le16_to_cpu(event->len) - (u16)len; ++ ++ /* ++ * event->len is reported by the device firmware ++ * and is not otherwise validated. Reject a ++ * length that underflows the header, or that ++ * would place the association request IEs ++ * outside the fixed-size event_body[] buffer the ++ * event was copied into; otherwise the IE walk ++ * in mwifiex_set_sta_ht_cap() reads past ++ * event_body and out of the adapter slab object. ++ */ ++ if (evt_len < len || ++ (u8 *)&event->frame_control + evt_len > ++ adapter->event_body + MAX_EVENT_SIZE) { ++ mwifiex_dbg(adapter, ERROR, ++ "invalid STA assoc event length\n"); ++ kfree(sinfo); ++ return -1; ++ } ++ sinfo->assoc_req_ies_len = evt_len - (u16)len; + } + } + cfg80211_new_sta(priv->netdev, event->sta_addr, sinfo, +-- +2.53.0 + diff --git a/queue-6.1/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch b/queue-6.1/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch new file mode 100644 index 0000000000..20b7602058 --- /dev/null +++ b/queue-6.1/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch @@ -0,0 +1,58 @@ +From 12046a45c98e4c5738195c3b56f4996914753d3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 15:20:06 +0530 +Subject: amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN + +From: Prashanth Kumar KR + +[ Upstream commit 4bf22afe53a1de4b44b04cf677fd5199089cbdff ] + +MAC_AUTO_SW (VR_MII_DIG_CTRL1 bit 9) enables automatic XPCS speed +mode switching after CL37 auto-negotiation and is only meaningful in +SGMII MAC mode. The original code unconditionally set this bit on +every call to xgbe_an37_set(), including when called from +xgbe_an37_disable() with enable=false. This left MAC_AUTO_SW=1 after +AN was disabled, causing the XPCS to autonomously switch speed from +stale AN state during subsequent mode changes, breaking SGMII speed +negotiation on 1G copper SFP modules. + +Patrick: This was breaking negotiation for all 1G SFP modules, +not just copper modules. + +Fixes: 42fd432fe6d3 ("amd-xgbe: align CL37 AN sequence as per databook") +Reported-by: Patrick Oppenlander +Link: https://lore.kernel.org/netdev/CAEg67GmFS0Q4oSZkz8zWdOzckSth9_vBPiOy6a7-d697C2w2Xg@mail.gmail.com +Signed-off-by: Prashanth Kumar KR +Tested-by: Patrick Oppenlander +Link: https://patch.msgid.link/20260709095006.3683940-1-prashanthkumar.k.r@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index ebb8b3e5b9a882..01c37ffc9ceb81 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -364,9 +364,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, + + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); + +- reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); +- reg |= XGBE_VEND2_MAC_AUTO_SW; +- XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ if (pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) { ++ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); ++ if (enable) ++ reg |= XGBE_VEND2_MAC_AUTO_SW; ++ else ++ reg &= ~XGBE_VEND2_MAC_AUTO_SW; ++ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ } + } + + static void xgbe_an37_restart(struct xgbe_prv_data *pdata) +-- +2.53.0 + diff --git a/queue-6.1/amt-make-the-head-writable-before-rewriting-the-l2-h.patch b/queue-6.1/amt-make-the-head-writable-before-rewriting-the-l2-h.patch new file mode 100644 index 0000000000..486ac02eae --- /dev/null +++ b/queue-6.1/amt-make-the-head-writable-before-rewriting-the-l2-h.patch @@ -0,0 +1,67 @@ +From 76b7ab7d6d9b04ae2c7c4c46a6585dc759dd09aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:19:34 -0400 +Subject: amt: make the head writable before rewriting the L2 header + +From: Michael Bommarito + +[ Upstream commit 53969d704fa5b7c1751e277fac96bfc22b435eac ] + +amt_multicast_data_handler(), amt_membership_query_handler() and +amt_update_handler() rewrite the ethernet header of the decapsulated skb +in place (eth->h_proto, eth->h_dest and, for the query, also +eth->h_source) before handing it up the stack. The skb head may be +shared, for example when a packet tap has cloned it on the underlay +interface, so writing through it corrupts the other reader's copy. + +Call skb_cow_head() before the rewrite so the head is private. It is +placed before the pointers into the head are (re-)derived, so a +reallocation caused by the copy is picked up by those derivations. + +Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") +Signed-off-by: Michael Bommarito +Reviewed-by: Simon Horman +Reviewed-by: Taehee Yoo +Link: https://patch.msgid.link/20260711151934.2955226-3-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/amt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/amt.c b/drivers/net/amt.c +index 64aff304c51c66..4799f8fd03c45c 100644 +--- a/drivers/net/amt.c ++++ b/drivers/net/amt.c +@@ -2315,6 +2315,9 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + skb_reset_mac_header(skb); + skb_pull(skb, sizeof(*eth)); + ++ if (skb_cow_head(skb, 0)) ++ return true; ++ + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + iph = ip_hdr(skb); +@@ -2391,6 +2394,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_network_header(skb); + eth = eth_hdr(skb); + ether_addr_copy(h_source, oeth->h_source); ++ if (skb_cow_head(skb, 0)) ++ return true; + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + +@@ -2516,6 +2521,9 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + ++ if (skb_cow_head(skb, 0)) ++ return true; ++ + iph = ip_hdr(skb); + if (iph->version == 4) { + if (ip_mc_check_igmp(skb)) { +-- +2.53.0 + diff --git a/queue-6.1/amt-re-read-skb-header-pointers-after-every-pull.patch b/queue-6.1/amt-re-read-skb-header-pointers-after-every-pull.patch new file mode 100644 index 0000000000..0b5b686e34 --- /dev/null +++ b/queue-6.1/amt-re-read-skb-header-pointers-after-every-pull.patch @@ -0,0 +1,367 @@ +From f11e1ca7ac2315deab39e293e43de806a8b5a6d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:19:33 -0400 +Subject: amt: re-read skb header pointers after every pull + +From: Michael Bommarito + +[ Upstream commit 3656a79f94c471827a08f2cacce5f94ad5e52c24 ] + +Several AMT receive and transmit paths cache a pointer into the skb head +(ip_hdr(), ipv6_hdr(), eth_hdr() or the AMT message header) and then call +a helper that can reallocate that head before the cached pointer is used +again. pskb_may_pull(), ip_mc_may_pull(), ipv6_mc_may_pull(), +iptunnel_pull_header(), ip_mc_check_igmp() and ipv6_mc_check_mld() can all +free the old head and move the data, so a pointer taken before the call +dangles afterwards and the later access is a use-after-free of the freed +head. + +The affected sites are: + + amt_rcv() caches ip_hdr() before amt_parse_type() pulls, then reads + iph->saddr. + + amt_dev_xmit() caches ip_hdr()/ipv6_hdr() before ip_mc_check_igmp()/ + ipv6_mc_check_mld() and pskb_may_pull(), then reads the group address. + + amt_multicast_data_handler() caches eth_hdr() before pskb_may_pull(), + then writes the L2 header. + + amt_membership_query_handler() caches the AMT header, the outer and + inner eth_hdr() and ip_hdr() before iptunnel_pull_header() and several + pulls, then reads and writes them. + + amt_igmpv3_report_handler() and amt_mldv2_report_handler() cache + ip_hdr()/ipv6_hdr() and the current group record and read the record + count from the report header inside the record loop, across the + *_mc_may_pull() calls. + + amt_update_handler() caches ip_hdr() and the AMT membership-update + header before pskb_may_pull(), iptunnel_pull_header(), + ip_mc_check_igmp() and the report handler, then reads iph->daddr and + amtmu->nonce / amtmu->response_mac. + +Fix each site by either snapshotting the scalar that is used after the +pull before the first pull runs, or re-deriving the header pointer from +the skb after the last pull that can move the head. Values that are +stable across the pull (source and group address, the response MAC and +nonce, the record count, the outer source MAC) are snapshotted; pointers +that are written through or read repeatedly are re-derived. + +Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") +Signed-off-by: Michael Bommarito +Reviewed-by: Simon Horman +Reviewed-by: Taehee Yoo +Link: https://patch.msgid.link/20260711151934.2955226-2-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/amt.c | 79 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 55 insertions(+), 24 deletions(-) + +diff --git a/drivers/net/amt.c b/drivers/net/amt.c +index f2da0c49171f5d..64aff304c51c66 100644 +--- a/drivers/net/amt.c ++++ b/drivers/net/amt.c +@@ -1206,7 +1206,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + data = true; + } + v6 = false; +- group.ip4 = iph->daddr; ++ group.ip4 = ip_hdr(skb)->daddr; + #if IS_ENABLED(CONFIG_IPV6) + } else if (iph->version == 6) { + ip6h = ipv6_hdr(skb); +@@ -1230,7 +1230,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + data = true; + } + v6 = true; +- group.ip6 = ip6h->daddr; ++ group.ip6 = ipv6_hdr(skb)->daddr; + #endif + } else { + dev->stats.tx_errors++; +@@ -1273,12 +1273,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash], + node) { + if (!v6) { +- if (gnode->group_addr.ip4 == iph->daddr) ++ if (gnode->group_addr.ip4 == group.ip4) + goto found; + #if IS_ENABLED(CONFIG_IPV6) + } else { + if (ipv6_addr_equal(&gnode->group_addr.ip6, +- &ip6h->daddr)) ++ &group.ip6)) + goto found; + #endif + } +@@ -1995,14 +1995,18 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb, + struct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb); + int len = skb_transport_offset(skb) + sizeof(*ihrv3); + void *zero_grec = (void *)&igmpv3_zero_grec; +- struct iphdr *iph = ip_hdr(skb); + struct amt_group_node *gnode; + union amt_addr group, host; + struct igmpv3_grec *grec; ++ __be32 saddr; + u16 nsrcs; ++ u16 ngrec; + int i; + +- for (i = 0; i < ntohs(ihrv3->ngrec); i++) { ++ saddr = ip_hdr(skb)->saddr; ++ ngrec = ntohs(ihrv3->ngrec); ++ ++ for (i = 0; i < ngrec; i++) { + len += sizeof(*grec); + if (!ip_mc_may_pull(skb, len)) + break; +@@ -2014,10 +2018,13 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb, + if (!ip_mc_may_pull(skb, len)) + break; + ++ grec = (void *)(skb->data + len - sizeof(*grec) - ++ nsrcs * sizeof(__be32)); ++ + memset(&group, 0, sizeof(union amt_addr)); + group.ip4 = grec->grec_mca; + memset(&host, 0, sizeof(union amt_addr)); +- host.ip4 = iph->saddr; ++ host.ip4 = saddr; + gnode = amt_lookup_group(tunnel, &group, &host, false); + if (!gnode) { + gnode = amt_add_group(amt, tunnel, &group, &host, +@@ -2157,14 +2164,18 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb, + struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb); + int len = skb_transport_offset(skb) + sizeof(*mld2r); + void *zero_grec = (void *)&mldv2_zero_grec; +- struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct amt_group_node *gnode; + union amt_addr group, host; + struct mld2_grec *grec; ++ struct in6_addr saddr; + u16 nsrcs; ++ u16 ngrec; + int i; + +- for (i = 0; i < ntohs(mld2r->mld2r_ngrec); i++) { ++ saddr = ipv6_hdr(skb)->saddr; ++ ngrec = ntohs(mld2r->mld2r_ngrec); ++ ++ for (i = 0; i < ngrec; i++) { + len += sizeof(*grec); + if (!ipv6_mc_may_pull(skb, len)) + break; +@@ -2176,10 +2187,13 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb, + if (!ipv6_mc_may_pull(skb, len)) + break; + ++ grec = (void *)(skb->data + len - sizeof(*grec) - ++ nsrcs * sizeof(struct in6_addr)); ++ + memset(&group, 0, sizeof(union amt_addr)); + group.ip6 = grec->grec_mca; + memset(&host, 0, sizeof(union amt_addr)); +- host.ip6 = ip6h->saddr; ++ host.ip6 = saddr; + gnode = amt_lookup_group(tunnel, &group, &host, true); + if (!gnode) { + gnode = amt_add_group(amt, tunnel, &group, &host, +@@ -2300,7 +2314,6 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + skb_push(skb, sizeof(*eth)); + skb_reset_mac_header(skb); + skb_pull(skb, sizeof(*eth)); +- eth = eth_hdr(skb); + + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; +@@ -2310,6 +2323,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!ipv4_is_multicast(iph->daddr)) + return true; + skb->protocol = htons(ETH_P_IP); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IP); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) +@@ -2323,6 +2337,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!ipv6_addr_is_multicast(&ip6h->daddr)) + return true; + skb->protocol = htons(ETH_P_IPV6); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IPV6); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif +@@ -2346,10 +2361,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + struct sk_buff *skb) + { + struct amt_header_membership_query *amtmq; +- struct igmpv3_query *ihv3; + struct ethhdr *eth, *oeth; ++ struct igmpv3_query *ihv3; ++ u8 h_source[ETH_ALEN]; + struct iphdr *iph; + int hdr_size, len; ++ u64 response_mac; + + hdr_size = sizeof(*amtmq) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) +@@ -2362,6 +2379,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + if (amtmq->nonce != amt->nonce) + return true; + ++ response_mac = amtmq->response_mac; ++ + hdr_size -= sizeof(*eth); + if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false)) + return true; +@@ -2371,6 +2390,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_pull(skb, sizeof(*eth)); + skb_reset_network_header(skb); + eth = eth_hdr(skb); ++ ether_addr_copy(h_source, oeth->h_source); + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + +@@ -2383,6 +2403,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + sizeof(*ihv3))) + return true; + ++ iph = ip_hdr(skb); + if (!ipv4_is_multicast(iph->daddr)) + return true; + +@@ -2390,10 +2411,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS); + WRITE_ONCE(amt->ready4, true); +- amt->mac = amtmq->response_mac; ++ amt->mac = response_mac; + amt->req_cnt = 0; + amt->qi = ihv3->qqic; + skb->protocol = htons(ETH_P_IP); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IP); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) +@@ -2416,10 +2438,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS); + WRITE_ONCE(amt->ready6, true); +- amt->mac = amtmq->response_mac; ++ amt->mac = response_mac; + amt->req_cnt = 0; + amt->qi = mld2q->mld2q_qqic; + skb->protocol = htons(ETH_P_IPV6); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IPV6); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif +@@ -2427,7 +2450,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + return true; + } + +- ether_addr_copy(eth->h_source, oeth->h_source); ++ ether_addr_copy(eth->h_source, h_source); + skb->pkt_type = PACKET_MULTICAST; + skb->ip_summed = CHECKSUM_NONE; + len = skb->len; +@@ -2450,8 +2473,11 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + struct ethhdr *eth; + struct iphdr *iph; + int len, hdr_size; ++ u64 response_mac; ++ __be32 saddr; ++ __be32 nonce; + +- iph = ip_hdr(skb); ++ saddr = ip_hdr(skb)->saddr; + + hdr_size = sizeof(*amtmu) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) +@@ -2461,15 +2487,18 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + if (amtmu->reserved || amtmu->version) + return true; + ++ nonce = amtmu->nonce; ++ response_mac = amtmu->response_mac; ++ + if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false)) + return true; + + skb_reset_network_header(skb); + + list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) { +- if (tunnel->ip4 == iph->saddr) { +- if ((amtmu->nonce == tunnel->nonce && +- amtmu->response_mac == tunnel->mac)) { ++ if (tunnel->ip4 == saddr) { ++ if ((nonce == tunnel->nonce && ++ response_mac == tunnel->mac)) { + mod_delayed_work(amt_wq, &tunnel->gc_wq, + msecs_to_jiffies(amt_gmi(amt)) + * 3); +@@ -2503,6 +2532,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + eth = eth_hdr(skb); + skb->protocol = htons(ETH_P_IP); + eth->h_proto = htons(ETH_P_IP); ++ iph = ip_hdr(skb); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) + } else if (iph->version == 6) { +@@ -2522,6 +2552,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + eth = eth_hdr(skb); + skb->protocol = htons(ETH_P_IPV6); + eth->h_proto = htons(ETH_P_IPV6); ++ ip6h = ipv6_hdr(skb); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif + } else { +@@ -2767,7 +2798,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb) + static int amt_rcv(struct sock *sk, struct sk_buff *skb) + { + struct amt_dev *amt; +- struct iphdr *iph; ++ __be32 saddr; + int type; + bool err; + +@@ -2780,7 +2811,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + } + + skb->dev = amt->dev; +- iph = ip_hdr(skb); ++ saddr = ip_hdr(skb)->saddr; + type = amt_parse_type(skb); + if (type == -1) { + err = true; +@@ -2790,7 +2821,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + if (amt->mode == AMT_MODE_GATEWAY) { + switch (type) { + case AMT_MSG_ADVERTISEMENT: +- if (iph->saddr != amt->discovery_ip) { ++ if (saddr != amt->discovery_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +@@ -2802,7 +2833,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + } + goto out; + case AMT_MSG_MULTICAST_DATA: +- if (iph->saddr != amt->remote_ip) { ++ if (saddr != amt->remote_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +@@ -2813,7 +2844,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + else + goto out; + case AMT_MSG_MEMBERSHIP_QUERY: +- if (iph->saddr != amt->remote_ip) { ++ if (saddr != amt->remote_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +-- +2.53.0 + diff --git a/queue-6.1/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch b/queue-6.1/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch new file mode 100644 index 0000000000..41ccd271b0 --- /dev/null +++ b/queue-6.1/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch @@ -0,0 +1,72 @@ +From 2b6fb554572acaee6698efa47a76b4a47b6862f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 18:06:20 +0800 +Subject: ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI + +From: Shengjiu Wang + +[ Upstream commit 0b604e886ece11b71c4daaeccc512c784b89b014 ] + +The bt-sco-pcm-wb DAI uses the same stream_name strings as bt-sco-pcm +("Playback" and "Capture"). This causes duplicate DAPM AIF widget +names within the same component, leading to debugfs warnings: + + debugfs: 'Playback' already exists in 'dapm' + debugfs: 'Capture' already exists in 'dapm' + +Give the wideband DAI distinct stream names ("WB Playback" and +"WB Capture") and add corresponding DAPM AIF widgets and routes for +them. + +Fixes: 5947e1b4992e ("ASoC: bt-sco: extend rate and add a general compatible string") +Assisted-by: VeroCoder:claude-sonnet-4-5 +Signed-off-by: Shengjiu Wang +Link: https://patch.msgid.link/20260715100620.1387159-1-shengjiu.wang@oss.nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/bt-sco.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c +index 4086b6a53de8ca..2a8796176c6da6 100644 +--- a/sound/soc/codecs/bt-sco.c ++++ b/sound/soc/codecs/bt-sco.c +@@ -17,11 +17,17 @@ static const struct snd_soc_dapm_widget bt_sco_widgets[] = { + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0, + SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_IN("BT_SCO_RX_WB", "WB Playback", 0, ++ SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("BT_SCO_TX_WB", "WB Capture", 0, ++ SND_SOC_NOPM, 0, 0), + }; + + static const struct snd_soc_dapm_route bt_sco_routes[] = { + { "BT_SCO_TX", NULL, "RX" }, + { "TX", NULL, "BT_SCO_RX" }, ++ { "BT_SCO_TX_WB", NULL, "RX" }, ++ { "TX", NULL, "BT_SCO_RX_WB" }, + }; + + static struct snd_soc_dai_driver bt_sco_dai[] = { +@@ -45,14 +51,14 @@ static struct snd_soc_dai_driver bt_sco_dai[] = { + { + .name = "bt-sco-pcm-wb", + .playback = { +- .stream_name = "Playback", ++ .stream_name = "WB Playback", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { +- .stream_name = "Capture", ++ .stream_name = "WB Capture", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, +-- +2.53.0 + diff --git a/queue-6.1/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch b/queue-6.1/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch new file mode 100644 index 0000000000..97ea0ea1b8 --- /dev/null +++ b/queue-6.1/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch @@ -0,0 +1,75 @@ +From 5ae8d03886215922cdb5339adf5c33baeef05789 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 09:06:22 +0800 +Subject: bonding: fix devconf_all NULL dereference when IPv6 is disabled + +From: Zhaolong Zhang + +[ Upstream commit 1c975de3343cdef506f2eecc833cc1f14b0401c4 ] + +When booting with the 'ipv6.disable=1' parameter, the devconf_all is +never initialized because inet6_init() exits before addrconf_init() is +called which initializes it. bond_send_validate(), however, will still +call bond_ns_send_all() even ipv6 is indeed disabled. It will lead to +NULL derefence of net->ipv6.devconf_all in ip6_pol_route(). + + BUG: kernel NULL pointer dereference, address: 000000000000000c + [...] + Workqueue: bond0 bond_arp_monitor [bonding] + RIP: 0010:ip6_pol_route+0x69/0x480 + [...] + Call Trace: + + ? srso_return_thunk+0x5/0x5f + ? __pfx_ip6_pol_route_output+0x10/0x10 + fib6_rule_lookup+0xfe/0x260 + ? wakeup_preempt+0x8a/0x90 + ? srso_return_thunk+0x5/0x5f + ? srso_return_thunk+0x5/0x5f + ? sched_balance_rq+0x369/0x810 + ip6_route_output_flags+0xd7/0x170 + bond_ns_send_all+0xde/0x280 [bonding] + bond_ab_arp_probe+0x296/0x320 [bonding] + ? srso_return_thunk+0x5/0x5f + bond_activebackup_arp_mon+0xb4/0x2c0 [bonding] + process_one_work+0x196/0x370 + worker_thread+0x1af/0x320 + ? srso_return_thunk+0x5/0x5f + ? __pfx_worker_thread+0x10/0x10 + kthread+0xe3/0x120 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x199/0x260 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Fix this by adding ipv6_mod_enabled() condition check in the caller. + +Fixes: 4e24be018eb9 ("bonding: add new parameter ns_targets") +Signed-off-by: Qianheng Peng +Signed-off-by: Zhaolong Zhang +Reviewed-by: Hangbin Liu +Link: https://patch.msgid.link/20260707010622.487333-1-zhangzl2013@126.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 9898d85075d150..5a71893fc6a962 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -3415,7 +3415,8 @@ static void bond_send_validate(struct bonding *bond, struct slave *slave) + { + bond_arp_send_all(bond, slave); + #if IS_ENABLED(CONFIG_IPV6) +- bond_ns_send_all(bond, slave); ++ if (likely(ipv6_mod_enabled())) ++ bond_ns_send_all(bond, slave); + #endif + } + +-- +2.53.0 + diff --git a/queue-6.1/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch b/queue-6.1/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch new file mode 100644 index 0000000000..aac2ef807c --- /dev/null +++ b/queue-6.1/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch @@ -0,0 +1,79 @@ +From 4b05b665494d088cf42f43e4579a0c7a34d430d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jul 2026 18:38:56 +0800 +Subject: bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() + +From: Chengfeng Ye + +[ Upstream commit 2d66a033864e27ab8d5e44cb36f31d9d2413bee4 ] + +tcp_bpf_sendmsg() keeps msg_tx across sk_stream_wait_memory(), which +drops and reacquires the socket lock. Its error path tries to decide +whether msg_tx names the local temporary message by comparing it with +the current value of psock->cork. + +This comparison is unsafe when two threads send on the same socket: + + Thread A Thread B + msg_tx = psock->cork + sk_msg_alloc() fails + sk_stream_wait_memory() + releases the socket lock acquires the socket lock + completes the cork + psock->cork = NULL + frees the cork + reacquires the socket lock + msg_tx != psock->cork + sk_msg_free(msg_tx) + +The stale cork is therefore mistaken for the local temporary message +and freed again. KASAN reported: + + BUG: KASAN: slab-use-after-free in sk_msg_free+0x49/0x50 + Read of size 4 at addr ffff88810c908800 by task poc/90 + Call Trace: + sk_msg_free+0x49/0x50 + tcp_bpf_sendmsg+0x14f5/0x1cc0 + __sys_sendto+0x32c/0x3a0 + __x64_sys_sendto+0xdb/0x1b0 + Allocated by task 89: + __kasan_kmalloc+0x8f/0xa0 + tcp_bpf_sendmsg+0x16b3/0x1cc0 + Freed by task 91: + __kasan_slab_free+0x43/0x70 + kfree+0x131/0x3c0 + tcp_bpf_sendmsg+0xec3/0x1cc0 + +msg_tx can only name the stack-local tmp or the shared cork. Check for +tmp directly so a changed psock->cork cannot turn a shared message into +an apparent local one. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Chengfeng Ye +Reviewed-by: Emil Tsalapatis +Reviewed-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/87fr18lmzo.fsf%40cloudflare.com/ +Link: https://lore.kernel.org/netdev/20260719161630.2901208-1-nicoyip.dev%40gmail.com/ [v1] +Link: https://patch.msgid.link/20260724103856.3399001-1-nicoyip.dev@gmail.com +Signed-off-by: Eduard Zingerman +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 9af7595bf8c452..06cc4112cbfec1 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -566,7 +566,7 @@ static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + wait_for_memory: + err = sk_stream_wait_memory(sk, &timeo); + if (err) { +- if (msg_tx && msg_tx != psock->cork) ++ if (msg_tx == &tmp) + sk_msg_free(sk, msg_tx); + goto out_err; + } +-- +2.53.0 + diff --git a/queue-6.1/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch b/queue-6.1/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch new file mode 100644 index 0000000000..8a206a14bb --- /dev/null +++ b/queue-6.1/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch @@ -0,0 +1,55 @@ +From c5b99cb46ce3c6a272da064ab6627a7aff3f3990 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jun 2026 18:39:07 +0800 +Subject: btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8 + +From: You-Kai Zheng + +[ Upstream commit b95181f3929ff98949fa9460ca93eccebbf2d7fc ] + +The variable-sized buffer buf in struct btrfs_ioctl_search_args_v2 is +declared as __u64[], but it holds a packed byte stream of search results, +where all offsets into the buffer are in bytes. + +Declaring buf as __u64[] makes it easy for user space to write incorrect +pointer arithmetic: adding a byte offset directly to a __u64 pointer +scales the offset by 8, landing at byte position offset*8 instead of +offset. + +This recently caused an infinite loop in btrfs-progs: the accessor read +all-zero data from misaddressed items, which fed zeroed search keys back +into the ioctl loop and spun forever. The issue was worked around at the +time by disabling TREE_SEARCH_V2 entirely in btrfs-progs (d73e69824854: +"btrfs-progs: temporarily disable usage of v2 of search tree ioctl"). + +The kernel side already treats buf as a byte buffer, so change the +declaration to __u8[] to match the actual semantics and prevent similar +misuse in user space. The change is ABI compatible: both the structure size +and alignment are unchanged. + +Fixes: cc68a8a5a433 ("btrfs: new ioctl TREE_SEARCH_V2") +Reviewed-by: Qu Wenruo +Signed-off-by: You-Kai Zheng +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + include/uapi/linux/btrfs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h +index 24b54635bae90f..7b9e199de89286 100644 +--- a/include/uapi/linux/btrfs.h ++++ b/include/uapi/linux/btrfs.h +@@ -568,7 +568,7 @@ struct btrfs_ioctl_search_args_v2 { + __u64 buf_size; /* in - size of buffer + * out - on EOVERFLOW: needed size + * to store item */ +- __u64 buf[]; /* out - found items */ ++ __u8 buf[]; /* out - found items */ + }; + + struct btrfs_ioctl_clone_range_args { +-- +2.53.0 + diff --git a/queue-6.1/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch b/queue-6.1/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch new file mode 100644 index 0000000000..b62a1db1c8 --- /dev/null +++ b/queue-6.1/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch @@ -0,0 +1,47 @@ +From 0bcef8b97e722701549244bde5974fa0186d8e0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 03:17:28 +0000 +Subject: btrfs: free mapping node on duplicate reloc root insert + +From: Guanghui Yang <3497809730@qq.com> + +[ Upstream commit 6a8269b6459ed870a8156c106a0f597383907872 ] + +__add_reloc_root() allocates a mapping_node before inserting it into +rc->reloc_root_tree. If rb_simple_insert() finds an existing entry, it +returns the existing rb_node and leaves the newly allocated node unlinked. + +The error path then returns -EEXIST without freeing the new node. Since +the node was never inserted into reloc_root_tree, the later cleanup in +put_reloc_control() cannot find it either. + +Free the newly allocated node before returning -EEXIST. + +The callers currently assert that -EEXIST should not happen, so this is a +defensive cleanup for an unexpected duplicate insert path. If the path is +ever reached, the local allocation should still be released. + +Fixes: 57a304cfd43b ("btrfs: do not panic in __add_reloc_root") +Reviewed-by: Qu Wenruo +Signed-off-by: Guanghui Yang <3497809730@qq.com> +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 2e66a0672ba7fa..d37904a806d6a0 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -645,6 +645,7 @@ static int __must_check __add_reloc_root(struct btrfs_root *root) + btrfs_err(fs_info, + "Duplicate root found for start=%llu while inserting into relocation tree", + node->bytenr); ++ kfree(node); + return -EEXIST; + } + +-- +2.53.0 + diff --git a/queue-6.1/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch b/queue-6.1/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..30705efda2 --- /dev/null +++ b/queue-6.1/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,48 @@ +From 805bcdab6017cbbb131ad4e9d27c367847c70380 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:17:37 +0800 +Subject: dpaa2-eth: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit b4b201cc93ff70150853aba03e14d314d1980ca0 ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The Ethernet connect path stores that +device in mac->mc_dev and keeps it for the lifetime of the connected MAC +object. + +However, the disconnect path only disconnects and closes the MAC before +freeing the dpaa2_mac object. It does not drop the endpoint device +reference stored in mac->mc_dev, so every successful connect leaks that +device reference when the MAC is later disconnected. + +Drop the endpoint device reference after closing the MAC and before +freeing the dpaa2_mac object. + +Fixes: 719479230893 ("dpaa2-eth: add MAC/PHY support through phylink") +Signed-off-by: Guangshuo Li +Reviewed-by: Ioana Ciornei +Reviewed-by: Ioana Ciornei +Link: https://patch.msgid.link/20260708111738.750391-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index 6727e17fb5145e..bae533897f63f9 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -4502,6 +4502,7 @@ static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-6.1/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch b/queue-6.1/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..e0a38b4c8f --- /dev/null +++ b/queue-6.1/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,46 @@ +From 8ab06486aaf5ff914a5e1618e946b811993dc5c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:10:25 +0800 +Subject: dpaa2-switch: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit 4c1eabbef7a1707635652e956e39db1269c3af2b ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The switch port connect path stores +that device in mac->mc_dev and keeps it for the lifetime of the connected +MAC object. + +However, the disconnect path only closes the MAC and frees the dpaa2_mac +object. It does not drop the endpoint device reference stored in +mac->mc_dev, so every successful connect leaks that device reference when +the MAC is later disconnected. + +Drop the endpoint device reference before freeing the dpaa2_mac object. + +Fixes: 84cba72956fd ("dpaa2-switch: integrate the MAC endpoint support") +Signed-off-by: Guangshuo Li +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708111025.749311-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +index c8478fdcb3aa5f..8f7c3466f52c45 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +@@ -1514,6 +1514,7 @@ static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-6.1/firewire-net-fix-fragmented-datagram-reassembly.patch b/queue-6.1/firewire-net-fix-fragmented-datagram-reassembly.patch new file mode 100644 index 0000000000..513049c5d2 --- /dev/null +++ b/queue-6.1/firewire-net-fix-fragmented-datagram-reassembly.patch @@ -0,0 +1,99 @@ +From 84734da77581e9a2e6522ff5f074c2d0866e7359 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 23:04:54 +0800 +Subject: firewire: net: Fix fragmented datagram reassembly + +From: Ruoyu Wang + +[ Upstream commit d52a13adbb8ccbab99cd3bad36804e87d8b5c052 ] + +fwnet_frag_new() keeps a sorted list of received fragments for a partial +datagram. When a new fragment is adjacent to an existing fragment, the +code checks whether the new fragment also closes the gap to the next or +previous list entry. + +Those neighbor lookups currently assume that the current fragment always +has a real next or previous fragment. At a list edge, the next or +previous entry is the list head, not a struct fwnet_fragment_info. + +The gap checks also compare against the old edge of the current fragment +instead of the edge after adding the new fragment. As a result, a +fragment that bridges two existing ranges may leave two adjacent ranges +unmerged, so fwnet_pd_is_complete() can miss a complete datagram. + +Check for the list head before looking up the neighboring fragment, and +compare the neighbor against the new fragment's far edge when deciding +whether to merge all three ranges. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: c76acec6d551 ("firewire: add IPv4 support") +Signed-off-by: Ruoyu Wang +Link: https://lore.kernel.org/r/20260707150454.2265951-1-ruoyuw560@gmail.com +Signed-off-by: Takashi Sakamoto +Signed-off-by: Sasha Levin +--- + drivers/firewire/net.c | 39 +++++++++++++++++++++------------------ + 1 file changed, 21 insertions(+), 18 deletions(-) + +diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c +index a53eacebca3391..75fdda6171dfab 100644 +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -297,31 +297,34 @@ static struct fwnet_fragment_info *fwnet_frag_new( + if (fi->offset + fi->len == offset) { + /* The new fragment can be tacked on to the end */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.next, +- struct fwnet_fragment_info, fi_link); +- if (fi->offset + fi->len == fi2->offset) { +- /* glue fragments together */ +- fi->len += len + fi2->len; +- list_del(&fi2->fi_link); +- kfree(fi2); +- } else { +- fi->len += len; ++ if (!list_is_last(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_next_entry(fi, fi_link); ++ if (offset + len == fi2->offset) { ++ /* glue fragments together */ ++ fi->len += len + fi2->len; ++ list_del(&fi2->fi_link); ++ kfree(fi2); ++ ++ return fi; ++ } + } ++ fi->len += len; + + return fi; + } + if (offset + len == fi->offset) { + /* The new fragment can be tacked on to the beginning */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.prev, +- struct fwnet_fragment_info, fi_link); +- if (fi2->offset + fi2->len == fi->offset) { +- /* glue fragments together */ +- fi2->len += fi->len + len; +- list_del(&fi->fi_link); +- kfree(fi); +- +- return fi2; ++ if (!list_is_first(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_prev_entry(fi, fi_link); ++ if (fi2->offset + fi2->len == offset) { ++ /* glue fragments together */ ++ fi2->len += fi->len + len; ++ list_del(&fi->fi_link); ++ kfree(fi); ++ ++ return fi2; ++ } + } + fi->offset = offset; + fi->len += len; +-- +2.53.0 + diff --git a/queue-6.1/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch b/queue-6.1/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch new file mode 100644 index 0000000000..a6d668540b --- /dev/null +++ b/queue-6.1/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch @@ -0,0 +1,58 @@ +From e579fb41fe1ba088f135aa36ed8619327c046393 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 23:07:24 +0000 +Subject: gtp: check skb_pull_data() return in gtp1u_send_echo_resp() + +From: Xiang Mei (Microsoft) + +[ Upstream commit cd170f051dba9ac146fabcd1b91726487c0cb9fa ] + +gtp1u_send_echo_resp() ignores skb_pull_data()'s return value. Its +caller gtp1u_udp_encap_recv() only guarantees 16 bytes (udphdr + +gtp1_header), but the pull requests 20 (gtp1_header_long + udphdr). For +a 16-19 byte echo request the pull fails and returns NULL without +advancing skb->data; execution continues, and the following skb_push() +plus the IP header pushed by iptunnel_xmit() move skb->data below +skb->head, tripping skb_under_panic(). + +Fix it by dropping the packet when skb_pull_data() fails. + + skbuff: skb_under_panic: ... + kernel BUG at net/core/skbuff.c:214! + Call Trace: + skb_push (net/core/skbuff.c:2648) + iptunnel_xmit (net/ipv4/ip_tunnel_core.c:82) + gtp_encap_recv (drivers/net/gtp.c:701 drivers/net/gtp.c:808 drivers/net/gtp.c:920) + udp_queue_rcv_one_skb (net/ipv4/udp.c:2388) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 9af41cc33471 ("gtp: Implement GTP echo response") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Link: https://patch.msgid.link/20260710230724.942574-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/gtp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index 797886f10868af..59c9bd459b2fb5 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -489,8 +489,9 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb) + return -1; + + /* pull GTP and UDP headers */ +- skb_pull_data(skb, +- sizeof(struct gtp1_header_long) + sizeof(struct udphdr)); ++ if (!skb_pull_data(skb, sizeof(struct gtp1_header_long) + ++ sizeof(struct udphdr))) ++ return -1; + + gtp_pkt = skb_push(skb, sizeof(struct gtp1u_packet)); + memset(gtp_pkt, 0, sizeof(struct gtp1u_packet)); +-- +2.53.0 + diff --git a/queue-6.1/hinic-remove-unused-ethtool-rss-user-configuration-b.patch b/queue-6.1/hinic-remove-unused-ethtool-rss-user-configuration-b.patch new file mode 100644 index 0000000000..f109945d15 --- /dev/null +++ b/queue-6.1/hinic-remove-unused-ethtool-rss-user-configuration-b.patch @@ -0,0 +1,83 @@ +From 8642443e2cb8d96e1b23681ee24b70cf667948c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:53:53 +0800 +Subject: hinic: remove unused ethtool RSS user configuration buffers + +From: Chenguang Zhao + +[ Upstream commit fe0c002928c6749b7f4a726f6f600f6dd70280ea ] + +rss_indir_user and rss_hkey_user are allocated and filled in +__set_rss_rxfh() when the user configures RSS via ethtool, but +nothing ever reads them. hinic_get_rxfh() fetches the state from +the device, and the hardware is programmed from the original +indir/key arguments. These buffers only leaked on driver unload. + +Drop the unused allocations, memcpys, and struct fields. + +Fixes: 4fdc51bb4e92 ("hinic: add support for rss parameters with ethtool") +Signed-off-by: Chenguang Zhao +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260722025353.328179-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/huawei/hinic/hinic_dev.h | 2 -- + .../net/ethernet/huawei/hinic/hinic_ethtool.c | 21 ------------------- + 2 files changed, 23 deletions(-) + +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +index a4fbf44f944cd3..46b24f3c5e168d 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h ++++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +@@ -100,8 +100,6 @@ struct hinic_dev { + u16 num_rss; + u16 rss_limit; + struct hinic_rss_type rss_type; +- u8 *rss_hkey_user; +- s32 *rss_indir_user; + struct hinic_intr_coal_info *rx_intr_coalesce; + struct hinic_intr_coal_info *tx_intr_coalesce; + struct hinic_sriov_info sriov_info; +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +index f4b68028691194..660ab3edf73939 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c ++++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +@@ -1061,17 +1061,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + int err; + + if (indir) { +- if (!nic_dev->rss_indir_user) { +- nic_dev->rss_indir_user = +- kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE, +- GFP_KERNEL); +- if (!nic_dev->rss_indir_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_indir_user, indir, +- sizeof(u32) * HINIC_RSS_INDIR_SIZE); +- + err = hinic_rss_set_indir_tbl(nic_dev, + nic_dev->rss_tmpl_idx, indir); + if (err) +@@ -1079,16 +1068,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + } + + if (key) { +- if (!nic_dev->rss_hkey_user) { +- nic_dev->rss_hkey_user = +- kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL); +- +- if (!nic_dev->rss_hkey_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE); +- + err = hinic_rss_set_template_tbl(nic_dev, + nic_dev->rss_tmpl_idx, key); + if (err) +-- +2.53.0 + diff --git a/queue-6.1/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch b/queue-6.1/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch new file mode 100644 index 0000000000..9ce06181e4 --- /dev/null +++ b/queue-6.1/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch @@ -0,0 +1,42 @@ +From a2282cd6a48d4a4e290f411eacf0c5686aa46954 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 15:05:05 +0200 +Subject: hwmon: (asus-ec-sensors) add missed handle for ENOMEM + +From: Eugene Shalygin + +[ Upstream commit 9813c1f49efeadbcb17e4a41972350ac783f9cac ] + +Add missing return value check in the setup function. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260712130602.1256700-2-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index d6f6c8113af7ec..d7a40070185ec2 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -990,9 +990,11 @@ static int asus_ec_probe(struct platform_device *pdev) + if (!nr_count[type]) + continue; + +- asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, +- nr_count[type], type, +- hwmon_attributes[type]); ++ status = asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, ++ nr_count[type], type, ++ hwmon_attributes[type]); ++ if (status) ++ return status; + *ptr_asus_ec_ci++ = asus_ec_hwmon_chan++; + } + +-- +2.53.0 + diff --git a/queue-6.1/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch b/queue-6.1/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch new file mode 100644 index 0000000000..98cd39c7d8 --- /dev/null +++ b/queue-6.1/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch @@ -0,0 +1,60 @@ +From 14e23f26b85514450ab68b03e4537fa66b4610f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 13:05:03 +0200 +Subject: hwmon: (asus-ec-sensors) fix EC read intervals + +From: Eugene Shalygin + +[ Upstream commit 60710b2af13b81da71b429d3f8b19dd70310729d ] + +Take INITIAL_JIFFIES into account when setting up next update time. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260712110650.1240071-2-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index c81c6e3264bb05..d6f6c8113af7ec 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -525,7 +525,7 @@ struct ec_sensors_data { + /* sorted list of unique register banks */ + u8 banks[ASUS_EC_MAX_BANK + 1]; + /* in jiffies */ +- unsigned long last_updated; ++ u64 next_update; + struct lock_data lock_data; + /* number of board EC sensors */ + u8 nr_sensors; +@@ -794,13 +794,12 @@ static int get_cached_value_or_update(const struct device *dev, + int sensor_index, + struct ec_sensors_data *state, s32 *value) + { +- if (time_after(jiffies, state->last_updated + HZ)) { ++ if (time_after64(get_jiffies_64(), state->next_update)) { + if (update_ec_sensors(dev, state)) { + dev_err(dev, "update_ec_sensors() failure\n"); + return -EIO; + } +- +- state->last_updated = jiffies; ++ state->next_update = get_jiffies_64() + HZ; + } + + *value = state->sensors[sensor_index].cached_value; +@@ -918,6 +917,7 @@ static int asus_ec_probe(struct platform_device *pdev) + if (!ec_data) + return -ENOMEM; + ++ ec_data->next_update = INITIAL_JIFFIES; + dev_set_drvdata(dev, ec_data); + ec_data->board_info = pboard_info; + +-- +2.53.0 + diff --git a/queue-6.1/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch b/queue-6.1/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch new file mode 100644 index 0000000000..f4bf663b50 --- /dev/null +++ b/queue-6.1/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch @@ -0,0 +1,37 @@ +From 4385fe19670d0aa4f18b449b049f411e551e4d9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 09:42:07 +0200 +Subject: hwmon: (asus-ec-sensors) fix looping over banks while reading from EC + +From: Eugene Shalygin + +[ Upstream commit e741d13cc2abfc6fccebe2008057aa52e285223e ] + +Do not assume there are only bank 0 and bank 1 available, just use '!=' +for bank comparison. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260711074217.554656-1-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index c9222c83ba2409..c81c6e3264bb05 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -705,7 +705,7 @@ static int asus_ec_block_read(const struct device *dev, + } + for (ireg = 0; ireg < ec->nr_registers; ireg++) { + reg_bank = register_bank(ec->registers[ireg]); +- if (reg_bank < bank) { ++ if (reg_bank != bank) { + continue; + } + ec_read(register_index(ec->registers[ireg]), +-- +2.53.0 + diff --git a/queue-6.1/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch b/queue-6.1/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch new file mode 100644 index 0000000000..cfdf96542b --- /dev/null +++ b/queue-6.1/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch @@ -0,0 +1,41 @@ +From 2c1234790a325de8fd2e1518150012085b9d92cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 17:52:54 -0700 +Subject: hwmon: (corsair-cpro) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 94c87871b051d7ad758828a805215a2ec194512a ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 40c3a44542257 ("hwmon: add Corsair Commander Pro driver") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-cpro.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c +index 18da3e013c20b7..62f9372f2d3551 100644 +--- a/drivers/hwmon/corsair-cpro.c ++++ b/drivers/hwmon/corsair-cpro.c +@@ -558,6 +558,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) + + out_hw_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.1/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch b/queue-6.1/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..33f8950344 --- /dev/null +++ b/queue-6.1/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,89 @@ +From b3349e9d9c4f2e41aea4eeb9a17e72ca2e50a4fe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Apr 2026 12:12:26 +0800 +Subject: hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop + +From: Edward Adam Davis + +[ Upstream commit 9ab8656548cd737b98d0b19c4253aff8d68e97f4 ] + +hid_hw_stop() does not stop the device IO. + +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +corsairpsu_probe(). If the probe operation fails after "io start" has +been initiated, this race condition will result in a uaf vulnerability +[1]. + +CPU0 CPU1 +==== ==== +corsairpsu_probe() + hid_device_io_start() + ... unlock driver_input_lock + hid_hw_stop() + kfree(hidraw) __hid_input_report() + ... acquire driver_input_lock + hid_report_raw_event() + hidraw_report_event() + ... access hidraw's list_lock // trigger uaf + +Consequently, when corsairpsu_probe() fails and hid_hw_stop() needs to +be executed, the io_started flag is first cleared while holding the +driver_input_lock to prevent potential race conditions involving input +reports. + +[1] +BUG: KASAN: slab-use-after-free in rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56 +Call Trace: + hidraw_report_event+0x5d/0x3a0 drivers/hid/hidraw.c:577 + hid_report_raw_event+0x311/0x1730 drivers/hid/hid-core.c:2076 + __hid_input_report drivers/hid/hid-core.c:2152 [inline] + hid_input_report+0x44e/0x580 drivers/hid/hid-core.c:2174 + hid_irq_in+0x47e/0x6d0 drivers/hid/usbhid/hid-core.c:286 + __usb_hcd_giveback_urb+0x3b3/0x5e0 drivers/usb/core/hcd.c:1657 + dummy_timer+0x8a9/0x47d0 drivers/usb/gadget/udc/dummy_hcd.c:2005 + +Allocated by task 10: + hidraw_connect+0x57/0x430 drivers/hid/hidraw.c:606 + hid_connect+0x5bf/0x19d0 drivers/hid/hid-core.c:2277 + hid_hw_start+0xa8/0x120 drivers/hid/hid-core.c:2387 + corsairpsu_probe+0xd9/0x3c0 drivers/hwmon/corsair-psu.c:782 + +Freed by task 10: + hidraw_disconnect+0x4f/0x60 drivers/hid/hidraw.c:662 + hid_disconnect drivers/hid/hid-core.c:2362 [inline] + hid_hw_stop+0x101/0x1e0 drivers/hid/hid-core.c:2407 + corsairpsu_probe+0x327/0x3c0 drivers/hwmon/corsair-psu.c:826 + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Fixes: d115b51e0e56 ("hwmon: add Corsair PSU HID controller driver") +Reported-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9eebf5f6544c5e873858 +Tested-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Link: https://lore.kernel.org/r/tencent_BB7C33EB9EA41B7B4B5F1B8B25C0BA13BB08@qq.com +[groeck: Updated subject and description; + call hid_device_io_stop() only if IO has been started] +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-psu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c +index 1ecd6c58b4567b..2f2cbc067634ae 100644 +--- a/drivers/hwmon/corsair-psu.c ++++ b/drivers/hwmon/corsair-psu.c +@@ -769,6 +769,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id + + fail_and_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + fail_and_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.1/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch b/queue-6.1/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..b2d9917aa4 --- /dev/null +++ b/queue-6.1/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,42 @@ +From 188987e53d9e1454c79d7d20ac254ad3237ee62e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:00:32 -0700 +Subject: hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 59d104b54b0b42e30fd2a68d24ee5c49dcc54d1e ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 53e68c20aeb1e ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/nzxt-smart2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c +index a8e72d8fd06050..02816538d18eb4 100644 +--- a/drivers/hwmon/nzxt-smart2.c ++++ b/drivers/hwmon/nzxt-smart2.c +@@ -768,7 +768,7 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev, + + out_hw_close: + hid_hw_close(hdev); +- ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.1/hwmon-occ-validate-poll-response-sensor-blocks.patch b/queue-6.1/hwmon-occ-validate-poll-response-sensor-blocks.patch new file mode 100644 index 0000000000..e32bb52485 --- /dev/null +++ b/queue-6.1/hwmon-occ-validate-poll-response-sensor-blocks.patch @@ -0,0 +1,118 @@ +From 3f76bdc10ed5d0e0156b05d5269dffdec50de5c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:58:26 +0800 +Subject: hwmon: occ: validate poll response sensor blocks + +From: Pengpeng Hou + +[ Upstream commit 70e76e700fc6c46afb4e17aec099a1ea089b4a22 ] + +The OCC poll response parser walks a counted list of sensor data blocks. +It used the static backing-array capacity as the parse boundary, but a +transport response makes only data_length bytes current and valid. A +truncated response can therefore make the parser consume a block header or +block extent outside the current response. + +Use data_length as the parent boundary, prove the fixed poll header and +each current block header before reading them, and prove the complete block +before advancing. Keep parsed sensor metadata local until the complete +response has passed validation, then publish it. Propagate +malformed-response errors before publishing the OCC as active. + +Fixes: aa195fe49b03 ("hwmon (occ): Parse OCC poll response") +Signed-off-by: Pengpeng Hou +Link: https://lore.kernel.org/r/20260720115826.14813-1-pengpeng@iscas.ac.cn +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/common.c | 38 ++++++++++++++++++++++++++++++-------- + 1 file changed, 30 insertions(+), 8 deletions(-) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index c92d08e9827ac5..d0c8a043445a25 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -1052,32 +1052,49 @@ static int occ_setup_sensor_attrs(struct occ *occ) + } + + /* only need to do this once at startup, as OCC won't change sensors on us */ +-static void occ_parse_poll_response(struct occ *occ) ++static int occ_parse_poll_response(struct occ *occ) + { + unsigned int i, old_offset, offset = 0, size = 0; ++ u16 data_length; + struct occ_sensor *sensor; +- struct occ_sensors *sensors = &occ->sensors; ++ struct occ_sensors parsed = {}; ++ struct occ_sensors *sensors = &parsed; + struct occ_response *resp = &occ->resp; + struct occ_poll_response *poll = + (struct occ_poll_response *)&resp->data[0]; + struct occ_poll_response_header *header = &poll->header; + struct occ_sensor_data_block *block = &poll->block; + ++ data_length = get_unaligned_be16(&resp->data_length); ++ if (data_length < sizeof(*header) || data_length > OCC_RESP_DATA_BYTES) { ++ dev_err(occ->bus_dev, "invalid OCC poll response length %u\n", ++ data_length); ++ return -EMSGSIZE; ++ } ++ + dev_info(occ->bus_dev, "OCC found, code level: %.16s\n", + header->occ_code_level); + + for (i = 0; i < header->num_sensor_data_blocks; ++i) { + block = (struct occ_sensor_data_block *)((u8 *)block + offset); ++ if (size + sizeof(*header) + sizeof(block->header) > ++ data_length) { ++ dev_err(occ->bus_dev, ++ "truncated OCC sensor block header\n"); ++ return -EMSGSIZE; ++ } ++ + old_offset = offset; + offset = (block->header.num_sensors * + block->header.sensor_length) + sizeof(block->header); +- size += offset; + + /* validate all the length/size fields */ +- if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) { +- dev_warn(occ->bus_dev, "exceeded response buffer\n"); +- return; ++ if (size + sizeof(*header) + offset > data_length) { ++ dev_err(occ->bus_dev, ++ "exceeded OCC poll response length\n"); ++ return -EMSGSIZE; + } ++ size += offset; + + dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n", + old_offset, offset - 1, block->header.eye_catcher, +@@ -1107,6 +1124,9 @@ static void occ_parse_poll_response(struct occ *occ) + + dev_dbg(occ->bus_dev, "Max resp size: %u+%zd=%zd\n", size, + sizeof(*header), size + sizeof(*header)); ++ occ->sensors = parsed; ++ ++ return 0; + } + + int occ_active(struct occ *occ, bool active) +@@ -1138,10 +1158,12 @@ int occ_active(struct occ *occ, bool active) + goto unlock; + } + +- occ->active = true; + occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; +- occ_parse_poll_response(occ); ++ rc = occ_parse_poll_response(occ); ++ if (rc) ++ goto unlock; + ++ occ->active = true; + rc = occ_setup_sensor_attrs(occ); + if (rc) { + dev_err(occ->bus_dev, +-- +2.53.0 + diff --git a/queue-6.1/iommu-amd-bound-the-early-acpi-hid-map.patch b/queue-6.1/iommu-amd-bound-the-early-acpi-hid-map.patch new file mode 100644 index 0000000000..329a9d6c8a --- /dev/null +++ b/queue-6.1/iommu-amd-bound-the-early-acpi-hid-map.patch @@ -0,0 +1,45 @@ +From d146a624f6aefa4f2839c9c654a2dbf7b7bba130 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:46:13 +0800 +Subject: iommu/amd: Bound the early ACPI HID map + +From: Pengpeng Hou + +[ Upstream commit fb80117fddb5b477218dc99bb53911b72c3847f8 ] + +The ivrs_acpihid command-line parser appends entries to a fixed +four-element early_acpihid_map array. Unlike the sibling IOAPIC and HPET +parsers, it does not reject a fifth entry before incrementing the map size. + +Check the capacity at the common found label before parsing the HID and +UID or writing the entry. + +Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter") +Signed-off-by: Pengpeng Hou +Reviewed-by: Ankit Soni +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/init.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index 9cb53e384247e9..a0342682c01d24 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -3603,6 +3603,12 @@ static int __init parse_ivrs_acpihid(char *str) + return 1; + + found: ++ if (early_acpihid_map_size == EARLY_MAP_SIZE) { ++ pr_err("Early ACPI HID map overflow - ignoring ivrs_acpihid%s\n", ++ str); ++ return 1; ++ } ++ + p = acpiid; + hid = strsep(&p, ":"); + uid = p; +-- +2.53.0 + diff --git a/queue-6.1/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch b/queue-6.1/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch new file mode 100644 index 0000000000..648b1ff746 --- /dev/null +++ b/queue-6.1/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch @@ -0,0 +1,43 @@ +From 787d19ad6d3d76218390a62d259823308ed5e711 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:34:10 +0800 +Subject: iommu/intel: Fix out-of-bounds memset in dmar_latency_disable() + +From: Li RongQing + +[ Upstream commit 754f8efe45f87e3a9c6871b645b2f9d46d1b407b ] + +dmar_latency_disable() intends to zero out only the single +latency_statistic entry for the given type, but the memset size was +computed as sizeof(*lstat) * DMAR_LATENCY_NUM, which clears the entire +array starting from &lstat[type]. + +When type > 0, this writes beyond the end of the allocated array, +corrupting adjacent memory. + +Fix by using sizeof(*lstat) to clear only the target entry. + +Fixes: 55ee5e67a59a ("iommu/vt-d: Add common code for dmar latency performance monitors") +Signed-off-by: Li RongQing +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/perf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/intel/perf.c b/drivers/iommu/intel/perf.c +index ae64e1123f2571..08ffebdbd09cec 100644 +--- a/drivers/iommu/intel/perf.c ++++ b/drivers/iommu/intel/perf.c +@@ -63,7 +63,7 @@ void dmar_latency_disable(struct intel_iommu *iommu, enum latency_type type) + return; + + spin_lock_irqsave(&latency_lock, flags); +- memset(&lstat[type], 0, sizeof(*lstat) * DMAR_LATENCY_NUM); ++ memset(&lstat[type], 0, sizeof(*lstat)); + spin_unlock_irqrestore(&latency_lock, flags); + } + +-- +2.53.0 + diff --git a/queue-6.1/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch b/queue-6.1/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch new file mode 100644 index 0000000000..6bc92660e5 --- /dev/null +++ b/queue-6.1/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch @@ -0,0 +1,88 @@ +From d61449b78f961411ee4e192e9a7fd9797669b790 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:42:36 +0000 +Subject: ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup + +From: Eric Dumazet + +[ Upstream commit 853e164c2b321f0711361bc23505aaeb7dc432c3 ] + +When Linux forwards a packet and needs to generate an ICMP error, +icmp_route_lookup() performs a reverse-path relookup. For non-local +destinations, it performs a decoy lookup to find the expected egress +interface (rt2->dst.dev) before validating the path with ip_route_input(). + +Currently, the decoy flow structure (fl4_2) only sets .daddr = fl4_dec.saddr, +leaving .saddr, .flowi4_dscp, .flowi4_proto, .flowi4_mark, .flowi4_oif, +.fl4_sport, .fl4_dport, and .flowi4_uid zeroed out. + +When policy routing rules (such as ip rule add from $SRC lookup 100, or +dscp/fwmark/ipproto/port rules, or VRF bindings) are configured: +1. The decoy lookup fails to match the policy rule because saddr and other + key flow selectors are missing in fl4_2. +2. It resolves a route using the default table instead, returning an incorrect + egress netdev. +3. Passing the wrong netdev to ip_route_input() causes strict reverse-path + filtering (rp_filter=1) to fail, logging false-positive "martian source" + warnings and causing the relookup to fail. + +Fix this by initializing fl4_2 from fl4_dec and: +- Swapping source/destination IP addresses. +- Swapping L4 ports for transport protocols with ports (TCP, UDP, SCTP, DCCP) + so port-based policy routing matches correctly. Non-port protocols (such as + ICMP or GRE) leave the flowi_uli union fields intact to prevent corruption. +- Setting .flowi4_oif = l3mdev_master_ifindex(route_lookup_dev) to ensure + VRF routing tables are respected. +- Setting .flowi4_flags |= FLOWI_FLAG_ANYSRC to allow output route lookups + for non-local source IP addresses. +- Using __ip_route_output_key() instead of ip_route_output_key() for fl4_2 + so that raw FIB routing is used without triggering spurious XFRM policy + lookups on the decoy flow (the actual XFRM lookup is performed later using + fl4_dec). + +Fixes: 415b3334a21a ("icmp: Fix regression in nexthop resolution during replies.") +Reported-by: Muhammad Ziad +Closes: https://lore.kernel.org/netdev/CAOAwikA60AYKdFr_UDLyja3oU4hqyAE7uFZWqum5uRdaQsgRYg@mail.gmail.com/ +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260722104236.2938082-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index a9aef281631ee0..e8c59c2051c2de 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -536,11 +536,23 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4, + if (IS_ERR(rt2)) + err = PTR_ERR(rt2); + } else { +- struct flowi4 fl4_2 = {}; ++ struct flowi4 fl4_2 = fl4_dec; + unsigned long orefdst; + +- fl4_2.daddr = fl4_dec.saddr; +- rt2 = ip_route_output_key(net, &fl4_2); ++ swap(fl4_2.daddr, fl4_2.saddr); ++ switch (fl4_2.flowi4_proto) { ++ case IPPROTO_TCP: ++ case IPPROTO_UDP: ++ case IPPROTO_SCTP: ++ case IPPROTO_DCCP: ++ swap(fl4_2.fl4_sport, fl4_2.fl4_dport); ++ break; ++ } ++ ++ fl4_2.flowi4_oif = l3mdev_master_ifindex(route_lookup_dev); ++ fl4_2.flowi4_flags |= FLOWI_FLAG_ANYSRC; ++ ++ rt2 = __ip_route_output_key(net, &fl4_2); + if (IS_ERR(rt2)) { + err = PTR_ERR(rt2); + goto relookup_failed; +-- +2.53.0 + diff --git a/queue-6.1/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch b/queue-6.1/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch new file mode 100644 index 0000000000..e62a73a420 --- /dev/null +++ b/queue-6.1/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch @@ -0,0 +1,149 @@ +From 0e54b430d9d3b00d7815e65e0850f0775e05099e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:09:21 +0300 +Subject: net: bridge: vlan: fix vlan range dumps starting with pvid + +From: Nikolay Aleksandrov + +[ Upstream commit 43171c97e4714bf601b468401b37732244639c21 ] + +There is a bug in all range dumps that rely on br_vlan_can_enter_range() +when the PVID is a range starting VLAN, all following VLANs that match +its flags can enter the range, but when the range is filled in only the +PVID VLAN is dumped and the rest of the range is discarded because +br_vlan_fill_vids() checks for the PVID flag. Since the PVID VLAN can +be only one, we need to break ranges around it, the best way to do that +consistently for all is to alter br_vlan_can_enter_range() to take into +account the PVID and return false to break the range when it's matched. + +Before the fix: +$ ip l add br0 type bridge vlan_filtering 1 +$ ip l add dumdum type dummy +$ ip l set dumdum master br0 +$ ip l set br0 up +$ ip l set dumdum up +$ bridge vlan add dev dumdum vid 1 pvid untagged master +$ bridge vlan add dev dumdum vid 2 untagged master +$ bridge vlan show dev dumdum # use legacy dump to show all vlans +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged + +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + +VLAN 2 is missing, and if there are more matching VLANs afterwards +they'd be missing too. + +After the fix: +[ same setup steps ] +$ bridge vlan show dev dumdum +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + 2 Egress Untagged + state forwarding mcast_router 1 + +Fixes: 0ab558795184 ("net: bridge: vlan: add rtm range support") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260721140922.682265-2-razor@blackwall.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_netlink_tunnel.c | 3 ++- + net/bridge/br_private.h | 6 ++++-- + net/bridge/br_vlan.c | 10 ++++++---- + net/bridge/br_vlan_options.c | 3 +-- + 4 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/net/bridge/br_netlink_tunnel.c b/net/bridge/br_netlink_tunnel.c +index 8914290c75d480..e4aab077527011 100644 +--- a/net/bridge/br_netlink_tunnel.c ++++ b/net/bridge/br_netlink_tunnel.c +@@ -268,7 +268,8 @@ static void __vlan_tunnel_handle_range(const struct net_bridge_port *p, + if (!*v_start) + goto out_init; + +- if (v && curr_change && br_vlan_can_enter_range(v, *v_end)) { ++ if (v && curr_change && ++ br_vlan_can_enter_range(v, *v_end, br_get_pvid(vg))) { + *v_end = v; + return; + } +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index 7d2491c187d4ad..617e636a8a4c2b 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1487,7 +1487,8 @@ void br_vlan_notify(const struct net_bridge *br, + u16 vid, u16 vid_range, + int cmd); + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end); ++ const struct net_bridge_vlan *range_end, ++ u16 pvid); + + void br_vlan_fill_forward_path_pvid(struct net_bridge *br, + struct net_device_path_ctx *ctx, +@@ -1727,7 +1728,8 @@ static inline void br_vlan_notify(const struct net_bridge *br, + } + + static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { + return true; + } +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index 54b0f24eb08ff2..c442ed83c01f48 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1942,9 +1942,11 @@ void br_vlan_notify(const struct net_bridge *br, + + /* check if v_curr can enter a range ending in range_end */ + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { +- return v_curr->vid - range_end->vid == 1 && ++ return v_curr->vid != pvid && range_end->vid != pvid && ++ v_curr->vid - range_end->vid == 1 && + range_end->flags == v_curr->flags && + br_vlan_opts_eq_range(v_curr, range_end); + } +@@ -2026,8 +2028,8 @@ static int br_vlan_dump_dev(const struct net_device *dev, + idx += range_end->vid - range_start->vid + 1; + + range_start = v; +- } else if (dump_stats || v->vid == pvid || +- !br_vlan_can_enter_range(v, range_end)) { ++ } else if (dump_stats || ++ !br_vlan_can_enter_range(v, range_end, pvid)) { + u16 vlan_flags = br_vlan_flags(range_start, pvid); + + if (!br_vlan_fill_vids(skb, range_start->vid, +diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c +index a2724d03278c3b..166b96cc600312 100644 +--- a/net/bridge/br_vlan_options.c ++++ b/net/bridge/br_vlan_options.c +@@ -267,8 +267,7 @@ int br_vlan_process_options(const struct net_bridge *br, + continue; + } + +- if (v->vid == pvid || +- !br_vlan_can_enter_range(v, curr_end)) { ++ if (!br_vlan_can_enter_range(v, curr_end, pvid)) { + br_vlan_notify(br, p, curr_start->vid, + curr_end->vid, RTM_NEWVLAN); + curr_start = v; +-- +2.53.0 + diff --git a/queue-6.1/net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch b/queue-6.1/net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch new file mode 100644 index 0000000000..f2ea1e7ac6 --- /dev/null +++ b/queue-6.1/net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch @@ -0,0 +1,111 @@ +From ffe84b7040747ea7e1c56be7041983390dbf01a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 16:12:14 +0200 +Subject: net: dpaa2-eth: assign priv->mac after dpaa2_mac_connect() call + +From: Vladimir Oltean + +[ Upstream commit 02d61948e8daf3844d0af41ba5d563ef03cc7c4f ] + +There are 2 requirements for correct code: + +- Any time the driver accesses the priv->mac pointer at runtime, it + either holds NULL to indicate a DPNI-DPNI connection (or unconnected + DPNI), or a struct dpaa2_mac whose phylink instance was fully + initialized (created and connected to the PHY). No changes are made to + priv->mac while it is being used. Currently, rtnl_lock() watches over + the call to dpaa2_eth_connect_mac(), so it serves the purpose of + serializing this with all readers of priv->mac. + +- dpaa2_mac_connect() should run unlocked, because inside it are 2 + phylink calls with incompatible locking requirements: phylink_create() + requires that the rtnl_mutex isn't held, and phylink_fwnode_phy_connect() + requires that the rtnl_mutex is held. The only way to solve those + contradictory requirements is to let dpaa2_mac_connect() take + rtnl_lock() when it needs to. + +To solve both requirements, we need to identify the writer side of the +priv->mac pointer, which can be wrapped in a mutex private to the driver +in a future patch. The dpaa2_mac_connect() cannot be part of the writer +side critical section, because of an AB/BA deadlock with rtnl_lock(). + +So the strategy needs to be that where we prepare the DPMAC by calling +dpaa2_mac_connect(), and only make priv->mac point to it once it's fully +prepared. This ensures that the writer side critical section has the +absolute minimum surface it can. + +The reverse strategy is adopted in the dpaa2_eth_disconnect_mac() code +path. This makes sure that priv->mac is NULL when we start tearing down +the DPMAC that we disconnected from, and concurrent code will simply not +see it. + +No locking changes in this patch (concurrent code is still blocked by +the rtnl_mutex). + +Signed-off-by: Vladimir Oltean +Reviewed-by: Ioana Ciornei +Tested-by: Ioana Ciornei +Signed-off-by: Paolo Abeni +Stable-dep-of: b4b201cc93ff ("dpaa2-eth: put MAC endpoint device on disconnect") +Signed-off-by: Sasha Levin +--- + .../net/ethernet/freescale/dpaa2/dpaa2-eth.c | 21 +++++++++++-------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index 3c19be56af22e5..6727e17fb5145e 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -4466,9 +4466,8 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv) + err = dpaa2_mac_open(mac); + if (err) + goto err_free_mac; +- priv->mac = mac; + +- if (dpaa2_eth_is_type_phy(priv)) { ++ if (dpaa2_mac_is_type_phy(mac)) { + err = dpaa2_mac_connect(mac); + if (err && err != -EPROBE_DEFER) + netdev_err(priv->net_dev, "Error connecting to the MAC endpoint: %pe", +@@ -4477,11 +4476,12 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv) + goto err_close_mac; + } + ++ priv->mac = mac; ++ + return 0; + + err_close_mac: + dpaa2_mac_close(mac); +- priv->mac = NULL; + err_free_mac: + kfree(mac); + out_put_device: +@@ -4491,15 +4491,18 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv) + + static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) + { +- if (dpaa2_eth_is_type_phy(priv)) +- dpaa2_mac_disconnect(priv->mac); ++ struct dpaa2_mac *mac = priv->mac; + +- if (!dpaa2_eth_has_mac(priv)) ++ priv->mac = NULL; ++ ++ if (!mac) + return; + +- dpaa2_mac_close(priv->mac); +- kfree(priv->mac); +- priv->mac = NULL; ++ if (dpaa2_mac_is_type_phy(mac)) ++ dpaa2_mac_disconnect(mac); ++ ++ dpaa2_mac_close(mac); ++ kfree(mac); + } + + static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg) +-- +2.53.0 + diff --git a/queue-6.1/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch b/queue-6.1/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch new file mode 100644 index 0000000000..3dea91ea05 --- /dev/null +++ b/queue-6.1/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch @@ -0,0 +1,56 @@ +From 0a938d7887914a54afa1f46cc65a2ba44683b508 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 10:12:40 +0000 +Subject: net: hsr: fix memory leak on slave unregistration by removing synced + VLANs + +From: Eric Dumazet + +[ Upstream commit dcf15eaf5641812f1cfc5e96537380132a7da89d ] + +When an HSR master device is brought UP, it auto-adds VLAN 0 via +vlan_vid0_add(), which propagates VID 0 to its slave devices (slave A and B). + +If a slave device is later unregistered while HSR is active (e.g., during +netns cleanup or interface destruction), hsr_del_port() is called to +detach the slave port from the HSR master. However, hsr_del_port() currently +does not delete the VLAN IDs that were synced to the slave device by HSR. + +As a result, the slave device retains a refcount on VID 0 (and any other +synced VLANs). When the slave device is destroyed, its vlan_info / +vlan_vid_info structure remains allocated, leading to a memory leak. + +Fix this by calling vlan_vids_del_by_dev(port->dev, master->dev) in +hsr_del_port() before unlinking slave A or slave B ports, matching the +propagation logic in hsr_ndo_vlan_rx_add_vid() / hsr_ndo_vlan_rx_kill_vid() +and the cleanup behavior in bonding and team drivers. + +Fixes: 1a8a63a5305e ("net: hsr: Add VLAN CTAG filter support") +Reported-by: syzbot+456957213f32970c0762@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/6a4cb6ca.57639fcc.86d58.000b.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Fernando Fernandez Mancera +Reviewed-by: Felix Maurer +Link: https://patch.msgid.link/20260721101240.995597-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_slave.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c +index b8230faa567f77..58e757dc555461 100644 +--- a/net/hsr/hsr_slave.c ++++ b/net/hsr/hsr_slave.c +@@ -228,6 +228,8 @@ void hsr_del_port(struct hsr_port *port) + netdev_rx_handler_unregister(port->dev); + if (!port->hsr->fwd_offloaded) + dev_set_promiscuity(port->dev, -1); ++ if (port->type == HSR_PT_SLAVE_A || port->type == HSR_PT_SLAVE_B) ++ vlan_vids_del_by_dev(port->dev, master->dev); + netdev_upper_dev_unlink(port->dev, master->dev); + } + +-- +2.53.0 + diff --git a/queue-6.1/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch b/queue-6.1/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch new file mode 100644 index 0000000000..02f0c24cb1 --- /dev/null +++ b/queue-6.1/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch @@ -0,0 +1,48 @@ +From 45cdb148837d5bd6840ebc8d58f174e3b6796a56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 22:32:30 +0800 +Subject: net: ipv6: fix dif and sdif mismatch in raw6_icmp_error + +From: Li RongQing + +[ Upstream commit 440e274da4d1b93c7df2cb0ce893c3009dd4db55 ] + +In raw6_icmp_error(), raw_v6_match() is called with inet6_iif(skb) passed +to both the 'dif' and 'sdif' arguments. This is a copy-paste or typo error, +as the last argument should represent the secondary interface index (sdif). + +This mismatch breaks ICMPv6 error handling for IPv6 raw sockets in VRF +(Virtual Routing and Forwarding) environments. When a raw socket is bound +to a VRF master device, raw_v6_match() fails to find a match because it is +not given the correct sdif value, causing the socket to miss relevant +ICMPv6 error notifications. + +Fix this by properly passing inet6_sdif(skb) as the last argument to +raw_v6_match(). + +Fixes: 5108ab4bf446fa ("net: ipv6: add second dif to raw socket lookups") +Signed-off-by: Li RongQing +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260717143230.1836-1-lirongqing@baidu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/raw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index c644300680ba67..f6f18196ed6e4a 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -342,7 +342,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data; + + if (!raw_v6_match(net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr, +- inet6_iif(skb), inet6_iif(skb))) ++ inet6_iif(skb), inet6_sdif(skb))) + continue; + rawv6_err(sk, skb, NULL, type, code, inner_offset, info); + } +-- +2.53.0 + diff --git a/queue-6.1/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch b/queue-6.1/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch new file mode 100644 index 0000000000..4dea901c8b --- /dev/null +++ b/queue-6.1/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch @@ -0,0 +1,51 @@ +From 2aa14f099a97a178b25a76826bdfc00a23f48991 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:33:06 +0300 +Subject: net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule + +From: Yael Chemla + +[ Upstream commit d12956d083eb70f2c6d72711aebaf8c2ce21e170 ] + +esw_egress_acl_vlan_create() hardcodes num_dest=0 in its +mlx5_add_flow_rules() call. When invoked from the non-bond path +fwd_dest is NULL and num_dest=0 is correct. When invoked from +esw_acl_egress_ofld_rules_create() during a bond event, fwd_dest is +non-NULL and flow_act.action carries MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, +but _mlx5_add_flow_rules() rejects a non-NULL dest pointer paired with +dest_num<=0 and returns -EINVAL. The error propagates as +"configure slave vport egress fwd, err(-22)". The passive vport's egress +ACL table ends up with its flow groups allocated but no FTEs, so +prio-tagged packets are not popped and bond failover is broken on +prio_tag_required devices. + +Fix by passing fwd_dest ? 1 : 0 as num_dest to match the actual number +of destinations supplied. + +Fixes: bf773dc0e6d5 ("net/mlx5: E-Switch, Introduce APIs to enable egress acl forward-to-vport rule") +Signed-off-by: Yael Chemla +Reviewed-by: Cosmin Ratiu +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20260717073306.1242399-1-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +index 45b839116212df..61d299f8ca25ce 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +@@ -70,7 +70,7 @@ int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw, + flow_act.action = flow_action; + vport->egress.allowed_vlan = + mlx5_add_flow_rules(vport->egress.acl, spec, +- &flow_act, fwd_dest, 0); ++ &flow_act, fwd_dest, fwd_dest ? 1 : 0); + if (IS_ERR(vport->egress.allowed_vlan)) { + err = PTR_ERR(vport->egress.allowed_vlan); + esw_warn(esw->dev, +-- +2.53.0 + diff --git a/queue-6.1/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch b/queue-6.1/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch new file mode 100644 index 0000000000..232b6d0fef --- /dev/null +++ b/queue-6.1/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch @@ -0,0 +1,46 @@ +From cad707e9216107ab9635b98e6ef4c6c635a8a7d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:25 +0300 +Subject: net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation + +From: Alexei Lazar + +[ Upstream commit 9173e1d3c7c7d49a71eee813091f9e834ec7cee5 ] + +Credit Based (CB) TSA is not supported by the mlx5 driver, so reject +any configurations that specify it. + +Fixes: 08fb1dacdd76 ("net/mlx5e: Support DCBNL IEEE ETS") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-3-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 0bc3ae071e8324..1a73fa436a1368 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -309,6 +309,14 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev, + } + } + ++ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { ++ if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_CB_SHAPER) { ++ netdev_err(netdev, ++ "Failed to validate ETS: CB Shaper is not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ + /* Validate Bandwidth Sum */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { +-- +2.53.0 + diff --git a/queue-6.1/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch b/queue-6.1/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch new file mode 100644 index 0000000000..7677313eea --- /dev/null +++ b/queue-6.1/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch @@ -0,0 +1,53 @@ +From bf971e204343d64eb2aa8f653853ae131b99e999 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:24 +0300 +Subject: net/mlx5e: Report zero bandwidth for non-ETS traffic classes + +From: Alexei Lazar + +[ Upstream commit ffb1873b2df11945b8c395e859169248675c91c5 ] + +The IEEE 802.1Qaz standard defines that bandwidth allocation percentages +only apply to Enhanced Transmission Selection (ETS) traffic classes. +For STRICT and VENDOR transmission selection algorithms, bandwidth +percentage values are not applicable. + +Currently for non-ETS 100 bandwidth is being reported for all traffic +classes in the get operation due to hardware limitation, regardless of +their TSA type. + +Fix this by reporting 0 for non-ETS traffic classes. + +Fixes: 820c2c5e773d ("net/mlx5e: Read ETS settings directly from firmware") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-2-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index e29a8ed7e7ac13..0bc3ae071e8324 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -158,6 +158,13 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, + } + memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa)); + ++ /* Report 0 for non ETS TSA */ ++ for (i = 0; i < ets->ets_cap; i++) { ++ if (ets->tc_tx_bw[i] == MLX5E_MAX_BW_ALLOC && ++ priv->dcbx.tc_tsa[i] != IEEE_8021QAZ_TSA_ETS) ++ ets->tc_tx_bw[i] = 0; ++ } ++ + return err; + } + +-- +2.53.0 + diff --git a/queue-6.1/net-packet-avoid-fanout-hook-re-registration-after-u.patch b/queue-6.1/net-packet-avoid-fanout-hook-re-registration-after-u.patch new file mode 100644 index 0000000000..1ea62ee5ab --- /dev/null +++ b/queue-6.1/net-packet-avoid-fanout-hook-re-registration-after-u.patch @@ -0,0 +1,61 @@ +From c1064169f87171a301f32bb0794210e8cb2fd06a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:44:37 +0000 +Subject: net/packet: avoid fanout hook re-registration after unregister + +From: David Lee + +[ Upstream commit 50aff80475abd3533eef4320477037e6fcc6b56e ] + +packet_set_ring() temporarily detaches a socket from packet delivery while +reconfiguring its ring. It records the previous running state, clears +po->num, unregisters the protocol hook when needed, drops po->bind_lock, +and later restores po->num and re-registers the hook from the saved +was_running value. + +That unlocked window can race with NETDEV_UNREGISTER. The notifier can +observe the socket as not running, skip __unregister_prot_hook(), and +invalidate the per-socket binding by setting po->ifindex to -1 and clearing +po->prot_hook.dev. A one-member fanout group can still retain its shared +fanout hook device pointer. When packet_set_ring() resumes, re-registering +solely from the stale was_running state can re-add the fanout hook after +the device has been unregistered. + +Treat po->ifindex == -1 as an invalidated binding after reacquiring +po->bind_lock. This is distinct from ifindex 0, the normal +unbound/wildcard state: ifindex -1 marks an existing device binding that +was invalidated when the device was unregistered. Restore po->num as +before, but do not re-register the hook if device unregister already +detached the socket. + +Fixes: dc99f600698d ("packet: Add fanout support.") +Link: https://lore.kernel.org/netdev/20260701113947.23180-1-david.lee@trailofbits.com/ +Signed-off-by: David Lee +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260707104440.833129-1-david.lee@trailofbits.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index f3850784d66404..cf013102e77457 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -4584,7 +4584,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + + spin_lock(&po->bind_lock); + WRITE_ONCE(po->num, num); +- if (was_running) ++ /* ++ * NETDEV_UNREGISTER may have invalidated the binding while bind_lock ++ * was dropped above. Do not re-add a fanout hook to a dead device. ++ */ ++ if (was_running && READ_ONCE(po->ifindex) != -1) + register_prot_hook(sk); + + spin_unlock(&po->bind_lock); +-- +2.53.0 + diff --git a/queue-6.1/net-qrtr-restrict-socket-creation-to-the-initial-net.patch b/queue-6.1/net-qrtr-restrict-socket-creation-to-the-initial-net.patch new file mode 100644 index 0000000000..bea4fc0833 --- /dev/null +++ b/queue-6.1/net-qrtr-restrict-socket-creation-to-the-initial-net.patch @@ -0,0 +1,63 @@ +From dcfa856c56bf7f11084adc69d7472b12550f92a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 12:43:19 -0300 +Subject: net: qrtr: restrict socket creation to the initial network namespace + +From: Aldo Ariel Panzardo + +[ Upstream commit 3b536db8fb32da9e9c62f2bb45e2e319331f0426 ] + +QRTR keeps its entire port and node state in module-global variables +that are not partitioned per network namespace: qrtr_local_nid is a +single global node id (always 1) and qrtr_ports is a single global +xarray. qrtr_port_lookup() and qrtr_local_enqueue() operate on that +global state with no network-namespace check, and qrtr_create() places +no restriction on the namespace a socket is created in. + +As a result an unprivileged process that creates an AF_QIPCRTR socket +in a separate network namespace, e.g. via +unshare(CLONE_NEWUSER | CLONE_NEWNET), can send QRTR datagrams - +including control-plane messages such as QRTR_TYPE_NEW_SERVER - to QRTR +sockets owned by another namespace, and vice versa. The receiving +socket sees such a message as coming from node id 1, indistinguishable +from a legitimate local client, breaking the isolation that network +namespaces are expected to provide. + +QRTR is a transport to global hardware endpoints (the modem and other +remote processors) and has no per-namespace semantics; its in-kernel +name service already creates its socket in init_net only. Confine the +socket family to the initial network namespace, as other +non-namespace-aware socket families do (see llc_ui_create() and the +ieee802154 socket code). + +Fixes: bdabad3e363d ("net: Add Qualcomm IPC router") +Signed-off-by: Aldo Ariel Panzardo +Link: https://patch.msgid.link/20260716154319.3297699-1-qwe.aldo@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/qrtr/af_qrtr.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c +index b9d249004a0eec..d13ca058fef6db 100644 +--- a/net/qrtr/af_qrtr.c ++++ b/net/qrtr/af_qrtr.c +@@ -1257,6 +1257,14 @@ static int qrtr_create(struct net *net, struct socket *sock, + if (sock->type != SOCK_DGRAM) + return -EPROTOTYPE; + ++ /* QRTR keeps its port and node state in module-global variables that ++ * are not partitioned per network namespace, and the in-kernel name ++ * service only operates in init_net. Confine the family to init_net so ++ * a socket in another namespace cannot reach the global control plane. ++ */ ++ if (!net_eq(net, &init_net)) ++ return -EAFNOSUPPORT; ++ + sk = sk_alloc(net, AF_QIPCRTR, GFP_KERNEL, &qrtr_proto, kern); + if (!sk) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-6.1/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch b/queue-6.1/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch new file mode 100644 index 0000000000..8ea8fd30cd --- /dev/null +++ b/queue-6.1/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch @@ -0,0 +1,103 @@ +From 9f16d84812ce456186254be78185c7f3b7a376a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:15 -0700 +Subject: net: stmmac: fix l3l4 filter rejecting unsupported offload requests + +From: Nazim Amirul + +[ Upstream commit 5536d7c843637e9430279b94935fcf7df98babb3 ] + +The basic flow parser in tc_add_basic_flow() does not validate match +keys before proceeding. Unsupported offload configurations such as +partial protocol masks, non-IPv4 network proto, or non-TCP/UDP transport +proto are silently accepted instead of returning -EOPNOTSUPP. + +Add validation to return -EOPNOTSUPP early for: +- No network or transport proto present in the key +- Partial protocol mask (only full mask supported) +- Network proto is not IPv4 +- Transport proto is not TCP or UDP + +Each rejection includes an extack message so the user knows which part +of the match is unsupported. + +Also propagate -EOPNOTSUPP from tc_add_basic_flow() in tc_add_flow() +by returning it directly rather than using break. The break was silently +discarding the error for FLOW_CLS_REPLACE operations where entry->in_use +is already true, causing tc_add_flow() to return 0 (success) for +unsupported replace requests. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-4-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 34 +++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 27187f5286206a..6bf198b3f12369 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -456,6 +456,7 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv, + } + + #define ETHER_TYPE_FULL_MASK cpu_to_be16(~0) ++#define IP_PROTO_FULL_MASK 0xFF + + static int tc_add_basic_flow(struct stmmac_priv *priv, + struct flow_cls_offload *cls, +@@ -471,6 +472,37 @@ static int tc_add_basic_flow(struct stmmac_priv *priv, + + flow_rule_match_basic(rule, &match); + ++ /* Both network proto and transport proto not present in the key */ ++ if (!match.mask || !(match.mask->n_proto || match.mask->ip_proto)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "filter must specify network or transport protocol"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* If the proto is present in the key and is not full mask */ ++ if ((match.mask->n_proto && match.mask->n_proto != ETHER_TYPE_FULL_MASK) || ++ (match.mask->ip_proto && match.mask->ip_proto != IP_PROTO_FULL_MASK)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only full protocol mask is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Network proto is present in the key and is not IPv4 */ ++ if (match.mask->n_proto && match.key->n_proto != cpu_to_be16(ETH_P_IP)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only IPv4 network protocol is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Transport proto is present in the key and is not TCP or UDP */ ++ if (match.mask->ip_proto && ++ match.key->ip_proto != IPPROTO_TCP && ++ match.key->ip_proto != IPPROTO_UDP) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only TCP and UDP transport protocols are supported"); ++ return -EOPNOTSUPP; ++ } ++ + entry->ip_proto = match.key->ip_proto; + return 0; + } +@@ -608,6 +640,8 @@ static int tc_add_flow(struct stmmac_priv *priv, + ret = tc_flow_parsers[i].fn(priv, cls, entry); + if (!ret) + entry->in_use = true; ++ else if (ret == -EOPNOTSUPP) ++ return ret; + } + + if (!entry->in_use) +-- +2.53.0 + diff --git a/queue-6.1/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch b/queue-6.1/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch new file mode 100644 index 0000000000..357c16abcd --- /dev/null +++ b/queue-6.1/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch @@ -0,0 +1,43 @@ +From 949f3514c0fd2d5b41e51b38087e04aadfc4ed62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:16 -0700 +Subject: net: stmmac: reset residual action in L3L4 filters on delete + +From: Nazim Amirul + +[ Upstream commit a448f821289934b961dd9d8d0beb006cc8937ba2 ] + +When deleting an L3/L4 flower filter entry, the action field is not +reset. If a filter was previously configured with a drop action, that +action may persist and affect subsequent filter configurations +unintentionally. + +Clear the action field when the filter entry is deleted. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-5-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 6bf198b3f12369..e9aac51c1b9b78 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -671,6 +671,7 @@ static int tc_del_flow(struct stmmac_priv *priv, + entry->in_use = false; + entry->cookie = 0; + entry->is_l4 = false; ++ entry->action = 0; + return ret; + } + +-- +2.53.0 + diff --git a/queue-6.1/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch b/queue-6.1/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch new file mode 100644 index 0000000000..ca44a61e19 --- /dev/null +++ b/queue-6.1/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch @@ -0,0 +1,59 @@ +From ec6a09ff3f80d4b60e6b28ca796e4e9b8e2244eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 22:15:51 +0000 +Subject: nexthop: initialize extack in nh_res_bucket_migrate() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 6347c5314cee49f364aaf2e40ff15415a57a116e ] + +nh_res_bucket_migrate() passes an uninitialized netlink_ext_ack to +call_nexthop_res_bucket_notifiers(). When +nh_notifier_res_bucket_info_init() fails (e.g. the kzalloc returns +-ENOMEM), the error is propagated back before any notifier sets +extack._msg, and the error path formats the stale pointer with +pr_err_ratelimited("%s\n", extack._msg). With CONFIG_INIT_STACK_NONE +this dereferences uninitialized stack memory: + + Oops: general protection fault, probably for non-canonical address ... + KASAN: maybe wild-memory-access in range [...] + RIP: 0010:string (lib/vsprintf.c:730) + vsnprintf (lib/vsprintf.c:2945) + _printk (kernel/printk/printk.c:2504) + nh_res_bucket_migrate (net/ipv4/nexthop.c:1816) + nh_res_table_upkeep (net/ipv4/nexthop.c:1866) + rtm_new_nexthop (net/ipv4/nexthop.c:3323) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7076) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + Kernel panic - not syncing: Fatal exception + +Zero-initialize extack so _msg is NULL on error paths that never set it. + +Fixes: 7c37c7e00411 ("nexthop: Implement notifiers for resilient nexthop groups") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260713221551.3344650-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/nexthop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c +index 49871e5f46802d..13a798f9dc9cb4 100644 +--- a/net/ipv4/nexthop.c ++++ b/net/ipv4/nexthop.c +@@ -1504,8 +1504,8 @@ static bool nh_res_bucket_migrate(struct nh_res_table *res_table, + bool notify_nl, bool force) + { + struct nh_res_bucket *bucket = &res_table->nh_buckets[bucket_index]; ++ struct netlink_ext_ack extack = {}; + struct nh_grp_entry *new_nhge; +- struct netlink_ext_ack extack; + int err; + + new_nhge = list_first_entry_or_null(&res_table->uw_nh_entries, +-- +2.53.0 + diff --git a/queue-6.1/nfp-check-resource-mutex-allocation.patch b/queue-6.1/nfp-check-resource-mutex-allocation.patch new file mode 100644 index 0000000000..6f876c6e6d --- /dev/null +++ b/queue-6.1/nfp-check-resource-mutex-allocation.patch @@ -0,0 +1,52 @@ +From 4b2b1d98920b6e37de0e4c7d3af5c938e898b115 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:08 +0800 +Subject: nfp: Check resource mutex allocation + +From: Ruoyu Wang + +[ Upstream commit a61b4db34a753bdf5c9e77a7f3d3dddd41dcfacc ] + +nfp_cpp_resource_find() allocates a CPP mutex handle for the matching +resource-table entry and then reports success. nfp_resource_try_acquire() +immediately passes that handle to nfp_cpp_mutex_trylock(). + +However, nfp_cpp_mutex_alloc() returns NULL on failure. If that happens +for a matching table entry, the resource lookup still returns success and +the following trylock dereferences a NULL mutex pointer while opening the +resource. + +nfp_resource_acquire() already treats failure to allocate the table mutex +as -ENOMEM. Do the same for the resource mutex and fail the lookup before +publishing the rest of the resource handle. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: f01a2161577d ("nfp: add support for resources") +Signed-off-by: Ruoyu Wang +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708143408.3168425-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +index ce7492a6a98fad..908d99f398b819 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c ++++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +@@ -96,6 +96,9 @@ static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res) + res->mutex = + nfp_cpp_mutex_alloc(cpp, + NFP_RESOURCE_TBL_TARGET, addr, key); ++ if (!res->mutex) ++ return -ENOMEM; ++ + res->cpp_id = NFP_CPP_ID(entry.region.cpp_target, + entry.region.cpp_action, + entry.region.cpp_token); +-- +2.53.0 + diff --git a/queue-6.1/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch b/queue-6.1/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch new file mode 100644 index 0000000000..5dd1928fac --- /dev/null +++ b/queue-6.1/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch @@ -0,0 +1,40 @@ +From 3153112a335b6aa630b1df718a1101793d279451 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 10:50:07 +0530 +Subject: octeontx2-vf: set TC flower flag on MCAM entry allocation + +From: Suman Ghosh + +[ Upstream commit 0d4d31e3cc5dd6204fa1495c4107f5075acce5ed ] + +When MCAM entries are allocated for a VF netdev via the devlink +mcam_count parameter, only OTX2_FLAG_NTUPLE_SUPPORT was set. That +enabled ethtool ntuple filters but not tc flower offload. Also set +OTX2_FLAG_TC_FLOWER_SUPPORT when entries are successfully allocated. + +Fixes: 2da489432747 ("octeontx2-pf: devlink params support to set mcam entry count") +Signed-off-by: Suman Ghosh +Signed-off-by: Ratheesh Kannoth +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260715052007.2099851-1-rkannoth@marvell.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +index 7c7f8814fb3f95..cbf44f0d7d8bb6 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +@@ -153,6 +153,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count) + if (allocated) { + pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC; + pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT; ++ pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT; + } + + if (allocated != count) +-- +2.53.0 + diff --git a/queue-6.1/ppp-annotate-data-races-in-ppp_generic.patch b/queue-6.1/ppp-annotate-data-races-in-ppp_generic.patch new file mode 100644 index 0000000000..c1f776d2f5 --- /dev/null +++ b/queue-6.1/ppp-annotate-data-races-in-ppp_generic.patch @@ -0,0 +1,233 @@ +From 1410861e5e23a4d19a5d06da319530dc8581e3a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:16:05 +0000 +Subject: ppp: annotate data races in ppp_generic + +From: Eric Dumazet + +[ Upstream commit 543adf072165aaf2e3b635c0476204f9658ed3bf ] + +Several fields in struct ppp can be read or updated concurrently +from multiple CPUs without synchronization, causing data races: + +1. ppp->mru is read concurrently in ppp_receive_nonmp_frame() while + being updated via PPPIOCSMRU ioctl. Protect ppp->mru updates in + PPPIOCSMRU with ppp_recv_lock(ppp). + +2. PPPIOCGFLAGS reads ppp->flags, ppp->xstate, and ppp->rstate + unlocked. Wrap the read in ppp_lock(ppp) to get a consistent + snapshot. + +3. ppp->debug is updated via PPPIOCSDEBUG and read concurrently on + fast paths. Annotate reads with READ_ONCE() and writes with + WRITE_ONCE(). + +4. ppp->last_xmit and ppp->last_recv are updated on TX/RX data paths + and read via PPPIOCGIDLE32 / PPPIOCGIDLE64 ioctls. Annotate with + WRITE_ONCE() / READ_ONCE() and use max() to handle jiffies + subtraction. + +5. ppp->npmode[] is updated via PPPIOCSNPMODE and read on TX/RX + paths. Annotate with WRITE_ONCE() / READ_ONCE(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/20260722101605.2868548-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 50 ++++++++++++++++++++--------------- + 1 file changed, 28 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index a657155076af9d..51e5c872552805 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -811,7 +811,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case PPPIOCSMRU: + if (get_user(val, p)) + break; ++ ppp_recv_lock(ppp); + ppp->mru = val; ++ ppp_recv_unlock(ppp); + err = 0; + break; + +@@ -832,7 +834,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + + case PPPIOCGFLAGS: ++ ppp_lock(ppp); + val = ppp->flags | ppp->xstate | ppp->rstate; ++ ppp_unlock(ppp); + if (put_user(val, p)) + break; + err = 0; +@@ -856,7 +860,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case PPPIOCSDEBUG: + if (get_user(val, p)) + break; +- ppp->debug = val; ++ WRITE_ONCE(ppp->debug, val); + err = 0; + break; + +@@ -867,16 +871,16 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + + case PPPIOCGIDLE32: +- idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ; +- idle32.recv_idle = (jiffies - ppp->last_recv) / HZ; +- if (copy_to_user(argp, &idle32, sizeof(idle32))) ++ idle32.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ; ++ idle32.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ; ++ if (copy_to_user(argp, &idle32, sizeof(idle32))) + break; + err = 0; + break; + + case PPPIOCGIDLE64: +- idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ; +- idle64.recv_idle = (jiffies - ppp->last_recv) / HZ; ++ idle64.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ; ++ idle64.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ; + if (copy_to_user(argp, &idle64, sizeof(idle64))) + break; + err = 0; +@@ -917,7 +921,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + if (copy_to_user(argp, &npi, sizeof(npi))) + break; + } else { +- ppp->npmode[i] = npi.mode; ++ WRITE_ONCE(ppp->npmode[i], npi.mode); + /* we may be able to transmit more packets now (??) */ + netif_wake_queue(ppp->dev); + } +@@ -1454,7 +1458,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) + goto outf; + + /* Drop, accept or reject the packet */ +- switch (ppp->npmode[npi]) { ++ switch (READ_ONCE(ppp->npmode[npi])) { + case NPMODE_PASS: + break; + case NPMODE_QUEUE: +@@ -1769,7 +1773,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_OUTBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: outbound frame " + "not passed\n"); +@@ -1779,11 +1783,11 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + /* if this packet passes the active filter, record the time */ + if (!(ppp->active_filter && + bpf_prog_run(ppp->active_filter, skb) == 0)) +- ppp->last_xmit = jiffies; ++ WRITE_ONCE(ppp->last_xmit, jiffies); + skb_pull(skb, 2); + #else + /* for data packets, record the time */ +- ppp->last_xmit = jiffies; ++ WRITE_ONCE(ppp->last_xmit, jiffies); + #endif /* CONFIG_PPP_FILTER */ + } + +@@ -2159,7 +2163,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + noskb: + spin_unlock(&pch->downl); + err_linearize: +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); + ++ppp->dev->stats.tx_errors; + ++ppp->nxseq; +@@ -2505,7 +2509,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: inbound frame " + "not passed\n"); +@@ -2514,14 +2518,14 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + } + if (!(ppp->active_filter && + bpf_prog_run(ppp->active_filter, skb) == 0)) +- ppp->last_recv = jiffies; ++ WRITE_ONCE(ppp->last_recv, jiffies); + __skb_pull(skb, 2); + } else + #endif /* CONFIG_PPP_FILTER */ +- ppp->last_recv = jiffies; ++ WRITE_ONCE(ppp->last_recv, jiffies); + + if ((ppp->dev->flags & IFF_UP) == 0 || +- ppp->npmode[npi] != NPMODE_PASS) { ++ READ_ONCE(ppp->npmode[npi]) != NPMODE_PASS) { + kfree_skb(skb); + } else { + /* chop off protocol */ +@@ -2774,7 +2778,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + seq = seq_before(minseq, PPP_MP_CB(p)->sequence)? + minseq + 1: PPP_MP_CB(p)->sequence; + +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "lost frag %u..%u\n", + oldseq, seq-1); +@@ -2823,7 +2827,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + struct sk_buff *tmp2; + + skb_queue_reverse_walk_from_safe(list, p, tmp2) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "discarding frag %u\n", + PPP_MP_CB(p)->sequence); +@@ -2845,7 +2849,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + skb_queue_walk_safe(list, p, tmp) { + if (p == head) + break; +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "discarding frag %u\n", + PPP_MP_CB(p)->sequence); +@@ -2853,7 +2857,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + kfree_skb(p); + } + +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + " missed pkts %u..%u\n", + ppp->nextseq, +@@ -3163,7 +3167,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) + if (!ppp->rc_state) + break; + if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len, +- ppp->file.index, 0, ppp->mru, ppp->debug)) { ++ ppp->file.index, 0, ppp->mru, ++ READ_ONCE(ppp->debug))) { + ppp->rstate |= SC_DECOMP_RUN; + ppp->rstate &= ~(SC_DC_ERROR | SC_DC_FERROR); + } +@@ -3172,7 +3177,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) + if (!ppp->xc_state) + break; + if (ppp->xcomp->comp_init(ppp->xc_state, dp, len, +- ppp->file.index, 0, ppp->debug)) ++ ppp->file.index, 0, ++ READ_ONCE(ppp->debug))) + ppp->xstate |= SC_COMP_RUN; + } + break; +-- +2.53.0 + diff --git a/queue-6.1/ppp-convert-to-percpu-netstats.patch b/queue-6.1/ppp-convert-to-percpu-netstats.patch new file mode 100644 index 0000000000..d4390032c7 --- /dev/null +++ b/queue-6.1/ppp-convert-to-percpu-netstats.patch @@ -0,0 +1,137 @@ +From 60e61fd7ba5237b50c28be7ea86a198aebdd695e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 16:32:10 +0800 +Subject: ppp: convert to percpu netstats + +From: Qingfang Deng + +[ Upstream commit 1a3e9b7a6b09e8ab3d2af019e4a392622685855e ] + +Convert to percpu netstats to avoid lock contention when reading them. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20250610083211.909015-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 52 +++++++++++++---------------------- + 1 file changed, 19 insertions(+), 33 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 5d0cde253683d6..2575aaf316bc93 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -107,18 +107,6 @@ struct ppp_file { + #define PF_TO_PPP(pf) PF_TO_X(pf, struct ppp) + #define PF_TO_CHANNEL(pf) PF_TO_X(pf, struct channel) + +-/* +- * Data structure to hold primary network stats for which +- * we want to use 64 bit storage. Other network stats +- * are stored in dev->stats of the ppp strucute. +- */ +-struct ppp_link_stats { +- u64 rx_packets; +- u64 tx_packets; +- u64 rx_bytes; +- u64 tx_bytes; +-}; +- + /* + * Data structure describing one ppp unit. + * A ppp unit corresponds to a ppp network interface device +@@ -162,7 +150,6 @@ struct ppp { + struct bpf_prog *active_filter; /* filter for pkts to reset idle */ + #endif /* CONFIG_PPP_FILTER */ + struct net *ppp_net; /* the net we belong to */ +- struct ppp_link_stats stats64; /* 64 bit network stats */ + }; + + /* +@@ -1545,23 +1532,12 @@ ppp_net_siocdevprivate(struct net_device *dev, struct ifreq *ifr, + static void + ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) + { +- struct ppp *ppp = netdev_priv(dev); +- +- ppp_recv_lock(ppp); +- stats64->rx_packets = ppp->stats64.rx_packets; +- stats64->rx_bytes = ppp->stats64.rx_bytes; +- ppp_recv_unlock(ppp); +- +- ppp_xmit_lock(ppp); +- stats64->tx_packets = ppp->stats64.tx_packets; +- stats64->tx_bytes = ppp->stats64.tx_bytes; +- ppp_xmit_unlock(ppp); +- + stats64->rx_errors = dev->stats.rx_errors; + stats64->tx_errors = dev->stats.tx_errors; + stats64->rx_dropped = dev->stats.rx_dropped; + stats64->tx_dropped = dev->stats.tx_dropped; + stats64->rx_length_errors = dev->stats.rx_length_errors; ++ dev_fetch_sw_netstats(stats64, dev->tstats); + } + + static int ppp_dev_init(struct net_device *dev) +@@ -1659,6 +1635,7 @@ static void ppp_setup(struct net_device *dev) + dev->type = ARPHRD_PPP; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->priv_destructor = ppp_dev_priv_destructor; ++ dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; + netif_keep_dst(dev); + } + +@@ -1804,8 +1781,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + #endif /* CONFIG_PPP_FILTER */ + } + +- ++ppp->stats64.tx_packets; +- ppp->stats64.tx_bytes += skb->len - PPP_PROTO_LEN; ++ dev_sw_netstats_tx_add(ppp->dev, 1, skb->len - PPP_PROTO_LEN); + + switch (proto) { + case PPP_IP: +@@ -2483,8 +2459,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + break; + } + +- ++ppp->stats64.rx_packets; +- ppp->stats64.rx_bytes += skb->len - 2; ++ dev_sw_netstats_rx_add(ppp->dev, skb->len - PPP_PROTO_LEN); + + npi = proto_to_npindex(proto); + if (npi < 0) { +@@ -3312,14 +3287,25 @@ static void + ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) + { + struct slcompress *vj = ppp->vj; ++ int cpu; + + memset(st, 0, sizeof(*st)); +- st->p.ppp_ipackets = ppp->stats64.rx_packets; ++ for_each_possible_cpu(cpu) { ++ struct pcpu_sw_netstats *p = per_cpu_ptr(ppp->dev->tstats, cpu); ++ u64 rx_packets, rx_bytes, tx_packets, tx_bytes; ++ ++ rx_packets = u64_stats_read(&p->rx_packets); ++ rx_bytes = u64_stats_read(&p->rx_bytes); ++ tx_packets = u64_stats_read(&p->tx_packets); ++ tx_bytes = u64_stats_read(&p->tx_bytes); ++ ++ st->p.ppp_ipackets += rx_packets; ++ st->p.ppp_ibytes += rx_bytes; ++ st->p.ppp_opackets += tx_packets; ++ st->p.ppp_obytes += tx_bytes; ++ } + st->p.ppp_ierrors = ppp->dev->stats.rx_errors; +- st->p.ppp_ibytes = ppp->stats64.rx_bytes; +- st->p.ppp_opackets = ppp->stats64.tx_packets; + st->p.ppp_oerrors = ppp->dev->stats.tx_errors; +- st->p.ppp_obytes = ppp->stats64.tx_bytes; + if (!vj) + return; + st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; +-- +2.53.0 + diff --git a/queue-6.1/ppp-enable-tx-scatter-gather.patch b/queue-6.1/ppp-enable-tx-scatter-gather.patch new file mode 100644 index 0000000000..932ecb36f9 --- /dev/null +++ b/queue-6.1/ppp-enable-tx-scatter-gather.patch @@ -0,0 +1,115 @@ +From fab39ffa88ba28fe0502bbcd12e6b503d9127337 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Jan 2026 09:29:02 +0800 +Subject: ppp: enable TX scatter-gather + +From: Qingfang Deng + +[ Upstream commit 42fcb213e58a7da33d5d2d7517b4e521025c68c3 ] + +PPP channels using chan->direct_xmit prepend the PPP header to a skb and +call dev_queue_xmit() directly. In this mode the skb does not need to be +linear, but the PPP netdevice currently does not advertise +scatter-gather features, causing unnecessary linearization and +preventing GSO. + +Enable NETIF_F_SG and NETIF_F_FRAGLIST on PPP devices. In case a linear +buffer is required (PPP compression, multilink, and channels without +direct_xmit), call skb_linearize() explicitly. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20260129012902.941-1-dqfext@gmail.com +Signed-off-by: Paolo Abeni +Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 30 +++++++++++++++++++++++++----- + 1 file changed, 25 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 2575aaf316bc93..a657155076af9d 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1636,6 +1636,8 @@ static void ppp_setup(struct net_device *dev) + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->priv_destructor = ppp_dev_priv_destructor; + dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; ++ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST; ++ dev->hw_features = dev->features; + netif_keep_dst(dev); + } + +@@ -1700,6 +1702,10 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb) + ppp->xcomp->comp_extra + ppp->dev->hard_header_len; + int compressor_skb_size = ppp->dev->mtu + + ppp->xcomp->comp_extra + PPP_HDRLEN; ++ ++ if (skb_linearize(skb)) ++ return NULL; ++ + new_skb = alloc_skb(new_skb_size, GFP_ATOMIC); + if (!new_skb) { + if (net_ratelimit()) +@@ -1787,6 +1793,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + case PPP_IP: + if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0) + break; ++ ++ if (skb_linearize(skb)) ++ goto drop; ++ + /* try to do VJ TCP header compression */ + new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2, + GFP_ATOMIC); +@@ -1884,19 +1894,26 @@ ppp_push(struct ppp *ppp) + } + + if ((ppp->flags & SC_MULTILINK) == 0) { ++ struct ppp_channel *chan; + /* not doing multilink: send it down the first channel */ + list = list->next; + pch = list_entry(list, struct channel, clist); + + spin_lock(&pch->downl); +- if (pch->chan) { +- if (pch->chan->ops->start_xmit(pch->chan, skb)) +- ppp->xmit_pending = NULL; +- } else { +- /* channel got unregistered */ ++ chan = pch->chan; ++ if (unlikely(!chan || (!chan->direct_xmit && skb_linearize(skb)))) { ++ /* channel got unregistered, or it requires a linear ++ * skb but linearization failed ++ */ + kfree_skb(skb); + ppp->xmit_pending = NULL; ++ goto out; + } ++ ++ if (chan->ops->start_xmit(chan, skb)) ++ ppp->xmit_pending = NULL; ++ ++out: + spin_unlock(&pch->downl); + return; + } +@@ -1981,6 +1998,8 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + return 0; /* can't take now, leave it in xmit_pending */ + + /* Do protocol field compression */ ++ if (skb_linearize(skb)) ++ goto err_linearize; + p = skb->data; + len = skb->len; + if (*p == 0 && mp_protocol_compress) { +@@ -2139,6 +2158,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + + noskb: + spin_unlock(&pch->downl); ++ err_linearize: + if (ppp->debug & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); + ++ppp->dev->stats.tx_errors; +-- +2.53.0 + diff --git a/queue-6.1/ppp-use-iff_no_queue-in-virtual-interfaces.patch b/queue-6.1/ppp-use-iff_no_queue-in-virtual-interfaces.patch new file mode 100644 index 0000000000..bccde7887e --- /dev/null +++ b/queue-6.1/ppp-use-iff_no_queue-in-virtual-interfaces.patch @@ -0,0 +1,105 @@ +From 0394a3f497721844b03431dea16ec7f39eb87f6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 21:55:16 +0800 +Subject: ppp: use IFF_NO_QUEUE in virtual interfaces +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Qingfang Deng + +[ Upstream commit 95d0d094ba26432ec467e2260f4bf553053f1f8f ] + +For PPPoE, PPTP, and PPPoL2TP, the start_xmit() function directly +forwards packets to the underlying network stack and never returns +anything other than 1. So these interfaces do not require a qdisc, +and the IFF_NO_QUEUE flag should be set. + +Introduces a direct_xmit flag in struct ppp_channel to indicate when +IFF_NO_QUEUE should be applied. The flag is set in ppp_connect_channel() +for relevant protocols. + +While at it, remove the usused latency member from struct ppp_channel. + +Signed-off-by: Qingfang Deng +Reviewed-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20250301135517.695809-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 4 ++++ + drivers/net/ppp/pppoe.c | 1 + + drivers/net/ppp/pptp.c | 1 + + include/linux/ppp_channel.h | 3 +-- + net/l2tp/l2tp_ppp.c | 1 + + 5 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index d3ea1d6da20568..5d0cde253683d6 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -3508,6 +3508,10 @@ ppp_connect_channel(struct channel *pch, int unit) + ret = -ENOTCONN; + goto outl; + } ++ if (pch->chan->direct_xmit) ++ ppp->dev->priv_flags |= IFF_NO_QUEUE; ++ else ++ ppp->dev->priv_flags &= ~IFF_NO_QUEUE; + spin_unlock_bh(&pch->downl); + if (pch->file.hdrlen > ppp->file.hdrlen) + ppp->file.hdrlen = pch->file.hdrlen; +diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c +index 1744a3e3ae2cf7..6a1c1e1916698c 100644 +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -699,6 +699,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, + po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr) - 2; + po->chan.private = sk; + po->chan.ops = &pppoe_chan_ops; ++ po->chan.direct_xmit = true; + + error = ppp_register_net_channel(dev_net(dev), &po->chan); + if (error) { +diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c +index bf011bbb610589..466dd4575f9983 100644 +--- a/drivers/net/ppp/pptp.c ++++ b/drivers/net/ppp/pptp.c +@@ -469,6 +469,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, + po->chan.mtu -= PPTP_HEADER_OVERHEAD; + + po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header); ++ po->chan.direct_xmit = true; + error = ppp_register_channel(&po->chan); + if (error) { + pr_err("PPTP: failed to register PPP channel (%d)\n", error); +diff --git a/include/linux/ppp_channel.h b/include/linux/ppp_channel.h +index 45e6e427ceb8a0..f73fbea0dbc239 100644 +--- a/include/linux/ppp_channel.h ++++ b/include/linux/ppp_channel.h +@@ -42,8 +42,7 @@ struct ppp_channel { + int hdrlen; /* amount of headroom channel needs */ + void *ppp; /* opaque to channel */ + int speed; /* transfer rate (bytes/second) */ +- /* the following is not used at present */ +- int latency; /* overhead time in milliseconds */ ++ bool direct_xmit; /* no qdisc, xmit directly */ + }; + + #ifdef __KERNEL__ +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index 34d8582c0c072e..2e856a83a7506b 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -810,6 +810,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, + po->chan.private = sk; + po->chan.ops = &pppol2tp_chan_ops; + po->chan.mtu = pppol2tp_tunnel_mtu(tunnel); ++ po->chan.direct_xmit = true; + + error = ppp_register_net_channel(sock_net(sk), &po->chan); + if (error) { +-- +2.53.0 + diff --git a/queue-6.1/rds-drop-incoming-messages-that-cross-network-namesp.patch b/queue-6.1/rds-drop-incoming-messages-that-cross-network-namesp.patch new file mode 100644 index 0000000000..abe0a51339 --- /dev/null +++ b/queue-6.1/rds-drop-incoming-messages-that-cross-network-namesp.patch @@ -0,0 +1,78 @@ +From 60882f9769000c60ff7bee76d2df3c0179ad0e33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 19:43:14 -0700 +Subject: rds: drop incoming messages that cross network namespace boundaries + +From: Aldo Ariel Panzardo + +[ Upstream commit 5521ae71e32a8069ed4ca6e792179dc57bc43ab2 ] + +rds_find_bound() looks up the destination socket using a global +rhashtable keyed solely on (addr, port, scope_id). Network namespaces +are not part of the key, so a sender in netns A can deliver an incoming +message (inc) to a socket that lives in a different netns B. + +When this happens, inc->i_conn points to an rds_connection whose c_net +is netns A, but the receiving rs lives in netns B. Once the child +process that created netns A exits, cleanup_net() calls +rds_loop_exit_net() -> rds_loop_kill_conns() -> rds_conn_destroy(), +freeing that connection. If the survivor socket in netns B still holds +the inc, any subsequent dereference of inc->i_conn is a use-after-free. + +There are two dangerous sites in rds_clear_recv_queue(): + 1. inc->i_conn->c_lcong (offset 88 of freed rds_connection, size 200) + read via rds_recv_rcvbuf_delta() -- confirmed by KASAN. + 2. inc->i_conn->c_trans->inc_free(inc) (function pointer at offset 80) + called via rds_inc_put() when the inc refcount reaches zero -- same + race window, potential call-through-freed-object primitive. + +The bug is reachable from unprivileged user namespaces +(CLONE_NEWUSER + CLONE_NEWNET), available since Linux 3.8. + +Fix this by rejecting the delivery in rds_recv_incoming() when the +socket returned by rds_find_bound() belongs to a different network +namespace than the connection that carried the message. Use the +existing rds_conn_net() / sock_net() helpers and net_eq() for the +comparison. + +Fixes: c809195f5523 ("rds: clean up loopback rds_connections on netns deletion") +Signed-off-by: Aldo Ariel Panzardo +Reviewed-by: Allison Henderson +Tested-by: Allison Henderson +Signed-off-by: Allison Henderson +Link: https://patch.msgid.link/20260708024314.601139-1-achender@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/rds/recv.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/net/rds/recv.c b/net/rds/recv.c +index a316180d3c32ec..7fd77e1b4fe71c 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -365,6 +365,21 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr, + goto out; + } + ++ /* ++ * rds_find_bound() uses a global (netns-agnostic) hash table. ++ * An RDS connection created in netns A can match a socket bound ++ * in the init netns, delivering inc cross-netns with inc->i_conn ++ * pointing into netns A. When cleanup_net() then frees that conn, ++ * any subsequent dereference of inc->i_conn is a use-after-free. ++ * Drop the inc if the receiving socket lives in a different netns. ++ */ ++ if (!net_eq(sock_net(rds_rs_to_sk(rs)), rds_conn_net(conn))) { ++ rds_stats_inc(s_recv_drop_no_sock); ++ rds_sock_put(rs); ++ rs = NULL; ++ goto out; ++ } ++ + /* Process extension headers */ + rds_recv_incoming_exthdrs(inc, rs); + +-- +2.53.0 + diff --git a/queue-6.1/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch b/queue-6.1/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch new file mode 100644 index 0000000000..cd54299558 --- /dev/null +++ b/queue-6.1/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch @@ -0,0 +1,51 @@ +From 46a2acfb6fc2d162f079ee672855e61d712a356b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 09:55:32 +0800 +Subject: sctp: auth: verify auth requirement when auth_chunk is NULL + +From: Qing Luo + +[ Upstream commit 8e04823c120b376ef7dab14b60ebf6823aa16c14 ] + +sctp_auth_chunk_verify() returns true unconditionally when +chunk->auth_chunk is NULL, silently skipping authentication. +This is incorrect when: + +1. skb_clone() failed in the BH receive path, leaving auth_chunk + NULL. In sctp_endpoint_bh_rcv() asoc is NULL for new + connections, so the early sctp_auth_recv_cid() check cannot + catch this. + +2. No AUTH chunk precedes COOKIE-ECHO, so skb_clone() is never + called and auth_chunk remains NULL. + +Fix by checking sctp_auth_recv_cid() when auth_chunk is NULL: +if authentication is required, return false to drop the chunk; +otherwise continue normally. + +Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk") +Signed-off-by: Qing Luo +Acked-by: Xin Long +Link: https://patch.msgid.link/20260721015532.120157-2-l1138897701@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/sm_statefuns.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index d1cbc806fe84cb..86a0cb0a02503c 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -640,7 +640,7 @@ static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, + struct sctp_chunk auth; + + if (!chunk->auth_chunk) +- return true; ++ return !sctp_auth_recv_cid(chunk->chunk_hdr->type, asoc); + + /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo + * is supposed to be authenticated and we have to do delayed +-- +2.53.0 + diff --git a/queue-6.1/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch b/queue-6.1/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch new file mode 100644 index 0000000000..f47c574ecb --- /dev/null +++ b/queue-6.1/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch @@ -0,0 +1,46 @@ +From 75aa42e9cdfbed0a8de5b612d0bc30f1befedcf3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 03:20:21 +0000 +Subject: sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid + +From: HanQuan + +[ Upstream commit ff04b26794a16a8a879eb4fd2c02c2d6b03850e9 ] + +sctp_auth_ep_add_chunkid() uses SCTP_NUM_CHUNK_TYPES (20) as the +capacity limit for ep->auth_chunk_list, allowing it to hold up to +20 chunk entries (param_hdr.length up to 24). However, the copy +destination asoc->c.auth_chunks in struct sctp_cookie is only +SCTP_AUTH_MAX_CHUNKS (16) entries (20 bytes). When more than 16 +chunks are added, sctp_association_init() memcpy overflows the +destination by up to 4 bytes. + +Fix by using SCTP_AUTH_MAX_CHUNKS as the capacity limit, matching +the destination capacity. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Signed-off-by: HanQuan +Acked-by: Xin Long +Link: https://patch.msgid.link/20260713032021.3491702-1-zhoujian.zja@antgroup.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/auth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index 34964145514e6d..a983f96bb0c395 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -766,7 +766,7 @@ int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) + /* Check if we can add this chunk to the array */ + param_len = ntohs(p->param_hdr.length); + nchunks = param_len - sizeof(struct sctp_paramhdr); +- if (nchunks == SCTP_NUM_CHUNK_TYPES) ++ if (nchunks == SCTP_AUTH_MAX_CHUNKS) + return -EINVAL; + + p->chunks[nchunks] = chunk_id; +-- +2.53.0 + diff --git a/queue-6.1/sctp-validate-stream-count-in-sctp_process_strreset_.patch b/queue-6.1/sctp-validate-stream-count-in-sctp_process_strreset_.patch new file mode 100644 index 0000000000..4bcb7db061 --- /dev/null +++ b/queue-6.1/sctp-validate-stream-count-in-sctp_process_strreset_.patch @@ -0,0 +1,80 @@ +From 2886b52e53a61d6d631935973ac1fed03752e5af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 21:07:18 -0400 +Subject: sctp: validate stream count in sctp_process_strreset_inreq() + +From: Cen Zhang (Microsoft) + +[ Upstream commit 18ae07691d43183d270de8be9dc8e027906015d9 ] + +When processing a RESET_IN_REQUEST from a peer, +sctp_process_strreset_inreq() derives the stream count from the +parameter length but does not check whether the resulting +RESET_OUT_REQUEST would exceed SCTP_MAX_CHUNK_LEN. + +The OUT request header (sctp_strreset_outreq, 16 bytes) is 8 bytes +larger than the IN request header (sctp_strreset_inreq, 8 bytes). +Generally, the IP payload is bounded to 65535 bytes, so the stream +list cannot be large enough to trigger the overflow. However, on +interfaces with MTU > 65535 (e.g., loopback with IPv6 jumbograms), a +stream list that fits within the incoming IN parameter can cause a +__u16 overflow in sctp_make_strreset_req() when computing the OUT +request size, leading to an undersized skb allocation and a kernel +BUG: + + net/core/skbuff.c:207 skb_panic + net/core/skbuff.c:2625 skb_put + net/sctp/sm_make_chunk.c:1535 sctp_addto_chunk + net/sctp/sm_make_chunk.c:3695 sctp_make_strreset_req + net/sctp/stream.c:655 sctp_process_strreset_inreq + +The local setsockopt path validates the generated reset request size. +However, for an incoming-only reset, it accounts for the smaller IN +request even though the peer must generate an OUT request with the same +stream list. Such a request cannot be completed successfully by the +peer. + +Reject peer IN requests whose corresponding OUT request would exceed +SCTP_MAX_CHUNK_LEN. Also tighten the local check so it does not send an +IN request that would require an oversized OUT request from the peer. + +Fixes: 7f9d68ac944e ("sctp: implement sender-side procedures for SSN Reset Request Parameter") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/20260707203215.2752-1-blbllhy@gmail.com/ +Suggested-by: Xin Long +Signed-off-by: Cen Zhang (Microsoft) +Acked-by: Xin Long +Link: https://patch.msgid.link/20260710010718.20318-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/stream.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/stream.c b/net/sctp/stream.c +index d38e5431f359dc..34754ba23198ae 100644 +--- a/net/sctp/stream.c ++++ b/net/sctp/stream.c +@@ -308,7 +308,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc, + goto out; + + param_len += str_nums * sizeof(__u16) + +- sizeof(struct sctp_strreset_inreq); ++ (out ? sizeof(struct sctp_strreset_inreq) ++ : sizeof(struct sctp_strreset_outreq)); + } + + if (param_len > SCTP_MAX_CHUNK_LEN - +@@ -639,6 +640,9 @@ struct sctp_chunk *sctp_process_strreset_inreq( + + nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16); + str_p = inreq->list_of_streams; ++ if (nums * sizeof(__u16) + sizeof(struct sctp_strreset_outreq) > ++ SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_reconf_chunk)) ++ goto out; + for (i = 0; i < nums; i++) { + if (ntohs(str_p[i]) >= stream->outcnt) { + result = SCTP_STRRESET_ERR_WRONG_SSN; +-- +2.53.0 + diff --git a/queue-6.1/selftest-af_unix-add-kconfig-file.patch b/queue-6.1/selftest-af_unix-add-kconfig-file.patch new file mode 100644 index 0000000000..0067949ca2 --- /dev/null +++ b/queue-6.1/selftest-af_unix-add-kconfig-file.patch @@ -0,0 +1,49 @@ +From e6a7510d68cd0de7648e0017ce2a03bef4085fd7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Jun 2024 19:10:51 -0700 +Subject: selftest: af_unix: Add Kconfig file. + +From: Kuniyuki Iwashima + +[ Upstream commit 11b006d6896c0471ad29c6f1fb1af606e7ba278f ] + +diag_uid selftest failed on NIPA where the received nlmsg_type is +NLMSG_ERROR [0] because CONFIG_UNIX_DIAG is not set [1] by default +and sock_diag_lock_handler() failed to load the module. + + # # Starting 2 tests from 2 test cases. + # # RUN diag_uid.uid.1 ... + # # diag_uid.c:159:1:Expected nlh->nlmsg_type (2) == SOCK_DIAG_BY_FAMILY (20) + # # 1: Test terminated by assertion + # # FAIL diag_uid.uid.1 + # not ok 1 diag_uid.uid.1 + +Let's add all AF_UNIX Kconfig to the config file under af_unix dir +so that NIPA consumes it. + +Fixes: ac011361bd4f ("af_unix: Add test for sock_diag and UDIAG_SHOW_UID.") +Link: https://netdev-3.bots.linux.dev/vmksft-net/results/644841/104-diag-uid/stdout [0] +Link: https://netdev-3.bots.linux.dev/vmksft-net/results/644841/config [1] +Reported-by: Jakub Kicinski +Closes: https://lore.kernel.org/netdev/20240617073033.0cbb829d@kernel.org/ +Signed-off-by: Kuniyuki Iwashima +Signed-off-by: David S. Miller +Stable-dep-of: f8b1abed7361 ("selftests: af_unix: add USER_NS config") +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/af_unix/config | 3 +++ + 1 file changed, 3 insertions(+) + create mode 100644 tools/testing/selftests/net/af_unix/config + +diff --git a/tools/testing/selftests/net/af_unix/config b/tools/testing/selftests/net/af_unix/config +new file mode 100644 +index 00000000000000..37368567768cc0 +--- /dev/null ++++ b/tools/testing/selftests/net/af_unix/config +@@ -0,0 +1,3 @@ ++CONFIG_UNIX=y ++CONFIG_AF_UNIX_OOB=y ++CONFIG_UNIX_DIAG=m +-- +2.53.0 + diff --git a/queue-6.1/selftests-af_unix-add-user_ns-config.patch b/queue-6.1/selftests-af_unix-add-user_ns-config.patch new file mode 100644 index 0000000000..7207816c42 --- /dev/null +++ b/queue-6.1/selftests-af_unix-add-user_ns-config.patch @@ -0,0 +1,40 @@ +From a226c4358404aacf7c10bed338b43d66374bf8e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:41 +0200 +Subject: selftests: af_unix: add USER_NS config + +From: Matthieu Baerts (NGI0) + +[ Upstream commit f8b1abed736111f914b2c567d9a3db1f71e788e8 ] + +This is required to use unshare(CLONE_NEWUSER). + +This has not been seen on NIPA before, because the 'af_unix' tests are +executed with the 'net' ones, merging their config files. USER_NS is +present in tools/testing/selftests/net/config. + +This issue is visible when only the af_unix config is used on top of the +default one. This is the recommended way to execute selftest targets. + +Fixes: ac011361bd4f ("af_unix: Add test for sock_diag and UDIAG_SHOW_UID.") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-1-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/af_unix/config | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/net/af_unix/config b/tools/testing/selftests/net/af_unix/config +index 37368567768cc0..9c4fb9c31c9506 100644 +--- a/tools/testing/selftests/net/af_unix/config ++++ b/tools/testing/selftests/net/af_unix/config +@@ -1,3 +1,4 @@ + CONFIG_UNIX=y + CONFIG_AF_UNIX_OOB=y + CONFIG_UNIX_DIAG=m ++CONFIG_USER_NS=y +-- +2.53.0 + diff --git a/queue-6.1/selftests-openvswitch-add-config-file.patch b/queue-6.1/selftests-openvswitch-add-config-file.patch new file mode 100644 index 0000000000..1f075dabe6 --- /dev/null +++ b/queue-6.1/selftests-openvswitch-add-config-file.patch @@ -0,0 +1,59 @@ +From bf61173b3eebf56ea0d2518e6983c4ec49b61d9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:42 +0200 +Subject: selftests: openvswitch: add config file + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 441a820ccef9af80a9ac5a4c85b9c396e595967c ] + +The kselftests doc mentions that a config file should be present "if a +test needs specific kernel config options enabled". This selftest +requires some kernel config, but no config file was provided. + +We could say that a sub-target could use the parent's config file, but +the kselftests doc doesn't mention anything about that. Plus the +net/openvswitch target is the only net target without a config file. + +Here is a new config file, which is a trimmed version of the net one, +with hopefully the minimal required kconfig on top of 'make defconfig'. + +The Fixes tag points to the introduction of the net/openvswitch target, +just to help validating this target on stable kernels. + +Fixes: 25f16c873fb1 ("selftests: add openvswitch selftest suite") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Eelco Chaudron +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-2-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/openvswitch/config | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + create mode 100644 tools/testing/selftests/net/openvswitch/config + +diff --git a/tools/testing/selftests/net/openvswitch/config b/tools/testing/selftests/net/openvswitch/config +new file mode 100644 +index 00000000000000..c659749cd086c7 +--- /dev/null ++++ b/tools/testing/selftests/net/openvswitch/config +@@ -0,0 +1,16 @@ ++CONFIG_GENEVE=m ++CONFIG_INET_DIAG=y ++CONFIG_IPV6=y ++CONFIG_NETFILTER=y ++CONFIG_NET_IPGRE=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_OVS=y ++CONFIG_OPENVSWITCH=m ++CONFIG_OPENVSWITCH_GENEVE=m ++CONFIG_OPENVSWITCH_GRE=m ++CONFIG_OPENVSWITCH_VXLAN=m ++CONFIG_PSAMPLE=m ++CONFIG_VETH=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VXLAN=m +-- +2.53.0 + diff --git a/queue-6.1/series b/queue-6.1/series index afd95acb76..362569fac8 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -97,3 +97,73 @@ bpf-prefer-packs-that-won-t-trigger-an-ibpb-flush-on.patch bpf-prefer-dirty-packs-for-ebpf-allocations.patch bpf-fix-ld_-abs-ind-failure-path-analysis-in-subprog.patch usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch +wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch +wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch +hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch +hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch +hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch +watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch +wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch +wifi-ath11k-flush-the-posted-write-after-writing-to-.patch +firewire-net-fix-fragmented-datagram-reassembly.patch +wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch +wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch +wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch +wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch +wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch +btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch +btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch +asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch +wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch +usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch +hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch +hwmon-asus-ec-sensors-fix-ec-read-intervals.patch +hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch +smb-client-validate-dfs-referral-pathconsumed.patch +hwmon-occ-validate-poll-response-sensor-blocks.patch +net-packet-avoid-fanout-hook-re-registration-after-u.patch +bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch +rds-drop-incoming-messages-that-cross-network-namesp.patch +dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch +net-dpaa2-eth-assign-priv-mac-after-dpaa2_mac_connec.patch +dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch +nfp-check-resource-mutex-allocation.patch +wan-wanxl-only-reset-hardware-after-bar-mapping.patch +wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch +iommu-amd-bound-the-early-acpi-hid-map.patch +iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch +wifi-mac80211-recalculate-tim-when-a-station-enters-.patch +amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch +sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch +sctp-validate-stream-count-in-sctp_process_strreset_.patch +selftest-af_unix-add-kconfig-file.patch +selftests-af_unix-add-user_ns-config.patch +selftests-openvswitch-add-config-file.patch +gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch +nexthop-initialize-extack-in-nh_res_bucket_migrate.patch +tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch +wifi-mt76-mt7915-guard-he-capability-lookups.patch +wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch +wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch +amt-re-read-skb-header-pointers-after-every-pull.patch +amt-make-the-head-writable-before-rewriting-the-l2-h.patch +net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch +net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch +sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch +vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch +tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch +net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch +net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch +octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch +ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch +ppp-use-iff_no_queue-in-virtual-interfaces.patch +ppp-convert-to-percpu-netstats.patch +ppp-enable-tx-scatter-gather.patch +ppp-annotate-data-races-in-ppp_generic.patch +hinic-remove-unused-ethtool-rss-user-configuration-b.patch +net-qrtr-restrict-socket-creation-to-the-initial-net.patch +net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch +net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch +net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch +net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch +bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch diff --git a/queue-6.1/smb-client-validate-dfs-referral-pathconsumed.patch b/queue-6.1/smb-client-validate-dfs-referral-pathconsumed.patch new file mode 100644 index 0000000000..1e7a36ee39 --- /dev/null +++ b/queue-6.1/smb-client-validate-dfs-referral-pathconsumed.patch @@ -0,0 +1,97 @@ +From f85c8be09361448fb597fbfa5de8b66e1638e35c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 13:25:23 +0800 +Subject: smb: client: validate DFS referral PathConsumed + +From: Yichong Chen + +[ Upstream commit f6f5ee2aa33b350c671721b965251c42cebb962e ] + +parse_dfs_referrals() validates that the response contains the fixed +referral entry array and, on for-next, the per-referral string offsets. +However, the response also contains a PathConsumed value that is later +used for DFS path parsing. + +If a malformed response provides a PathConsumed value larger than the +search name, later DFS parsing can advance beyond the end of the path. + +Validate PathConsumed against the search name length before storing it in +the parsed referral. + +Fixes: 4ecce920e13a ("CIFS: move DFS response parsing out of SMB1 code") +Reviewed-by: Paulo Alcantara (Red Hat) +Signed-off-by: Yichong Chen +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/misc.c | 34 +++++++++++++++++++++++++--------- + 1 file changed, 25 insertions(+), 9 deletions(-) + +diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c +index 85e615ed7ca915..ddf105336f6607 100644 +--- a/fs/smb/client/misc.c ++++ b/fs/smb/client/misc.c +@@ -913,6 +913,8 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + int i, rc = 0; + char *data_end; + struct dfs_referral_level_3 *ref; ++ unsigned int path_consumed; ++ size_t search_name_len; + + if (rsp_size < sizeof(*rsp)) { + cifs_dbg(VFS | ONCE, +@@ -960,6 +962,7 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + rc = -ENOMEM; + goto parse_DFS_referrals_exit; + } ++ search_name_len = strlen(searchName); + + /* collect necessary data from referrals */ + for (i = 0; i < *num_of_nodes; i++) { +@@ -968,21 +971,34 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + struct dfs_info3_param *node = (*target_nodes)+i; + + node->flags = le32_to_cpu(rsp->DFSFlags); ++ path_consumed = le16_to_cpu(rsp->PathConsumed); + if (is_unicode) { +- __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, +- GFP_KERNEL); +- if (tmp == NULL) { ++ size_t search_name_utf16_len = search_name_len * 2 + 2; ++ __le16 *tmp; ++ ++ if (path_consumed > search_name_utf16_len) { ++ rc = -EINVAL; ++ goto parse_DFS_referrals_exit; ++ } ++ ++ tmp = kmalloc(search_name_utf16_len, GFP_KERNEL); ++ if (!tmp) { + rc = -ENOMEM; + goto parse_DFS_referrals_exit; + } +- cifsConvertToUTF16((__le16 *) tmp, searchName, ++ cifsConvertToUTF16((__le16 *)tmp, searchName, + PATH_MAX, nls_codepage, remap); +- node->path_consumed = cifs_utf16_bytes(tmp, +- le16_to_cpu(rsp->PathConsumed), +- nls_codepage); ++ node->path_consumed = cifs_utf16_bytes(tmp, path_consumed, ++ nls_codepage); + kfree(tmp); +- } else +- node->path_consumed = le16_to_cpu(rsp->PathConsumed); ++ } else { ++ if (path_consumed > search_name_len) { ++ rc = -EINVAL; ++ goto parse_DFS_referrals_exit; ++ } ++ ++ node->path_consumed = path_consumed; ++ } + + node->server_type = le16_to_cpu(ref->ServerType); + node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); +-- +2.53.0 + diff --git a/queue-6.1/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch b/queue-6.1/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch new file mode 100644 index 0000000000..e9e4e80662 --- /dev/null +++ b/queue-6.1/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch @@ -0,0 +1,47 @@ +From 01375e0a130bbc46839c78783c1e40dc17bf0117 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:49:35 -0300 +Subject: tipc: fix infinite loop in __tipc_nl_compat_dumpit + +From: Helen Koike + +[ Upstream commit 22f8aa35964e8f2ab026578f45befc9605fd1b28 ] + +cmd->dumpit callback can return a negative errno, causing an infinite +loop due to the while(len) condition. As the loop never terminates, +genl_mutex is never released, and other tasks waiting on it starve in D +state. + +Check dumpit's return value, propagate it and jump to err_out on error. + +Reported-by: syzbot+85d0bec020d805014a3a@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=85d0bec020d805014a3a +Fixes: d0796d1ef63d ("tipc: convert legacy nl bearer dump to nl compat") +Signed-off-by: Helen Koike +Reviewed-by: Tung Nguyen +Link: https://patch.msgid.link/20260713204940.647668-1-koike@igalia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/netlink_compat.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c +index 9eb7cab6b2f60f..5a722a8fa36d1b 100644 +--- a/net/tipc/netlink_compat.c ++++ b/net/tipc/netlink_compat.c +@@ -226,6 +226,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, + int rem; + + len = (*cmd->dumpit)(buf, &cb); ++ if (len < 0) { ++ err = len; ++ goto err_out; ++ } + + nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) { + err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN, +-- +2.53.0 + diff --git a/queue-6.1/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch b/queue-6.1/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch new file mode 100644 index 0000000000..67fa079fc3 --- /dev/null +++ b/queue-6.1/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch @@ -0,0 +1,72 @@ +From 2e656ce7d2bd4a90d65e75ab3af8c844e5bc1b0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 00:15:41 -0400 +Subject: tipc: fix u16 MTU truncation in media and bearer MTU validation + +From: Cen Zhang (Microsoft) + +[ Upstream commit 9f29cd8a8e7901a2617c8064ce9f50fc67b97cb8 ] + +Both TIPC_NL_MEDIA_SET and TIPC_NL_BEARER_SET accept user-supplied +MTU values but only enforce a minimum bound, not a maximum. When a user +sets the MTU to a value exceeding U16_MAX (65535), it passes validation +but is silently truncated when assigned to u16 fields l->mtu and +l->advertised_mtu in tipc_link_create(). Values like 65536 (0x10000) +truncate to 0, causing a division by zero in tipc_link_set_queue_limits() +which computes TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE). Other overflowing +values (e.g. 65537-131071) produce small incorrect MTU values, resulting +in link malfunction behaviors. + +Crash stack (triggered as unprivileged user via user namespace): + + tipc_link_set_queue_limits net/tipc/link.c:2531 + tipc_link_create net/tipc/link.c:520 + tipc_node_check_dest net/tipc/node.c:1279 + tipc_disc_rcv net/tipc/discover.c:252 + tipc_rcv net/tipc/node.c:2129 + tipc_udp_recv net/tipc/udp_media.c:392 + +Two independent paths lack the upper bound check: +1. tipc_udp_mtu_bad() -- called from __tipc_nl_media_set() (MEDIA_SET) +2. inline check in __tipc_nl_bearer_set() at bearer.c:1160 (BEARER_SET) + +Fix both by rejecting MTU values above U16_MAX. + +Fixes: 901271e0403a ("tipc: implement configuration of UDP media MTU") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/CAB8m9WgETt0AjmFwE=F-CKjGXsK6_WDv0=kbYRcC8-noo+amnA@mail.gmail.com +Reviewed-by: Vadim Fedorenko +Signed-off-by: Cen Zhang (Microsoft) +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260714041541.307702-1-blbllhy@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tipc/netlink.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c +index 8336a9664703fe..1307dd1a961341 100644 +--- a/net/tipc/netlink.c ++++ b/net/tipc/netlink.c +@@ -113,12 +113,16 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { + }; + + /* Properties valid for media, bearer and link */ ++static const struct netlink_range_validation tipc_nl_mtu_range = { ++ .max = U16_MAX, ++}; ++ + const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { + [TIPC_NLA_PROP_UNSPEC] = { .type = NLA_UNSPEC }, + [TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 }, +- [TIPC_NLA_PROP_MTU] = { .type = NLA_U32 }, ++ [TIPC_NLA_PROP_MTU] = NLA_POLICY_FULL_RANGE(NLA_U32, &tipc_nl_mtu_range), + [TIPC_NLA_PROP_BROADCAST] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_BROADCAST_RATIO] = { .type = NLA_U32 } + }; +-- +2.53.0 + diff --git a/queue-6.1/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch b/queue-6.1/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch new file mode 100644 index 0000000000..963210e234 --- /dev/null +++ b/queue-6.1/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch @@ -0,0 +1,93 @@ +From 5a798866e1e2249b0d8405d2ad1afbf8be0b06a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 02:07:04 -0600 +Subject: usb: atm: ueagle-atm: reject descriptors that confuse probe and + disconnect + +From: Diego Fernando Mancera Gomez + +[ Upstream commit 71132cedd1ecbc4032d76e9928c18a10f7e39b80 ] + +uea_probe() distinguishes a pre-firmware device from a post-firmware one +using the USB id (UEA_IS_PREFIRM()), and stores a different object as the +interface data in each case: a 'struct completion' for a pre-firmware +device (to be waited on in .disconnect()), or a 'struct usbatm_data' for a +post-firmware one. + +uea_disconnect() instead tells the two apart by the number of interfaces +of the active configuration (a pre-firmware device exposes a single +interface, ADI930 has 2 and eagle has 3), and casts the interface data +accordingly. + +Because the two handlers use different criteria, a crafted device that +advertises a pre-firmware id together with a multi-interface descriptor +(or a post-firmware id with a single interface) makes them disagree: the +small 'struct completion' stored by uea_probe() is then passed to +usbatm_usb_disconnect(), which casts it to 'struct usbatm_data' and takes +instance->serialize, reading past the end of the allocation: + + BUG: KASAN: slab-out-of-bounds in __mutex_lock+0x152a/0x1b80 + Read of size 8 at addr ffff8880470e2c60 by task kworker/1:2/982 + ... + __mutex_lock+0x152a/0x1b80 + usbatm_usb_disconnect+0x70/0x820 + uea_disconnect+0x133/0x2c0 + usb_unbind_interface+0x1dd/0x9e0 + ... + which belongs to the cache kmalloc-96 of size 96 + The buggy address is located 0 bytes to the right of + allocated 96-byte region [ffff8880470e2c00, ffff8880470e2c60) + +Reject such inconsistent descriptors in uea_probe() so that both handlers +always make the same pre/post-firmware decision. + +Reported-by: syzbot+e62a973f8322b3bbe3ac@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e62a973f8322b3bbe3ac +Fixes: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()") +Signed-off-by: Diego Fernando Mancera Gomez +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260717080704.1264-1-diegomancera.dev@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/atm/ueagle-atm.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c +index b41f352769f072..5dfe82a4c130da 100644 +--- a/drivers/usb/atm/ueagle-atm.c ++++ b/drivers/usb/atm/ueagle-atm.c +@@ -2591,6 +2591,7 @@ static struct usbatm_driver uea_usbatm_driver = { + static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + { + struct usb_device *usb = interface_to_usbdev(intf); ++ bool single_iface = usb->config->desc.bNumInterfaces == 1; + int ret; + + uea_enters(usb); +@@ -2600,6 +2601,22 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + le16_to_cpu(usb->descriptor.bcdDevice), + chip_name[UEA_CHIP_VERSION(id)]); + ++ /* ++ * uea_probe() decides between the pre-firmware and post-firmware case ++ * from the USB id and stores a different object as interface data in ++ * each case: a struct completion for a pre-firmware device, a struct ++ * usbatm_data for a post-firmware one. uea_disconnect() instead tells ++ * the two apart by the number of interfaces (a pre-firmware device ++ * exposes a single interface, ADI930 has 2 and eagle has 3). A crafted ++ * device advertising a pre-firmware id together with a multi-interface ++ * descriptor (or the other way around) makes the two disagree, so that ++ * usbatm_usb_disconnect() treats the small completion object as a ++ * struct usbatm_data and reads out of bounds. Reject such inconsistent ++ * descriptors so both paths make the same decision. ++ */ ++ if (UEA_IS_PREFIRM(id) != single_iface) ++ return -ENODEV; ++ + usb_reset_device(usb); + + if (UEA_IS_PREFIRM(id)) { +-- +2.53.0 + diff --git a/queue-6.1/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch b/queue-6.1/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch new file mode 100644 index 0000000000..92aea7975f --- /dev/null +++ b/queue-6.1/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch @@ -0,0 +1,84 @@ +From c5824649231308fe091edc50b7b4f2c1b7c9be6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 07:09:15 -0700 +Subject: vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets + +From: Harshaka Narayana + +[ Upstream commit 34a71f5361fc3adb5b7138da78750b0d535a8252 ] + +vmxnet3_get_hdr_len() assumes gdesc->rcd.v4/v6/tcp always describe the +outer header, but for a Geneve-encapsulated packet the device can set +them based on the inner header instead, signalled by the +VMXNET3_RCD_HDR_INNER_SHIFT bit in the completion descriptor. Since the +function never skips the outer encapsulation, this mismatch triggers: + +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP), because the outer + protocol is UDP (Geneve), not TCP. +- BUG_ON(hdr.eth->h_proto != ...), when the tunnel's outer and inner + IP versions differ (e.g. outer IPv6/inner IPv4 or vice versa). + +Check VMXNET3_RCD_HDR_INNER_SHIFT up front and bail out, since the +function cannot locate the inner header it would need to parse. Also +convert the remaining BUG_ON()s in this function to return 0 +defensively. + +Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)") +Signed-off-by: Harshaka Narayana +Reviewed-by: Ronak Doshi +Reviewed-by: Sankararaman Jayaraman +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260713140915.3381715-1-harshaka.narayana@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c +index 86b913d5ac5b7c..e6fb6c0ce27f5a 100644 +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -1365,7 +1365,11 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + struct ipv6hdr *ipv6; + struct tcphdr *tcp; + } hdr; +- BUG_ON(gdesc->rcd.tcp == 0); ++ ++ /* v4/v6/tcp then describe the inner header, which we can't locate. */ ++ if ((le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT)) || ++ gdesc->rcd.tcp == 0) ++ return 0; + + maplen = skb_headlen(skb); + if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen)) +@@ -1379,15 +1383,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + + hdr.eth = eth_hdr(skb); + if (gdesc->rcd.v4) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)); ++ if (hdr.eth->h_proto != htons(ETH_P_IP) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)) ++ return 0; ++ + hdr.ptr += hlen; +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP); ++ if (hdr.ipv4->protocol != IPPROTO_TCP) ++ return 0; ++ + hlen = hdr.ipv4->ihl << 2; + hdr.ptr += hdr.ipv4->ihl << 2; + } else if (gdesc->rcd.v6) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)); ++ if (hdr.eth->h_proto != htons(ETH_P_IPV6) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)) ++ return 0; ++ + hdr.ptr += hlen; + /* Use an estimated value, since we also need to handle + * TSO case. +-- +2.53.0 + diff --git a/queue-6.1/wan-wanxl-only-reset-hardware-after-bar-mapping.patch b/queue-6.1/wan-wanxl-only-reset-hardware-after-bar-mapping.patch new file mode 100644 index 0000000000..270d82e748 --- /dev/null +++ b/queue-6.1/wan-wanxl-only-reset-hardware-after-bar-mapping.patch @@ -0,0 +1,51 @@ +From c9d9512fd7fe54d7aaa5d4e8ca731574c0c908ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:15 +0800 +Subject: wan: wanxl: Only reset hardware after BAR mapping + +From: Ruoyu Wang + +[ Upstream commit 91957b89da995607cb654b1f9a3c126ddbaee10f ] + +wanxl_pci_init_one() stores the freshly allocated card in driver data +before the PLX BAR is mapped. Several early probe failures then unwind +through wanxl_pci_remove_one(), including failure to allocate the coherent +status area or to restore the DMA mask. + +wanxl_pci_remove_one() unconditionally calls wanxl_reset(), and +wanxl_reset() dereferences card->plx. On those early failures card->plx +is still NULL, so the error path can dereference a NULL MMIO pointer. + +Only issue the hardware reset once the BAR mapping exists. The remaining +cleanup in wanxl_pci_remove_one() already checks whether later resources +were allocated. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ruoyu Wang +Link: https://patch.msgid.link/20260708143415.3169358-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/wan/wanxl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c +index 5a9e262188efe1..c38dd741401e13 100644 +--- a/drivers/net/wan/wanxl.c ++++ b/drivers/net/wan/wanxl.c +@@ -514,7 +514,8 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) + if (card->irq) + free_irq(card->irq, card); + +- wanxl_reset(card); ++ if (card->plx) ++ wanxl_reset(card); + + for (i = 0; i < RX_QUEUE_LENGTH; i++) + if (card->rx_skbs[i]) { +-- +2.53.0 + diff --git a/queue-6.1/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch b/queue-6.1/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch new file mode 100644 index 0000000000..a1e0d67e5b --- /dev/null +++ b/queue-6.1/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch @@ -0,0 +1,48 @@ +From c178caafad713541182d2cfb2a1ea09db9bb6587 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:18:03 +0000 +Subject: watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() + +From: Tzung-Bi Shih + +[ Upstream commit 7362ba0f9c96ac3ad6a2ca3995bd9fc9a28a8661 ] + +When a watchdog governor is unregistered, it updates existing watchdog +devices that were using this governor by falling back to `default_gov`. + +If the governor being unregistered is currently set as `default_gov`, +the `default_gov` is never cleared. This leads to 2 use-after-free +issues: +1. New watchdog devices registered after this point will inherit the + dangling `default_gov`. +2. Existing watchdog devices using the unregistered governor will have + their `wdd->gov` reassigned to the dangling `default_gov`. + +Fix the UAF by clearing `default_gov` if it matches the governor being +unregistered. + +Fixes: da0d12ff2b82 ("watchdog: pretimeout: add panic pretimeout governor") +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20260707101803.3598173-1-tzungbi@kernel.org +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/watchdog_pretimeout.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c +index 376a495ab80c49..3c109f1db8f0e5 100644 +--- a/drivers/watchdog/watchdog_pretimeout.c ++++ b/drivers/watchdog/watchdog_pretimeout.c +@@ -165,6 +165,8 @@ void watchdog_unregister_governor(struct watchdog_governor *gov) + } + + spin_lock_irq(&pretimeout_lock); ++ if (default_gov == gov) ++ default_gov = NULL; + list_for_each_entry(p, &pretimeout_list, entry) + if (p->wdd->gov == gov) + p->wdd->gov = default_gov; +-- +2.53.0 + diff --git a/queue-6.1/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch b/queue-6.1/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch new file mode 100644 index 0000000000..f7d36d3923 --- /dev/null +++ b/queue-6.1/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch @@ -0,0 +1,68 @@ +From 257ea1cedfaf587a28867f29f9bfd41868a93f03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jun 2026 17:06:09 +0800 +Subject: wifi: ath11k: fix NULL pointer dereference in + ath11k_hal_srng_access_begin + +From: Gaole Zhang + +[ Upstream commit e8d85672dd7e2523f774caafba8f858384e18df7 ] + +In ATH11K_QMI_EVENT_FW_READY, ATH11K_FLAG_REGISTERED is set +unconditionally even when ath11k_core_qmi_firmware_ready() fails. +This leaves the driver in an inconsistent state where +initialization is considered complete although the firmware ready +handling did not finish successfully. During the subsequent SSR, +the driver enters the restart path based on this incorrect state +and dereferences uninitialized srng members, resulting in a NULL +pointer dereference. + +Call trace: + ath11k_hal_srng_access_begin+0xc/0x60 [ath11k] (P) + ath11k_ce_cleanup_pipes+0x17c/0x180 [ath11k] + ath11k_core_restart+0x40/0x168 [ath11k] + +Fix this by: +- skipping firmware_ready if ATH11K_FLAG_REGISTERED is already set +- setting ATH11K_FLAG_REGISTERED only when firmware_ready succeeds +- setting ATH11K_FLAG_QMI_FAIL and aborting the FW_READY handling +on error + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.2.0.c2-00204-QCAMSLSWPLZ-1 + +Fixes: 6fe62a8cec51c ("wifi: ath11k: Add cold boot calibration support on WCN6750") +Signed-off-by: Gaole Zhang +Reviewed-by: Baochen Qiang +Reviewed-by: Rameshkumar Sundaram +Link: https://patch.msgid.link/20260609090609.4041009-1-gaole.zhang@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/qmi.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index f790759c86115a..396f87a77dfcdb 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -3235,9 +3235,14 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) + clear_bit(ATH11K_FLAG_CRASH_FLUSH, + &ab->dev_flags); + clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); +- ath11k_core_qmi_firmware_ready(ab); +- set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); +- ++ if (!test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { ++ ret = ath11k_core_qmi_firmware_ready(ab); ++ if (ret) { ++ set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); ++ break; ++ } ++ set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); ++ } + break; + case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE: + break; +-- +2.53.0 + diff --git a/queue-6.1/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch b/queue-6.1/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch new file mode 100644 index 0000000000..e84a22ccf7 --- /dev/null +++ b/queue-6.1/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch @@ -0,0 +1,48 @@ +From 86b220080b91bdcef8d9bffef1862a47e1274e64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 May 2026 11:42:52 +0000 +Subject: wifi: ath11k: fix potential buffer underflow in + ath11k_hal_rx_msdu_list_get() + +From: Dmitry Morgun + +[ Upstream commit 7f11e70629650ff6ea140984e5ce188b775b2683 ] + +When the first entry in msdu_details has a zero buffer address, +the code accesses msdu_details[i - 1] with i == 0, causing a +buffer underflow. + +Fix similarly to ath12k_wifi7_hal_rx_msdu_list_get() by adding +a separate check for i == 0 before the main condition to prevent +the out-of-bounds access. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Dmitry Morgun +Reviewed-by: Rameshkumar Sundaram +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20260530114252.42615-1-d.morgun@ispras.ru +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 397ce654bb3fd5..ac9796e8cd595c 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -4549,6 +4549,9 @@ static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar, + msdu_details = &msdu_link->msdu_link[0]; + + for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) { ++ if (!i && FIELD_GET(BUFFER_ADDR_INFO0_ADDR, ++ msdu_details[i].buf_addr_info.info0) == 0) ++ break; + if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR, + msdu_details[i].buf_addr_info.info0) == 0) { + msdu_desc_info = &msdu_details[i - 1].rx_msdu_info; +-- +2.53.0 + diff --git a/queue-6.1/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch b/queue-6.1/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch new file mode 100644 index 0000000000..d928be15e4 --- /dev/null +++ b/queue-6.1/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch @@ -0,0 +1,60 @@ +From 7ff9b3369e27fb3c51794ba6a52237270e8eea5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 16:16:48 +0200 +Subject: wifi: ath11k: Flush the posted write after writing to + PCIE_SOC_GLOBAL_RESET + +From: Manivannan Sadhasivam + +[ Upstream commit 0fe8010fc5b147607fc19ba010ba469afc95f35f ] + +ath11k_pci_soc_global_reset() tries to reset the device by writing to the +PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure +that the write gets flushed to the device before the delay. + +This may lead to the delay on the host to be insufficient, if the posted +write doesn't reach the device before the delay. + +So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and +before the delay. + +Compile tested only. + +Fixes: f3c603d412b3 ("ath11k: reset MHI during power down and power up") +Reported-by: Alex Williamson +Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Reviewed-by: Raj Kumar Bhagat +Link: https://patch.msgid.link/20260623141649.41087-1-manivannan.sadhasivam@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c +index a8431ce1ab9acb..9f00245f73cd7b 100644 +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -180,6 +180,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) + val |= PCIE_SOC_GLOBAL_RESET_V; + + ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); + + /* TODO: exact time to sleep is uncertain */ + delay = 10; +@@ -189,6 +191,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) + val &= ~PCIE_SOC_GLOBAL_RESET_V; + + ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); + + mdelay(delay); + +-- +2.53.0 + diff --git a/queue-6.1/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch b/queue-6.1/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch new file mode 100644 index 0000000000..87678a3883 --- /dev/null +++ b/queue-6.1/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch @@ -0,0 +1,49 @@ +From 217f93b96bdb194661d52e2d3ebbfa2575d6728d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:50:08 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware IE lengths in connect event + +From: Tristan Madani + +[ Upstream commit 6b47b29730de3232b919d8362749f6814c5f2a33 ] + +The firmware-controlled beacon_ie_len, assoc_req_len, and assoc_resp_len +fields in ath6kl_wmi_connect_event_rx() are not validated against the +buffer length. Their sum (up to 765) can exceed the actual WMI event +data, causing out-of-bounds reads during IE parsing and state corruption +of wmi->is_wmm_enabled. + +Add a check that the total IE length fits within the buffer. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20260421135009.348084-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index a572952dd4b903..447896b871c3e2 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -874,6 +874,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, + + ev = (struct wmi_connect_event *) datap; + ++ if (len < sizeof(*ev) + ev->beacon_ie_len + ++ ev->assoc_req_len + ev->assoc_resp_len) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, ++ "connect event: IE lengths %u+%u+%u exceed buffer %d\n", ++ ev->beacon_ie_len, ev->assoc_req_len, ++ ev->assoc_resp_len, len); ++ return -EINVAL; ++ } + if (vif->nw_type == AP_NETWORK) { + /* AP mode start/STA connected event */ + struct net_device *dev = vif->ndev; +-- +2.53.0 + diff --git a/queue-6.1/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch b/queue-6.1/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch new file mode 100644 index 0000000000..6c573dfc09 --- /dev/null +++ b/queue-6.1/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch @@ -0,0 +1,53 @@ +From 6b24e6a1e7234e1ce7bc161ed106b924c62c2eb6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jun 2026 23:29:07 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware num_msg in TX complete + handler + +From: Tristan Madani + +[ Upstream commit 3a21c89215cc18f1a97c5e5bfd1da6d4f3d44495 ] + +The firmware-controlled num_msg field (u8, 0-255) drives the loop in +ath6kl_wmi_tx_complete_event_rx() without validation against the buffer +length. This allows out-of-bounds reads of up to 1020 bytes past the +WMI event buffer when the firmware sends an inflated num_msg. + +Add a check that the buffer is large enough to hold the fixed struct +and the num_msg variable-length entries. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Link: https://patch.msgid.link/20260625232907.3620746-1-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index 3787b9fb007559..a572952dd4b903 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -484,6 +484,18 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) + + evt = (struct wmi_tx_complete_event *) datap; + ++ if (len < sizeof(*evt)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d\n", ++ len); ++ return -EINVAL; ++ } ++ ++ if (len < sizeof(*evt) + evt->num_msg * sizeof(struct tx_complete_msg_v1)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d for %u msgs\n", ++ len, evt->num_msg); ++ return -EINVAL; ++ } ++ + ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", + evt->num_msg, evt->msg_len, evt->msg_type); + +-- +2.53.0 + diff --git a/queue-6.1/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch b/queue-6.1/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch new file mode 100644 index 0000000000..327cd60730 --- /dev/null +++ b/queue-6.1/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch @@ -0,0 +1,90 @@ +From 55d5827eeef50c54de2137e47b9f27b2fb0673b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 08:32:10 -0700 +Subject: wifi: ath9k: hif_usb: don't dereference hif_dev after re-arming + firmware request +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Cheng Yongkang + +[ Upstream commit dad9f96945d77ecd4708f730c06ef54dcd8cc057 ] + +ath9k_hif_request_firmware() re-arms an asynchronous firmware load via +request_firmware_nowait(), passing hif_dev as the completion context, and +then still dereferences hif_dev: + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", + hif_dev->fw_name); + +The re-armed callback ath9k_hif_usb_firmware_cb() runs on the "events" +workqueue and, when the firmware is missing, walks the retry chain into +ath9k_hif_usb_firmware_fail() -> complete_all(&hif_dev->fw_done). That +releases the wait_for_completion(&hif_dev->fw_done) in a concurrent +ath9k_hif_usb_disconnect(), which then kfree()s hif_dev. The trailing +dev_info() in the frame that re-armed the request can therefore read freed +memory (hif_dev->udev, the first field of struct hif_device_usb): + + BUG: KASAN: slab-use-after-free in ath9k_hif_request_firmware + Read of size 8 ... by task kworker/... + ath9k_hif_request_firmware + ath9k_hif_usb_firmware_cb drivers/net/wireless/ath/ath9k/hif_usb.c:1247 + request_firmware_work_func + Allocated by ...: + ath9k_hif_usb_probe drivers/net/wireless/ath/ath9k/hif_usb.c + Freed by ...: + ath9k_hif_usb_disconnect -> kfree drivers/net/wireless/ath/ath9k/hif_usb.c + +The fw_done barrier only makes disconnect wait for the firmware chain to +*terminate*; it does not protect the outer ath9k_hif_request_firmware() +frame that re-armed the request and keeps touching hif_dev afterwards. + +Drop the post-request dev_info(): it is the only use of hif_dev after the +async request is armed, and it is purely informational (the dev_err() on the +failure path runs only when request_firmware_nowait() did not arm a callback, +so hif_dev is still alive there). + +This was first reported by syzbot as a single, non-reproduced crash that was +later auto-obsoleted, and was independently rediscovered by the reFuzz fuzzer, +which produced a C reproducer (USB-gadget connect/disconnect of an ath9k_htc +device whose firmware download fails). The vulnerable code is unchanged and +still present in v7.1-rc6, where the slab-use-after-free reproduces under KASAN +once the (sub-microsecond) race window is widened. + +Fixes: e904cf6fe230 ("ath9k_htc: introduce support for different fw versions") +Reported-by: syzbot+50122cbc2874b1eb25b0@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=50122cbc2874b1eb25b0 +Signed-off-by: Cheng Yongkang +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260605153210.20471-1-1020691186@qq.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index 6c73c0c0b82a99..7650f14dca8dad 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -1227,15 +1227,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, + ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, + &hif_dev->udev->dev, GFP_KERNEL, + hif_dev, ath9k_hif_usb_firmware_cb); +- if (ret) { ++ if (ret) + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Async request for firmware %s failed\n", + hif_dev->fw_name); +- return ret; +- } +- +- dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", +- hif_dev->fw_name); + + return ret; + } +-- +2.53.0 + diff --git a/queue-6.1/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch b/queue-6.1/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch new file mode 100644 index 0000000000..22190efac9 --- /dev/null +++ b/queue-6.1/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch @@ -0,0 +1,69 @@ +From d2b1b6e680032b6858158ca02d72750233781ba7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 May 2026 16:38:59 +0800 +Subject: wifi: brcmfmac: fix 802.1X-SHA256 call trace warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Shelley Yang + +[ Upstream commit 7cb34f6c4fe8a68af621d870abe63bfca2275dd6 ] + +Based on wpa_auth as 1x_256 mode, need to set up +"use_fwsup" with BRCMF_PROFILE_FWSUP_1X. +Or it will happen trace warning when call brcmf_cfg80211_set_pmk(). + +[ 4481.831101] ------------[ cut here ]------------ +[ 4481.831102] WARNING: CPU: 1 PID: 2997 at +drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:7242 brcmf_cfg80211_set_pmk+0x77/0xd0 [brcmfmac] +[...] +[ 4481.831202] Call Trace: +[ 4481.831204]   +[ 4481.831205]  nl80211_set_pmk+0x183/0x250 [cfg80211] +[ 4481.831233]  genl_family_rcv_msg_doit+0xea/0x150 +[ 4481.831237]  genl_rcv_msg+0x104/0x240 +[ 4481.831239]  ? cfg80211_probe_status+0x2c0/0x2c0 [cfg80211] +[ 4481.831257]  ? genl_family_rcv_msg_doit+0x150/0x150 +[ 4481.831259]  netlink_rcv_skb+0x4e/0x100 +[ 4481.831261]  genl_rcv+0x24/0x40 +[ 4481.831262]  netlink_unicast+0x236/0x380 +[ 4481.831264]  netlink_sendmsg+0x250/0x4b0 +[ 4481.831266]  sock_sendmsg+0x5c/0x70 +[ 4481.831269]  ____sys_sendmsg+0x236/0x2b0 +[ 4481.831271]  ? copy_msghdr_from_user+0x6d/0xa0 +[ 4481.831272]  ___sys_sendmsg+0x86/0xd0 +[ 4481.831274]  ? avc_has_perm+0x8c/0x1a0 +[ 4481.831276]  ? preempt_count_add+0x6a/0xa0 +[ 4481.831279]  ? sock_has_perm+0x82/0xa0 +[ 4481.831280]  __sys_sendmsg+0x57/0xa0 +[ 4481.831282]  do_syscall_64+0x38/0x90 +[ 4481.831284]  entry_SYSCALL_64_after_hwframe+0x63/0xcd +[ 4481.831286] RIP: 0033:0x7fd270d369b4 + +Fixes: 2526ff21aa77 ("brcmfmac: support 4-way handshake offloading for 802.1X") +Signed-off-by: Shelley Yang +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260525083859.581246-1-shelley.yang@infineon.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 6e7de5dce49eb7..66c139bf49283a 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -1791,7 +1791,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) + sme->crypto.akm_suites[0]); + return -EINVAL; + } +- } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { ++ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_1X_SHA256)) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + val = WPA2_AUTH_UNSPECIFIED; +-- +2.53.0 + diff --git a/queue-6.1/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch b/queue-6.1/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch new file mode 100644 index 0000000000..c6377b2352 --- /dev/null +++ b/queue-6.1/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch @@ -0,0 +1,48 @@ +From 3991c7f9028b14e537e0ac9b1894d64cd0e6d793 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:26 +0000 +Subject: wifi: carl9170: bound memcpy length in cmd callback to prevent OOB + read + +From: Tristan Madani + +[ Upstream commit 4cde55b2feff9504d1f993ab80e84e7ccb62791c ] + +When the firmware sends a command response with a length mismatch, +carl9170_cmd_callback() logs the mismatch and calls carl9170_restart() +but then falls through to memcpy(ar->readbuf, buffer + 4, len - 4). +Since len comes from the firmware and can exceed ar->readlen, this +copies more data than the readbuf was allocated for. + +Bound the memcpy to min(len - 4, ar->readlen) so that the response +is still completed -- avoiding repeated restarts from queued garbage -- +while preventing an overread past the response buffer. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-2-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 908c4c8b7f8256..9a25c2a540b95f 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -150,7 +150,8 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) + spin_lock(&ar->cmd_lock); + if (ar->readbuf) { + if (len >= 4) +- memcpy(ar->readbuf, buffer + 4, len - 4); ++ memcpy(ar->readbuf, buffer + 4, ++ min_t(u32, len - 4, ar->readlen)); + + ar->readbuf = NULL; + } +-- +2.53.0 + diff --git a/queue-6.1/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch b/queue-6.1/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch new file mode 100644 index 0000000000..34e7990a76 --- /dev/null +++ b/queue-6.1/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch @@ -0,0 +1,46 @@ +From 801b9d60cbcd9265248bb7a10ffaf68f2ee1084e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:28 +0000 +Subject: wifi: carl9170: fix buffer overflow in rx_stream failover path + +From: Tristan Madani + +[ Upstream commit a1a21995c2e1cc2ca6b2226cfe4f5f018370182a ] + +The failover continuation in carl9170_rx_stream() copies the full tlen +from the second USB transfer instead of capping at rx_failover_missing +bytes. When both transfers are near maximum size, the total exceeds the +65535-byte failover SKB, triggering skb_over_panic. + +Limit the copy size to the missing byte count. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-4-tristmd@gmail.com +[Fix checkpatch CHECK:PARENTHESIS_ALIGNMENT] +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 9a25c2a540b95f..bda30b1f940459 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -918,7 +918,9 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) + } + } + +- skb_put_data(ar->rx_failover, tbuf, tlen); ++ skb_put_data(ar->rx_failover, tbuf, ++ min_t(unsigned int, tlen, ++ ar->rx_failover_missing)); + ar->rx_failover_missing -= tlen; + + if (ar->rx_failover_missing <= 0) { +-- +2.53.0 + diff --git a/queue-6.1/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch b/queue-6.1/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch new file mode 100644 index 0000000000..588c0e6d0b --- /dev/null +++ b/queue-6.1/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch @@ -0,0 +1,42 @@ +From b1a95d09f10025f9edb98ebb925b6dfa56fb6b0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:27 +0000 +Subject: wifi: carl9170: fix OOB read from off-by-two in TX status handler + +From: Tristan Madani + +[ Upstream commit a3f42f1049ad80c65560d2b078ad426c3134f78d ] + +The bounds check in carl9170_tx_process_status() uses +`i > ((cmd->hdr.len / 2) + 1)` which is off by two, allowing +2 extra iterations past valid _tx_status entries when the firmware- +controlled hdr.ext exceeds hdr.len/2. Fix by using the correct +comparison `i >= (cmd->hdr.len / 2)`. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c +index 88ef6e023f8266..d036ebb42c0d24 100644 +--- a/drivers/net/wireless/ath/carl9170/tx.c ++++ b/drivers/net/wireless/ath/carl9170/tx.c +@@ -693,7 +693,7 @@ void carl9170_tx_process_status(struct ar9170 *ar, + unsigned int i; + + for (i = 0; i < cmd->hdr.ext; i++) { +- if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) { ++ if (WARN_ON(i >= (cmd->hdr.len / 2))) { + print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE, + (void *) cmd, cmd->hdr.len + 4); + break; +-- +2.53.0 + diff --git a/queue-6.1/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch b/queue-6.1/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch new file mode 100644 index 0000000000..7188809ee9 --- /dev/null +++ b/queue-6.1/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch @@ -0,0 +1,50 @@ +From 03fb124bdcfc12fe5dfd67992a104b967a78bd38 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:08 +0300 +Subject: wifi: iwlwifi: mvm: fix read in wake packet notification handler + +From: Shahar Tzarfati + +[ Upstream commit 9d7657aae8c1579584c67b0b66114a6a98db8b2f ] + +In iwl_mvm_wowlan_store_wake_pkt(), packet_len was initialized from +notif->wake_packet_length before the explicit check that len >= +sizeof(*notif). + +Move the assignment of packet_len to after the size check so that +notif->wake_packet_length is only accessed once the payload length +has been validated. + +Fixes: 219ed58feda9 ("wifi: iwlwifi: mvm: Add support for wowlan wake packet notification") +Signed-off-by: Shahar Tzarfati +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.99d5cf85a528.Ic4aa736011d4fe88e0cd19723d1d48bb24642198@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +index 1425763fec4ea1..d7b2781a1eeaf1 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +@@ -2627,7 +2627,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, + struct iwl_wowlan_status_data *status, + u32 len) + { +- u32 data_size, packet_len = le32_to_cpu(notif->wake_packet_length); ++ u32 data_size, packet_len; + + if (len < sizeof(*notif)) { + IWL_ERR(mvm, "Invalid WoWLAN wake packet notification!\n"); +@@ -2646,6 +2646,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, + return -EIO; + } + ++ packet_len = le32_to_cpu(notif->wake_packet_length); + data_size = len - offsetof(struct iwl_wowlan_wake_pkt_notif, wake_packet); + + /* data_size got the padding from the notification, remove it. */ +-- +2.53.0 + diff --git a/queue-6.1/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch b/queue-6.1/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch new file mode 100644 index 0000000000..c80161f3e2 --- /dev/null +++ b/queue-6.1/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch @@ -0,0 +1,56 @@ +From d5fcb784ede35bdf461def6b94e366e25b075a1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:17:51 +1000 +Subject: wifi: mac80211: recalculate TIM when a station enters power save + +From: Andrew Pope + +[ Upstream commit a007a384c9eb17610f53a53e2f59944c31f1565a ] + +When an AP buffers frames for a station on its per-station TXQs and the +station subsequently enters power save, sta_ps_start() records the +buffered TIDs in txq_buffered_tids but does not update the TIM. The +station's TIM bit is only ever set when a further frame is buffered +while the station is already asleep +(ieee80211_tx_h_unicast_ps_buf() -> sta_info_recalc_tim()). + +If no further downlink frame arrives for that station the beacon +TIM never advertises the buffered traffic. A station relying on the +TIM then remains in doze indefinitely on top of a non-empty queue. Its +TXQs were removed from the scheduler's active list at PS entry, nothing +pages it, and the flow deadlocks until an unrelated event wakes the +station. + +Recalculate the TIM at the end of sta_ps_start(), so traffic +already buffered at PS entry is advertised immediately. +sta_info_recalc_tim() already consults txq_buffered_tids, which is +updated above, and is safe in this context (it is already called +from equivalent paths such as the tx handlers and +ieee80211_handle_filtered_frame()). + +Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation") +Signed-off-by: Andrew Pope +Link: https://patch.msgid.link/20260717011751.79524-1-andrew.pope@morsemicro.com +[add wifi: subject prefix] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index a6636e9f5c087a..1fbccdb37166a6 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1590,6 +1590,8 @@ static void sta_ps_start(struct sta_info *sta) + else + clear_bit(tid, &sta->txq_buffered_tids); + } ++ ++ sta_info_recalc_tim(sta); + } + + static void sta_ps_end(struct sta_info *sta) +-- +2.53.0 + diff --git a/queue-6.1/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch b/queue-6.1/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..3490ce752e --- /dev/null +++ b/queue-6.1/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,38 @@ +From fef0213eb33273e4617a2bd57d81bc70d97ac28e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:24:59 +0200 +Subject: wifi: mt76: connac: fix possible NULL-pointer deref in + mt76_connac_mcu_uni_bss_he_tlv() + +From: Lorenzo Bianconi + +[ Upstream commit 2c1fb2335f5e3afb34f91bc07ecb63517c328090 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: d0e274af2f2e4 ("mt76: mt76_connac: create mcu library") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-1-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index 6b5bfdbec8b11d..6f4b1a784a0786 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -1298,6 +1298,8 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct bss_info_uni_he *he; + + cap = mt76_connac_get_he_phy_cap(phy, vif); ++ if (!cap) ++ return; + + he = (struct bss_info_uni_he *)tlv; + he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; +-- +2.53.0 + diff --git a/queue-6.1/wifi-mt76-mt7915-guard-he-capability-lookups.patch b/queue-6.1/wifi-mt76-mt7915-guard-he-capability-lookups.patch new file mode 100644 index 0000000000..17b12361a9 --- /dev/null +++ b/queue-6.1/wifi-mt76-mt7915-guard-he-capability-lookups.patch @@ -0,0 +1,90 @@ +From fb53816266c1014235141279f06282690bd382d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 23:53:32 +0800 +Subject: wifi: mt76: mt7915: guard HE capability lookups + +From: Ruoyu Wang + +[ Upstream commit 8e9db062654a388d0fa587acbeeae68dd33eba41 ] + +mt7915_mcu_bss_he_tlv() and mt7915_mcu_sta_bfer_tlv() both run after +checking HE support, then dereference the HE PHY capability returned by +mt76_connac_get_he_phy_cap(). That helper can return NULL when no +capability entry matches the vif type. + +Fetch the capability before appending the TLV and skip the HE-specific +setup when no matching capability is available. + +Fixes: e6d557a78b60 ("mt76: mt7915: rely on mt76_connac_get_phy utilities") +Signed-off-by: Ruoyu Wang +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260620155332.81120-1-ruoyuw560@gmail.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +index 44fbfe3775e060..777ae8206df0ca 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +@@ -518,6 +518,8 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!cap) ++ return; + + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he)); + +@@ -1098,13 +1100,12 @@ mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy, + } + + static void +-mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, +- struct mt7915_phy *phy, struct sta_rec_bf *bf) ++mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, ++ const struct ieee80211_sta_he_cap *vc, ++ struct sta_rec_bf *bf) + { + struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap; + struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; +- const struct ieee80211_sta_he_cap *vc = +- mt76_connac_get_he_phy_cap(phy->mt76, vif); + const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; + u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); + u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map); +@@ -1163,6 +1164,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_phy *phy = mvif->phy; ++ const struct ieee80211_sta_he_cap *vc = NULL; + int tx_ant = hweight8(phy->mt76->chainmask) - 1; + struct sta_rec_bf *bf; + struct tlv *tlv; +@@ -1181,6 +1183,12 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + if (!ebf && !dev->ibf) + return; + ++ if (sta->deflink.he_cap.has_he && ebf) { ++ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!vc) ++ return; ++ } ++ + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); + bf = (struct sta_rec_bf *)tlv; + +@@ -1189,7 +1197,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + * ht: iBF only, since mac80211 lacks of eBF support + */ + if (sta->deflink.he_cap.has_he && ebf) +- mt7915_mcu_sta_bfer_he(sta, vif, phy, bf); ++ mt7915_mcu_sta_bfer_he(sta, vc, bf); + else if (sta->deflink.vht_cap.vht_supported) + mt7915_mcu_sta_bfer_vht(sta, phy, bf, ebf); + else if (sta->deflink.ht_cap.ht_supported) +-- +2.53.0 + diff --git a/queue-6.1/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch b/queue-6.1/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch new file mode 100644 index 0000000000..9d41e82cee --- /dev/null +++ b/queue-6.1/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch @@ -0,0 +1,104 @@ +From ed7aa69836a26cda82accfd9b652fc732cbfa9dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 22:57:11 +0900 +Subject: wifi: mwifiex: bound uAP association event IEs to the event buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit f0858bfc7d3cab411a447b88e3ef970e575032c9 ] + +mwifiex_process_uap_event() handles EVENT_UAP_STA_ASSOC by exposing the +(re)association request IEs that the firmware copies into the event: + + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - (u8 *)&event->frame_control; + sinfo->assoc_req_ies_len = le16_to_cpu(event->len) - (u16)len; + +event->len is supplied by the device firmware and is never validated, +and the subtraction is unchecked. assoc_req_ies points into +adapter->event_body[MAX_EVENT_SIZE], a fixed-size array embedded in the +kmalloc()'d struct mwifiex_adapter. + +On the ap_11n_enabled path mwifiex_set_sta_ht_cap() walks these IEs with +cfg80211_find_ie(), whose for_each_element() loop dereferences each +element header. A firmware-reported event->len larger than the bytes +actually received makes assoc_req_ies_len describe IEs that extend past +event_body, so the walk reads out of the adapter slab object, a +slab-out-of-bounds read (KASAN: slab-out-of-bounds in cfg80211_find_ie). +An event->len smaller than the header instead makes the int subtraction +negative, which wraps to a huge size_t when stored in assoc_req_ies_len. +The same length is handed to cfg80211_new_sta(), so a more modest +over-claim can also copy stale event_body bytes into the +NL80211_CMD_NEW_STATION notification. + +A malicious or malfunctioning mwifiex device (USB/SDIO/PCIe) can deliver +such an event while the interface is in AP/uAP mode. + +Validate event->len before use: reject a length that underflows the +header or that would place the IEs outside the event_body[] buffer the +event was copied into. event->len here is struct mwifiex_assoc_event.len, +a payload field internal to this event, not the transport frame length, +so it is validated in this handler rather than at the generic +MWIFIEX_TYPE_EVENT receive path, which only sees the event cause and the +transport frame length. The bound is against event_body[MAX_EVENT_SIZE] +rather than the actually-received length because the transports store the +event differently (USB and SDIO leave the 4-byte event header in +event_skb, PCIe strips it via skb_pull), whereas event_body is the single +fixed buffer all of them copy the event into. This is the event-path +analogue of the receive-path bounds checks added in commit 119585281617 +("wifi: mwifiex: Fix OOB and integer underflow when rx packets"). + +Fixes: e568634ae7ac ("mwifiex: add AP event handling framework") +Signed-off-by: HE WEI (ギカク) +Reviewed-by: Francesco Dolcini +Link: https://patch.msgid.link/20260715135711.34688-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + .../net/wireless/marvell/mwifiex/uap_event.c | 24 +++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c +index 58ef5020a46a73..c7383abf064f50 100644 +--- a/drivers/net/wireless/marvell/mwifiex/uap_event.c ++++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c +@@ -123,11 +123,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) + len = ETH_ALEN; + + if (len != -1) { ++ u16 evt_len = le16_to_cpu(event->len); ++ + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - + (u8 *)&event->frame_control; +- sinfo->assoc_req_ies_len = +- le16_to_cpu(event->len) - (u16)len; ++ ++ /* ++ * event->len is reported by the device firmware ++ * and is not otherwise validated. Reject a ++ * length that underflows the header, or that ++ * would place the association request IEs ++ * outside the fixed-size event_body[] buffer the ++ * event was copied into; otherwise the IE walk ++ * in mwifiex_set_sta_ht_cap() reads past ++ * event_body and out of the adapter slab object. ++ */ ++ if (evt_len < len || ++ (u8 *)&event->frame_control + evt_len > ++ adapter->event_body + MAX_EVENT_SIZE) { ++ mwifiex_dbg(adapter, ERROR, ++ "invalid STA assoc event length\n"); ++ kfree(sinfo); ++ return -1; ++ } ++ sinfo->assoc_req_ies_len = evt_len - (u16)len; + } + } + cfg80211_new_sta(priv->netdev, event->sta_addr, sinfo, +-- +2.53.0 + diff --git a/queue-6.12/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs3.patch b/queue-6.12/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs3.patch new file mode 100644 index 0000000000..60378a08a6 --- /dev/null +++ b/queue-6.12/alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs3.patch @@ -0,0 +1,44 @@ +From 99a286157c7f34182267f4bf62bddf8955cf3123 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Oct 2025 10:38:31 +0300 +Subject: ALSA: hda: cs35l41: Fix NULL pointer dereference in + cs35l41_get_acpi_mute_state() + +From: Denis Arefev + +[ Upstream commit 8527bbb33936340525a3504a00932b2f8fd75754 ] + +Return value of a function acpi_evaluate_dsm() is dereferenced without +checking for NULL, but it is usually checked for this function. + +acpi_evaluate_dsm() may return NULL, when acpi_evaluate_object() returns +acpi_status other than ACPI_SUCCESS, so add a check to prevent the crach. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: 447106e92a0c ("ALSA: hda: cs35l41: Support mute notifications for CS35L41 HDA") +Cc: stable@vger.kernel.org +Signed-off-by: Denis Arefev +Signed-off-by: Takashi Iwai +Stable-dep-of: 3b597d24dc04 ("ALSA: hda: cs35l41: validate and free ACPI mute object") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/cs35l41_hda.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c +index 099b8e9582b841..bc84415416aae5 100644 +--- a/sound/pci/hda/cs35l41_hda.c ++++ b/sound/pci/hda/cs35l41_hda.c +@@ -1403,6 +1403,8 @@ static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle + + if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) { + ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL); ++ if (!ret) ++ return -EINVAL; + mute = *ret->buffer.pointer; + dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute); + } +-- +2.53.0 + diff --git a/queue-6.12/alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch b/queue-6.12/alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch new file mode 100644 index 0000000000..16dfa4131e --- /dev/null +++ b/queue-6.12/alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch @@ -0,0 +1,60 @@ +From 1fccec907e773c9e7cf1247c62ed561d27c2d015 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:36:25 +0800 +Subject: ALSA: hda: cs35l41: validate and free ACPI mute object + +From: Guangshuo Li + +[ Upstream commit 3b597d24dc0455ae926f1053f97c2725038fc3cd ] + +cs35l41_get_acpi_mute_state() evaluates a _DSM method to get the ACPI +mute state and reads the first byte from the returned object. + +However, the returned ACPI object is owned by the caller and is never +freed after use, so each successful query leaks the _DSM result object. + +The code also assumes that the returned object is a buffer with at least +one byte. A malformed firmware response can return a different object +type or an empty buffer, and the direct ret->buffer.pointer dereference +can then access an invalid pointer. + +Use the typed _DSM helper, validate that the returned buffer contains at +least one byte, and free the ACPI object after reading it. + +Fixes: 447106e92a0c ("ALSA: hda: cs35l41: Support mute notifications for CS35L41 HDA") +Signed-off-by: Guangshuo Li +Link: https://patch.msgid.link/20260708113625.752913-1-lgs201920130244@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/cs35l41_hda.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c +index bc84415416aae5..031978a62cb996 100644 +--- a/sound/pci/hda/cs35l41_hda.c ++++ b/sound/pci/hda/cs35l41_hda.c +@@ -1402,10 +1402,19 @@ static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle + guid_parse(CS35L41_UUID, &guid); + + if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) { +- ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL); ++ ret = acpi_evaluate_dsm_typed(handle, &guid, 0, ++ CS35L41_DSM_GET_MUTE, NULL, ++ ACPI_TYPE_BUFFER); ++ + if (!ret) + return -EINVAL; ++ if (!ret->buffer.length || !ret->buffer.pointer) { ++ ACPI_FREE(ret); ++ return -EINVAL; ++ } ++ + mute = *ret->buffer.pointer; ++ ACPI_FREE(ret); + dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute); + } + +-- +2.53.0 + diff --git a/queue-6.12/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch b/queue-6.12/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch new file mode 100644 index 0000000000..9a1d3a7394 --- /dev/null +++ b/queue-6.12/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch @@ -0,0 +1,58 @@ +From c4ded5fc148247e23d4f9472110c04f1f8252b9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 15:20:06 +0530 +Subject: amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN + +From: Prashanth Kumar KR + +[ Upstream commit 4bf22afe53a1de4b44b04cf677fd5199089cbdff ] + +MAC_AUTO_SW (VR_MII_DIG_CTRL1 bit 9) enables automatic XPCS speed +mode switching after CL37 auto-negotiation and is only meaningful in +SGMII MAC mode. The original code unconditionally set this bit on +every call to xgbe_an37_set(), including when called from +xgbe_an37_disable() with enable=false. This left MAC_AUTO_SW=1 after +AN was disabled, causing the XPCS to autonomously switch speed from +stale AN state during subsequent mode changes, breaking SGMII speed +negotiation on 1G copper SFP modules. + +Patrick: This was breaking negotiation for all 1G SFP modules, +not just copper modules. + +Fixes: 42fd432fe6d3 ("amd-xgbe: align CL37 AN sequence as per databook") +Reported-by: Patrick Oppenlander +Link: https://lore.kernel.org/netdev/CAEg67GmFS0Q4oSZkz8zWdOzckSth9_vBPiOy6a7-d697C2w2Xg@mail.gmail.com +Signed-off-by: Prashanth Kumar KR +Tested-by: Patrick Oppenlander +Link: https://patch.msgid.link/20260709095006.3683940-1-prashanthkumar.k.r@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index 75e9cb3fc7aa66..804945ea602790 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -376,9 +376,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, + + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); + +- reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); +- reg |= XGBE_VEND2_MAC_AUTO_SW; +- XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ if (pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) { ++ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); ++ if (enable) ++ reg |= XGBE_VEND2_MAC_AUTO_SW; ++ else ++ reg &= ~XGBE_VEND2_MAC_AUTO_SW; ++ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ } + } + + static void xgbe_an37_restart(struct xgbe_prv_data *pdata) +-- +2.53.0 + diff --git a/queue-6.12/amt-make-the-head-writable-before-rewriting-the-l2-h.patch b/queue-6.12/amt-make-the-head-writable-before-rewriting-the-l2-h.patch new file mode 100644 index 0000000000..cea19a2e21 --- /dev/null +++ b/queue-6.12/amt-make-the-head-writable-before-rewriting-the-l2-h.patch @@ -0,0 +1,67 @@ +From 91ff7e8f9b554386f236938c3c55d7627471ee0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:19:34 -0400 +Subject: amt: make the head writable before rewriting the L2 header + +From: Michael Bommarito + +[ Upstream commit 53969d704fa5b7c1751e277fac96bfc22b435eac ] + +amt_multicast_data_handler(), amt_membership_query_handler() and +amt_update_handler() rewrite the ethernet header of the decapsulated skb +in place (eth->h_proto, eth->h_dest and, for the query, also +eth->h_source) before handing it up the stack. The skb head may be +shared, for example when a packet tap has cloned it on the underlay +interface, so writing through it corrupts the other reader's copy. + +Call skb_cow_head() before the rewrite so the head is private. It is +placed before the pointers into the head are (re-)derived, so a +reallocation caused by the copy is picked up by those derivations. + +Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") +Signed-off-by: Michael Bommarito +Reviewed-by: Simon Horman +Reviewed-by: Taehee Yoo +Link: https://patch.msgid.link/20260711151934.2955226-3-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/amt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/amt.c b/drivers/net/amt.c +index 062798fb8aa655..77d6c443d81bf6 100644 +--- a/drivers/net/amt.c ++++ b/drivers/net/amt.c +@@ -2315,6 +2315,9 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + skb_reset_mac_header(skb); + skb_pull(skb, sizeof(*eth)); + ++ if (skb_cow_head(skb, 0)) ++ return true; ++ + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + iph = ip_hdr(skb); +@@ -2391,6 +2394,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_network_header(skb); + eth = eth_hdr(skb); + ether_addr_copy(h_source, oeth->h_source); ++ if (skb_cow_head(skb, 0)) ++ return true; + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + +@@ -2516,6 +2521,9 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + ++ if (skb_cow_head(skb, 0)) ++ return true; ++ + iph = ip_hdr(skb); + if (iph->version == 4) { + if (ip_mc_check_igmp(skb)) { +-- +2.53.0 + diff --git a/queue-6.12/amt-re-read-skb-header-pointers-after-every-pull.patch b/queue-6.12/amt-re-read-skb-header-pointers-after-every-pull.patch new file mode 100644 index 0000000000..f2047aad86 --- /dev/null +++ b/queue-6.12/amt-re-read-skb-header-pointers-after-every-pull.patch @@ -0,0 +1,367 @@ +From 9857454764339ce86e04b9d4dbb934b928a180b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:19:33 -0400 +Subject: amt: re-read skb header pointers after every pull + +From: Michael Bommarito + +[ Upstream commit 3656a79f94c471827a08f2cacce5f94ad5e52c24 ] + +Several AMT receive and transmit paths cache a pointer into the skb head +(ip_hdr(), ipv6_hdr(), eth_hdr() or the AMT message header) and then call +a helper that can reallocate that head before the cached pointer is used +again. pskb_may_pull(), ip_mc_may_pull(), ipv6_mc_may_pull(), +iptunnel_pull_header(), ip_mc_check_igmp() and ipv6_mc_check_mld() can all +free the old head and move the data, so a pointer taken before the call +dangles afterwards and the later access is a use-after-free of the freed +head. + +The affected sites are: + + amt_rcv() caches ip_hdr() before amt_parse_type() pulls, then reads + iph->saddr. + + amt_dev_xmit() caches ip_hdr()/ipv6_hdr() before ip_mc_check_igmp()/ + ipv6_mc_check_mld() and pskb_may_pull(), then reads the group address. + + amt_multicast_data_handler() caches eth_hdr() before pskb_may_pull(), + then writes the L2 header. + + amt_membership_query_handler() caches the AMT header, the outer and + inner eth_hdr() and ip_hdr() before iptunnel_pull_header() and several + pulls, then reads and writes them. + + amt_igmpv3_report_handler() and amt_mldv2_report_handler() cache + ip_hdr()/ipv6_hdr() and the current group record and read the record + count from the report header inside the record loop, across the + *_mc_may_pull() calls. + + amt_update_handler() caches ip_hdr() and the AMT membership-update + header before pskb_may_pull(), iptunnel_pull_header(), + ip_mc_check_igmp() and the report handler, then reads iph->daddr and + amtmu->nonce / amtmu->response_mac. + +Fix each site by either snapshotting the scalar that is used after the +pull before the first pull runs, or re-deriving the header pointer from +the skb after the last pull that can move the head. Values that are +stable across the pull (source and group address, the response MAC and +nonce, the record count, the outer source MAC) are snapshotted; pointers +that are written through or read repeatedly are re-derived. + +Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") +Signed-off-by: Michael Bommarito +Reviewed-by: Simon Horman +Reviewed-by: Taehee Yoo +Link: https://patch.msgid.link/20260711151934.2955226-2-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/amt.c | 79 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 55 insertions(+), 24 deletions(-) + +diff --git a/drivers/net/amt.c b/drivers/net/amt.c +index ef6848c2e60841..062798fb8aa655 100644 +--- a/drivers/net/amt.c ++++ b/drivers/net/amt.c +@@ -1206,7 +1206,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + data = true; + } + v6 = false; +- group.ip4 = iph->daddr; ++ group.ip4 = ip_hdr(skb)->daddr; + #if IS_ENABLED(CONFIG_IPV6) + } else if (iph->version == 6) { + ip6h = ipv6_hdr(skb); +@@ -1230,7 +1230,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + data = true; + } + v6 = true; +- group.ip6 = ip6h->daddr; ++ group.ip6 = ipv6_hdr(skb)->daddr; + #endif + } else { + dev->stats.tx_errors++; +@@ -1273,12 +1273,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash], + node) { + if (!v6) { +- if (gnode->group_addr.ip4 == iph->daddr) ++ if (gnode->group_addr.ip4 == group.ip4) + goto found; + #if IS_ENABLED(CONFIG_IPV6) + } else { + if (ipv6_addr_equal(&gnode->group_addr.ip6, +- &ip6h->daddr)) ++ &group.ip6)) + goto found; + #endif + } +@@ -1995,14 +1995,18 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb, + struct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb); + int len = skb_transport_offset(skb) + sizeof(*ihrv3); + void *zero_grec = (void *)&igmpv3_zero_grec; +- struct iphdr *iph = ip_hdr(skb); + struct amt_group_node *gnode; + union amt_addr group, host; + struct igmpv3_grec *grec; ++ __be32 saddr; + u16 nsrcs; ++ u16 ngrec; + int i; + +- for (i = 0; i < ntohs(ihrv3->ngrec); i++) { ++ saddr = ip_hdr(skb)->saddr; ++ ngrec = ntohs(ihrv3->ngrec); ++ ++ for (i = 0; i < ngrec; i++) { + len += sizeof(*grec); + if (!ip_mc_may_pull(skb, len)) + break; +@@ -2014,10 +2018,13 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb, + if (!ip_mc_may_pull(skb, len)) + break; + ++ grec = (void *)(skb->data + len - sizeof(*grec) - ++ nsrcs * sizeof(__be32)); ++ + memset(&group, 0, sizeof(union amt_addr)); + group.ip4 = grec->grec_mca; + memset(&host, 0, sizeof(union amt_addr)); +- host.ip4 = iph->saddr; ++ host.ip4 = saddr; + gnode = amt_lookup_group(tunnel, &group, &host, false); + if (!gnode) { + gnode = amt_add_group(amt, tunnel, &group, &host, +@@ -2157,14 +2164,18 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb, + struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb); + int len = skb_transport_offset(skb) + sizeof(*mld2r); + void *zero_grec = (void *)&mldv2_zero_grec; +- struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct amt_group_node *gnode; + union amt_addr group, host; + struct mld2_grec *grec; ++ struct in6_addr saddr; + u16 nsrcs; ++ u16 ngrec; + int i; + +- for (i = 0; i < ntohs(mld2r->mld2r_ngrec); i++) { ++ saddr = ipv6_hdr(skb)->saddr; ++ ngrec = ntohs(mld2r->mld2r_ngrec); ++ ++ for (i = 0; i < ngrec; i++) { + len += sizeof(*grec); + if (!ipv6_mc_may_pull(skb, len)) + break; +@@ -2176,10 +2187,13 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb, + if (!ipv6_mc_may_pull(skb, len)) + break; + ++ grec = (void *)(skb->data + len - sizeof(*grec) - ++ nsrcs * sizeof(struct in6_addr)); ++ + memset(&group, 0, sizeof(union amt_addr)); + group.ip6 = grec->grec_mca; + memset(&host, 0, sizeof(union amt_addr)); +- host.ip6 = ip6h->saddr; ++ host.ip6 = saddr; + gnode = amt_lookup_group(tunnel, &group, &host, true); + if (!gnode) { + gnode = amt_add_group(amt, tunnel, &group, &host, +@@ -2300,7 +2314,6 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + skb_push(skb, sizeof(*eth)); + skb_reset_mac_header(skb); + skb_pull(skb, sizeof(*eth)); +- eth = eth_hdr(skb); + + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; +@@ -2310,6 +2323,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!ipv4_is_multicast(iph->daddr)) + return true; + skb->protocol = htons(ETH_P_IP); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IP); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) +@@ -2323,6 +2337,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!ipv6_addr_is_multicast(&ip6h->daddr)) + return true; + skb->protocol = htons(ETH_P_IPV6); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IPV6); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif +@@ -2346,10 +2361,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + struct sk_buff *skb) + { + struct amt_header_membership_query *amtmq; +- struct igmpv3_query *ihv3; + struct ethhdr *eth, *oeth; ++ struct igmpv3_query *ihv3; ++ u8 h_source[ETH_ALEN]; + struct iphdr *iph; + int hdr_size, len; ++ u64 response_mac; + + hdr_size = sizeof(*amtmq) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) +@@ -2362,6 +2379,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + if (amtmq->nonce != amt->nonce) + return true; + ++ response_mac = amtmq->response_mac; ++ + hdr_size -= sizeof(*eth); + if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false)) + return true; +@@ -2371,6 +2390,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_pull(skb, sizeof(*eth)); + skb_reset_network_header(skb); + eth = eth_hdr(skb); ++ ether_addr_copy(h_source, oeth->h_source); + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + +@@ -2383,6 +2403,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + sizeof(*ihv3))) + return true; + ++ iph = ip_hdr(skb); + if (!ipv4_is_multicast(iph->daddr)) + return true; + +@@ -2390,10 +2411,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS); + WRITE_ONCE(amt->ready4, true); +- amt->mac = amtmq->response_mac; ++ amt->mac = response_mac; + amt->req_cnt = 0; + amt->qi = ihv3->qqic; + skb->protocol = htons(ETH_P_IP); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IP); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) +@@ -2416,10 +2438,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS); + WRITE_ONCE(amt->ready6, true); +- amt->mac = amtmq->response_mac; ++ amt->mac = response_mac; + amt->req_cnt = 0; + amt->qi = mld2q->mld2q_qqic; + skb->protocol = htons(ETH_P_IPV6); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IPV6); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif +@@ -2427,7 +2450,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + return true; + } + +- ether_addr_copy(eth->h_source, oeth->h_source); ++ ether_addr_copy(eth->h_source, h_source); + skb->pkt_type = PACKET_MULTICAST; + skb->ip_summed = CHECKSUM_NONE; + len = skb->len; +@@ -2450,8 +2473,11 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + struct ethhdr *eth; + struct iphdr *iph; + int len, hdr_size; ++ u64 response_mac; ++ __be32 saddr; ++ __be32 nonce; + +- iph = ip_hdr(skb); ++ saddr = ip_hdr(skb)->saddr; + + hdr_size = sizeof(*amtmu) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) +@@ -2461,15 +2487,18 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + if (amtmu->reserved || amtmu->version) + return true; + ++ nonce = amtmu->nonce; ++ response_mac = amtmu->response_mac; ++ + if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false)) + return true; + + skb_reset_network_header(skb); + + list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) { +- if (tunnel->ip4 == iph->saddr) { +- if ((amtmu->nonce == tunnel->nonce && +- amtmu->response_mac == tunnel->mac)) { ++ if (tunnel->ip4 == saddr) { ++ if ((nonce == tunnel->nonce && ++ response_mac == tunnel->mac)) { + mod_delayed_work(amt_wq, &tunnel->gc_wq, + msecs_to_jiffies(amt_gmi(amt)) + * 3); +@@ -2503,6 +2532,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + eth = eth_hdr(skb); + skb->protocol = htons(ETH_P_IP); + eth->h_proto = htons(ETH_P_IP); ++ iph = ip_hdr(skb); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) + } else if (iph->version == 6) { +@@ -2522,6 +2552,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + eth = eth_hdr(skb); + skb->protocol = htons(ETH_P_IPV6); + eth->h_proto = htons(ETH_P_IPV6); ++ ip6h = ipv6_hdr(skb); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif + } else { +@@ -2767,7 +2798,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb) + static int amt_rcv(struct sock *sk, struct sk_buff *skb) + { + struct amt_dev *amt; +- struct iphdr *iph; ++ __be32 saddr; + int type; + bool err; + +@@ -2780,7 +2811,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + } + + skb->dev = amt->dev; +- iph = ip_hdr(skb); ++ saddr = ip_hdr(skb)->saddr; + type = amt_parse_type(skb); + if (type == -1) { + err = true; +@@ -2790,7 +2821,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + if (amt->mode == AMT_MODE_GATEWAY) { + switch (type) { + case AMT_MSG_ADVERTISEMENT: +- if (iph->saddr != amt->discovery_ip) { ++ if (saddr != amt->discovery_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +@@ -2802,7 +2833,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + } + goto out; + case AMT_MSG_MULTICAST_DATA: +- if (iph->saddr != amt->remote_ip) { ++ if (saddr != amt->remote_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +@@ -2813,7 +2844,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + else + goto out; + case AMT_MSG_MEMBERSHIP_QUERY: +- if (iph->saddr != amt->remote_ip) { ++ if (saddr != amt->remote_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +-- +2.53.0 + diff --git a/queue-6.12/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch b/queue-6.12/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch new file mode 100644 index 0000000000..129f9d8539 --- /dev/null +++ b/queue-6.12/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch @@ -0,0 +1,72 @@ +From f95146449ff374f11d13554e6ce02f7b7572a76b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 18:06:20 +0800 +Subject: ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI + +From: Shengjiu Wang + +[ Upstream commit 0b604e886ece11b71c4daaeccc512c784b89b014 ] + +The bt-sco-pcm-wb DAI uses the same stream_name strings as bt-sco-pcm +("Playback" and "Capture"). This causes duplicate DAPM AIF widget +names within the same component, leading to debugfs warnings: + + debugfs: 'Playback' already exists in 'dapm' + debugfs: 'Capture' already exists in 'dapm' + +Give the wideband DAI distinct stream names ("WB Playback" and +"WB Capture") and add corresponding DAPM AIF widgets and routes for +them. + +Fixes: 5947e1b4992e ("ASoC: bt-sco: extend rate and add a general compatible string") +Assisted-by: VeroCoder:claude-sonnet-4-5 +Signed-off-by: Shengjiu Wang +Link: https://patch.msgid.link/20260715100620.1387159-1-shengjiu.wang@oss.nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/bt-sco.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c +index 3afcef2dfa3529..c0bf45b76cb8c5 100644 +--- a/sound/soc/codecs/bt-sco.c ++++ b/sound/soc/codecs/bt-sco.c +@@ -17,11 +17,17 @@ static const struct snd_soc_dapm_widget bt_sco_widgets[] = { + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0, + SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_IN("BT_SCO_RX_WB", "WB Playback", 0, ++ SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("BT_SCO_TX_WB", "WB Capture", 0, ++ SND_SOC_NOPM, 0, 0), + }; + + static const struct snd_soc_dapm_route bt_sco_routes[] = { + { "BT_SCO_TX", NULL, "RX" }, + { "TX", NULL, "BT_SCO_RX" }, ++ { "BT_SCO_TX_WB", NULL, "RX" }, ++ { "TX", NULL, "BT_SCO_RX_WB" }, + }; + + static struct snd_soc_dai_driver bt_sco_dai[] = { +@@ -45,14 +51,14 @@ static struct snd_soc_dai_driver bt_sco_dai[] = { + { + .name = "bt-sco-pcm-wb", + .playback = { +- .stream_name = "Playback", ++ .stream_name = "WB Playback", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { +- .stream_name = "Capture", ++ .stream_name = "WB Capture", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, +-- +2.53.0 + diff --git a/queue-6.12/asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch b/queue-6.12/asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch new file mode 100644 index 0000000000..175068eb32 --- /dev/null +++ b/queue-6.12/asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch @@ -0,0 +1,61 @@ +From c2b98fdacd425a07d866c04a69ca49b762c65ef4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 May 2026 17:11:23 +0100 +Subject: ASoC: cs35l56: Don't use devres to unregister component + +From: Richard Fitzgerald + +[ Upstream commit bee87cf0f1248c0f20710d7a79df41fe892d9f88 ] + +Manually call snd_soc_unregister_component() from cs35l56_remove() +instead of using devres cleanup. This ensures that the component is +destroyed before cs35l56_remove() starts cleanup of anything the +component code could be using. + +Devres cleanup happens after the driver remove() callback, so if +snd_soc_register_component() is used, it will not be destroyed until +after cs35l56_remove() has returned. But there is some cleanup that +must be done in cs35l56_remove(), or wrapped in a custom devres +cleanup handler to ensure correct ordering. The simplest option is +to call snd_soc_unregister_component() at the start of cs35l56_remove(). + +Fixes: e49611252900 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Closes: https://sashiko.dev/#/patchset/20260501103002.2843735-1-rf%40opensource.cirrus.com +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260505161124.3621000-2-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Stable-dep-of: 93c2a8ea2454 ("ASoC: cs35l56: Fix potential probe() deadlock") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index c78f7f95f127d0..ee5357ac0ceab5 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -1330,9 +1330,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + goto err; + } + +- ret = devm_snd_soc_register_component(cs35l56->base.dev, +- &soc_component_dev_cs35l56, +- cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); ++ ret = snd_soc_register_component(cs35l56->base.dev, ++ &soc_component_dev_cs35l56, ++ cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); + if (ret < 0) { + dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n"); + goto err_remove_wm_adsp; +@@ -1434,6 +1434,8 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_SOC_CS35L56_CORE); + + void cs35l56_remove(struct cs35l56_private *cs35l56) + { ++ snd_soc_unregister_component(cs35l56->base.dev); ++ + cs35l56->base.init_done = false; + + /* +-- +2.53.0 + diff --git a/queue-6.12/asoc-cs35l56-fix-potential-probe-deadlock.patch b/queue-6.12/asoc-cs35l56-fix-potential-probe-deadlock.patch new file mode 100644 index 0000000000..35c3a8e877 --- /dev/null +++ b/queue-6.12/asoc-cs35l56-fix-potential-probe-deadlock.patch @@ -0,0 +1,111 @@ +From aa11c0523e3ae5eb36c81e56b25ea8e8d72a9c3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 14:20:44 +0100 +Subject: ASoC: cs35l56: Fix potential probe() deadlock + +From: Richard Fitzgerald + +[ Upstream commit 93c2a8ea2454b7b14eb378a58cad8a83c0ffc903 ] + +On I2C/SPI call cs35l56_init() before calling +snd_soc_register_component() to prevent the potential for a deadlock +on init_completion. + +For most buses all the hardware would be ready when probe() returns, +but on SoundWire, probe() must return before the SoundWire bus driver +will enumerate the device. All access to the registers must be deferred +until the driver receives an ATTACHED notification. But anything that +could return -EPROBE_DEFER must be called during probe, and that includes +snd_soc_register_component(). Because of that, on SoundWire the ASoC +component can be created before the registers are accssible, so +cs35l56_component_probe() waits for init_completion to signal that the +registers are accessible. + +On I2C/SPI this 2-stage startup isn't required so their probe() +functions simply called cs35l56_common_probe() and then cs35l56_init(). +The problem with this was that snd_soc_register_component() was still +called early. If this triggered ASoC to create the card, ASoC would call +cs35l56_component_probe() which waits on init_completion - but this would +be running inside the cs35l56 driver probe() so blocking it from reaching +the code that signals init_completion, causing a deadlock. + +Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Reported-by: Salman S. Tahir +Closes: https://lore.kernel.org/linux-sound/95c21574-97d5-4311-9263-9e174d22d22c@opensource.cirrus.com/T/#u +Tested-by: Salman S. Tahir +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260716132045.1469156-2-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56-i2c.c | 4 +--- + sound/soc/codecs/cs35l56-spi.c | 4 +--- + sound/soc/codecs/cs35l56.c | 15 +++++++++++++++ + 3 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c +index 2bd2ff75cd5047..93ee9e60ba79c9 100644 +--- a/sound/soc/codecs/cs35l56-i2c.c ++++ b/sound/soc/codecs/cs35l56-i2c.c +@@ -40,9 +40,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client) + if (ret != 0) + return ret; + +- ret = cs35l56_init(cs35l56); +- if (ret == 0) +- ret = cs35l56_irq_request(&cs35l56->base, client->irq); ++ ret = cs35l56_irq_request(&cs35l56->base, client->irq); + if (ret < 0) + cs35l56_remove(cs35l56); + +diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c +index 568f554a8638bf..a5bae05d6433e9 100644 +--- a/sound/soc/codecs/cs35l56-spi.c ++++ b/sound/soc/codecs/cs35l56-spi.c +@@ -41,9 +41,7 @@ static int cs35l56_spi_probe(struct spi_device *spi) + if (ret != 0) + return ret; + +- ret = cs35l56_init(cs35l56); +- if (ret == 0) +- ret = cs35l56_irq_request(&cs35l56->base, spi->irq); ++ ret = cs35l56_irq_request(&cs35l56->base, spi->irq); + if (ret < 0) + cs35l56_remove(cs35l56); + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index ee5357ac0ceab5..b657a0df1ed166 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -1330,6 +1330,16 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + goto err; + } + ++ /* ++ * On SoundWire the cs35l56_init() cannot be run until after the ++ * device has been enumerated by the SoundWire core. ++ */ ++ if (!cs35l56->sdw_peripheral) { ++ ret = cs35l56_init(cs35l56); ++ if (ret) ++ goto err_remove_wm_adsp; ++ } ++ + ret = snd_soc_register_component(cs35l56->base.dev, + &soc_component_dev_cs35l56, + cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); +@@ -1344,6 +1354,11 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + wm_adsp2_remove(&cs35l56->dsp); + + err: ++ if (pm_runtime_enabled(cs35l56->base.dev)) { ++ pm_runtime_dont_use_autosuspend(cs35l56->base.dev); ++ pm_runtime_disable(cs35l56->base.dev); ++ } ++ + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); + regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + +-- +2.53.0 + diff --git a/queue-6.12/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch b/queue-6.12/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch new file mode 100644 index 0000000000..7f472d4942 --- /dev/null +++ b/queue-6.12/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch @@ -0,0 +1,57 @@ +From 921521ac131d476d6d2aa1fd22e3f833254421cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 14:20:45 +0100 +Subject: ASoC: cs35l56: Use complete_all() to signal init_completion + +From: Richard Fitzgerald + +[ Upstream commit e0bffb63a2eda0af82ed7e6357ac67c2db990c21 ] + +In cs35l56_init() use complete_all() to signal init_completion instead +of complete(). + +cs35l56_init() was signaling init_completion using the complete() function. +This only releases ONE waiter. + +If cs35l56_component_probe() was called multiple times the first time +would consume that one signal, then future calls would timeout waiting for +the completion. This could happen if: + + - The component is probed, removed, then probed again without the cs35l56 + module being removed. + + - A call to component_probe() returns an error and ASoC calls it again + later. + +It should use complete_all() so that after it has been signaled it will +allow any code that waits on it to continue immediately. + +The one case where the driver must wait for initialization to run again is +when waiting for a reboot after firmware download, and here the code +correctly calls reinit_completion() first. + +Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260716132045.1469156-3-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index b657a0df1ed166..2eff866713aefd 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -1441,7 +1441,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56) + return dev_err_probe(cs35l56->base.dev, ret, "Failed to write ASP1_CONTROL3\n"); + + cs35l56->base.init_done = true; +- complete(&cs35l56->init_completion); ++ complete_all(&cs35l56->init_completion); + + return 0; + } +-- +2.53.0 + diff --git a/queue-6.12/asoc-tas2781-bound-firmware-description-string-parsi.patch b/queue-6.12/asoc-tas2781-bound-firmware-description-string-parsi.patch new file mode 100644 index 0000000000..88065906e7 --- /dev/null +++ b/queue-6.12/asoc-tas2781-bound-firmware-description-string-parsi.patch @@ -0,0 +1,153 @@ +From a01940b1650ae4c78b1c7d08725dd0066ee15a18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:45:39 +0800 +Subject: ASoC: tas2781: bound firmware description string parsing + +From: Pengpeng Hou + +[ Upstream commit bc889dfcea9294a1eae7f8e2f3573a90764ae4d0 ] + +The TAS2781 firmware parser reads several variable-length description +strings with strlen() before checking that the string terminator is +present inside the firmware blob. A malformed firmware image without a +NUL terminator can therefore make the parser walk past the end of the +firmware buffer before the later size checks run. + +Add a small bounded string-length helper and use it for all description +fields that are parsed from the firmware buffer. Keep the existing size +checks for the fixed bytes that follow each string. + +Fixes: 915f5eadebd2 ("ASoC: tas2781: firmware lib") +Signed-off-by: Pengpeng Hou +Link: https://patch.msgid.link/20260706144540.93929-1-pengpeng@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2781-fmwlib.c | 63 ++++++++++++++++++++++++++++--- + 1 file changed, 57 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c +index 0aeb88abbf52f1..a2c4602eb57440 100644 +--- a/sound/soc/codecs/tas2781-fmwlib.c ++++ b/sound/soc/codecs/tas2781-fmwlib.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -891,13 +892,42 @@ static int tasdevice_load_block_kernel( + return 0; + } + ++static int tasdevice_fw_strnlen(const struct firmware *fmw, int offset) ++{ ++ const u8 *start; ++ const u8 *nul; ++ size_t remaining; ++ size_t len; ++ ++ if (offset < 0 || offset >= fmw->size) ++ return -EINVAL; ++ ++ start = fmw->data + offset; ++ remaining = fmw->size - offset; ++ nul = memchr(start, '\0', remaining); ++ if (!nul) ++ return -EINVAL; ++ ++ len = nul - start; ++ if (len > INT_MAX) ++ return -EOVERFLOW; ++ ++ return len; ++} ++ + static int fw_parse_variable_hdr(struct tasdevice_priv + *tas_priv, struct tasdevice_dspfw_hdr *fw_hdr, + const struct firmware *fmw, int offset) + { + const unsigned char *buf = fmw->data; +- int len = strlen((char *)&buf[offset]); ++ int len; + ++ len = tasdevice_fw_strnlen(fmw, offset); ++ if (len < 0) { ++ dev_err(tas_priv->dev, "%s: Description error\n", __func__); ++ offset = len; ++ goto out; ++ } + len++; + + if (offset + len + 8 > fmw->size) { +@@ -1029,7 +1059,12 @@ static int fw_parse_data(struct tasdevice_fw *tas_fmw, + memcpy(img_data->name, &data[offset], 64); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_fmw->dev, "%s: Description error\n", __func__); ++ offset = n; ++ goto out; ++ } + n++; + if (offset + n + 2 > fmw->size) { + dev_err(tas_fmw->dev, "%s: Description error\n", __func__); +@@ -1102,7 +1137,12 @@ static int fw_parse_program_data(struct tasdevice_priv *tas_priv, + } + offset += 64; + +- n = strlen((char *)&buf[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + /* skip '\0' and 5 unused bytes */ + n += 6; + if (offset + n > fmw->size) { +@@ -1165,7 +1205,12 @@ static int fw_parse_configuration_data( + memcpy(config->name, &data[offset], 64); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + n += 15; + if (offset + n > fmw->size) { + dev_err(tas_priv->dev, "Description err\n"); +@@ -1819,7 +1864,8 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, + { + struct tasdevice_calibration *calibration; + unsigned char *data = (unsigned char *)fmw->data; +- unsigned int i, n; ++ unsigned int i; ++ int n; + + if (offset + 2 > fmw->size) { + dev_err(tas_priv->dev, "%s: Calibrations error\n", __func__); +@@ -1851,7 +1897,12 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, + calibration = &(tas_fmw->calibrations[i]); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + /* skip '\0' and 2 unused bytes */ + n += 3; + if (offset + n > fmw->size) { +-- +2.53.0 + diff --git a/queue-6.12/bluetooth-btusb-validate-realtek-vendor-event-length.patch b/queue-6.12/bluetooth-btusb-validate-realtek-vendor-event-length.patch new file mode 100644 index 0000000000..40fb578d06 --- /dev/null +++ b/queue-6.12/bluetooth-btusb-validate-realtek-vendor-event-length.patch @@ -0,0 +1,48 @@ +From 5304c58148fd27531290ed9163c4affedc80507f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:47:17 +0800 +Subject: Bluetooth: btusb: validate Realtek vendor event length + +From: Pengpeng Hou + +[ Upstream commit df541cd485ff80a5ddc579d99687bc7506df9851 ] + +btusb_recv_event_realtek() reads the event code at data[0] and the Realtek +subevent code at data[2] before deciding whether to consume a vendor event +as a coredump. + +For example, the two-byte event ff 00 contains a complete vendor-event +header declaring zero parameters. The old classifier still reads a +nonexistent third byte and can misclassify the event as a coredump if the +adjacent byte is 0x34. + +Require the HCI event header and first parameter to be present before +inspecting the Realtek subevent code. Short events continue through the +normal HCI receive path, which owns their protocol validation. + +Fixes: 044014ce85a1 ("Bluetooth: btrtl: Add Realtek devcoredump support") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index 903d43380d038f..aadbda2fd5a20a 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2707,7 +2707,9 @@ static int btusb_setup_realtek(struct hci_dev *hdev) + + static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb) + { +- if (skb->data[0] == HCI_VENDOR_PKT && skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) { ++ if (skb->len >= HCI_EVENT_HDR_SIZE + 1 && ++ skb->data[0] == HCI_VENDOR_PKT && ++ skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) { + struct rtk_dev_coredump_hdr hdr = { + .code = RTK_DEVCOREDUMP_CODE_MEMDUMP, + }; +-- +2.53.0 + diff --git a/queue-6.12/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch b/queue-6.12/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch new file mode 100644 index 0000000000..294c4b32c1 --- /dev/null +++ b/queue-6.12/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch @@ -0,0 +1,75 @@ +From 75285f10070aebe8e9d1df2826c8116cb86c5052 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 09:06:22 +0800 +Subject: bonding: fix devconf_all NULL dereference when IPv6 is disabled + +From: Zhaolong Zhang + +[ Upstream commit 1c975de3343cdef506f2eecc833cc1f14b0401c4 ] + +When booting with the 'ipv6.disable=1' parameter, the devconf_all is +never initialized because inet6_init() exits before addrconf_init() is +called which initializes it. bond_send_validate(), however, will still +call bond_ns_send_all() even ipv6 is indeed disabled. It will lead to +NULL derefence of net->ipv6.devconf_all in ip6_pol_route(). + + BUG: kernel NULL pointer dereference, address: 000000000000000c + [...] + Workqueue: bond0 bond_arp_monitor [bonding] + RIP: 0010:ip6_pol_route+0x69/0x480 + [...] + Call Trace: + + ? srso_return_thunk+0x5/0x5f + ? __pfx_ip6_pol_route_output+0x10/0x10 + fib6_rule_lookup+0xfe/0x260 + ? wakeup_preempt+0x8a/0x90 + ? srso_return_thunk+0x5/0x5f + ? srso_return_thunk+0x5/0x5f + ? sched_balance_rq+0x369/0x810 + ip6_route_output_flags+0xd7/0x170 + bond_ns_send_all+0xde/0x280 [bonding] + bond_ab_arp_probe+0x296/0x320 [bonding] + ? srso_return_thunk+0x5/0x5f + bond_activebackup_arp_mon+0xb4/0x2c0 [bonding] + process_one_work+0x196/0x370 + worker_thread+0x1af/0x320 + ? srso_return_thunk+0x5/0x5f + ? __pfx_worker_thread+0x10/0x10 + kthread+0xe3/0x120 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x199/0x260 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Fix this by adding ipv6_mod_enabled() condition check in the caller. + +Fixes: 4e24be018eb9 ("bonding: add new parameter ns_targets") +Signed-off-by: Qianheng Peng +Signed-off-by: Zhaolong Zhang +Reviewed-by: Hangbin Liu +Link: https://patch.msgid.link/20260707010622.487333-1-zhangzl2013@126.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 7d71cfc2c93741..2919329a8c2006 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -3512,7 +3512,8 @@ static void bond_send_validate(struct bonding *bond, struct slave *slave) + { + bond_arp_send_all(bond, slave); + #if IS_ENABLED(CONFIG_IPV6) +- bond_ns_send_all(bond, slave); ++ if (likely(ipv6_mod_enabled())) ++ bond_ns_send_all(bond, slave); + #endif + } + +-- +2.53.0 + diff --git a/queue-6.12/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch b/queue-6.12/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch new file mode 100644 index 0000000000..ef645cc8e1 --- /dev/null +++ b/queue-6.12/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch @@ -0,0 +1,79 @@ +From 10477eed9635839abaef8dc3e4182fcec8da78bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jul 2026 18:38:56 +0800 +Subject: bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() + +From: Chengfeng Ye + +[ Upstream commit 2d66a033864e27ab8d5e44cb36f31d9d2413bee4 ] + +tcp_bpf_sendmsg() keeps msg_tx across sk_stream_wait_memory(), which +drops and reacquires the socket lock. Its error path tries to decide +whether msg_tx names the local temporary message by comparing it with +the current value of psock->cork. + +This comparison is unsafe when two threads send on the same socket: + + Thread A Thread B + msg_tx = psock->cork + sk_msg_alloc() fails + sk_stream_wait_memory() + releases the socket lock acquires the socket lock + completes the cork + psock->cork = NULL + frees the cork + reacquires the socket lock + msg_tx != psock->cork + sk_msg_free(msg_tx) + +The stale cork is therefore mistaken for the local temporary message +and freed again. KASAN reported: + + BUG: KASAN: slab-use-after-free in sk_msg_free+0x49/0x50 + Read of size 4 at addr ffff88810c908800 by task poc/90 + Call Trace: + sk_msg_free+0x49/0x50 + tcp_bpf_sendmsg+0x14f5/0x1cc0 + __sys_sendto+0x32c/0x3a0 + __x64_sys_sendto+0xdb/0x1b0 + Allocated by task 89: + __kasan_kmalloc+0x8f/0xa0 + tcp_bpf_sendmsg+0x16b3/0x1cc0 + Freed by task 91: + __kasan_slab_free+0x43/0x70 + kfree+0x131/0x3c0 + tcp_bpf_sendmsg+0xec3/0x1cc0 + +msg_tx can only name the stack-local tmp or the shared cork. Check for +tmp directly so a changed psock->cork cannot turn a shared message into +an apparent local one. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Chengfeng Ye +Reviewed-by: Emil Tsalapatis +Reviewed-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/87fr18lmzo.fsf%40cloudflare.com/ +Link: https://lore.kernel.org/netdev/20260719161630.2901208-1-nicoyip.dev%40gmail.com/ [v1] +Link: https://patch.msgid.link/20260724103856.3399001-1-nicoyip.dev@gmail.com +Signed-off-by: Eduard Zingerman +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index b9a58fde9c31b7..132ffc13087f5a 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -590,7 +590,7 @@ static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + wait_for_memory: + err = sk_stream_wait_memory(sk, &timeo); + if (err) { +- if (msg_tx && msg_tx != psock->cork) ++ if (msg_tx == &tmp) + sk_msg_free(sk, msg_tx); + goto out_err; + } +-- +2.53.0 + diff --git a/queue-6.12/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch b/queue-6.12/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch new file mode 100644 index 0000000000..2460af64ae --- /dev/null +++ b/queue-6.12/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch @@ -0,0 +1,55 @@ +From a5a2523b5f1be78f59dff250774abde13dc41c21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jun 2026 18:39:07 +0800 +Subject: btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8 + +From: You-Kai Zheng + +[ Upstream commit b95181f3929ff98949fa9460ca93eccebbf2d7fc ] + +The variable-sized buffer buf in struct btrfs_ioctl_search_args_v2 is +declared as __u64[], but it holds a packed byte stream of search results, +where all offsets into the buffer are in bytes. + +Declaring buf as __u64[] makes it easy for user space to write incorrect +pointer arithmetic: adding a byte offset directly to a __u64 pointer +scales the offset by 8, landing at byte position offset*8 instead of +offset. + +This recently caused an infinite loop in btrfs-progs: the accessor read +all-zero data from misaddressed items, which fed zeroed search keys back +into the ioctl loop and spun forever. The issue was worked around at the +time by disabling TREE_SEARCH_V2 entirely in btrfs-progs (d73e69824854: +"btrfs-progs: temporarily disable usage of v2 of search tree ioctl"). + +The kernel side already treats buf as a byte buffer, so change the +declaration to __u8[] to match the actual semantics and prevent similar +misuse in user space. The change is ABI compatible: both the structure size +and alignment are unchanged. + +Fixes: cc68a8a5a433 ("btrfs: new ioctl TREE_SEARCH_V2") +Reviewed-by: Qu Wenruo +Signed-off-by: You-Kai Zheng +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + include/uapi/linux/btrfs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h +index cdf6ad872149cd..8c5490c6ff99db 100644 +--- a/include/uapi/linux/btrfs.h ++++ b/include/uapi/linux/btrfs.h +@@ -597,7 +597,7 @@ struct btrfs_ioctl_search_args_v2 { + __u64 buf_size; /* in - size of buffer + * out - on EOVERFLOW: needed size + * to store item */ +- __u64 buf[]; /* out - found items */ ++ __u8 buf[]; /* out - found items */ + }; + + /* With a @src_length of zero, the range from @src_offset->EOF is cloned! */ +-- +2.53.0 + diff --git a/queue-6.12/btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch b/queue-6.12/btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch new file mode 100644 index 0000000000..60292ac062 --- /dev/null +++ b/queue-6.12/btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch @@ -0,0 +1,62 @@ +From 2031fcd50b05679c2cc994dd63deb3ddd355bfdb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jun 2026 12:58:05 -0700 +Subject: btrfs: don't propagate EXTENT_FLAG_LOGGING to split extent maps + +From: Leo Martins + +[ Upstream commit 5eff4d5b17fa1950e80bfd1ba43dc0699e61a644 ] + +When btrfs_drop_extent_map_range() splits an extent map, the new split +maps inherit the original map's flags through a local 'flags' variable. +Commit f86f7a75e2fb ("btrfs: use the flags of an extent map to identify +the compression type") changed the EXTENT_FLAG_LOGGING clearing to +operate on em->flags instead of that local 'flags' copy, so a split of +an extent map that is currently being logged wrongly inherits +EXTENT_FLAG_LOGGING. + +The flag is then never cleared on the split, and when it is freed while +still on the inode's modified_extents list (for example by the extent +map shrinker) it trips the WARN_ON(!list_empty(&em->list)) in +btrfs_free_extent_map() and leads to a use-after-free. + +Clear EXTENT_FLAG_LOGGING from the local 'flags' copy used for the +splits and only clear EXTENT_FLAG_PINNED from em->flags, restoring the +behaviour prior to f86f7a75e2fb. + +CC: Jeff Layton +Link: https://lore.kernel.org/all/20260629-btrfs-skip-logging-v1-1-4e3a28c1acaf@kernel.org/ +Fixes: f86f7a75e2fb ("btrfs: use the flags of an extent map to identify the compression type") +Reviewed-by: Jeff Layton +Reviewed-by: Filipe Manana +Signed-off-by: Leo Martins +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_map.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c +index 36af9aa9aab13f..044970109c7b58 100644 +--- a/fs/btrfs/extent_map.c ++++ b/fs/btrfs/extent_map.c +@@ -859,13 +859,13 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, + goto next; + } + +- flags = em->flags; + /* + * In case we split the extent map, we want to preserve the + * EXTENT_FLAG_LOGGING flag on our extent map, but we don't want + * it on the new extent maps. + */ +- em->flags &= ~(EXTENT_FLAG_PINNED | EXTENT_FLAG_LOGGING); ++ flags = em->flags & ~EXTENT_FLAG_LOGGING; ++ em->flags &= ~EXTENT_FLAG_PINNED; + modified = !list_empty(&em->list); + + /* +-- +2.53.0 + diff --git a/queue-6.12/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch b/queue-6.12/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch new file mode 100644 index 0000000000..41af058c82 --- /dev/null +++ b/queue-6.12/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch @@ -0,0 +1,47 @@ +From b0ec4fce930ce765db592696e3f029af5ea783d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 03:17:28 +0000 +Subject: btrfs: free mapping node on duplicate reloc root insert + +From: Guanghui Yang <3497809730@qq.com> + +[ Upstream commit 6a8269b6459ed870a8156c106a0f597383907872 ] + +__add_reloc_root() allocates a mapping_node before inserting it into +rc->reloc_root_tree. If rb_simple_insert() finds an existing entry, it +returns the existing rb_node and leaves the newly allocated node unlinked. + +The error path then returns -EEXIST without freeing the new node. Since +the node was never inserted into reloc_root_tree, the later cleanup in +put_reloc_control() cannot find it either. + +Free the newly allocated node before returning -EEXIST. + +The callers currently assert that -EEXIST should not happen, so this is a +defensive cleanup for an unexpected duplicate insert path. If the path is +ever reached, the local allocation should still be released. + +Fixes: 57a304cfd43b ("btrfs: do not panic in __add_reloc_root") +Reviewed-by: Qu Wenruo +Signed-off-by: Guanghui Yang <3497809730@qq.com> +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index d2a1323e8b1034..8130bfd1abbf2b 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -580,6 +580,7 @@ static int __add_reloc_root(struct btrfs_root *root) + btrfs_err(fs_info, + "Duplicate root found for start=%llu while inserting into relocation tree", + node->bytenr); ++ kfree(node); + return -EEXIST; + } + +-- +2.53.0 + diff --git a/queue-6.12/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch b/queue-6.12/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..17a21918ff --- /dev/null +++ b/queue-6.12/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,48 @@ +From 3f40bd47412e1db03fe5bfe95452422aac13d69b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:17:37 +0800 +Subject: dpaa2-eth: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit b4b201cc93ff70150853aba03e14d314d1980ca0 ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The Ethernet connect path stores that +device in mac->mc_dev and keeps it for the lifetime of the connected MAC +object. + +However, the disconnect path only disconnects and closes the MAC before +freeing the dpaa2_mac object. It does not drop the endpoint device +reference stored in mac->mc_dev, so every successful connect leaks that +device reference when the MAC is later disconnected. + +Drop the endpoint device reference after closing the MAC and before +freeing the dpaa2_mac object. + +Fixes: 719479230893 ("dpaa2-eth: add MAC/PHY support through phylink") +Signed-off-by: Guangshuo Li +Reviewed-by: Ioana Ciornei +Reviewed-by: Ioana Ciornei +Link: https://patch.msgid.link/20260708111738.750391-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index f56a14e09d4a3f..047a09e9e6da2d 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -4721,6 +4721,7 @@ static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-6.12/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch b/queue-6.12/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..f4a5b1d000 --- /dev/null +++ b/queue-6.12/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,46 @@ +From 437752f455a3d7abb414dd96c8b871c80f106ccb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:10:25 +0800 +Subject: dpaa2-switch: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit 4c1eabbef7a1707635652e956e39db1269c3af2b ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The switch port connect path stores +that device in mac->mc_dev and keeps it for the lifetime of the connected +MAC object. + +However, the disconnect path only closes the MAC and frees the dpaa2_mac +object. It does not drop the endpoint device reference stored in +mac->mc_dev, so every successful connect leaks that device reference when +the MAC is later disconnected. + +Drop the endpoint device reference before freeing the dpaa2_mac object. + +Fixes: 84cba72956fd ("dpaa2-switch: integrate the MAC endpoint support") +Signed-off-by: Guangshuo Li +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708111025.749311-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +index 4520c2788b1c56..8469ca27086994 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +@@ -1510,6 +1510,7 @@ static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-6.12/dpll-add-clock-quality-level-attribute-and-op.patch b/queue-6.12/dpll-add-clock-quality-level-attribute-and-op.patch new file mode 100644 index 0000000000..f891e5477d --- /dev/null +++ b/queue-6.12/dpll-add-clock-quality-level-attribute-and-op.patch @@ -0,0 +1,187 @@ +From 39e17ef510c2ecca69971bb546948135181ceccd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Oct 2024 09:11:56 +0100 +Subject: dpll: add clock quality level attribute and op + +From: Jiri Pirko + +[ Upstream commit a1afb959add1fad43cb337448c244ed70bac3109 ] + +In order to allow driver expose quality level of the clock it is +running, introduce a new netlink attr with enum to carry it to the +userspace. Also, introduce an op the dpll netlink code calls into the +driver to obtain the value. + +Signed-off-by: Jiri Pirko +Link: https://patch.msgid.link/20241030081157.966604-2-jiri@resnulli.us +Signed-off-by: Jakub Kicinski +Stable-dep-of: 11c057d23465 ("net/mlx5: Fix MCIA register buffer overflow on 32 dword reads") +Signed-off-by: Sasha Levin +--- + Documentation/netlink/specs/dpll.yaml | 41 +++++++++++++++++++++++++++ + drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++ + include/linux/dpll.h | 4 +++ + include/uapi/linux/dpll.h | 24 ++++++++++++++++ + 4 files changed, 93 insertions(+) + +diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml +index cb5763f79ac2ae..c799d43b8833d1 100644 +--- a/Documentation/netlink/specs/dpll.yaml ++++ b/Documentation/netlink/specs/dpll.yaml +@@ -85,6 +85,36 @@ definitions: + This may happen for example if dpll device was previously + locked on an input pin of type PIN_TYPE_SYNCE_ETH_PORT. + render-max: true ++ - ++ type: enum ++ name: clock-quality-level ++ doc: | ++ level of quality of a clock device. This mainly applies when ++ the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER. ++ The current list is defined according to the table 11-7 contained ++ in ITU-T G.8264/Y.1364 document. One may extend this list freely ++ by other ITU-T defined clock qualities, or different ones defined ++ by another standardization body (for those, please use ++ different prefix). ++ entries: ++ - ++ name: itu-opt1-prc ++ value: 1 ++ - ++ name: itu-opt1-ssu-a ++ - ++ name: itu-opt1-ssu-b ++ - ++ name: itu-opt1-eec1 ++ - ++ name: itu-opt1-prtc ++ - ++ name: itu-opt1-eprtc ++ - ++ name: itu-opt1-eeec ++ - ++ name: itu-opt1-eprc ++ render-max: true + - + type: const + name: temp-divider +@@ -252,6 +282,17 @@ attribute-sets: + name: lock-status-error + type: u32 + enum: lock-status-error ++ - ++ name: clock-quality-level ++ type: u32 ++ enum: clock-quality-level ++ multi-attr: true ++ doc: | ++ Level of quality of a clock device. This mainly applies when ++ the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER. This could ++ be put to message multiple times to indicate possible parallel ++ quality levels (e.g. one specified by ITU option 1 and another ++ one specified by option 2). + - + name: pin + enum-name: dpll_a_pin +diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c +index e3fb08e1578d85..c66f57a5814c8c 100644 +--- a/drivers/dpll/dpll_netlink.c ++++ b/drivers/dpll/dpll_netlink.c +@@ -187,6 +187,27 @@ dpll_msg_add_temp(struct sk_buff *msg, struct dpll_device *dpll, + return 0; + } + ++static int ++dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll, ++ struct netlink_ext_ack *extack) ++{ ++ const struct dpll_device_ops *ops = dpll_device_ops(dpll); ++ DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) = { 0 }; ++ enum dpll_clock_quality_level ql; ++ int ret; ++ ++ if (!ops->clock_quality_level_get) ++ return 0; ++ ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack); ++ if (ret) ++ return ret; ++ for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) ++ if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql)) ++ return -EMSGSIZE; ++ ++ return 0; ++} ++ + static int + dpll_msg_add_pin_prio(struct sk_buff *msg, struct dpll_pin *pin, + struct dpll_pin_ref *ref, +@@ -623,6 +644,9 @@ dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg, + if (ret) + return ret; + ret = dpll_msg_add_lock_status(msg, dpll, extack); ++ if (ret) ++ return ret; ++ ret = dpll_msg_add_clock_quality_level(msg, dpll, extack); + if (ret) + return ret; + ret = dpll_msg_add_mode(msg, dpll, extack); +diff --git a/include/linux/dpll.h b/include/linux/dpll.h +index 3c03b19d939070..5d62e9a0b8243c 100644 +--- a/include/linux/dpll.h ++++ b/include/linux/dpll.h +@@ -28,6 +28,10 @@ struct dpll_device_ops { + struct netlink_ext_ack *extack); + int (*temp_get)(const struct dpll_device *dpll, void *dpll_priv, + s32 *temp, struct netlink_ext_ack *extack); ++ int (*clock_quality_level_get)(const struct dpll_device *dpll, ++ void *dpll_priv, ++ unsigned long *qls, ++ struct netlink_ext_ack *extack); + }; + + struct dpll_pin_ops { +diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h +index 7fa641b3a20adb..12a43bf9a863bc 100644 +--- a/include/uapi/linux/dpll.h ++++ b/include/uapi/linux/dpll.h +@@ -79,6 +79,29 @@ enum dpll_lock_status_error { + DPLL_LOCK_STATUS_ERROR_MAX = (__DPLL_LOCK_STATUS_ERROR_MAX - 1) + }; + ++/** ++ * enum dpll_clock_quality_level - level of quality of a clock device. This ++ * mainly applies when the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER. The ++ * current list is defined according to the table 11-7 contained in ITU-T ++ * G.8264/Y.1364 document. One may extend this list freely by other ITU-T ++ * defined clock qualities, or different ones defined by another ++ * standardization body (for those, please use different prefix). ++ */ ++enum dpll_clock_quality_level { ++ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRC = 1, ++ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_A, ++ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_B, ++ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEC1, ++ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRTC, ++ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRTC, ++ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEEC, ++ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRC, ++ ++ /* private: */ ++ __DPLL_CLOCK_QUALITY_LEVEL_MAX, ++ DPLL_CLOCK_QUALITY_LEVEL_MAX = (__DPLL_CLOCK_QUALITY_LEVEL_MAX - 1) ++}; ++ + #define DPLL_TEMP_DIVIDER 1000 + + /** +@@ -180,6 +203,7 @@ enum dpll_a { + DPLL_A_TEMP, + DPLL_A_TYPE, + DPLL_A_LOCK_STATUS_ERROR, ++ DPLL_A_CLOCK_QUALITY_LEVEL, + + __DPLL_A_MAX, + DPLL_A_MAX = (__DPLL_A_MAX - 1) +-- +2.53.0 + diff --git a/queue-6.12/drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch b/queue-6.12/drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch new file mode 100644 index 0000000000..80ee92a392 --- /dev/null +++ b/queue-6.12/drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch @@ -0,0 +1,42 @@ +From 6eaf8817160c0752cd22c354a7662864e5a46455 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 11:05:21 +0000 +Subject: drivers/virt: pkvm: Fix end calculation in mmio_guard_ioremap_hook() + +From: Mostafa Saleh + +[ Upstream commit 62c740f823a8e47ffe56e45a7472c27cf988e2f6 ] + +Sashiko (locally) reports a logical issues in mmio_guard_ioremap_hook() + +mmio_guard_ioremap_hook() attempts to handle unaligned addresses and +sizes. However, aligning the start address before adding the size, might +shift the end to the page before. + +Fixes: 0f1269495800 ("drivers/virt: pkvm: Intercept ioremap using pKVM MMIO_GUARD hypercall") +Signed-off-by: Mostafa Saleh +Reviewed-by: Catalin Marinas +Tested-by: Aneesh Kumar K.V (Arm) +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c +index 4230b817a80bd8..d66291def0f408 100644 +--- a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c ++++ b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c +@@ -82,8 +82,8 @@ static int mmio_guard_ioremap_hook(phys_addr_t phys, size_t size, + if (protval != PROT_DEVICE_nGnRE && protval != PROT_DEVICE_nGnRnE) + return 0; + ++ end = PAGE_ALIGN(phys + size); + phys = PAGE_ALIGN_DOWN(phys); +- end = phys + PAGE_ALIGN(size); + + while (phys < end) { + const int func_id = ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_FUNC_ID; +-- +2.53.0 + diff --git a/queue-6.12/drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch b/queue-6.12/drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch new file mode 100644 index 0000000000..58ab909110 --- /dev/null +++ b/queue-6.12/drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch @@ -0,0 +1,108 @@ +From 723f9d6f9cf177e0881c832c9051a5e7e7b93a40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 17:07:43 +0200 +Subject: drm/tests: shmem: Set DMA mask to 64-bit in drm_gem_shmem +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit b04a248cfa6cfa1e7dc9ce91cb1eb88b1a70dd69 ] + +drm_gem_shmem_test_purge [1] and drm_gem_shmem_test_get_pages_sgt [2] +intermittently fail on ppc64le and s390x CI systems with a DMA address +overflow: + + DMA addr 0x0000000100307000+4096 overflow (mask ffffffff, bus limit 0) + WARNING: kernel/dma/direct.h:114 dma_direct_map_sg+0x778/0x920 + + drm_gem_shmem_test_purge: ASSERTION FAILED at + drivers/gpu/drm/tests/drm_gem_shmem_test.c:330 + Expected sgt is not error, but is: -5 + +The call chain leading to the failure is: + + drm_gem_shmem_test_purge() / drm_gem_shmem_test_get_pages_sgt() + drm_gem_shmem_get_pages_sgt() + drm_gem_shmem_get_pages_sgt_locked() [drm_gem_shmem_helper.c] + dma_map_sgtable() [mapping.c] + __dma_map_sg_attrs() + dma_direct_map_sg() [direct.c] + dma_direct_map_phys() [kernel/dma/direct.h] + dma_capable() Checks addr against DMA mask + -> FAILS: addr > 0xFFFFFFFF + +The root cause is that KUnit devices are initialized with a 32-bit DMA +mask (DMA_BIT_MASK(32)) in lib/kunit/device.c. On ppc64le and s390x +systems with physical memory above 4GB, page allocations can land at +addresses that exceed this mask. When drm_gem_shmem_get_pages_sgt() +attempts to DMA-map these pages via dma_map_sgtable(), the DMA layer +rejects the mapping because the physical address overflows the 32-bit +mask. + +The failure is intermittent because pages may or may not be allocated +above 4GB on any given run depend on memory pressure. + +Fix by setting a 64-bit DMA mask on the device before calling +drm_gem_shmem_get_pages_sgt() for all tests, following the same pattern +already used in drm_gem_shmem_test_obj_create_private(). + +[1] https://s3.amazonaws.com/arr-cki-prod-trusted-artifacts/trusted-artifacts/2643976103/test_s390x/15128551935/artifacts/jobwatch/logs/recipes/21561049/tasks/220716793/results/1014626315/logs/dmesg.log +[2] https://s3.amazonaws.com/arr-cki-prod-trusted-artifacts/trusted-artifacts/2643976103/test_ppc64le/15128551933/artifacts/jobwatch/logs/recipes/21561041/tasks/220716705/results/1014628163/logs/dmesg.log + +Fixes: 93032ae634d4 ("drm/test: add a test suite for GEM objects backed by shmem") +Closes: https://datawarehouse.cki-project.org/issue/5345 +Closes: https://datawarehouse.cki-project.org/issue/3184 +Assisted-by: Claude:claude-4.6-opus +Reviewed-by: Thomas Zimmermann +Signed-off-by: José Expósito +Link: https://patch.msgid.link/20260703150808.3832-1-jose.exposito89@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/tests/drm_gem_shmem_test.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/tests/drm_gem_shmem_test.c b/drivers/gpu/drm/tests/drm_gem_shmem_test.c +index 0c8c46ca158c06..cc40d63ab809e7 100644 +--- a/drivers/gpu/drm/tests/drm_gem_shmem_test.c ++++ b/drivers/gpu/drm/tests/drm_gem_shmem_test.c +@@ -90,13 +90,9 @@ static void drm_gem_shmem_test_obj_create_private(struct kunit *test) + sg_init_one(sgt->sgl, buf, TEST_SIZE); + + /* +- * Set the DMA mask to 64-bits and map the sgtables +- * otherwise drm_gem_shmem_free will cause a warning +- * on debug kernels. ++ * Map the sgtables otherwise drm_gem_shmem_free will cause a warning on ++ * debug kernels. + */ +- ret = dma_set_mask(drm_dev->dev, DMA_BIT_MASK(64)); +- KUNIT_ASSERT_EQ(test, ret, 0); +- + ret = dma_map_sgtable(drm_dev->dev, sgt, DMA_BIDIRECTIONAL, 0); + KUNIT_ASSERT_EQ(test, ret, 0); + +@@ -342,11 +338,19 @@ static int drm_gem_shmem_test_init(struct kunit *test) + { + struct device *dev; + struct drm_device *drm_dev; ++ int ret; + + /* Allocate a parent device */ + dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + ++ /* ++ * Set the DMA mask to 64-bits to avoid intermittent failures calling ++ * drm_gem_shmem_get_pages_sgt(). ++ */ ++ ret = dma_set_mask(dev, DMA_BIT_MASK(64)); ++ KUNIT_ASSERT_EQ(test, ret, 0); ++ + /* + * The DRM core will automatically initialize the GEM core and create + * a DRM Memory Manager object which provides an address space pool +-- +2.53.0 + diff --git a/queue-6.12/firewire-net-fix-fragmented-datagram-reassembly.patch b/queue-6.12/firewire-net-fix-fragmented-datagram-reassembly.patch new file mode 100644 index 0000000000..cfad89fe93 --- /dev/null +++ b/queue-6.12/firewire-net-fix-fragmented-datagram-reassembly.patch @@ -0,0 +1,99 @@ +From 54be9f7088cbaa363a2d57abeb73135be20c367e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 23:04:54 +0800 +Subject: firewire: net: Fix fragmented datagram reassembly + +From: Ruoyu Wang + +[ Upstream commit d52a13adbb8ccbab99cd3bad36804e87d8b5c052 ] + +fwnet_frag_new() keeps a sorted list of received fragments for a partial +datagram. When a new fragment is adjacent to an existing fragment, the +code checks whether the new fragment also closes the gap to the next or +previous list entry. + +Those neighbor lookups currently assume that the current fragment always +has a real next or previous fragment. At a list edge, the next or +previous entry is the list head, not a struct fwnet_fragment_info. + +The gap checks also compare against the old edge of the current fragment +instead of the edge after adding the new fragment. As a result, a +fragment that bridges two existing ranges may leave two adjacent ranges +unmerged, so fwnet_pd_is_complete() can miss a complete datagram. + +Check for the list head before looking up the neighboring fragment, and +compare the neighbor against the new fragment's far edge when deciding +whether to merge all three ranges. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: c76acec6d551 ("firewire: add IPv4 support") +Signed-off-by: Ruoyu Wang +Link: https://lore.kernel.org/r/20260707150454.2265951-1-ruoyuw560@gmail.com +Signed-off-by: Takashi Sakamoto +Signed-off-by: Sasha Levin +--- + drivers/firewire/net.c | 39 +++++++++++++++++++++------------------ + 1 file changed, 21 insertions(+), 18 deletions(-) + +diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c +index 423ead5fa9c135..a601a0130414ff 100644 +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -298,31 +298,34 @@ static struct fwnet_fragment_info *fwnet_frag_new( + if (fi->offset + fi->len == offset) { + /* The new fragment can be tacked on to the end */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.next, +- struct fwnet_fragment_info, fi_link); +- if (fi->offset + fi->len == fi2->offset) { +- /* glue fragments together */ +- fi->len += len + fi2->len; +- list_del(&fi2->fi_link); +- kfree(fi2); +- } else { +- fi->len += len; ++ if (!list_is_last(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_next_entry(fi, fi_link); ++ if (offset + len == fi2->offset) { ++ /* glue fragments together */ ++ fi->len += len + fi2->len; ++ list_del(&fi2->fi_link); ++ kfree(fi2); ++ ++ return fi; ++ } + } ++ fi->len += len; + + return fi; + } + if (offset + len == fi->offset) { + /* The new fragment can be tacked on to the beginning */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.prev, +- struct fwnet_fragment_info, fi_link); +- if (fi2->offset + fi2->len == fi->offset) { +- /* glue fragments together */ +- fi2->len += fi->len + len; +- list_del(&fi->fi_link); +- kfree(fi); +- +- return fi2; ++ if (!list_is_first(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_prev_entry(fi, fi_link); ++ if (fi2->offset + fi2->len == offset) { ++ /* glue fragments together */ ++ fi2->len += fi->len + len; ++ list_del(&fi->fi_link); ++ kfree(fi); ++ ++ return fi2; ++ } + } + fi->offset = offset; + fi->len += len; +-- +2.53.0 + diff --git a/queue-6.12/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch b/queue-6.12/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch new file mode 100644 index 0000000000..d782ece2eb --- /dev/null +++ b/queue-6.12/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch @@ -0,0 +1,58 @@ +From f960116b1870d94380da00e3410776c2f6096ab6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 23:07:24 +0000 +Subject: gtp: check skb_pull_data() return in gtp1u_send_echo_resp() + +From: Xiang Mei (Microsoft) + +[ Upstream commit cd170f051dba9ac146fabcd1b91726487c0cb9fa ] + +gtp1u_send_echo_resp() ignores skb_pull_data()'s return value. Its +caller gtp1u_udp_encap_recv() only guarantees 16 bytes (udphdr + +gtp1_header), but the pull requests 20 (gtp1_header_long + udphdr). For +a 16-19 byte echo request the pull fails and returns NULL without +advancing skb->data; execution continues, and the following skb_push() +plus the IP header pushed by iptunnel_xmit() move skb->data below +skb->head, tripping skb_under_panic(). + +Fix it by dropping the packet when skb_pull_data() fails. + + skbuff: skb_under_panic: ... + kernel BUG at net/core/skbuff.c:214! + Call Trace: + skb_push (net/core/skbuff.c:2648) + iptunnel_xmit (net/ipv4/ip_tunnel_core.c:82) + gtp_encap_recv (drivers/net/gtp.c:701 drivers/net/gtp.c:808 drivers/net/gtp.c:920) + udp_queue_rcv_one_skb (net/ipv4/udp.c:2388) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 9af41cc33471 ("gtp: Implement GTP echo response") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Link: https://patch.msgid.link/20260710230724.942574-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/gtp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index dc4770e79990f0..b99cab7f10ce7a 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -665,8 +665,9 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb) + return -1; + + /* pull GTP and UDP headers */ +- skb_pull_data(skb, +- sizeof(struct gtp1_header_long) + sizeof(struct udphdr)); ++ if (!skb_pull_data(skb, sizeof(struct gtp1_header_long) + ++ sizeof(struct udphdr))) ++ return -1; + + gtp_pkt = skb_push(skb, sizeof(struct gtp1u_packet)); + memset(gtp_pkt, 0, sizeof(struct gtp1u_packet)); +-- +2.53.0 + diff --git a/queue-6.12/gtp-parse-extension-headers-before-reading-inner-pro.patch b/queue-6.12/gtp-parse-extension-headers-before-reading-inner-pro.patch new file mode 100644 index 0000000000..b8df3fece5 --- /dev/null +++ b/queue-6.12/gtp-parse-extension-headers-before-reading-inner-pro.patch @@ -0,0 +1,67 @@ +From 30fb3ed97458eb0e44723deb8ee6b671be601481 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:22:44 +0800 +Subject: gtp: parse extension headers before reading inner protocol + +From: Zhixing Chen + +[ Upstream commit 96e37e2f618e931aa97af95e707dcdfb1ec41264 ] + +GTPv1-U packets may carry a chain of extension headers before the inner +IP packet. The receive path already parses and skips these extension +headers, but it currently reads the inner protocol before doing so. + +As a result, the first extension header byte is interpreted as the inner +IP version. Packets with extension headers are then dropped before PDP +lookup. + +Parse the extension header chain before calling gtp_inner_proto(), so the +inner protocol is read from the actual inner IP header. + +Fixes: c75fc0b9e5be ("gtp: identify tunnel via GTP device + GTP version + TEID + family") +Signed-off-by: Zhixing Chen +Link: https://patch.msgid.link/20260708042244.120898-1-running910@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/gtp.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index d7f644dfaa8d9e..dc4770e79990f0 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -821,13 +821,17 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) + if (!pskb_may_pull(skb, hdrlen)) + return -1; + ++ gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); ++ ++ if (gtp1->flags & GTP1_F_EXTHDR && ++ gtp_parse_exthdrs(skb, &hdrlen) < 0) ++ return -1; ++ + if (gtp_inner_proto(skb, hdrlen, &inner_proto) < 0) { + netdev_dbg(gtp->dev, "GTP packet does not encapsulate an IP packet\n"); + return -1; + } + +- gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); +- + pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid), + gtp_proto_to_family(inner_proto)); + if (!pctx) { +@@ -835,10 +839,6 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) + return 1; + } + +- if (gtp1->flags & GTP1_F_EXTHDR && +- gtp_parse_exthdrs(skb, &hdrlen) < 0) +- return -1; +- + return gtp_rx(pctx, skb, hdrlen, gtp->role, inner_proto); + } + +-- +2.53.0 + diff --git a/queue-6.12/hinic-remove-unused-ethtool-rss-user-configuration-b.patch b/queue-6.12/hinic-remove-unused-ethtool-rss-user-configuration-b.patch new file mode 100644 index 0000000000..72fb9bb6fd --- /dev/null +++ b/queue-6.12/hinic-remove-unused-ethtool-rss-user-configuration-b.patch @@ -0,0 +1,83 @@ +From c98f150e003bd67559658f2070eb30215f923543 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:53:53 +0800 +Subject: hinic: remove unused ethtool RSS user configuration buffers + +From: Chenguang Zhao + +[ Upstream commit fe0c002928c6749b7f4a726f6f600f6dd70280ea ] + +rss_indir_user and rss_hkey_user are allocated and filled in +__set_rss_rxfh() when the user configures RSS via ethtool, but +nothing ever reads them. hinic_get_rxfh() fetches the state from +the device, and the hardware is programmed from the original +indir/key arguments. These buffers only leaked on driver unload. + +Drop the unused allocations, memcpys, and struct fields. + +Fixes: 4fdc51bb4e92 ("hinic: add support for rss parameters with ethtool") +Signed-off-by: Chenguang Zhao +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260722025353.328179-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/huawei/hinic/hinic_dev.h | 2 -- + .../net/ethernet/huawei/hinic/hinic_ethtool.c | 21 ------------------- + 2 files changed, 23 deletions(-) + +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +index 52ea97c818b8ec..d9ab94910a2a79 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h ++++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +@@ -104,8 +104,6 @@ struct hinic_dev { + u16 num_rss; + u16 rss_limit; + struct hinic_rss_type rss_type; +- u8 *rss_hkey_user; +- s32 *rss_indir_user; + struct hinic_intr_coal_info *rx_intr_coalesce; + struct hinic_intr_coal_info *tx_intr_coalesce; + struct hinic_sriov_info sriov_info; +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +index c559dd4291d306..dba76a768e672a 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c ++++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +@@ -1061,17 +1061,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + int err; + + if (indir) { +- if (!nic_dev->rss_indir_user) { +- nic_dev->rss_indir_user = +- kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE, +- GFP_KERNEL); +- if (!nic_dev->rss_indir_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_indir_user, indir, +- sizeof(u32) * HINIC_RSS_INDIR_SIZE); +- + err = hinic_rss_set_indir_tbl(nic_dev, + nic_dev->rss_tmpl_idx, indir); + if (err) +@@ -1079,16 +1068,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + } + + if (key) { +- if (!nic_dev->rss_hkey_user) { +- nic_dev->rss_hkey_user = +- kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL); +- +- if (!nic_dev->rss_hkey_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE); +- + err = hinic_rss_set_template_tbl(nic_dev, + nic_dev->rss_tmpl_idx, key); + if (err) +-- +2.53.0 + diff --git a/queue-6.12/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch b/queue-6.12/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch new file mode 100644 index 0000000000..6de81994c7 --- /dev/null +++ b/queue-6.12/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch @@ -0,0 +1,42 @@ +From 8e079d86e5d291a3ea23eee54a69c51747f9adc2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 15:05:05 +0200 +Subject: hwmon: (asus-ec-sensors) add missed handle for ENOMEM + +From: Eugene Shalygin + +[ Upstream commit 9813c1f49efeadbcb17e4a41972350ac783f9cac ] + +Add missing return value check in the setup function. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260712130602.1256700-2-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index d08abd1adc0812..ad1a2ff618a38a 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -1064,9 +1064,11 @@ static int asus_ec_probe(struct platform_device *pdev) + if (!nr_count[type]) + continue; + +- asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, +- nr_count[type], type, +- hwmon_attributes[type]); ++ status = asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, ++ nr_count[type], type, ++ hwmon_attributes[type]); ++ if (status) ++ return status; + *ptr_asus_ec_ci++ = asus_ec_hwmon_chan++; + } + +-- +2.53.0 + diff --git a/queue-6.12/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch b/queue-6.12/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch new file mode 100644 index 0000000000..9609ddd6c2 --- /dev/null +++ b/queue-6.12/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch @@ -0,0 +1,60 @@ +From bc7d967cebb45f5e873bb92e90e385d1f335e50c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 13:05:03 +0200 +Subject: hwmon: (asus-ec-sensors) fix EC read intervals + +From: Eugene Shalygin + +[ Upstream commit 60710b2af13b81da71b429d3f8b19dd70310729d ] + +Take INITIAL_JIFFIES into account when setting up next update time. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260712110650.1240071-2-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index 909720fbf2685f..d08abd1adc0812 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -596,7 +596,7 @@ struct ec_sensors_data { + /* sorted list of unique register banks */ + u8 banks[ASUS_EC_MAX_BANK + 1]; + /* in jiffies */ +- unsigned long last_updated; ++ u64 next_update; + struct lock_data lock_data; + /* number of board EC sensors */ + u8 nr_sensors; +@@ -865,13 +865,12 @@ static int get_cached_value_or_update(const struct device *dev, + int sensor_index, + struct ec_sensors_data *state, s32 *value) + { +- if (time_after(jiffies, state->last_updated + HZ)) { ++ if (time_after64(get_jiffies_64(), state->next_update)) { + if (update_ec_sensors(dev, state)) { + dev_err(dev, "update_ec_sensors() failure\n"); + return -EIO; + } +- +- state->last_updated = jiffies; ++ state->next_update = get_jiffies_64() + HZ; + } + + *value = state->sensors[sensor_index].cached_value; +@@ -989,6 +988,7 @@ static int asus_ec_probe(struct platform_device *pdev) + if (!ec_data) + return -ENOMEM; + ++ ec_data->next_update = INITIAL_JIFFIES; + dev_set_drvdata(dev, ec_data); + ec_data->board_info = pboard_info; + +-- +2.53.0 + diff --git a/queue-6.12/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch b/queue-6.12/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch new file mode 100644 index 0000000000..26fd5e4833 --- /dev/null +++ b/queue-6.12/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch @@ -0,0 +1,37 @@ +From 1e12e20c01ae44ba7852e3d2b1e6a169152eb149 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 09:42:07 +0200 +Subject: hwmon: (asus-ec-sensors) fix looping over banks while reading from EC + +From: Eugene Shalygin + +[ Upstream commit e741d13cc2abfc6fccebe2008057aa52e285223e ] + +Do not assume there are only bank 0 and bank 1 available, just use '!=' +for bank comparison. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260711074217.554656-1-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index 483dfb806cc510..909720fbf2685f 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -776,7 +776,7 @@ static int asus_ec_block_read(const struct device *dev, + } + for (ireg = 0; ireg < ec->nr_registers; ireg++) { + reg_bank = register_bank(ec->registers[ireg]); +- if (reg_bank < bank) { ++ if (reg_bank != bank) { + continue; + } + ec_read(register_index(ec->registers[ireg]), +-- +2.53.0 + diff --git a/queue-6.12/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch b/queue-6.12/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch new file mode 100644 index 0000000000..d2a249cd76 --- /dev/null +++ b/queue-6.12/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch @@ -0,0 +1,41 @@ +From 5ac6bcc46c1e703906c22109904d0de785e64f4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 17:52:54 -0700 +Subject: hwmon: (corsair-cpro) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 94c87871b051d7ad758828a805215a2ec194512a ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 40c3a44542257 ("hwmon: add Corsair Commander Pro driver") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-cpro.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c +index b7b911f8359c7f..71e48b3bba60f0 100644 +--- a/drivers/hwmon/corsair-cpro.c ++++ b/drivers/hwmon/corsair-cpro.c +@@ -645,6 +645,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) + + out_hw_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.12/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch b/queue-6.12/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..ba0fa29f9e --- /dev/null +++ b/queue-6.12/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,89 @@ +From 2021aef1d8cb213bbfce7c241ffc00bd8dbf9661 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Apr 2026 12:12:26 +0800 +Subject: hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop + +From: Edward Adam Davis + +[ Upstream commit 9ab8656548cd737b98d0b19c4253aff8d68e97f4 ] + +hid_hw_stop() does not stop the device IO. + +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +corsairpsu_probe(). If the probe operation fails after "io start" has +been initiated, this race condition will result in a uaf vulnerability +[1]. + +CPU0 CPU1 +==== ==== +corsairpsu_probe() + hid_device_io_start() + ... unlock driver_input_lock + hid_hw_stop() + kfree(hidraw) __hid_input_report() + ... acquire driver_input_lock + hid_report_raw_event() + hidraw_report_event() + ... access hidraw's list_lock // trigger uaf + +Consequently, when corsairpsu_probe() fails and hid_hw_stop() needs to +be executed, the io_started flag is first cleared while holding the +driver_input_lock to prevent potential race conditions involving input +reports. + +[1] +BUG: KASAN: slab-use-after-free in rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56 +Call Trace: + hidraw_report_event+0x5d/0x3a0 drivers/hid/hidraw.c:577 + hid_report_raw_event+0x311/0x1730 drivers/hid/hid-core.c:2076 + __hid_input_report drivers/hid/hid-core.c:2152 [inline] + hid_input_report+0x44e/0x580 drivers/hid/hid-core.c:2174 + hid_irq_in+0x47e/0x6d0 drivers/hid/usbhid/hid-core.c:286 + __usb_hcd_giveback_urb+0x3b3/0x5e0 drivers/usb/core/hcd.c:1657 + dummy_timer+0x8a9/0x47d0 drivers/usb/gadget/udc/dummy_hcd.c:2005 + +Allocated by task 10: + hidraw_connect+0x57/0x430 drivers/hid/hidraw.c:606 + hid_connect+0x5bf/0x19d0 drivers/hid/hid-core.c:2277 + hid_hw_start+0xa8/0x120 drivers/hid/hid-core.c:2387 + corsairpsu_probe+0xd9/0x3c0 drivers/hwmon/corsair-psu.c:782 + +Freed by task 10: + hidraw_disconnect+0x4f/0x60 drivers/hid/hidraw.c:662 + hid_disconnect drivers/hid/hid-core.c:2362 [inline] + hid_hw_stop+0x101/0x1e0 drivers/hid/hid-core.c:2407 + corsairpsu_probe+0x327/0x3c0 drivers/hwmon/corsair-psu.c:826 + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Fixes: d115b51e0e56 ("hwmon: add Corsair PSU HID controller driver") +Reported-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9eebf5f6544c5e873858 +Tested-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Link: https://lore.kernel.org/r/tencent_BB7C33EB9EA41B7B4B5F1B8B25C0BA13BB08@qq.com +[groeck: Updated subject and description; + call hid_device_io_stop() only if IO has been started] +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-psu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c +index 93937e1bce196b..4ab73bcef1d125 100644 +--- a/drivers/hwmon/corsair-psu.c ++++ b/drivers/hwmon/corsair-psu.c +@@ -831,6 +831,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id + + fail_and_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + fail_and_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.12/hwmon-gigabyte_waterforce-stop-device-io-before-call.patch b/queue-6.12/hwmon-gigabyte_waterforce-stop-device-io-before-call.patch new file mode 100644 index 0000000000..7c75554dbb --- /dev/null +++ b/queue-6.12/hwmon-gigabyte_waterforce-stop-device-io-before-call.patch @@ -0,0 +1,51 @@ +From 5b65873e6773643e14085ba928f33d37b78bd171 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 17:59:10 -0700 +Subject: hwmon: (gigabyte_waterforce) Stop device IO before calling + hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit ff0c5c53d08274e200b48a4d53aa078265e873cb ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 42ac68e3d4ba0 ("hwmon: Add driver for Gigabyte AORUS Waterforce AIO coolers") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/gigabyte_waterforce.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/hwmon/gigabyte_waterforce.c b/drivers/hwmon/gigabyte_waterforce.c +index 27487e215bddff..4eea05f8b569c2 100644 +--- a/drivers/hwmon/gigabyte_waterforce.c ++++ b/drivers/hwmon/gigabyte_waterforce.c +@@ -371,13 +371,15 @@ static int waterforce_probe(struct hid_device *hdev, const struct hid_device_id + if (IS_ERR(priv->hwmon_dev)) { + ret = PTR_ERR(priv->hwmon_dev); + hid_err(hdev, "hwmon registration failed with %d\n", ret); +- goto fail_and_close; ++ goto fail_and_io_stop; + } + + waterforce_debugfs_init(priv); + + return 0; + ++fail_and_io_stop: ++ hid_device_io_stop(hdev); + fail_and_close: + hid_hw_close(hdev); + fail_and_stop: +-- +2.53.0 + diff --git a/queue-6.12/hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch b/queue-6.12/hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch new file mode 100644 index 0000000000..ff24280926 --- /dev/null +++ b/queue-6.12/hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch @@ -0,0 +1,59 @@ +From 30bcaaaf352bde1fb2d865b59987e7d9d0619f08 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:01:58 -0700 +Subject: hwmon: (nzxt-kraken3) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit f151d0143ac4e086f92f52328ebdbdc50933d8ef ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: f3b4b146eb107 ("hwmon: Add driver for NZXT Kraken X and Z series AIO CPU coolers") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/nzxt-kraken3.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/hwmon/nzxt-kraken3.c b/drivers/hwmon/nzxt-kraken3.c +index d00409bcab93ad..05525406c5fbb5 100644 +--- a/drivers/hwmon/nzxt-kraken3.c ++++ b/drivers/hwmon/nzxt-kraken3.c +@@ -948,7 +948,7 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id + ret = kraken3_init_device(hdev); + if (ret < 0) { + hid_err(hdev, "device init failed with %d\n", ret); +- goto fail_and_close; ++ goto fail_and_stop_io; + } + + ret = kraken3_get_fw_ver(hdev); +@@ -960,13 +960,15 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id + if (IS_ERR(priv->hwmon_dev)) { + ret = PTR_ERR(priv->hwmon_dev); + hid_err(hdev, "hwmon registration failed with %d\n", ret); +- goto fail_and_close; ++ goto fail_and_stop_io; + } + + kraken3_debugfs_init(priv, device_name); + + return 0; + ++fail_and_stop_io: ++ hid_device_io_stop(hdev); + fail_and_close: + hid_hw_close(hdev); + fail_and_stop: +-- +2.53.0 + diff --git a/queue-6.12/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch b/queue-6.12/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..550451afa5 --- /dev/null +++ b/queue-6.12/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,42 @@ +From 518f68695f9a69841e1d31392d972c7b0c6d37e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:00:32 -0700 +Subject: hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 59d104b54b0b42e30fd2a68d24ee5c49dcc54d1e ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 53e68c20aeb1e ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/nzxt-smart2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c +index c2d1173f42fefb..6f8febda4277c9 100644 +--- a/drivers/hwmon/nzxt-smart2.c ++++ b/drivers/hwmon/nzxt-smart2.c +@@ -774,7 +774,7 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev, + + out_hw_close: + hid_hw_close(hdev); +- ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.12/hwmon-occ-validate-poll-response-sensor-blocks.patch b/queue-6.12/hwmon-occ-validate-poll-response-sensor-blocks.patch new file mode 100644 index 0000000000..b5efb830c8 --- /dev/null +++ b/queue-6.12/hwmon-occ-validate-poll-response-sensor-blocks.patch @@ -0,0 +1,118 @@ +From 74a466dc8099ec5b78159d8b8c3d7a6936c34101 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:58:26 +0800 +Subject: hwmon: occ: validate poll response sensor blocks + +From: Pengpeng Hou + +[ Upstream commit 70e76e700fc6c46afb4e17aec099a1ea089b4a22 ] + +The OCC poll response parser walks a counted list of sensor data blocks. +It used the static backing-array capacity as the parse boundary, but a +transport response makes only data_length bytes current and valid. A +truncated response can therefore make the parser consume a block header or +block extent outside the current response. + +Use data_length as the parent boundary, prove the fixed poll header and +each current block header before reading them, and prove the complete block +before advancing. Keep parsed sensor metadata local until the complete +response has passed validation, then publish it. Propagate +malformed-response errors before publishing the OCC as active. + +Fixes: aa195fe49b03 ("hwmon (occ): Parse OCC poll response") +Signed-off-by: Pengpeng Hou +Link: https://lore.kernel.org/r/20260720115826.14813-1-pengpeng@iscas.ac.cn +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/common.c | 38 ++++++++++++++++++++++++++++++-------- + 1 file changed, 30 insertions(+), 8 deletions(-) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index e18e80e832fd3f..175208d712b06e 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -1052,32 +1052,49 @@ static int occ_setup_sensor_attrs(struct occ *occ) + } + + /* only need to do this once at startup, as OCC won't change sensors on us */ +-static void occ_parse_poll_response(struct occ *occ) ++static int occ_parse_poll_response(struct occ *occ) + { + unsigned int i, old_offset, offset = 0, size = 0; ++ u16 data_length; + struct occ_sensor *sensor; +- struct occ_sensors *sensors = &occ->sensors; ++ struct occ_sensors parsed = {}; ++ struct occ_sensors *sensors = &parsed; + struct occ_response *resp = &occ->resp; + struct occ_poll_response *poll = + (struct occ_poll_response *)&resp->data[0]; + struct occ_poll_response_header *header = &poll->header; + struct occ_sensor_data_block *block = &poll->block; + ++ data_length = get_unaligned_be16(&resp->data_length); ++ if (data_length < sizeof(*header) || data_length > OCC_RESP_DATA_BYTES) { ++ dev_err(occ->bus_dev, "invalid OCC poll response length %u\n", ++ data_length); ++ return -EMSGSIZE; ++ } ++ + dev_info(occ->bus_dev, "OCC found, code level: %.16s\n", + header->occ_code_level); + + for (i = 0; i < header->num_sensor_data_blocks; ++i) { + block = (struct occ_sensor_data_block *)((u8 *)block + offset); ++ if (size + sizeof(*header) + sizeof(block->header) > ++ data_length) { ++ dev_err(occ->bus_dev, ++ "truncated OCC sensor block header\n"); ++ return -EMSGSIZE; ++ } ++ + old_offset = offset; + offset = (block->header.num_sensors * + block->header.sensor_length) + sizeof(block->header); +- size += offset; + + /* validate all the length/size fields */ +- if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) { +- dev_warn(occ->bus_dev, "exceeded response buffer\n"); +- return; ++ if (size + sizeof(*header) + offset > data_length) { ++ dev_err(occ->bus_dev, ++ "exceeded OCC poll response length\n"); ++ return -EMSGSIZE; + } ++ size += offset; + + dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n", + old_offset, offset - 1, block->header.eye_catcher, +@@ -1107,6 +1124,9 @@ static void occ_parse_poll_response(struct occ *occ) + + dev_dbg(occ->bus_dev, "Max resp size: %u+%zd=%zd\n", size, + sizeof(*header), size + sizeof(*header)); ++ occ->sensors = parsed; ++ ++ return 0; + } + + int occ_active(struct occ *occ, bool active) +@@ -1138,10 +1158,12 @@ int occ_active(struct occ *occ, bool active) + goto unlock; + } + +- occ->active = true; + occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; +- occ_parse_poll_response(occ); ++ rc = occ_parse_poll_response(occ); ++ if (rc) ++ goto unlock; + ++ occ->active = true; + rc = occ_setup_sensor_attrs(occ); + if (rc) { + dev_err(occ->bus_dev, +-- +2.53.0 + diff --git a/queue-6.12/ice-allow-creating-vfs-when-config_ice_switchdev.patch b/queue-6.12/ice-allow-creating-vfs-when-config_ice_switchdev.patch new file mode 100644 index 0000000000..d46215deab --- /dev/null +++ b/queue-6.12/ice-allow-creating-vfs-when-config_ice_switchdev.patch @@ -0,0 +1,90 @@ +From 0bb2b1d5f94ab865a227c1722d481e8711369a3b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:53:23 -0700 +Subject: ice: allow creating VFs when !CONFIG_ICE_SWITCHDEV + +From: Vincent Chen + +[ Upstream commit 99d0f42b0e5c57e4c02070a908aaff082881293a ] + +Currently ice_eswitch_attach_vf() is called unconditionally in +ice_start_vfs(), which causes VF creation to fail when CONFIG_ICE_SWITCHDEV +is not defined. + +Fix this by adding switchdev mode checks at the call sites before +calling ice_eswitch_attach_vf(), consistent with how +ice_eswitch_attach_sf() is already handled in ice_devlink_port_new(). +This is similar to commit aacca7a83b97 ("ice: allow creating VFs for +!CONFIG_NET_SWITCHDEV") which fixed the same issue for the previous +ice_eswitch_configure() API. + +Fixes: 415db8399d06 ("ice: make representor code generic") +Signed-off-by: Vincent Chen +Reviewed-by: Aleksandr Loktionov +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260717185340.3595286-2-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_eswitch.c | 3 --- + drivers/net/ethernet/intel/ice/ice_sriov.c | 14 ++++++++------ + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 3 ++- + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c +index 32b52ecff04ffb..fa7f1e02bfafed 100644 +--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c ++++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c +@@ -506,9 +506,6 @@ int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf) + struct ice_repr *repr; + int err; + +- if (!ice_is_eswitch_mode_switchdev(pf)) +- return 0; +- + repr = ice_repr_create_vf(vf); + if (IS_ERR(repr)) + return PTR_ERR(repr); +diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c +index 8aabf7749aa5e0..d33a761cfdc04e 100644 +--- a/drivers/net/ethernet/intel/ice/ice_sriov.c ++++ b/drivers/net/ethernet/intel/ice/ice_sriov.c +@@ -596,12 +596,14 @@ static int ice_start_vfs(struct ice_pf *pf) + goto teardown; + } + +- retval = ice_eswitch_attach_vf(pf, vf); +- if (retval) { +- dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d", +- vf->vf_id, retval); +- ice_vf_vsi_release(vf); +- goto teardown; ++ if (ice_is_eswitch_mode_switchdev(pf)) { ++ retval = ice_eswitch_attach_vf(pf, vf); ++ if (retval) { ++ dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d", ++ vf->vf_id, retval); ++ ice_vf_vsi_release(vf); ++ goto teardown; ++ } + } + + set_bit(ICE_VF_STATE_INIT, vf->vf_states); +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +index afa9e7ce463763..71530ae79a87e8 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +@@ -811,7 +811,8 @@ void ice_reset_all_vfs(struct ice_pf *pf) + } + ice_vf_post_vsi_rebuild(vf); + +- ice_eswitch_attach_vf(pf, vf); ++ if (ice_is_eswitch_mode_switchdev(pf)) ++ ice_eswitch_attach_vf(pf, vf); + + mutex_unlock(&vf->cfg_lock); + } +-- +2.53.0 + diff --git a/queue-6.12/ice-fix-lag-recipe-to-profile-association.patch b/queue-6.12/ice-fix-lag-recipe-to-profile-association.patch new file mode 100644 index 0000000000..eac46b16ae --- /dev/null +++ b/queue-6.12/ice-fix-lag-recipe-to-profile-association.patch @@ -0,0 +1,49 @@ +From 8f2ff503eb7454ac2dc4e38138bf351ab22e2a3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:53:28 -0700 +Subject: ice: fix LAG recipe to profile association + +From: Marcin Szycik + +[ Upstream commit d6da9b7d48599db078aea6144997a381f8d90d45 ] + +ice_init_lag() associates recipes to profiles, assuming that Link +Aggregation-related profiles will always have profile ID lower than 70 +(ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER). This value seems arbitrary and +might not always be valid for some versions of DDP package, i.e. LAG +profiles may have profile ID greater than 70. This would lead to +misconfigured switch and LAG not working properly. + +Fix it by checking up to maximum profile ID. + +Fixes: 1e0f9881ef79 ("ice: Flesh out implementation of support for SRIOV on bonded interface") +Signed-off-by: Marcin Szycik +Reviewed-by: Michal Swiatkowski +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Dave Ertman +Reviewed-by: Simon Horman +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260717185340.3595286-7-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_lag.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c +index d132eb4775513c..da1cd103a4d905 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lag.c ++++ b/drivers/net/ethernet/intel/ice/ice_lag.c +@@ -2095,7 +2095,7 @@ int ice_init_lag(struct ice_pf *pf) + goto free_rcp_res; + + /* associate recipes to profiles */ +- for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) { ++ for (n = 0; n < ICE_MAX_NUM_PROFILES; n++) { + err = ice_aq_get_recipe_to_profile(&pf->hw, n, + &recipe_bits, NULL); + if (err) +-- +2.53.0 + diff --git a/queue-6.12/iomap-correct-the-range-of-a-partial-dirty-clear.patch b/queue-6.12/iomap-correct-the-range-of-a-partial-dirty-clear.patch new file mode 100644 index 0000000000..51a66b329d --- /dev/null +++ b/queue-6.12/iomap-correct-the-range-of-a-partial-dirty-clear.patch @@ -0,0 +1,60 @@ +From 61a14b7bc349077470d25d66822d70a22499caf0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:23:21 +0800 +Subject: iomap: correct the range of a partial dirty clear + +From: Zhang Yi + +[ Upstream commit 88c26515313169806a412a362b32a1eca53d21bd ] + +The block range calculation in ifs_clear_range_dirty() is incorrect when +partially clearing a range in a folio. We cannot clear the dirty bit of +the first block or the last block if the start or end offset is not +blocksize-aligned. This has not yet caused any issues since we always +clear a whole folio in iomap_writeback_folio(). + +Fix this by rounding up the first block to blocksize alignment, and +calculate the last block by rounding down (using truncation). Correct +the nr_blks calculation accordingly. + +Fixes: 4ce02c679722 ("iomap: Add per-block dirty state tracking to improve performance") +Signed-off-by: Zhang Yi +Link: https://patch.msgid.link/20260714082325.325163-2-yi.zhang@huaweicloud.com +Reviewed-by: Joanne Koong +Reviewed-by: "Darrick J. Wong" +Reviewed-by: Christoph Hellwig +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/iomap/buffered-io.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index 5f885286b2f4a0..44f5c9889cefcb 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -137,13 +137,17 @@ static void ifs_clear_range_dirty(struct folio *folio, + { + struct inode *inode = folio->mapping->host; + unsigned int blks_per_folio = i_blocks_per_folio(inode, folio); +- unsigned int first_blk = (off >> inode->i_blkbits); +- unsigned int last_blk = (off + len - 1) >> inode->i_blkbits; +- unsigned int nr_blks = last_blk - first_blk + 1; ++ unsigned int first_blk = round_up(off, i_blocksize(inode)) >> ++ inode->i_blkbits; ++ unsigned int last_blk = (off + len) >> inode->i_blkbits; + unsigned long flags; + ++ if (first_blk >= last_blk) ++ return; ++ + spin_lock_irqsave(&ifs->state_lock, flags); +- bitmap_clear(ifs->state, first_blk + blks_per_folio, nr_blks); ++ bitmap_clear(ifs->state, first_blk + blks_per_folio, ++ last_blk - first_blk); + spin_unlock_irqrestore(&ifs->state_lock, flags); + } + +-- +2.53.0 + diff --git a/queue-6.12/iommu-amd-bound-the-early-acpi-hid-map.patch b/queue-6.12/iommu-amd-bound-the-early-acpi-hid-map.patch new file mode 100644 index 0000000000..70849a259b --- /dev/null +++ b/queue-6.12/iommu-amd-bound-the-early-acpi-hid-map.patch @@ -0,0 +1,45 @@ +From d47624d50eb4bf7b7df7babef151d4f68785710a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:46:13 +0800 +Subject: iommu/amd: Bound the early ACPI HID map + +From: Pengpeng Hou + +[ Upstream commit fb80117fddb5b477218dc99bb53911b72c3847f8 ] + +The ivrs_acpihid command-line parser appends entries to a fixed +four-element early_acpihid_map array. Unlike the sibling IOAPIC and HPET +parsers, it does not reject a fifth entry before incrementing the map size. + +Check the capacity at the common found label before parsing the HID and +UID or writing the entry. + +Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter") +Signed-off-by: Pengpeng Hou +Reviewed-by: Ankit Soni +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/init.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index 7fa340281b9fb2..36a814b6c4de56 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -3696,6 +3696,12 @@ static int __init parse_ivrs_acpihid(char *str) + return 1; + + found: ++ if (early_acpihid_map_size == EARLY_MAP_SIZE) { ++ pr_err("Early ACPI HID map overflow - ignoring ivrs_acpihid%s\n", ++ str); ++ return 1; ++ } ++ + p = acpiid; + hid = strsep(&p, ":"); + uid = p; +-- +2.53.0 + diff --git a/queue-6.12/iommu-amd-wait-for-completion-instead-of-returning-e.patch b/queue-6.12/iommu-amd-wait-for-completion-instead-of-returning-e.patch new file mode 100644 index 0000000000..9a04500b44 --- /dev/null +++ b/queue-6.12/iommu-amd-wait-for-completion-instead-of-returning-e.patch @@ -0,0 +1,95 @@ +From afd9aa2e1f5ceabacc7156610fe2e1cd9b3b4c4c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 22:16:22 +0800 +Subject: iommu/amd: Wait for completion instead of returning early in + iommu_completion_wait() + +From: Guanghui Feng + +[ Upstream commit 1e75a8255f11c81fb07e81e5029cfd75804350a0 ] + +need_sync is a per-IOMMU flag shared by all domains and devices behind +that IOMMU. It is set whenever a command is queued with sync == true and +cleared when a completion-wait (CWAIT) command is queued. However, a +cleared need_sync only means that a covering CWAIT has been queued, not +that all previously queued commands have actually completed in hardware. + +iommu_completion_wait() read need_sync locklessly and returned early +when it was false. This breaks the "block until all previously queued +commands have completed" contract in a multi-CPU scenario: + + CPU2: queue inv-B => need_sync = true + CPU1: queue CWAIT(N); need_sync = false; then wait_on_sem(N) + CPU2: read need_sync == false => return 0 (no wait!) + +CPU2 returns without waiting for any sequence number even though its +inv-B may not have completed yet (CWAIT(N), queued after inv-B, has not +been signaled). CPU2 then proceeds to, for example, free page-table +pages while the IOMMU can still walk stale translations, opening a +use-after-free window. This is a logical race in the meaning of the +flag, not a memory-visibility issue, so barriers alone do not help. + +Fix it without losing the optimization of avoiding redundant CWAIT +commands: take iommu->lock before testing need_sync, and when it is +false do not return early but wait for the last allocated sequence +number (cmd_sem_val). Since need_sync == false implies no sync command +was queued after the last CWAIT, that CWAIT is FIFO-ordered after every +not-yet-completed command, so waiting for its sequence number guarantees +all prior commands (possibly queued by another CPU) have completed. The +common path with pending work is unchanged and no extra hardware command +is issued. + +Signed-off-by: Guanghui Feng +Fixes: 815b33fdc279 ("x86/amd-iommu: Cleanup completion-wait handling") +Reviewed-by: Vasant Hegde +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/iommu.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c +index b4052fa9cc76bc..3f109a99a9e401 100644 +--- a/drivers/iommu/amd/iommu.c ++++ b/drivers/iommu/amd/iommu.c +@@ -1424,11 +1424,23 @@ static int iommu_completion_wait(struct amd_iommu *iommu) + int ret; + u64 data; + +- if (!iommu->need_sync) +- return 0; +- + raw_spin_lock_irqsave(&iommu->lock, flags); + ++ if (!iommu->need_sync) { ++ /* ++ * No command has been queued since the last completion-wait. ++ * A concurrent CPU may have already queued that CWAIT and ++ * cleared need_sync; need_sync == false only means a covering ++ * CWAIT is queued, not that all prior commands have completed. ++ * Wait for the last allocated sequence number so that any ++ * command queued before this call (possibly on another CPU) ++ * is guaranteed to have completed before returning. ++ */ ++ data = iommu->cmd_sem_val; ++ raw_spin_unlock_irqrestore(&iommu->lock, flags); ++ return wait_on_sem(iommu, data); ++ } ++ + data = get_cmdsem_val(iommu); + build_completion_wait(&cmd, iommu, data); + +@@ -1438,9 +1450,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu) + if (ret) + return ret; + +- ret = wait_on_sem(iommu, data); +- +- return ret; ++ return wait_on_sem(iommu, data); + } + + static void domain_flush_complete(struct protection_domain *domain) +-- +2.53.0 + diff --git a/queue-6.12/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch b/queue-6.12/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch new file mode 100644 index 0000000000..3163763401 --- /dev/null +++ b/queue-6.12/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch @@ -0,0 +1,43 @@ +From 23a81c2dcf4f32c7a33017a00ad0e4f2c39b70f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:34:10 +0800 +Subject: iommu/intel: Fix out-of-bounds memset in dmar_latency_disable() + +From: Li RongQing + +[ Upstream commit 754f8efe45f87e3a9c6871b645b2f9d46d1b407b ] + +dmar_latency_disable() intends to zero out only the single +latency_statistic entry for the given type, but the memset size was +computed as sizeof(*lstat) * DMAR_LATENCY_NUM, which clears the entire +array starting from &lstat[type]. + +When type > 0, this writes beyond the end of the allocated array, +corrupting adjacent memory. + +Fix by using sizeof(*lstat) to clear only the target entry. + +Fixes: 55ee5e67a59a ("iommu/vt-d: Add common code for dmar latency performance monitors") +Signed-off-by: Li RongQing +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/perf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/intel/perf.c b/drivers/iommu/intel/perf.c +index dceeadc3ee7cdd..6afb55073e9f10 100644 +--- a/drivers/iommu/intel/perf.c ++++ b/drivers/iommu/intel/perf.c +@@ -63,7 +63,7 @@ void dmar_latency_disable(struct intel_iommu *iommu, enum latency_type type) + return; + + spin_lock_irqsave(&latency_lock, flags); +- memset(&lstat[type], 0, sizeof(*lstat) * DMAR_LATENCY_NUM); ++ memset(&lstat[type], 0, sizeof(*lstat)); + spin_unlock_irqrestore(&latency_lock, flags); + } + +-- +2.53.0 + diff --git a/queue-6.12/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch b/queue-6.12/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch new file mode 100644 index 0000000000..5b7d80edd2 --- /dev/null +++ b/queue-6.12/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch @@ -0,0 +1,88 @@ +From 687f1efeb10184c5770b723a2a1b6283a1e19a21 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:42:36 +0000 +Subject: ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup + +From: Eric Dumazet + +[ Upstream commit 853e164c2b321f0711361bc23505aaeb7dc432c3 ] + +When Linux forwards a packet and needs to generate an ICMP error, +icmp_route_lookup() performs a reverse-path relookup. For non-local +destinations, it performs a decoy lookup to find the expected egress +interface (rt2->dst.dev) before validating the path with ip_route_input(). + +Currently, the decoy flow structure (fl4_2) only sets .daddr = fl4_dec.saddr, +leaving .saddr, .flowi4_dscp, .flowi4_proto, .flowi4_mark, .flowi4_oif, +.fl4_sport, .fl4_dport, and .flowi4_uid zeroed out. + +When policy routing rules (such as ip rule add from $SRC lookup 100, or +dscp/fwmark/ipproto/port rules, or VRF bindings) are configured: +1. The decoy lookup fails to match the policy rule because saddr and other + key flow selectors are missing in fl4_2. +2. It resolves a route using the default table instead, returning an incorrect + egress netdev. +3. Passing the wrong netdev to ip_route_input() causes strict reverse-path + filtering (rp_filter=1) to fail, logging false-positive "martian source" + warnings and causing the relookup to fail. + +Fix this by initializing fl4_2 from fl4_dec and: +- Swapping source/destination IP addresses. +- Swapping L4 ports for transport protocols with ports (TCP, UDP, SCTP, DCCP) + so port-based policy routing matches correctly. Non-port protocols (such as + ICMP or GRE) leave the flowi_uli union fields intact to prevent corruption. +- Setting .flowi4_oif = l3mdev_master_ifindex(route_lookup_dev) to ensure + VRF routing tables are respected. +- Setting .flowi4_flags |= FLOWI_FLAG_ANYSRC to allow output route lookups + for non-local source IP addresses. +- Using __ip_route_output_key() instead of ip_route_output_key() for fl4_2 + so that raw FIB routing is used without triggering spurious XFRM policy + lookups on the decoy flow (the actual XFRM lookup is performed later using + fl4_dec). + +Fixes: 415b3334a21a ("icmp: Fix regression in nexthop resolution during replies.") +Reported-by: Muhammad Ziad +Closes: https://lore.kernel.org/netdev/CAOAwikA60AYKdFr_UDLyja3oU4hqyAE7uFZWqum5uRdaQsgRYg@mail.gmail.com/ +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260722104236.2938082-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index 4f55b6041feb49..c7af8b914e13cd 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -540,11 +540,23 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4, + if (IS_ERR(rt2)) + err = PTR_ERR(rt2); + } else { +- struct flowi4 fl4_2 = {}; ++ struct flowi4 fl4_2 = fl4_dec; + unsigned long orefdst; + +- fl4_2.daddr = fl4_dec.saddr; +- rt2 = ip_route_output_key(net, &fl4_2); ++ swap(fl4_2.daddr, fl4_2.saddr); ++ switch (fl4_2.flowi4_proto) { ++ case IPPROTO_TCP: ++ case IPPROTO_UDP: ++ case IPPROTO_SCTP: ++ case IPPROTO_DCCP: ++ swap(fl4_2.fl4_sport, fl4_2.fl4_dport); ++ break; ++ } ++ ++ fl4_2.flowi4_oif = l3mdev_master_ifindex(route_lookup_dev); ++ fl4_2.flowi4_flags |= FLOWI_FLAG_ANYSRC; ++ ++ rt2 = __ip_route_output_key(net, &fl4_2); + if (IS_ERR(rt2)) { + err = PTR_ERR(rt2); + goto relookup_failed; +-- +2.53.0 + diff --git a/queue-6.12/net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch b/queue-6.12/net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch new file mode 100644 index 0000000000..69a965f9ae --- /dev/null +++ b/queue-6.12/net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch @@ -0,0 +1,47 @@ +From 9bb78033fed5da5b0d99f9499f638a4ab9036268 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 13:22:28 +0200 +Subject: net: airoha: fix ETS channel derivation in + airoha_tc_setup_qdisc_ets() + +From: Lorenzo Bianconi + +[ Upstream commit 649ea07fc25a17aa51bff710baac1ab161022a7c ] + +Derive the hardware QoS channel from opt->parent instead of opt->handle +in airoha_tc_setup_qdisc_ets(). The ETS qdisc handle is either +user-specified or auto-allocated by qdisc_alloc_handle() and bears no +relation to the HTB leaf classid that identifies the hardware channel. +HTB derives the channel from TC_H_MIN(opt->classid), and ETS is always +attached as a child of an HTB leaf, so its opt->parent matches that +classid. Using opt->handle instead can cause two ETS qdiscs on different +HTB leaves to collide on the same hardware channel, corrupting scheduler +configuration and stats. + +Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support") +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260720-airoha-ets-handle-fix-v2-1-6f7129ddc06f@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/airoha/airoha_eth.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c +index db4b87c17a2864..58e5791e9cd4d4 100644 +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2803,8 +2803,7 @@ static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port, + if (opt->parent == TC_H_ROOT) + return -EINVAL; + +- channel = TC_H_MAJ(opt->handle) >> 16; +- channel = channel % AIROHA_NUM_QOS_CHANNELS; ++ channel = TC_H_MIN(opt->parent) % AIROHA_NUM_QOS_CHANNELS; + + switch (opt->command) { + case TC_ETS_REPLACE: +-- +2.53.0 + diff --git a/queue-6.12/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch b/queue-6.12/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch new file mode 100644 index 0000000000..269a578c40 --- /dev/null +++ b/queue-6.12/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch @@ -0,0 +1,149 @@ +From feb7077c761c8a9382a3f84671c7911d4b7cea8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:09:21 +0300 +Subject: net: bridge: vlan: fix vlan range dumps starting with pvid + +From: Nikolay Aleksandrov + +[ Upstream commit 43171c97e4714bf601b468401b37732244639c21 ] + +There is a bug in all range dumps that rely on br_vlan_can_enter_range() +when the PVID is a range starting VLAN, all following VLANs that match +its flags can enter the range, but when the range is filled in only the +PVID VLAN is dumped and the rest of the range is discarded because +br_vlan_fill_vids() checks for the PVID flag. Since the PVID VLAN can +be only one, we need to break ranges around it, the best way to do that +consistently for all is to alter br_vlan_can_enter_range() to take into +account the PVID and return false to break the range when it's matched. + +Before the fix: +$ ip l add br0 type bridge vlan_filtering 1 +$ ip l add dumdum type dummy +$ ip l set dumdum master br0 +$ ip l set br0 up +$ ip l set dumdum up +$ bridge vlan add dev dumdum vid 1 pvid untagged master +$ bridge vlan add dev dumdum vid 2 untagged master +$ bridge vlan show dev dumdum # use legacy dump to show all vlans +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged + +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + +VLAN 2 is missing, and if there are more matching VLANs afterwards +they'd be missing too. + +After the fix: +[ same setup steps ] +$ bridge vlan show dev dumdum +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + 2 Egress Untagged + state forwarding mcast_router 1 + +Fixes: 0ab558795184 ("net: bridge: vlan: add rtm range support") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260721140922.682265-2-razor@blackwall.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_netlink_tunnel.c | 3 ++- + net/bridge/br_private.h | 6 ++++-- + net/bridge/br_vlan.c | 10 ++++++---- + net/bridge/br_vlan_options.c | 3 +-- + 4 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/net/bridge/br_netlink_tunnel.c b/net/bridge/br_netlink_tunnel.c +index 71a12da30004c7..a713668ea34f0e 100644 +--- a/net/bridge/br_netlink_tunnel.c ++++ b/net/bridge/br_netlink_tunnel.c +@@ -271,7 +271,8 @@ static void __vlan_tunnel_handle_range(const struct net_bridge_port *p, + if (!*v_start) + goto out_init; + +- if (v && curr_change && br_vlan_can_enter_range(v, *v_end)) { ++ if (v && curr_change && ++ br_vlan_can_enter_range(v, *v_end, br_get_pvid(vg))) { + *v_end = v; + return; + } +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index b2e4e2d04f02b8..3854ea1a515470 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1587,7 +1587,8 @@ void br_vlan_notify(const struct net_bridge *br, + u16 vid, u16 vid_range, + int cmd); + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end); ++ const struct net_bridge_vlan *range_end, ++ u16 pvid); + + void br_vlan_fill_forward_path_pvid(struct net_bridge *br, + struct net_device_path_ctx *ctx, +@@ -1828,7 +1829,8 @@ static inline void br_vlan_notify(const struct net_bridge *br, + } + + static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { + return true; + } +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index 13d6c3f51c29d0..1aa38303529487 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1943,9 +1943,11 @@ void br_vlan_notify(const struct net_bridge *br, + + /* check if v_curr can enter a range ending in range_end */ + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { +- return v_curr->vid - range_end->vid == 1 && ++ return v_curr->vid != pvid && range_end->vid != pvid && ++ v_curr->vid - range_end->vid == 1 && + range_end->flags == v_curr->flags && + br_vlan_opts_eq_range(v_curr, range_end); + } +@@ -2027,8 +2029,8 @@ static int br_vlan_dump_dev(const struct net_device *dev, + idx += range_end->vid - range_start->vid + 1; + + range_start = v; +- } else if (dump_stats || v->vid == pvid || +- !br_vlan_can_enter_range(v, range_end)) { ++ } else if (dump_stats || ++ !br_vlan_can_enter_range(v, range_end, pvid)) { + u16 vlan_flags = br_vlan_flags(range_start, pvid); + + if (!br_vlan_fill_vids(skb, range_start->vid, +diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c +index 8fa89b04ee942d..4a736e005bad7e 100644 +--- a/net/bridge/br_vlan_options.c ++++ b/net/bridge/br_vlan_options.c +@@ -310,8 +310,7 @@ int br_vlan_process_options(const struct net_bridge *br, + continue; + } + +- if (v->vid == pvid || +- !br_vlan_can_enter_range(v, curr_end)) { ++ if (!br_vlan_can_enter_range(v, curr_end, pvid)) { + br_vlan_notify(br, p, curr_start->vid, + curr_end->vid, RTM_NEWVLAN); + curr_start = v; +-- +2.53.0 + diff --git a/queue-6.12/net-dpaa-fix-mode-setting.patch b/queue-6.12/net-dpaa-fix-mode-setting.patch new file mode 100644 index 0000000000..cd89d9729e --- /dev/null +++ b/queue-6.12/net-dpaa-fix-mode-setting.patch @@ -0,0 +1,81 @@ +From eb152d927f89b61a1b39f0a7c4f342b6bbb99c9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 15:20:29 +0200 +Subject: net: dpaa: fix mode setting + +From: Michael Walle + +[ Upstream commit da2c6bcc5e30b1496ac587785dcacf6e849eb6ef ] + +Before converting to the phylink interface, the init function would have +set a non-reserved I/F mode in the maccfg2 register. After converting to +phylink, 0 is written as mode, which is a reserved value (although it's +the hardware default). Without a valid mode, a SGMII link is never +established between the MAC and the PHY and thus .link_up() is never +called which could set the correct mode according to the actual speed. + +Fix it by setting the maximum speed of the phy_interface_t in use in +.mac_config() - just like the driver did before the phylink conversion. + +Fixes: 5d93cfcf7360 ("net: dpaa: Convert to phylink") +Suggested-by: Sean Anderson +Signed-off-by: Michael Walle +Reviewed-by: Sean Anderson +Reviewed-by: Sean Anderson +Link: https://patch.msgid.link/20260717132401.2653252-1-mwalle@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/freescale/fman/fman_dtsec.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +index 3088da7adf0f84..074ca626a51508 100644 +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +@@ -900,22 +900,28 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, + { + struct mac_device *mac_dev = fman_config_to_mac(config); + struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs; +- u32 tmp; ++ u32 ecntrl, maccfg2; ++ ++ maccfg2 = ioread32be(®s->maccfg2); ++ maccfg2 &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); + + switch (state->interface) { + case PHY_INTERFACE_MODE_RMII: +- tmp = DTSEC_ECNTRL_RMM; ++ ecntrl = DTSEC_ECNTRL_RMM; ++ maccfg2 |= MACCFG2_NIBBLE_MODE; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: +- tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; ++ ecntrl = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; ++ maccfg2 |= MACCFG2_BYTE_MODE; + break; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: +- tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; ++ ecntrl = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; ++ maccfg2 |= MACCFG2_BYTE_MODE; + break; + default: + dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n", +@@ -923,7 +929,8 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, + return; + } + +- iowrite32be(tmp, ®s->ecntrl); ++ iowrite32be(ecntrl, ®s->ecntrl); ++ iowrite32be(maccfg2, ®s->maccfg2); + } + + static void dtsec_link_up(struct phylink_config *config, struct phy_device *phy, +-- +2.53.0 + diff --git a/queue-6.12/net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch b/queue-6.12/net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch new file mode 100644 index 0000000000..0b0b6a4b99 --- /dev/null +++ b/queue-6.12/net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch @@ -0,0 +1,92 @@ +From 175d585162d449a0b245f9c3b5c0dc306775d7c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:09:45 +0800 +Subject: net: gre: fix lltx regression for GRE tunnels with SEQ/CSUM + +From: Yun Zhou + +[ Upstream commit 675ed582c1aa4d919dd535490de08c015005c653 ] + +Before commit 00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to +dev->lltx"), NETIF_F_LLTX was set unconditionally in both +__gre_tunnel_init() and ip6gre_tnl_init_features() alongside +GRE_FEATURES: + + dev->features |= GRE_FEATURES | NETIF_F_LLTX; + +When that commit converted NETIF_F_LLTX to the dev->lltx flag, it +placed 'dev->lltx = true' after the SEQ/CSUM early returns instead +of before them. This causes GRE/GRETAP/ip6gre tunnels with SEQ or +CSUM+encap to lose lockless TX, reintroducing _xmit_lock acquisition +around their ndo_start_xmit. Since GRE xmit re-enters the stack via +ip_tunnel_xmit(), holding _xmit_lock risks ABBA deadlock with the +underlay device. + + CPU0 CPU1 + ---- ---- + lock(&qdisc_xmit_lock_key#6); + lock(&qdisc_xmit_lock_key#3); + lock(&qdisc_xmit_lock_key#6); + lock(&qdisc_xmit_lock_key#3); + +Fix by moving dev->lltx = true before the early returns in both +functions, restoring the original unconditional behavior. + +Fixes: 00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to dev->lltx") +Signed-off-by: Yun Zhou +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260713150945.1779628-1-yun.zhou@windriver.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_gre.c | 4 ++-- + net/ipv6/ip6_gre.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index ffad16b023addf..f344e9bb31fbb3 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -1012,6 +1012,8 @@ static void __gre_tunnel_init(struct net_device *dev) + dev->features |= GRE_FEATURES; + dev->hw_features |= GRE_FEATURES; + ++ dev->lltx = true; ++ + /* TCP offload with GRE SEQ is not supported, nor can we support 2 + * levels of outer headers requiring an update. + */ +@@ -1023,8 +1025,6 @@ static void __gre_tunnel_init(struct net_device *dev) + + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; +- +- dev->lltx = true; + } + + static int ipgre_tunnel_init(struct net_device *dev) +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index f1dc1244ade301..dac2e589849df3 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -1483,6 +1483,8 @@ static void ip6gre_tnl_init_features(struct net_device *dev) + dev->features |= GRE6_FEATURES; + dev->hw_features |= GRE6_FEATURES; + ++ dev->lltx = true; ++ + /* TCP offload with GRE SEQ is not supported, nor can we support 2 + * levels of outer headers requiring an update. + */ +@@ -1494,8 +1496,6 @@ static void ip6gre_tnl_init_features(struct net_device *dev) + + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; +- +- dev->lltx = true; + } + + static int ip6gre_tunnel_init_common(struct net_device *dev) +-- +2.53.0 + diff --git a/queue-6.12/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch b/queue-6.12/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch new file mode 100644 index 0000000000..764a8ee4fa --- /dev/null +++ b/queue-6.12/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch @@ -0,0 +1,56 @@ +From e1b7cdd914226edd027f17513472c202767f2024 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 10:12:40 +0000 +Subject: net: hsr: fix memory leak on slave unregistration by removing synced + VLANs + +From: Eric Dumazet + +[ Upstream commit dcf15eaf5641812f1cfc5e96537380132a7da89d ] + +When an HSR master device is brought UP, it auto-adds VLAN 0 via +vlan_vid0_add(), which propagates VID 0 to its slave devices (slave A and B). + +If a slave device is later unregistered while HSR is active (e.g., during +netns cleanup or interface destruction), hsr_del_port() is called to +detach the slave port from the HSR master. However, hsr_del_port() currently +does not delete the VLAN IDs that were synced to the slave device by HSR. + +As a result, the slave device retains a refcount on VID 0 (and any other +synced VLANs). When the slave device is destroyed, its vlan_info / +vlan_vid_info structure remains allocated, leading to a memory leak. + +Fix this by calling vlan_vids_del_by_dev(port->dev, master->dev) in +hsr_del_port() before unlinking slave A or slave B ports, matching the +propagation logic in hsr_ndo_vlan_rx_add_vid() / hsr_ndo_vlan_rx_kill_vid() +and the cleanup behavior in bonding and team drivers. + +Fixes: 1a8a63a5305e ("net: hsr: Add VLAN CTAG filter support") +Reported-by: syzbot+456957213f32970c0762@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/6a4cb6ca.57639fcc.86d58.000b.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Fernando Fernandez Mancera +Reviewed-by: Felix Maurer +Link: https://patch.msgid.link/20260721101240.995597-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_slave.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c +index 70472726c60494..ffc72597295273 100644 +--- a/net/hsr/hsr_slave.c ++++ b/net/hsr/hsr_slave.c +@@ -238,6 +238,8 @@ void hsr_del_port(struct hsr_port *port) + netdev_rx_handler_unregister(port->dev); + if (!port->hsr->fwd_offloaded) + dev_set_promiscuity(port->dev, -1); ++ if (port->type == HSR_PT_SLAVE_A || port->type == HSR_PT_SLAVE_B) ++ vlan_vids_del_by_dev(port->dev, master->dev); + netdev_upper_dev_unlink(port->dev, master->dev); + } + +-- +2.53.0 + diff --git a/queue-6.12/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch b/queue-6.12/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch new file mode 100644 index 0000000000..0958a3456a --- /dev/null +++ b/queue-6.12/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch @@ -0,0 +1,48 @@ +From 68c69fa89d08b656b7dfe330873d6927a6ffc5c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 22:32:30 +0800 +Subject: net: ipv6: fix dif and sdif mismatch in raw6_icmp_error + +From: Li RongQing + +[ Upstream commit 440e274da4d1b93c7df2cb0ce893c3009dd4db55 ] + +In raw6_icmp_error(), raw_v6_match() is called with inet6_iif(skb) passed +to both the 'dif' and 'sdif' arguments. This is a copy-paste or typo error, +as the last argument should represent the secondary interface index (sdif). + +This mismatch breaks ICMPv6 error handling for IPv6 raw sockets in VRF +(Virtual Routing and Forwarding) environments. When a raw socket is bound +to a VRF master device, raw_v6_match() fails to find a match because it is +not given the correct sdif value, causing the socket to miss relevant +ICMPv6 error notifications. + +Fix this by properly passing inet6_sdif(skb) as the last argument to +raw_v6_match(). + +Fixes: 5108ab4bf446fa ("net: ipv6: add second dif to raw socket lookups") +Signed-off-by: Li RongQing +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260717143230.1836-1-lirongqing@baidu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/raw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index d148f1b03c5d09..deaaae63bda0ab 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -348,7 +348,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data; + + if (!raw_v6_match(net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr, +- inet6_iif(skb), inet6_iif(skb))) ++ inet6_iif(skb), inet6_sdif(skb))) + continue; + rawv6_err(sk, skb, type, code, inner_offset, info); + } +-- +2.53.0 + diff --git a/queue-6.12/net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch b/queue-6.12/net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch new file mode 100644 index 0000000000..01c8379be5 --- /dev/null +++ b/queue-6.12/net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch @@ -0,0 +1,68 @@ +From 6bba785bf6585f7229122fff901b53ffc3acba20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 16:25:17 +0900 +Subject: net: mctp i3c: clean up notifier and buses if driver register fails + +From: Myeonghun Pak + +[ Upstream commit 03d1057305ef17ac3f5936ac1580bc9a1a826e14 ] + +mctp_i3c_mod_init() registers the I3C bus notifier and then walks the +existing buses with i3c_for_each_bus_locked(mctp_i3c_bus_add_new, NULL) +before registering the I3C device driver. If i3c_driver_register() +fails, the function returns the error directly, leaving the notifier +registered and every mctp_i3c_bus object created for the existing buses +allocated. The notifier is left pointing into the module that failed to +load and the bus list is leaked. + +Mirror the module exit path on this failure: unregister the notifier and +tear down the buses that were added before returning the error. + +This issue was identified during our ongoing static-analysis research while +reviewing kernel code. + +Fixes: c8755b29b58e ("mctp i3c: MCTP I3C driver") +Co-developed-by: Ijae Kim +Signed-off-by: Ijae Kim +Signed-off-by: Myeonghun Pak +Acked-by: Jeremy Kerr +Link: https://patch.msgid.link/20260715072517.13216-1-mhun512@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/mctp/mctp-i3c.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c +index 47513ebbc68079..fbcd48f1971a45 100644 +--- a/drivers/net/mctp/mctp-i3c.c ++++ b/drivers/net/mctp/mctp-i3c.c +@@ -731,18 +731,21 @@ static __init int mctp_i3c_mod_init(void) + int rc; + + rc = i3c_register_notifier(&mctp_i3c_notifier); +- if (rc < 0) { +- i3c_driver_unregister(&mctp_i3c_driver); ++ if (rc < 0) + return rc; +- } + + i3c_for_each_bus_locked(mctp_i3c_bus_add_new, NULL); + + rc = i3c_driver_register(&mctp_i3c_driver); + if (rc < 0) +- return rc; ++ goto err_unregister_notifier; + + return 0; ++ ++err_unregister_notifier: ++ i3c_unregister_notifier(&mctp_i3c_notifier); ++ mctp_i3c_bus_remove_all(); ++ return rc; + } + + static __exit void mctp_i3c_mod_exit(void) +-- +2.53.0 + diff --git a/queue-6.12/net-mlx5-dpll-add-clock-quality-level-op-implementat.patch b/queue-6.12/net-mlx5-dpll-add-clock-quality-level-op-implementat.patch new file mode 100644 index 0000000000..3c970f37eb --- /dev/null +++ b/queue-6.12/net-mlx5-dpll-add-clock-quality-level-op-implementat.patch @@ -0,0 +1,120 @@ +From ab30e55d57b0dd3f28d45e066d517a55d1851549 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Oct 2024 09:11:57 +0100 +Subject: net/mlx5: DPLL, Add clock quality level op implementation + +From: Jiri Pirko + +[ Upstream commit e2017f27b6f888fb4ebc5c9a6d984bbf2f8b99ff ] + +Use MSECQ register to query clock quality from firmware. Implement the +dpll op and fill-up the quality level value properly. + +Reviewed-by: Arkadiusz Kubalewski +Signed-off-by: Jiri Pirko +Link: https://patch.msgid.link/20241030081157.966604-3-jiri@resnulli.us +Signed-off-by: Jakub Kicinski +Stable-dep-of: 11c057d23465 ("net/mlx5: Fix MCIA register buffer overflow on 32 dword reads") +Signed-off-by: Sasha Levin +--- + .../net/ethernet/mellanox/mlx5/core/dpll.c | 81 +++++++++++++++++++ + 1 file changed, 81 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c +index 904e08de852eac..31142f6cc37293 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c +@@ -166,9 +166,90 @@ static int mlx5_dpll_device_mode_get(const struct dpll_device *dpll, + return 0; + } + ++enum { ++ MLX5_DPLL_SSM_CODE_PRC = 0b0010, ++ MLX5_DPLL_SSM_CODE_SSU_A = 0b0100, ++ MLX5_DPLL_SSM_CODE_SSU_B = 0b1000, ++ MLX5_DPLL_SSM_CODE_EEC1 = 0b1011, ++ MLX5_DPLL_SSM_CODE_PRTC = 0b0010, ++ MLX5_DPLL_SSM_CODE_EPRTC = 0b0010, ++ MLX5_DPLL_SSM_CODE_EEEC = 0b1011, ++ MLX5_DPLL_SSM_CODE_EPRC = 0b0010, ++}; ++ ++enum { ++ MLX5_DPLL_ENHANCED_SSM_CODE_PRC = 0xff, ++ MLX5_DPLL_ENHANCED_SSM_CODE_SSU_A = 0xff, ++ MLX5_DPLL_ENHANCED_SSM_CODE_SSU_B = 0xff, ++ MLX5_DPLL_ENHANCED_SSM_CODE_EEC1 = 0xff, ++ MLX5_DPLL_ENHANCED_SSM_CODE_PRTC = 0x20, ++ MLX5_DPLL_ENHANCED_SSM_CODE_EPRTC = 0x21, ++ MLX5_DPLL_ENHANCED_SSM_CODE_EEEC = 0x22, ++ MLX5_DPLL_ENHANCED_SSM_CODE_EPRC = 0x23, ++}; ++ ++#define __MLX5_DPLL_SSM_COMBINED_CODE(ssm_code, enhanced_ssm_code) \ ++ ((ssm_code) | ((enhanced_ssm_code) << 8)) ++ ++#define MLX5_DPLL_SSM_COMBINED_CODE(type) \ ++ __MLX5_DPLL_SSM_COMBINED_CODE(MLX5_DPLL_SSM_CODE_##type, \ ++ MLX5_DPLL_ENHANCED_SSM_CODE_##type) ++ ++static int mlx5_dpll_clock_quality_level_get(const struct dpll_device *dpll, ++ void *priv, unsigned long *qls, ++ struct netlink_ext_ack *extack) ++{ ++ u8 network_option, ssm_code, enhanced_ssm_code; ++ u32 out[MLX5_ST_SZ_DW(msecq_reg)] = {}; ++ u32 in[MLX5_ST_SZ_DW(msecq_reg)] = {}; ++ struct mlx5_dpll *mdpll = priv; ++ int err; ++ ++ err = mlx5_core_access_reg(mdpll->mdev, in, sizeof(in), ++ out, sizeof(out), MLX5_REG_MSECQ, 0, 0); ++ if (err) ++ return err; ++ network_option = MLX5_GET(msecq_reg, out, network_option); ++ if (network_option != 1) ++ goto errout; ++ ssm_code = MLX5_GET(msecq_reg, out, local_ssm_code); ++ enhanced_ssm_code = MLX5_GET(msecq_reg, out, local_enhanced_ssm_code); ++ ++ switch (__MLX5_DPLL_SSM_COMBINED_CODE(ssm_code, enhanced_ssm_code)) { ++ case MLX5_DPLL_SSM_COMBINED_CODE(PRC): ++ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRC, qls); ++ return 0; ++ case MLX5_DPLL_SSM_COMBINED_CODE(SSU_A): ++ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_A, qls); ++ return 0; ++ case MLX5_DPLL_SSM_COMBINED_CODE(SSU_B): ++ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_B, qls); ++ return 0; ++ case MLX5_DPLL_SSM_COMBINED_CODE(EEC1): ++ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEC1, qls); ++ return 0; ++ case MLX5_DPLL_SSM_COMBINED_CODE(PRTC): ++ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRTC, qls); ++ return 0; ++ case MLX5_DPLL_SSM_COMBINED_CODE(EPRTC): ++ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRTC, qls); ++ return 0; ++ case MLX5_DPLL_SSM_COMBINED_CODE(EEEC): ++ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEEC, qls); ++ return 0; ++ case MLX5_DPLL_SSM_COMBINED_CODE(EPRC): ++ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRC, qls); ++ return 0; ++ } ++errout: ++ NL_SET_ERR_MSG_MOD(extack, "Invalid clock quality level obtained from firmware\n"); ++ return -EINVAL; ++} ++ + static const struct dpll_device_ops mlx5_dpll_device_ops = { + .lock_status_get = mlx5_dpll_device_lock_status_get, + .mode_get = mlx5_dpll_device_mode_get, ++ .clock_quality_level_get = mlx5_dpll_clock_quality_level_get, + }; + + static int mlx5_dpll_pin_direction_get(const struct dpll_pin *pin, +-- +2.53.0 + diff --git a/queue-6.12/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch b/queue-6.12/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch new file mode 100644 index 0000000000..0ffafd41f7 --- /dev/null +++ b/queue-6.12/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch @@ -0,0 +1,51 @@ +From 6cc9cfea73ef188cc7d055a3d746813013e6e9d4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:33:06 +0300 +Subject: net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule + +From: Yael Chemla + +[ Upstream commit d12956d083eb70f2c6d72711aebaf8c2ce21e170 ] + +esw_egress_acl_vlan_create() hardcodes num_dest=0 in its +mlx5_add_flow_rules() call. When invoked from the non-bond path +fwd_dest is NULL and num_dest=0 is correct. When invoked from +esw_acl_egress_ofld_rules_create() during a bond event, fwd_dest is +non-NULL and flow_act.action carries MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, +but _mlx5_add_flow_rules() rejects a non-NULL dest pointer paired with +dest_num<=0 and returns -EINVAL. The error propagates as +"configure slave vport egress fwd, err(-22)". The passive vport's egress +ACL table ends up with its flow groups allocated but no FTEs, so +prio-tagged packets are not popped and bond failover is broken on +prio_tag_required devices. + +Fix by passing fwd_dest ? 1 : 0 as num_dest to match the actual number +of destinations supplied. + +Fixes: bf773dc0e6d5 ("net/mlx5: E-Switch, Introduce APIs to enable egress acl forward-to-vport rule") +Signed-off-by: Yael Chemla +Reviewed-by: Cosmin Ratiu +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20260717073306.1242399-1-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +index d599e50af346be..fc545bfb54de76 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +@@ -71,7 +71,7 @@ int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw, + flow_act.action = flow_action; + vport->egress.allowed_vlan = + mlx5_add_flow_rules(vport->egress.acl, spec, +- &flow_act, fwd_dest, 0); ++ &flow_act, fwd_dest, fwd_dest ? 1 : 0); + if (IS_ERR(vport->egress.allowed_vlan)) { + err = PTR_ERR(vport->egress.allowed_vlan); + esw_warn(esw->dev, +-- +2.53.0 + diff --git a/queue-6.12/net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch b/queue-6.12/net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch new file mode 100644 index 0000000000..b3504efccb --- /dev/null +++ b/queue-6.12/net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch @@ -0,0 +1,93 @@ +From 47d91ab96fea67c3c2b51cf4b1ed9ee12686a5e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:23:38 +0300 +Subject: net/mlx5: Fix MCIA register buffer overflow on 32 dword reads + +From: Gal Pressman + +[ Upstream commit 11c057d23465c7a5817a7284c896d19d54c0b616 ] + +The MCIA register can return up to 32 dwords (128 bytes) when the device +advertises the mcia_32dwords capability, but struct +mlx5_ifc_mcia_reg_bits only defines dword_0..11, leaving room for just +12 dwords (48 bytes) of data. + +mlx5_query_mcia() clamps the read size to mlx5_mcia_max_bytes() and then +memcpy()s that many bytes out of the register, potentially reading past +the end of the 'out' buffer. On kernels built with FORTIFY_SOURCE this +is caught as a buffer overflow while reading the module EEPROM via +ethtool: + + detected buffer overflow in memcpy + kernel BUG at lib/string_helpers.c:1048! + RIP: 0010:fortify_panic+0x13/0x20 + Call Trace: + mlx5_query_mcia.isra.0+0x200/0x210 [mlx5_core] + mlx5_query_module_eeprom_by_page+0x4a/0xa0 [mlx5_core] + mlx5e_get_module_eeprom_by_page+0xbb/0x120 [mlx5_core] + eeprom_prepare_data+0xf3/0x170 + ethnl_default_doit+0xf1/0x3b0 + +Extend the mcia_reg layout to 32 dwords. + +Fixes: 271907ee2f29 ("net/mlx5: Query the maximum MCIA register read size from firmware") +Signed-off-by: Gal Pressman +Reviewed-by: Alex Lazar +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20260717072338.1240582-1-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/port.c | 4 ++-- + include/linux/mlx5/mlx5_ifc.h | 13 +------------ + 2 files changed, 3 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c +index c0f189b8cd1ad6..1a60a989b16349 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c +@@ -314,7 +314,7 @@ static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num, + return -EIO; + } + +- ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); ++ ptr = MLX5_ADDR_OF(mcia_reg, out, dwords); + + *module_id = ptr[0]; + +@@ -397,7 +397,7 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev, + if (*status) + return -EIO; + +- ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); ++ ptr = MLX5_ADDR_OF(mcia_reg, out, dwords); + memcpy(data, ptr, size); + + return size; +diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h +index 6ea35c8ce00fb4..c0864fa3883b84 100644 +--- a/include/linux/mlx5/mlx5_ifc.h ++++ b/include/linux/mlx5/mlx5_ifc.h +@@ -11803,18 +11803,7 @@ struct mlx5_ifc_mcia_reg_bits { + + u8 reserved_at_60[0x20]; + +- u8 dword_0[0x20]; +- u8 dword_1[0x20]; +- u8 dword_2[0x20]; +- u8 dword_3[0x20]; +- u8 dword_4[0x20]; +- u8 dword_5[0x20]; +- u8 dword_6[0x20]; +- u8 dword_7[0x20]; +- u8 dword_8[0x20]; +- u8 dword_9[0x20]; +- u8 dword_10[0x20]; +- u8 dword_11[0x20]; ++ u8 dwords[0x400]; + }; + + struct mlx5_ifc_dcbx_param_bits { +-- +2.53.0 + diff --git a/queue-6.12/net-mlx5-refactor-eeprom-query-error-handling-to-ret.patch b/queue-6.12/net-mlx5-refactor-eeprom-query-error-handling-to-ret.patch new file mode 100644 index 0000000000..db76940b6a --- /dev/null +++ b/queue-6.12/net-mlx5-refactor-eeprom-query-error-handling-to-ret.patch @@ -0,0 +1,235 @@ +From d6ba827bb152840cf1253b1bbae542ecbbae292f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 23:42:05 +0200 +Subject: net/mlx5: Refactor EEPROM query error handling to return status + separately + +From: Gal Pressman + +[ Upstream commit 2e4c44b12f4da60d3e8dcbc1ccf38bb28a878050 ] + +Matthew and Jakub reported [1] issues where inventory automation tools +are calling EEPROM query repeatedly on a port that doesn't have an SFP +connected, resulting in millions of error prints. + +Move MCIA register status extraction from the query functions to the +callers, allowing use of extack reporting instead of a dmesg print when +using the netlink API. + +[1] https://lore.kernel.org/netdev/20251028194011.39877-1-mattc@purestorage.com/ + +Cc: Matthew W Carlis +Signed-off-by: Gal Pressman +Reviewed-by: Jianbo Liu +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1763415729-1238421-2-git-send-email-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 11c057d23465 ("net/mlx5: Fix MCIA register buffer overflow on 32 dword reads") +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlx5/core/en_ethtool.c | 19 +++++----- + .../ethernet/mellanox/mlx5/core/mlx5_core.h | 4 +-- + .../net/ethernet/mellanox/mlx5/core/port.c | 35 +++++++++---------- + 3 files changed, 30 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +index d278542677efb2..026f2867b84900 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +@@ -1912,7 +1912,7 @@ static int mlx5e_get_module_info(struct net_device *netdev, + int size_read = 0; + u8 data[4] = {0}; + +- size_read = mlx5_query_module_eeprom(dev, 0, 2, data); ++ size_read = mlx5_query_module_eeprom(dev, 0, 2, data, NULL); + if (size_read < 2) + return -EIO; + +@@ -1954,6 +1954,7 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + int offset = ee->offset; + int size_read; ++ u8 status = 0; + int i = 0; + + if (!ee->len) +@@ -1963,15 +1964,15 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev, + + while (i < ee->len) { + size_read = mlx5_query_module_eeprom(mdev, offset, ee->len - i, +- data + i); +- ++ data + i, &status); + if (!size_read) + /* Done reading */ + return 0; + + if (size_read < 0) { +- netdev_err(priv->netdev, "%s: mlx5_query_eeprom failed:0x%x\n", +- __func__, size_read); ++ netdev_err(netdev, ++ "%s: mlx5_query_eeprom failed:0x%x, status %u\n", ++ __func__, size_read, status); + return size_read; + } + +@@ -1991,6 +1992,7 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + u8 *data = page_data->data; + int size_read; ++ u8 status = 0; + int i = 0; + + if (!page_data->length) +@@ -2004,7 +2006,8 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev, + query.page = page_data->page; + while (i < page_data->length) { + query.size = page_data->length - i; +- size_read = mlx5_query_module_eeprom_by_page(mdev, &query, data + i); ++ size_read = mlx5_query_module_eeprom_by_page(mdev, &query, ++ data + i, &status); + + /* Done reading, return how many bytes was read */ + if (!size_read) +@@ -2013,8 +2016,8 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev, + if (size_read < 0) { + NL_SET_ERR_MSG_FMT_MOD( + extack, +- "Query module eeprom by page failed, read %u bytes, err %d", +- i, size_read); ++ "Query module eeprom by page failed, read %u bytes, err %d, status %u", ++ i, size_read, status); + return size_read; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +index 1ca75f1815ef64..2e152f8571c7df 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +@@ -342,11 +342,11 @@ int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable); + void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported, + bool *enabled); + int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, +- u16 offset, u16 size, u8 *data); ++ u16 offset, u16 size, u8 *data, u8 *status); + int + mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev, + struct mlx5_module_eeprom_query_params *params, +- u8 *data); ++ u8 *data, u8 *status); + + int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out); + int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c +index 79c477e05e46cf..c0f189b8cd1ad6 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c +@@ -289,11 +289,11 @@ int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) + } + + static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num, +- u8 *module_id) ++ u8 *module_id, u8 *status) + { + u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {}; + u32 out[MLX5_ST_SZ_DW(mcia_reg)]; +- int err, status; ++ int err; + u8 *ptr; + + MLX5_SET(mcia_reg, in, i2c_device_address, MLX5_I2C_ADDR_LOW); +@@ -308,12 +308,12 @@ static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num, + if (err) + return err; + +- status = MLX5_GET(mcia_reg, out, status); +- if (status) { +- mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n", +- status); ++ if (MLX5_GET(mcia_reg, out, status)) { ++ if (status) ++ *status = MLX5_GET(mcia_reg, out, status); + return -EIO; + } ++ + ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); + + *module_id = ptr[0]; +@@ -370,13 +370,14 @@ static int mlx5_mcia_max_bytes(struct mlx5_core_dev *dev) + } + + static int mlx5_query_mcia(struct mlx5_core_dev *dev, +- struct mlx5_module_eeprom_query_params *params, u8 *data) ++ struct mlx5_module_eeprom_query_params *params, ++ u8 *data, u8 *status) + { + u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {}; + u32 out[MLX5_ST_SZ_DW(mcia_reg)]; +- int status, err; + void *ptr; + u16 size; ++ int err; + + size = min_t(int, params->size, mlx5_mcia_max_bytes(dev)); + +@@ -392,12 +393,9 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev, + if (err) + return err; + +- status = MLX5_GET(mcia_reg, out, status); +- if (status) { +- mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n", +- status); ++ *status = MLX5_GET(mcia_reg, out, status); ++ if (*status) + return -EIO; +- } + + ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); + memcpy(data, ptr, size); +@@ -406,7 +404,7 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev, + } + + int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, +- u16 offset, u16 size, u8 *data) ++ u16 offset, u16 size, u8 *data, u8 *status) + { + struct mlx5_module_eeprom_query_params query = {0}; + u8 module_id; +@@ -416,7 +414,8 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, + if (err) + return err; + +- err = mlx5_query_module_id(dev, query.module_number, &module_id); ++ err = mlx5_query_module_id(dev, query.module_number, &module_id, ++ status); + if (err) + return err; + +@@ -442,12 +441,12 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, + query.size = size; + query.offset = offset; + +- return mlx5_query_mcia(dev, &query, data); ++ return mlx5_query_mcia(dev, &query, data, status); + } + + int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev, + struct mlx5_module_eeprom_query_params *params, +- u8 *data) ++ u8 *data, u8 *status) + { + int err; + +@@ -461,7 +460,7 @@ int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev, + return -EINVAL; + } + +- return mlx5_query_mcia(dev, params, data); ++ return mlx5_query_mcia(dev, params, data, status); + } + + static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc, +-- +2.53.0 + diff --git a/queue-6.12/net-mlx5-remove-newline-at-the-end-of-a-netlink-erro.patch b/queue-6.12/net-mlx5-remove-newline-at-the-end-of-a-netlink-erro.patch new file mode 100644 index 0000000000..c7d18e0f33 --- /dev/null +++ b/queue-6.12/net-mlx5-remove-newline-at-the-end-of-a-netlink-erro.patch @@ -0,0 +1,99 @@ +From c892af1956e0be5ec56fa43a965b7a1957b622de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Feb 2025 11:39:01 +0200 +Subject: net/mlx5: Remove newline at the end of a netlink error message + +From: Gal Pressman + +[ Upstream commit 3a2295ff3f00d44c97baec37c43b6ede3eea9df9 ] + +Netlink error messages should not have a newline at the end of the +string. + +Reviewed-by: Tariq Toukan +Signed-off-by: Gal Pressman +Reviewed-by: Michal Swiatkowski +Link: https://patch.msgid.link/20250226093904.6632-3-gal@nvidia.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 11c057d23465 ("net/mlx5: Fix MCIA register buffer overflow on 32 dword reads") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/dpll.c | 2 +- + drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c | 2 +- + drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 2 +- + drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c | 6 +++--- + 4 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c +index 31142f6cc37293..1e5522a194839c 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c +@@ -242,7 +242,7 @@ static int mlx5_dpll_clock_quality_level_get(const struct dpll_device *dpll, + return 0; + } + errout: +- NL_SET_ERR_MSG_MOD(extack, "Invalid clock quality level obtained from firmware\n"); ++ NL_SET_ERR_MSG_MOD(extack, "Invalid clock quality level obtained from firmware"); + return -EINVAL; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c +index b9cf79e2712440..7a18a469961db8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c +@@ -140,7 +140,7 @@ static int mlx5e_tc_tun_parse_vxlan_gbp_option(struct mlx5e_priv *priv, + gbp_mask = (u32 *)&enc_opts.mask->data[0]; + + if (*gbp_mask & ~VXLAN_GBP_MASK) { +- NL_SET_ERR_MSG_FMT_MOD(extack, "Wrong VxLAN GBP mask(0x%08X)\n", *gbp_mask); ++ NL_SET_ERR_MSG_FMT_MOD(extack, "Wrong VxLAN GBP mask(0x%08X)", *gbp_mask); + return -EINVAL; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +index 1f55c5a7edf31b..d278542677efb2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +@@ -2013,7 +2013,7 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev, + if (size_read < 0) { + NL_SET_ERR_MSG_FMT_MOD( + extack, +- "Query module eeprom by page failed, read %u bytes, err %d\n", ++ "Query module eeprom by page failed, read %u bytes, err %d", + i, size_read); + return size_read; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +index c5ea1d1d2b035c..282cef59e6173f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +@@ -1861,7 +1861,7 @@ int mlx5_esw_bridge_port_mdb_add(struct net_device *dev, u16 vport_num, u16 esw_ + "Failed to lookup bridge port to add MDB (MAC=%pM,vport=%u)\n", + addr, vport_num); + NL_SET_ERR_MSG_FMT_MOD(extack, +- "Failed to lookup bridge port to add MDB (MAC=%pM,vport=%u)\n", ++ "Failed to lookup bridge port to add MDB (MAC=%pM,vport=%u)", + addr, vport_num); + return -EINVAL; + } +@@ -1874,7 +1874,7 @@ int mlx5_esw_bridge_port_mdb_add(struct net_device *dev, u16 vport_num, u16 esw_ + "Failed to lookup bridge port vlan metadata to create MDB (MAC=%pM,vid=%u,vport=%u)\n", + addr, vid, vport_num); + NL_SET_ERR_MSG_FMT_MOD(extack, +- "Failed to lookup vlan metadata for MDB (MAC=%pM,vid=%u,vport=%u)\n", ++ "Failed to lookup vlan metadata for MDB (MAC=%pM,vid=%u,vport=%u)", + addr, vid, vport_num); + return -EINVAL; + } +@@ -1882,7 +1882,7 @@ int mlx5_esw_bridge_port_mdb_add(struct net_device *dev, u16 vport_num, u16 esw_ + + err = mlx5_esw_bridge_port_mdb_attach(dev, port, addr, vid); + if (err) { +- NL_SET_ERR_MSG_FMT_MOD(extack, "Failed to add MDB (MAC=%pM,vid=%u,vport=%u)\n", ++ NL_SET_ERR_MSG_FMT_MOD(extack, "Failed to add MDB (MAC=%pM,vid=%u,vport=%u)", + addr, vid, vport_num); + return err; + } +-- +2.53.0 + diff --git a/queue-6.12/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch b/queue-6.12/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch new file mode 100644 index 0000000000..ea417bf46e --- /dev/null +++ b/queue-6.12/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch @@ -0,0 +1,46 @@ +From b8869c0e91d680e9a048f2b2a80323561c3a2bf7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:25 +0300 +Subject: net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation + +From: Alexei Lazar + +[ Upstream commit 9173e1d3c7c7d49a71eee813091f9e834ec7cee5 ] + +Credit Based (CB) TSA is not supported by the mlx5 driver, so reject +any configurations that specify it. + +Fixes: 08fb1dacdd76 ("net/mlx5e: Support DCBNL IEEE ETS") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-3-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index d74ff20f825954..98ca8f486d52cd 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -309,6 +309,14 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev, + } + } + ++ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { ++ if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_CB_SHAPER) { ++ netdev_err(netdev, ++ "Failed to validate ETS: CB Shaper is not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ + /* Validate Bandwidth Sum */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { +-- +2.53.0 + diff --git a/queue-6.12/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch b/queue-6.12/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch new file mode 100644 index 0000000000..941103ab0e --- /dev/null +++ b/queue-6.12/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch @@ -0,0 +1,53 @@ +From 634dabc4aec875df7bfbf63e63ad68401f82d816 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:24 +0300 +Subject: net/mlx5e: Report zero bandwidth for non-ETS traffic classes + +From: Alexei Lazar + +[ Upstream commit ffb1873b2df11945b8c395e859169248675c91c5 ] + +The IEEE 802.1Qaz standard defines that bandwidth allocation percentages +only apply to Enhanced Transmission Selection (ETS) traffic classes. +For STRICT and VENDOR transmission selection algorithms, bandwidth +percentage values are not applicable. + +Currently for non-ETS 100 bandwidth is being reported for all traffic +classes in the get operation due to hardware limitation, regardless of +their TSA type. + +Fix this by reporting 0 for non-ETS traffic classes. + +Fixes: 820c2c5e773d ("net/mlx5e: Read ETS settings directly from firmware") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-2-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 84e700777941ec..d74ff20f825954 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -158,6 +158,13 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, + } + memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa)); + ++ /* Report 0 for non ETS TSA */ ++ for (i = 0; i < ets->ets_cap; i++) { ++ if (ets->tc_tx_bw[i] == MLX5E_MAX_BW_ALLOC && ++ priv->dcbx.tc_tsa[i] != IEEE_8021QAZ_TSA_ETS) ++ ets->tc_tx_bw[i] = 0; ++ } ++ + return err; + } + +-- +2.53.0 + diff --git a/queue-6.12/net-packet-avoid-fanout-hook-re-registration-after-u.patch b/queue-6.12/net-packet-avoid-fanout-hook-re-registration-after-u.patch new file mode 100644 index 0000000000..15e1776825 --- /dev/null +++ b/queue-6.12/net-packet-avoid-fanout-hook-re-registration-after-u.patch @@ -0,0 +1,61 @@ +From fc90fd6a5b8164f41a392054f8cb605ae1a5fad9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:44:37 +0000 +Subject: net/packet: avoid fanout hook re-registration after unregister + +From: David Lee + +[ Upstream commit 50aff80475abd3533eef4320477037e6fcc6b56e ] + +packet_set_ring() temporarily detaches a socket from packet delivery while +reconfiguring its ring. It records the previous running state, clears +po->num, unregisters the protocol hook when needed, drops po->bind_lock, +and later restores po->num and re-registers the hook from the saved +was_running value. + +That unlocked window can race with NETDEV_UNREGISTER. The notifier can +observe the socket as not running, skip __unregister_prot_hook(), and +invalidate the per-socket binding by setting po->ifindex to -1 and clearing +po->prot_hook.dev. A one-member fanout group can still retain its shared +fanout hook device pointer. When packet_set_ring() resumes, re-registering +solely from the stale was_running state can re-add the fanout hook after +the device has been unregistered. + +Treat po->ifindex == -1 as an invalidated binding after reacquiring +po->bind_lock. This is distinct from ifindex 0, the normal +unbound/wildcard state: ifindex -1 marks an existing device binding that +was invalidated when the device was unregistered. Restore po->num as +before, but do not re-register the hook if device unregister already +detached the socket. + +Fixes: dc99f600698d ("packet: Add fanout support.") +Link: https://lore.kernel.org/netdev/20260701113947.23180-1-david.lee@trailofbits.com/ +Signed-off-by: David Lee +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260707104440.833129-1-david.lee@trailofbits.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 562c860cca577a..c5900752522652 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -4604,7 +4604,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + + spin_lock(&po->bind_lock); + WRITE_ONCE(po->num, num); +- if (was_running) ++ /* ++ * NETDEV_UNREGISTER may have invalidated the binding while bind_lock ++ * was dropped above. Do not re-add a fanout hook to a dead device. ++ */ ++ if (was_running && READ_ONCE(po->ifindex) != -1) + register_prot_hook(sk); + + spin_unlock(&po->bind_lock); +-- +2.53.0 + diff --git a/queue-6.12/net-qrtr-restrict-socket-creation-to-the-initial-net.patch b/queue-6.12/net-qrtr-restrict-socket-creation-to-the-initial-net.patch new file mode 100644 index 0000000000..b5e441ca65 --- /dev/null +++ b/queue-6.12/net-qrtr-restrict-socket-creation-to-the-initial-net.patch @@ -0,0 +1,63 @@ +From 21147013febf9fc28d3a2ef237da6af769a055a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 12:43:19 -0300 +Subject: net: qrtr: restrict socket creation to the initial network namespace + +From: Aldo Ariel Panzardo + +[ Upstream commit 3b536db8fb32da9e9c62f2bb45e2e319331f0426 ] + +QRTR keeps its entire port and node state in module-global variables +that are not partitioned per network namespace: qrtr_local_nid is a +single global node id (always 1) and qrtr_ports is a single global +xarray. qrtr_port_lookup() and qrtr_local_enqueue() operate on that +global state with no network-namespace check, and qrtr_create() places +no restriction on the namespace a socket is created in. + +As a result an unprivileged process that creates an AF_QIPCRTR socket +in a separate network namespace, e.g. via +unshare(CLONE_NEWUSER | CLONE_NEWNET), can send QRTR datagrams - +including control-plane messages such as QRTR_TYPE_NEW_SERVER - to QRTR +sockets owned by another namespace, and vice versa. The receiving +socket sees such a message as coming from node id 1, indistinguishable +from a legitimate local client, breaking the isolation that network +namespaces are expected to provide. + +QRTR is a transport to global hardware endpoints (the modem and other +remote processors) and has no per-namespace semantics; its in-kernel +name service already creates its socket in init_net only. Confine the +socket family to the initial network namespace, as other +non-namespace-aware socket families do (see llc_ui_create() and the +ieee802154 socket code). + +Fixes: bdabad3e363d ("net: Add Qualcomm IPC router") +Signed-off-by: Aldo Ariel Panzardo +Link: https://patch.msgid.link/20260716154319.3297699-1-qwe.aldo@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/qrtr/af_qrtr.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c +index 305523cebe3baa..fcd24a7df3f00d 100644 +--- a/net/qrtr/af_qrtr.c ++++ b/net/qrtr/af_qrtr.c +@@ -1261,6 +1261,14 @@ static int qrtr_create(struct net *net, struct socket *sock, + if (sock->type != SOCK_DGRAM) + return -EPROTOTYPE; + ++ /* QRTR keeps its port and node state in module-global variables that ++ * are not partitioned per network namespace, and the in-kernel name ++ * service only operates in init_net. Confine the family to init_net so ++ * a socket in another namespace cannot reach the global control plane. ++ */ ++ if (!net_eq(net, &init_net)) ++ return -EAFNOSUPPORT; ++ + sk = sk_alloc(net, AF_QIPCRTR, GFP_KERNEL, &qrtr_proto, kern); + if (!sk) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-6.12/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch b/queue-6.12/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch new file mode 100644 index 0000000000..f1bf9f62bf --- /dev/null +++ b/queue-6.12/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch @@ -0,0 +1,186 @@ +From 7ea416c14f37e07f6b35d4a7f4f3bb734d646423 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 10:49:11 +0300 +Subject: net: stmmac: enable the MAC on link up for all supported speeds + +From: vadik likholetov + +[ Upstream commit 9c99db3a2080b8c2cbbb1100369586a9bea43321 ] + +stmmac_mac_link_down() clears the MAC's transmit and receive enable bits. +stmmac_mac_link_up() is expected to set them again through +stmmac_mac_set(..., true), but it first switches on the negotiated speed +and returns early for a speed the switch does not list. The MAC is then +left gated off. + +The speed selection is split into three switches, keyed on the interface. +The generic branch -- taken for everything that is neither USXGMII nor +XLGMII, so including PHY_INTERFACE_MODE_10GBASER -- lists only SPEED_2500, +SPEED_1000, SPEED_100 and SPEED_10. + +MGBE on Tegra234 runs 10GBASE-R into an Aquantia AQR113C. That PHY does +rate matching, so phylink_link_up() replaces the media speed with the +MAC-side interface speed before calling into the MAC: + + case RATE_MATCH_PAUSE: + speed = phylink_interface_max_speed(link_state.interface); + duplex = DUPLEX_FULL; + +The driver is therefore called as + + stmmac_mac_link_up(interface=10GBASER, speed=10000, duplex=1) + +which falls through to "default: return;". The interface stops passing +traffic after the first link flap. + +The failure is easy to misread. The link still comes up, because the PHY +is polled over MDIO and needs no MAC, so the interface reports carrier 1 +at the media speed. The DMA is untouched, so its start bits stay set and +descriptors are still consumed. Only the MAC itself is gated off: the +receiver counts nothing (mmc_rx_framecount_gb stops advancing, RE is 0) +and nothing reaches the wire (TE is 0). The interface survives boot only +because stmmac_hw_setup(), called from ndo_open, enables the MAC +unconditionally -- so the problem appears only once the cable has been +unplugged and plugged back in, and "ip link set dev down && ip +link set dev up" appears to fix it. + +The interface is not what the speed bits depend on: with the single +exception of 2.5G, which is selected through the XGMII block on USXGMII +and through the regular speed bits otherwise, each speed maps to one +field of struct mac_link. The per-interface switches are speed +validation, and phylink already validates the speed against +priv->hw->link.caps. So collapse the three switches into one keyed on the +speed alone, keeping the interface test only for the 2.5G case. This +covers 10G on 10GBASE-R, and equally 5G, and 1G/100/10 on USXGMII, all of +which hit "default: return;" today. + +A core that does not support a speed leaves the corresponding mac_link +field at 0, and phylink will not offer it that speed in the first place. +For dwxgmac2 at 10G, link.xgmii.speed10000 is XGMAC_CONFIG_SS_10000, +which is 0 and is the correct speed selection for a 10GBASE-R MAC: ctrl +then equals old_ctrl, the register write is skipped, and execution +reaches stmmac_mac_set(..., true). + +Log an error in the default case, since a speed with no entry here leaves +the MAC disabled and the symptom does not point at the cause. + +Fixes: d8ca113724e7 ("net: stmmac: tegra: Add MGBE support") +Suggested-by: Maxime Chevallier +Signed-off-by: vadik likholetov +Reviewed-by: Jacob Keller +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260713074911.30090-1-vadikas@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 92 ++++++++----------- + 1 file changed, 37 insertions(+), 55 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 893746b2a49613..44fd0fadc137dd 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1032,63 +1032,45 @@ static void stmmac_mac_link_up(struct phylink_config *config, + old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG); + ctrl = old_ctrl & ~priv->hw->link.speed_mask; + +- if (interface == PHY_INTERFACE_MODE_USXGMII) { +- switch (speed) { +- case SPEED_10000: +- ctrl |= priv->hw->link.xgmii.speed10000; +- break; +- case SPEED_5000: +- ctrl |= priv->hw->link.xgmii.speed5000; +- break; +- case SPEED_2500: ++ switch (speed) { ++ case SPEED_100000: ++ ctrl |= priv->hw->link.xlgmii.speed100000; ++ break; ++ case SPEED_50000: ++ ctrl |= priv->hw->link.xlgmii.speed50000; ++ break; ++ case SPEED_40000: ++ ctrl |= priv->hw->link.xlgmii.speed40000; ++ break; ++ case SPEED_25000: ++ ctrl |= priv->hw->link.xlgmii.speed25000; ++ break; ++ case SPEED_10000: ++ ctrl |= priv->hw->link.xgmii.speed10000; ++ break; ++ case SPEED_5000: ++ ctrl |= priv->hw->link.xgmii.speed5000; ++ break; ++ case SPEED_2500: ++ if (interface == PHY_INTERFACE_MODE_USXGMII) + ctrl |= priv->hw->link.xgmii.speed2500; +- break; +- default: +- return; +- } +- } else if (interface == PHY_INTERFACE_MODE_XLGMII) { +- switch (speed) { +- case SPEED_100000: +- ctrl |= priv->hw->link.xlgmii.speed100000; +- break; +- case SPEED_50000: +- ctrl |= priv->hw->link.xlgmii.speed50000; +- break; +- case SPEED_40000: +- ctrl |= priv->hw->link.xlgmii.speed40000; +- break; +- case SPEED_25000: +- ctrl |= priv->hw->link.xlgmii.speed25000; +- break; +- case SPEED_10000: +- ctrl |= priv->hw->link.xgmii.speed10000; +- break; +- case SPEED_2500: +- ctrl |= priv->hw->link.speed2500; +- break; +- case SPEED_1000: +- ctrl |= priv->hw->link.speed1000; +- break; +- default: +- return; +- } +- } else { +- switch (speed) { +- case SPEED_2500: ++ else + ctrl |= priv->hw->link.speed2500; +- break; +- case SPEED_1000: +- ctrl |= priv->hw->link.speed1000; +- break; +- case SPEED_100: +- ctrl |= priv->hw->link.speed100; +- break; +- case SPEED_10: +- ctrl |= priv->hw->link.speed10; +- break; +- default: +- return; +- } ++ break; ++ case SPEED_1000: ++ ctrl |= priv->hw->link.speed1000; ++ break; ++ case SPEED_100: ++ ctrl |= priv->hw->link.speed100; ++ break; ++ case SPEED_10: ++ ctrl |= priv->hw->link.speed10; ++ break; ++ default: ++ netdev_err(priv->dev, ++ "unsupported speed %s on %s, leaving the MAC disabled\n", ++ phy_speed_to_str(speed), phy_modes(interface)); ++ return; + } + + priv->speed = speed; +-- +2.53.0 + diff --git a/queue-6.12/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch b/queue-6.12/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch new file mode 100644 index 0000000000..ed881dd73d --- /dev/null +++ b/queue-6.12/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch @@ -0,0 +1,103 @@ +From a66bcccfc5244e8f26ffde2faec1426a3d804a75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:15 -0700 +Subject: net: stmmac: fix l3l4 filter rejecting unsupported offload requests + +From: Nazim Amirul + +[ Upstream commit 5536d7c843637e9430279b94935fcf7df98babb3 ] + +The basic flow parser in tc_add_basic_flow() does not validate match +keys before proceeding. Unsupported offload configurations such as +partial protocol masks, non-IPv4 network proto, or non-TCP/UDP transport +proto are silently accepted instead of returning -EOPNOTSUPP. + +Add validation to return -EOPNOTSUPP early for: +- No network or transport proto present in the key +- Partial protocol mask (only full mask supported) +- Network proto is not IPv4 +- Transport proto is not TCP or UDP + +Each rejection includes an extack message so the user knows which part +of the match is unsupported. + +Also propagate -EOPNOTSUPP from tc_add_basic_flow() in tc_add_flow() +by returning it directly rather than using break. The break was silently +discarding the error for FLOW_CLS_REPLACE operations where entry->in_use +is already true, causing tc_add_flow() to return 0 (success) for +unsupported replace requests. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-4-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 34 +++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 75ad2da1a37f1a..f0874b20b0a2cd 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -446,6 +446,7 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv, + } + + #define ETHER_TYPE_FULL_MASK cpu_to_be16(~0) ++#define IP_PROTO_FULL_MASK 0xFF + + static int tc_add_basic_flow(struct stmmac_priv *priv, + struct flow_cls_offload *cls, +@@ -461,6 +462,37 @@ static int tc_add_basic_flow(struct stmmac_priv *priv, + + flow_rule_match_basic(rule, &match); + ++ /* Both network proto and transport proto not present in the key */ ++ if (!match.mask || !(match.mask->n_proto || match.mask->ip_proto)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "filter must specify network or transport protocol"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* If the proto is present in the key and is not full mask */ ++ if ((match.mask->n_proto && match.mask->n_proto != ETHER_TYPE_FULL_MASK) || ++ (match.mask->ip_proto && match.mask->ip_proto != IP_PROTO_FULL_MASK)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only full protocol mask is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Network proto is present in the key and is not IPv4 */ ++ if (match.mask->n_proto && match.key->n_proto != cpu_to_be16(ETH_P_IP)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only IPv4 network protocol is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Transport proto is present in the key and is not TCP or UDP */ ++ if (match.mask->ip_proto && ++ match.key->ip_proto != IPPROTO_TCP && ++ match.key->ip_proto != IPPROTO_UDP) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only TCP and UDP transport protocols are supported"); ++ return -EOPNOTSUPP; ++ } ++ + entry->ip_proto = match.key->ip_proto; + return 0; + } +@@ -598,6 +630,8 @@ static int tc_add_flow(struct stmmac_priv *priv, + ret = tc_flow_parsers[i].fn(priv, cls, entry); + if (!ret) + entry->in_use = true; ++ else if (ret == -EOPNOTSUPP) ++ return ret; + } + + if (!entry->in_use) +-- +2.53.0 + diff --git a/queue-6.12/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch b/queue-6.12/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch new file mode 100644 index 0000000000..2688416bff --- /dev/null +++ b/queue-6.12/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch @@ -0,0 +1,43 @@ +From 18f029bec493ba10f22d0e8aa5e1f71186163dba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:16 -0700 +Subject: net: stmmac: reset residual action in L3L4 filters on delete + +From: Nazim Amirul + +[ Upstream commit a448f821289934b961dd9d8d0beb006cc8937ba2 ] + +When deleting an L3/L4 flower filter entry, the action field is not +reset. If a filter was previously configured with a drop action, that +action may persist and affect subsequent filter configurations +unintentionally. + +Clear the action field when the filter entry is deleted. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-5-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index f0874b20b0a2cd..49f133dec810d8 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -661,6 +661,7 @@ static int tc_del_flow(struct stmmac_priv *priv, + entry->in_use = false; + entry->cookie = 0; + entry->is_l4 = false; ++ entry->action = 0; + return ret; + } + +-- +2.53.0 + diff --git a/queue-6.12/net-txgbe-fix-fdir-filter-leak-on-remove.patch b/queue-6.12/net-txgbe-fix-fdir-filter-leak-on-remove.patch new file mode 100644 index 0000000000..2b882023bf --- /dev/null +++ b/queue-6.12/net-txgbe-fix-fdir-filter-leak-on-remove.patch @@ -0,0 +1,40 @@ +From bf454bdf80abe8f83822fc35356bfbc127000a2b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:19:11 +0800 +Subject: net: txgbe: fix FDIR filter leak on remove + +From: Chenguang Zhao + +[ Upstream commit ecaa37826340520664a4e5522f803ff48fc3f564 ] + +Perfect FDIR filters can be added while the interface is down and are +kept on the software list for later restore. unregister_netdev() only +calls ndo_stop when the device is up, so txgbe_fdir_filter_exit() in +txgbe_close() is skipped in that case and the filters are leaked on +driver remove. Free the filter list from txgbe_remove() as well. + +Fixes: 4bdb441105dc ("net: txgbe: support Flow Director perfect filters") +Signed-off-by: Chenguang Zhao +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20260713091911.1614795-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +index 32fc1bec2728ff..113b2dfa2e4b03 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +@@ -744,6 +744,7 @@ static void txgbe_remove(struct pci_dev *pdev) + + netdev = wx->netdev; + unregister_netdev(netdev); ++ txgbe_fdir_filter_exit(wx); + + txgbe_remove_phy(txgbe); + wx_free_isb_resources(wx); +-- +2.53.0 + diff --git a/queue-6.12/netlink-specs-rt-link-convert-bridge-port-flag-attri.patch b/queue-6.12/netlink-specs-rt-link-convert-bridge-port-flag-attri.patch new file mode 100644 index 0000000000..dee55f39ad --- /dev/null +++ b/queue-6.12/netlink-specs-rt-link-convert-bridge-port-flag-attri.patch @@ -0,0 +1,144 @@ +From e496c5c19e59d00e1b3accf5cb4c12330b72e2c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:03:04 +0300 +Subject: netlink: specs: rt-link: convert bridge port flag attributes to u8 + +From: Danielle Ratson + +[ Upstream commit f6e3b21608e974c4aaa4cfd73a239dacf1d8a9a3 ] + +A number of IFLA_BRPORT_* attributes are documented in the rt-link spec +as having the "flag" type, i.e. a payload-less NLA_FLAG attribute whose +meaning is presence-only. This does not match the kernel, which emits +these attributes with nla_put_u8() and validates them as NLA_U8 in +br_port_policy[]. The values are not mere presence flags but carry a u8 +payload (0/1). + +Convert these bridge port attributes from "flag" to "u8" so the spec +reflects the actual wire format. + +Fixes: 077b6022d24b ("doc/netlink/specs: Add sub-message type to rt_link family") +Reviewed-by: Petr Machata +Acked-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Signed-off-by: Danielle Ratson +Link: https://patch.msgid.link/a57cdfcfc4a6dcb92106c25b4dde5059fde2bd44.1783236731.git.danieller@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + Documentation/netlink/specs/rt_link.yaml | 40 ++++++++++++------------ + 1 file changed, 20 insertions(+), 20 deletions(-) + +diff --git a/Documentation/netlink/specs/rt_link.yaml b/Documentation/netlink/specs/rt_link.yaml +index a048fc30389d68..5fb757dcb53c2e 100644 +--- a/Documentation/netlink/specs/rt_link.yaml ++++ b/Documentation/netlink/specs/rt_link.yaml +@@ -1619,31 +1619,31 @@ attribute-sets: + type: u32 + - + name: mode +- type: flag ++ type: u8 + - + name: guard +- type: flag ++ type: u8 + - + name: protect +- type: flag ++ type: u8 + - + name: fast-leave +- type: flag ++ type: u8 + - + name: learning +- type: flag ++ type: u8 + - + name: unicast-flood +- type: flag ++ type: u8 + - + name: proxyarp +- type: flag ++ type: u8 + - + name: learning-sync +- type: flag ++ type: u8 + - + name: proxyarp-wifi +- type: flag ++ type: u8 + - + name: root-id + type: binary +@@ -1690,34 +1690,34 @@ attribute-sets: + type: pad + - + name: mcast-flood +- type: flag ++ type: u8 + - + name: mcast-to-ucast +- type: flag ++ type: u8 + - + name: vlan-tunnel +- type: flag ++ type: u8 + - + name: bcast-flood +- type: flag ++ type: u8 + - + name: group-fwd-mask + type: u16 + - + name: neigh-suppress +- type: flag ++ type: u8 + - + name: isolated +- type: flag ++ type: u8 + - + name: backup-port + type: u32 + - + name: mrp-ring-open +- type: flag ++ type: u8 + - + name: mrp-in-open +- type: flag ++ type: u8 + - + name: mcast-eht-hosts-limit + type: u32 +@@ -1726,10 +1726,10 @@ attribute-sets: + type: u32 + - + name: locked +- type: flag ++ type: u8 + - + name: mab +- type: flag ++ type: u8 + - + name: mcast-n-groups + type: u32 +@@ -1738,7 +1738,7 @@ attribute-sets: + type: u32 + - + name: neigh-vlan-suppress +- type: flag ++ type: u8 + - + name: backup-nhid + type: u32 +-- +2.53.0 + diff --git a/queue-6.12/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch b/queue-6.12/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch new file mode 100644 index 0000000000..067e85086d --- /dev/null +++ b/queue-6.12/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch @@ -0,0 +1,59 @@ +From f4078987dec0b125f9978d824e9b87a1cc6b8bb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 22:15:51 +0000 +Subject: nexthop: initialize extack in nh_res_bucket_migrate() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 6347c5314cee49f364aaf2e40ff15415a57a116e ] + +nh_res_bucket_migrate() passes an uninitialized netlink_ext_ack to +call_nexthop_res_bucket_notifiers(). When +nh_notifier_res_bucket_info_init() fails (e.g. the kzalloc returns +-ENOMEM), the error is propagated back before any notifier sets +extack._msg, and the error path formats the stale pointer with +pr_err_ratelimited("%s\n", extack._msg). With CONFIG_INIT_STACK_NONE +this dereferences uninitialized stack memory: + + Oops: general protection fault, probably for non-canonical address ... + KASAN: maybe wild-memory-access in range [...] + RIP: 0010:string (lib/vsprintf.c:730) + vsnprintf (lib/vsprintf.c:2945) + _printk (kernel/printk/printk.c:2504) + nh_res_bucket_migrate (net/ipv4/nexthop.c:1816) + nh_res_table_upkeep (net/ipv4/nexthop.c:1866) + rtm_new_nexthop (net/ipv4/nexthop.c:3323) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7076) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + Kernel panic - not syncing: Fatal exception + +Zero-initialize extack so _msg is NULL on error paths that never set it. + +Fixes: 7c37c7e00411 ("nexthop: Implement notifiers for resilient nexthop groups") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260713221551.3344650-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/nexthop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c +index 52d4890be83e86..ef323775f09acb 100644 +--- a/net/ipv4/nexthop.c ++++ b/net/ipv4/nexthop.c +@@ -1778,8 +1778,8 @@ static bool nh_res_bucket_migrate(struct nh_res_table *res_table, + bool notify_nl, bool force) + { + struct nh_res_bucket *bucket = &res_table->nh_buckets[bucket_index]; ++ struct netlink_ext_ack extack = {}; + struct nh_grp_entry *new_nhge; +- struct netlink_ext_ack extack; + int err; + + new_nhge = list_first_entry_or_null(&res_table->uw_nh_entries, +-- +2.53.0 + diff --git a/queue-6.12/nfp-check-resource-mutex-allocation.patch b/queue-6.12/nfp-check-resource-mutex-allocation.patch new file mode 100644 index 0000000000..0ba4acfd43 --- /dev/null +++ b/queue-6.12/nfp-check-resource-mutex-allocation.patch @@ -0,0 +1,52 @@ +From 88f8f892a59245648a90f7e0a6eed8b16fc71a42 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:08 +0800 +Subject: nfp: Check resource mutex allocation + +From: Ruoyu Wang + +[ Upstream commit a61b4db34a753bdf5c9e77a7f3d3dddd41dcfacc ] + +nfp_cpp_resource_find() allocates a CPP mutex handle for the matching +resource-table entry and then reports success. nfp_resource_try_acquire() +immediately passes that handle to nfp_cpp_mutex_trylock(). + +However, nfp_cpp_mutex_alloc() returns NULL on failure. If that happens +for a matching table entry, the resource lookup still returns success and +the following trylock dereferences a NULL mutex pointer while opening the +resource. + +nfp_resource_acquire() already treats failure to allocate the table mutex +as -ENOMEM. Do the same for the resource mutex and fail the lookup before +publishing the rest of the resource handle. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: f01a2161577d ("nfp: add support for resources") +Signed-off-by: Ruoyu Wang +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708143408.3168425-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +index 279ea0b5695577..55525f45e447b7 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c ++++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +@@ -96,6 +96,9 @@ static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res) + res->mutex = + nfp_cpp_mutex_alloc(cpp, + NFP_RESOURCE_TBL_TARGET, addr, key); ++ if (!res->mutex) ++ return -ENOMEM; ++ + res->cpp_id = NFP_CPP_ID(entry.region.cpp_target, + entry.region.cpp_action, + entry.region.cpp_token); +-- +2.53.0 + diff --git a/queue-6.12/octeontx2-pf-tc-fix-egress-ratelimiting.patch b/queue-6.12/octeontx2-pf-tc-fix-egress-ratelimiting.patch new file mode 100644 index 0000000000..b7464df795 --- /dev/null +++ b/queue-6.12/octeontx2-pf-tc-fix-egress-ratelimiting.patch @@ -0,0 +1,89 @@ +From 13b0a0999af55d9d76556ab6487f8eff8d1b774c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 14:13:49 +0530 +Subject: octeontx2-pf: tc: fix egress ratelimiting + +From: Hariprasad Kelam + +[ Upstream commit bb0d96ebe5f4d1acccf4dc36ca7f01f9a8fa1ba1 ] + +The egress rate calculation computes an incorrect mantissa and exponent, +causing up to ~50% deviation from the configured rate at lower speeds. + +Rework the computation to follow the hardware rate formula: + + rate = 2 * (1 + mantissa/256) * 2^exp / (1 << div_exp) + +Keep div_exp = 0 and derive exp and mantissa from half of the requested +rate. Rates below 2 Mbps are floored to the smallest encodable step +(exp = 0, mantissa = 0). + +Fixes: e638a83f167e ("octeontx2-pf: TC_MATCHALL egress ratelimiting offload") +Signed-off-by: Hariprasad Kelam +Signed-off-by: Nitin Shetty J +Link: https://patch.msgid.link/20260717084349.2227796-1-nshettyj@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 29 ++++++++++--------- + 1 file changed, 16 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +index ed041c3f714f26..b26fc848430f50 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +@@ -30,6 +30,7 @@ + #define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4) + + #define MCAST_INVALID_GRP (-1U) ++#define RATE_MANTISSA_BITS 8 + + struct otx2_tc_flow_stats { + u64 bytes; +@@ -90,28 +91,30 @@ static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, + static void otx2_get_egress_rate_cfg(u64 maxrate, u32 *exp, + u32 *mantissa, u32 *div_exp) + { +- u64 tmp; +- + /* Rate calculation by hardware + * + * PIR_ADD = ((256 + mantissa) << exp) / 256 + * rate = (2 * PIR_ADD) / ( 1 << div_exp) + * The resultant rate is in Mbps. ++ * ++ * Use div_exp = 0 and compute exp/mantissa for maxrate / 2; the ++ * leading factor of two yields the full rate. Rates below 2 Mbps ++ * are floored to the smallest step (exp = 0, mantissa = 0). + */ + +- /* 2Mbps to 100Gbps can be expressed with div_exp = 0. +- * Setting this to '0' will ease the calculation of +- * exponent and mantissa. +- */ + *div_exp = 0; +- + if (maxrate) { +- *exp = ilog2(maxrate) ? ilog2(maxrate) - 1 : 0; +- tmp = maxrate - rounddown_pow_of_two(maxrate); +- if (maxrate < MAX_RATE_MANTISSA) +- *mantissa = tmp * 2; +- else +- *mantissa = tmp / (1ULL << (*exp - 7)); ++ maxrate = maxrate / 2; ++ if (!maxrate) { ++ /* Rates below 2 Mbps map to the smallest step */ ++ *exp = 0; ++ *mantissa = 0; ++ } else { ++ *exp = ilog2(maxrate); ++ /* Clear MSB and derive fractional bits */ ++ maxrate &= ~BIT(*exp); ++ *mantissa = (maxrate << RATE_MANTISSA_BITS) >> *exp; ++ } + } else { + /* Instead of disabling rate limiting, set all values to max */ + *exp = MAX_RATE_EXPONENT; +-- +2.53.0 + diff --git a/queue-6.12/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch b/queue-6.12/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch new file mode 100644 index 0000000000..005d970fb6 --- /dev/null +++ b/queue-6.12/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch @@ -0,0 +1,40 @@ +From 2a2fecd059a9410c0d22d89295b5f0e0be28bd1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 10:50:07 +0530 +Subject: octeontx2-vf: set TC flower flag on MCAM entry allocation + +From: Suman Ghosh + +[ Upstream commit 0d4d31e3cc5dd6204fa1495c4107f5075acce5ed ] + +When MCAM entries are allocated for a VF netdev via the devlink +mcam_count parameter, only OTX2_FLAG_NTUPLE_SUPPORT was set. That +enabled ethtool ntuple filters but not tc flower offload. Also set +OTX2_FLAG_TC_FLOWER_SUPPORT when entries are successfully allocated. + +Fixes: 2da489432747 ("octeontx2-pf: devlink params support to set mcam entry count") +Signed-off-by: Suman Ghosh +Signed-off-by: Ratheesh Kannoth +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260715052007.2099851-1-rkannoth@marvell.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +index 2750326bfcf8b1..a9057711b62255 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +@@ -151,6 +151,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count) + if (allocated) { + pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC; + pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT; ++ pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT; + } + + if (allocated != count) +-- +2.53.0 + diff --git a/queue-6.12/ovl-fix-trusted-xattr-escape-prefix-matching.patch b/queue-6.12/ovl-fix-trusted-xattr-escape-prefix-matching.patch new file mode 100644 index 0000000000..3afbab18ac --- /dev/null +++ b/queue-6.12/ovl-fix-trusted-xattr-escape-prefix-matching.patch @@ -0,0 +1,49 @@ +From 956db553c2d06a75673d032212c3587442300df8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:22:21 +0800 +Subject: ovl: fix trusted xattr escape prefix matching + +From: Yichong Chen + +[ Upstream commit a8e72879cd0d8422c0b47d6d3c1802274fe73b98 ] + +In the trusted.* xattr namespace, ovl_is_escaped_xattr() compares +one byte less than the escaped overlay xattr prefix length. This makes +it match "trusted.overlay.overlay" without requiring the trailing dot. + +As a result, an xattr such as "trusted.overlay.overlayfoo" is +incorrectly treated as an escaped overlay xattr. This can be reproduced +by setting "trusted.overlay.overlayfoo" on a lower file and listing xattrs +through an overlay mount. listxattr() then exposes it as +"trusted.overlay.oo", and a following getxattr() on that listed name fails +with ENODATA. + +Compare the full escaped prefix, including the trailing dot, so +similarly-prefixed private xattrs are not misclassified. + +Fixes: dad02fad84cbc ("ovl: Support escaped overlay.* xattrs") +Signed-off-by: Yichong Chen +Link: https://patch.msgid.link/20260708082221.633602-1-chenyichong@uniontech.com +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/overlayfs/xattrs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/overlayfs/xattrs.c b/fs/overlayfs/xattrs.c +index 383978e4663c2a..6ba79ee00f7370 100644 +--- a/fs/overlayfs/xattrs.c ++++ b/fs/overlayfs/xattrs.c +@@ -13,7 +13,7 @@ static bool ovl_is_escaped_xattr(struct super_block *sb, const char *name) + OVL_XATTR_ESCAPE_USER_PREFIX_LEN) == 0; + else + return strncmp(name, OVL_XATTR_ESCAPE_TRUSTED_PREFIX, +- OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN - 1) == 0; ++ OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN) == 0; + } + + static bool ovl_is_own_xattr(struct super_block *sb, const char *name) +-- +2.53.0 + diff --git a/queue-6.12/pds_core-check-for-workqueue-allocation-failure.patch b/queue-6.12/pds_core-check-for-workqueue-allocation-failure.patch new file mode 100644 index 0000000000..8a0eb6a0fd --- /dev/null +++ b/queue-6.12/pds_core-check-for-workqueue-allocation-failure.patch @@ -0,0 +1,71 @@ +From b164fa02bb6b02bf38e1eb982e69143a8a8e0dc3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:27:13 +0000 +Subject: pds_core: check for workqueue allocation failure + +From: Nikhil P. Rao + +[ Upstream commit 3a660ca49e2c3807bffe0519db3cff677a5906e0 ] + +pdsc_init_pf() does not check whether create_singlethread_workqueue() +succeeded. + +Fail probe on failure. The workqueue is set up before the timer and +mutexes, so its failure path must unwind only the earlier setup. + +Fixes: c2dbb0904310 ("pds_core: health timer and workqueue") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Brett Creeley +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714212713.1788438-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/main.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c +index 8a4ca474813888..c78b17d230a841 100644 +--- a/drivers/net/ethernet/amd/pds_core/main.c ++++ b/drivers/net/ethernet/amd/pds_core/main.c +@@ -239,6 +239,10 @@ static int pdsc_init_pf(struct pdsc *pdsc) + /* General workqueue and timer, but don't start timer yet */ + snprintf(wq_name, sizeof(wq_name), "%s.%d", PDS_CORE_DRV_NAME, pdsc->uid); + pdsc->wq = create_singlethread_workqueue(wq_name); ++ if (!pdsc->wq) { ++ err = -ENOMEM; ++ goto err_out_unmap_bars; ++ } + INIT_WORK(&pdsc->health_work, pdsc_health_thread); + INIT_WORK(&pdsc->pci_reset_work, pdsc_pci_reset_thread); + timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0); +@@ -254,7 +258,7 @@ static int pdsc_init_pf(struct pdsc *pdsc) + err = pdsc_setup(pdsc, PDSC_SETUP_INIT); + if (err) { + mutex_unlock(&pdsc->config_lock); +- goto err_out_unmap_bars; ++ goto err_out_shutdown_timer; + } + + err = pdsc_start(pdsc); +@@ -300,13 +304,14 @@ static int pdsc_init_pf(struct pdsc *pdsc) + pdsc_stop(pdsc); + err_out_teardown: + pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING); +-err_out_unmap_bars: ++err_out_shutdown_timer: + timer_shutdown_sync(&pdsc->wdtimer); + if (pdsc->wq) + destroy_workqueue(pdsc->wq); + mutex_destroy(&pdsc->config_lock); + mutex_destroy(&pdsc->devcmd_lock); + pci_free_irq_vectors(pdsc->pdev); ++err_out_unmap_bars: + pdsc_unmap_bars(pdsc); + err_out_release_regions: + pci_release_regions(pdsc->pdev); +-- +2.53.0 + diff --git a/queue-6.12/pds_core-fix-auxiliary-device-add-del-races.patch b/queue-6.12/pds_core-fix-auxiliary-device-add-del-races.patch new file mode 100644 index 0000000000..cc91c2d16b --- /dev/null +++ b/queue-6.12/pds_core-fix-auxiliary-device-add-del-races.patch @@ -0,0 +1,80 @@ +From 66b9d718b1d4f7b915191e5e519ad2ba8c424e91 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:07:45 +0000 +Subject: pds_core: fix auxiliary device add/del races + +From: Nikhil P. Rao + +[ Upstream commit bfa33cd513c7ceb93c5a4c30e5662acd73c0a916 ] + +Two paths add or delete the same slot (pf->vfs[vf_id].padev): a VF's +pdsc_reset_done() and the PF's devlink enable_vnet/disable_vnet handler. +They serialize on config_lock, but neither guards the slot under it +correctly. + +add() registers and stores a new auxiliary device without first checking +the slot, so a second add of an already-populated slot leaks the first +device. del() makes that check outside config_lock, so two concurrent +dels can both pass it; the first clears the slot, and the second +dereferences a NULL pointer. + +Check and update the slot under config_lock in both paths. + +Fixes: b699bdc720c0 ("pds_core: specify auxiliary_device to be created") +Reported-by: sashiko-bot@kernel.org # Running on a local machine +Signed-off-by: Nikhil P. Rao +Reviewed-by: Brett Creeley +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714210745.1785625-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/auxbus.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c +index 889a18962270aa..7d7c87fe9e8f27 100644 +--- a/drivers/net/ethernet/amd/pds_core/auxbus.c ++++ b/drivers/net/ethernet/amd/pds_core/auxbus.c +@@ -177,17 +177,21 @@ void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf, + { + struct pds_auxiliary_dev *padev; + +- if (!*pd_ptr) +- return; +- + mutex_lock(&pf->config_lock); + ++ /* A concurrent del may have already torn this device down and ++ * cleared it. ++ */ + padev = *pd_ptr; ++ if (!padev) ++ goto out_unlock; ++ + pds_client_unregister(pf, padev->client_id); + auxiliary_device_delete(&padev->aux_dev); + auxiliary_device_uninit(&padev->aux_dev); + *pd_ptr = NULL; + ++out_unlock: + mutex_unlock(&pf->config_lock); + } + +@@ -210,6 +214,13 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf, + + mutex_lock(&pf->config_lock); + ++ /* Nothing to do if the aux device is already present. This also ++ * guards against a second add overwriting *pd_ptr and leaking the ++ * first, symmetric with the check in pdsc_auxbus_dev_del(). ++ */ ++ if (*pd_ptr) ++ goto out_unlock; ++ + mask = BIT_ULL(PDSC_S_FW_DEAD) | + BIT_ULL(PDSC_S_STOPPING_DRIVER); + if (cf->state & mask) { +-- +2.53.0 + diff --git a/queue-6.12/pds_core-fix-deadlock-between-reset-thread-and-remov.patch b/queue-6.12/pds_core-fix-deadlock-between-reset-thread-and-remov.patch new file mode 100644 index 0000000000..61b2ef6965 --- /dev/null +++ b/queue-6.12/pds_core-fix-deadlock-between-reset-thread-and-remov.patch @@ -0,0 +1,59 @@ +From 07258034a0780cbd53d70247d41c5e34283d24d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:02:22 +0000 +Subject: pds_core: fix deadlock between reset thread and remove + +From: Nikhil P. Rao + +[ Upstream commit ab0eec0ff0a421737a37f510ceab5c6ea59cd05a ] + +pci_reset_function() acquires device_lock before performing the reset. +pdsc_remove() is called by the PCI core with device_lock already held. +If pdsc_pci_reset_thread() is running when pdsc_remove() is called, +destroy_workqueue() will block waiting for the work to complete, while +the work is blocked waiting for device_lock - deadlock. + +Use pci_try_reset_function() which uses pci_dev_trylock() internally. +This acquires both the device lock and the PCI config access lock +without blocking - if either lock is contended, it returns -EAGAIN +immediately. This avoids the deadlock while also ensuring proper +config space access serialization during the reset. + +The pci_dev_get/put calls are also removed as they were unnecessary - +the driver-owned workqueue is destroyed in pdsc_remove(), guaranteeing +the work completes before remove returns. The PCI core holds its +reference to pci_dev throughout the entire unbind sequence. + +Fixes: 81665adf25d2 ("pds_core: Fix pdsc_check_pci_health function to use work thread") +Reported-by: sashiko-bot +Closes: https://patchwork.kernel.org/comment/27002369/ +Signed-off-by: Nikhil P. Rao +Reviewed-by: Harshitha Ramamurthy +Link: https://patch.msgid.link/20260714180223.1642792-2-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/core.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c +index 3c60d4cf9d0e17..c99cbb038f5d98 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.c ++++ b/drivers/net/ethernet/amd/pds_core/core.c +@@ -597,9 +597,10 @@ void pdsc_pci_reset_thread(struct work_struct *work) + struct pdsc *pdsc = container_of(work, struct pdsc, pci_reset_work); + struct pci_dev *pdev = pdsc->pdev; + +- pci_dev_get(pdev); +- pci_reset_function(pdev); +- pci_dev_put(pdev); ++ /* Use try variant to avoid deadlock with pdsc_remove(). ++ * If lock is contended, the watchdog timer will retry. ++ */ ++ pci_try_reset_function(pdev); + } + + static void pdsc_check_pci_health(struct pdsc *pdsc) +-- +2.53.0 + diff --git a/queue-6.12/pds_core-fix-use-after-free-on-workqueue-during-remo.patch b/queue-6.12/pds_core-fix-use-after-free-on-workqueue-during-remo.patch new file mode 100644 index 0000000000..612d9d27d0 --- /dev/null +++ b/queue-6.12/pds_core-fix-use-after-free-on-workqueue-during-remo.patch @@ -0,0 +1,120 @@ +From 15a42e0a7960d4708270c39c60f28fdee021b8fd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:02:23 +0000 +Subject: pds_core: fix use-after-free on workqueue during remove + +From: Nikhil P. Rao + +[ Upstream commit 0ad134881508c36b65c1a8864f8bec53adbd3327 ] + +In pdsc_remove(), the workqueue is destroyed before pdsc_teardown() +is called. This ordering allows two paths to queue work on the +destroyed workqueue: + +1. If pdsc_teardown() -> pdsc_devcmd_reset() times out, the error + path in pdsc_devcmd_locked() queues health_work. + +2. A NotifyQ event can trigger the ISR and queue work before free_irq() + is called in pdsc_teardown(). + +Fix by moving destroy_workqueue() after pdsc_teardown() so the +workqueue outlives every queuer; destroy_workqueue() then flushes any +work still pending. + +Draining the queued work also requires ordering the teardown so the +resources that work touches are freed last: + + - In pdsc_qcq_free(), after freeing the interrupt, cancel_work_sync() + the queue's work and only then clear qcq->intx, so + pdsc_process_adminq()'s read of qcq->intx for interrupt-credit + return cannot race with the clear. + + - Free adminqcq before notifyqcq: the shared adminq ISR is released + when adminqcq is freed, and the adminq work accesses notifyqcq, so + both must be stopped before notifyqcq is freed. + +Fixes: 01ba61b55b20 ("pds_core: Add adminq processing and commands") +Reported-by: sashiko-bot +Closes: https://patchwork.kernel.org/comment/27002369/ +Signed-off-by: Nikhil P. Rao +Link: https://patch.msgid.link/20260714180223.1642792-3-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/core.c | 14 ++++++++++---- + drivers/net/ethernet/amd/pds_core/main.c | 5 +++-- + 2 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c +index c99cbb038f5d98..985ef535e41583 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.c ++++ b/drivers/net/ethernet/amd/pds_core/core.c +@@ -110,7 +110,6 @@ static void pdsc_qcq_intr_free(struct pdsc *pdsc, struct pdsc_qcq *qcq) + return; + + pdsc_intr_free(pdsc, qcq->intx); +- qcq->intx = PDS_CORE_INTR_INDEX_NOT_ASSIGNED; + } + + static int pdsc_qcq_intr_alloc(struct pdsc *pdsc, struct pdsc_qcq *qcq) +@@ -145,6 +144,12 @@ void pdsc_qcq_free(struct pdsc *pdsc, struct pdsc_qcq *qcq) + + pdsc_qcq_intr_free(pdsc, qcq); + ++ /* Drain any work queued by ISR before it was freed above */ ++ if (qcq->work.func) ++ cancel_work_sync(&qcq->work); ++ ++ qcq->intx = PDS_CORE_INTR_INDEX_NOT_ASSIGNED; ++ + if (qcq->q_base) + dma_free_coherent(dev, qcq->q_size, + qcq->q_base, qcq->q_base_pa); +@@ -304,8 +309,11 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index, + + static void pdsc_core_uninit(struct pdsc *pdsc) + { +- pdsc_qcq_free(pdsc, &pdsc->notifyqcq); ++ /* Free adminqcq first: its work accesses notifyqcq, so we must ++ * disable its IRQ and drain its work before freeing notifyqcq. ++ */ + pdsc_qcq_free(pdsc, &pdsc->adminqcq); ++ pdsc_qcq_free(pdsc, &pdsc->notifyqcq); + + if (pdsc->kern_dbpage) { + iounmap(pdsc->kern_dbpage); +@@ -472,8 +480,6 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing) + { + if (!pdsc->pdev->is_virtfn) + pdsc_devcmd_reset(pdsc); +- if (pdsc->adminqcq.work.func) +- cancel_work_sync(&pdsc->adminqcq.work); + + pdsc_core_uninit(pdsc); + +diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c +index a3a68889137b63..8a4ca474813888 100644 +--- a/drivers/net/ethernet/amd/pds_core/main.c ++++ b/drivers/net/ethernet/amd/pds_core/main.c +@@ -429,8 +429,6 @@ static void pdsc_remove(struct pci_dev *pdev) + pdsc_sriov_configure(pdev, 0); + + timer_shutdown_sync(&pdsc->wdtimer); +- if (pdsc->wq) +- destroy_workqueue(pdsc->wq); + + mutex_lock(&pdsc->config_lock); + set_bit(PDSC_S_STOPPING_DRIVER, &pdsc->state); +@@ -438,6 +436,9 @@ static void pdsc_remove(struct pci_dev *pdev) + pdsc_stop(pdsc); + pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING); + mutex_unlock(&pdsc->config_lock); ++ ++ if (pdsc->wq) ++ destroy_workqueue(pdsc->wq); + mutex_destroy(&pdsc->config_lock); + mutex_destroy(&pdsc->devcmd_lock); + +-- +2.53.0 + diff --git a/queue-6.12/pds_core-order-completion-reads-after-the-ownership-.patch b/queue-6.12/pds_core-order-completion-reads-after-the-ownership-.patch new file mode 100644 index 0000000000..90c7fa5b7a --- /dev/null +++ b/queue-6.12/pds_core-order-completion-reads-after-the-ownership-.patch @@ -0,0 +1,62 @@ +From 572064b0e713619dbbade8511b82163743fb99c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 20:41:45 +0000 +Subject: pds_core: order completion reads after the ownership check + +From: Nikhil P. Rao + +[ Upstream commit dd6b1cc748cd28147c113f9daa76393916ad9494 ] + +pdsc_process_adminq() and pdsc_process_notifyq() decide a completion is +valid from its ownership field - the color bit for the adminq, the event +id for the notifyq - then read the rest of the descriptor, with no +barrier in between. + +On a weakly ordered architecture the CPU may read the payload first. Add +dma_rmb() between the ownership read and the payload reads. + +Fixes: 7e82a8745b95 ("pds_core: Prevent race issues involving the adminq") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Eric Joyner +Link: https://patch.msgid.link/20260714204145.1782390-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/adminq.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/adminq.c b/drivers/net/ethernet/amd/pds_core/adminq.c +index 506f682d15c10a..12eca570cb1da1 100644 +--- a/drivers/net/ethernet/amd/pds_core/adminq.c ++++ b/drivers/net/ethernet/amd/pds_core/adminq.c +@@ -18,7 +18,13 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq) + comp = cq_info->comp; + eid = le64_to_cpu(comp->event.eid); + while (eid > pdsc->last_eid) { +- u16 ecode = le16_to_cpu(comp->event.ecode); ++ u16 ecode; ++ ++ /* Order the payload read after the event id, the field the ++ * driver uses to detect a new completion. ++ */ ++ dma_rmb(); ++ ecode = le16_to_cpu(comp->event.ecode); + + switch (ecode) { + case PDS_EVENT_LINK_CHANGE: +@@ -101,6 +107,10 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq) + spin_lock_irqsave(&pdsc->adminq_lock, irqflags); + comp = cq->info[cq->tail_idx].comp; + while (pdsc_color_match(comp->color, cq->done_color)) { ++ /* Order the payload reads after the color bit, the field the ++ * driver uses to detect a new completion. ++ */ ++ dma_rmb(); + q_info = &q->info[q->tail_idx]; + q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1); + +-- +2.53.0 + diff --git a/queue-6.12/pds_core-reject-component-parameter-in-legacy-firmwa.patch b/queue-6.12/pds_core-reject-component-parameter-in-legacy-firmwa.patch new file mode 100644 index 0000000000..04a6a02734 --- /dev/null +++ b/queue-6.12/pds_core-reject-component-parameter-in-legacy-firmwa.patch @@ -0,0 +1,44 @@ +From 417b19ba549002f9fa99cf3a6bde7e87e798d687 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:36:49 +0000 +Subject: pds_core: reject component parameter in legacy firmware update + +From: Nikhil P. Rao + +[ Upstream commit 7be2552e601c247a328a5aba6fc06ac844b94a16 ] + +The legacy firmware update path does not support per-component updates. +If a user specifies a component parameter with devlink flash, reject +the request with -EOPNOTSUPP rather than silently ignoring the component +parameter and flashing the entire firmware image. + +Fixes: 49ce92fbee0b ("pds_core: add FW update feature to devlink") +Signed-off-by: Nikhil P. Rao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708163649.128620-1-nikhil.rao@amd.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/devlink.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c +index 621791a3c543be..e35572f099c884 100644 +--- a/drivers/net/ethernet/amd/pds_core/devlink.c ++++ b/drivers/net/ethernet/amd/pds_core/devlink.c +@@ -89,6 +89,12 @@ int pdsc_dl_flash_update(struct devlink *dl, + { + struct pdsc *pdsc = devlink_priv(dl); + ++ if (params->component) { ++ NL_SET_ERR_MSG_MOD(extack, ++ "Component update not supported by this device"); ++ return -EOPNOTSUPP; ++ } ++ + return pdsc_firmware_update(pdsc, params->fw, extack); + } + +-- +2.53.0 + diff --git a/queue-6.12/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch b/queue-6.12/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch new file mode 100644 index 0000000000..9dac24303d --- /dev/null +++ b/queue-6.12/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch @@ -0,0 +1,53 @@ +From 2e5aefbfca11d7eeefe516cd92453f5bd0e53251 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 20:14:56 +0000 +Subject: pds_core: yield the CPU while waiting for the adminq to drain + +From: Nikhil P. Rao + +[ Upstream commit a11f0b8a204296fe7db9eaec53441012222cb004 ] + +pdsc_adminq_wait_and_dec_once_unused() busy-waits for adminq_refcnt to +drop to one: + + while (!refcount_dec_if_one(&pdsc->adminq_refcnt)) + cpu_relax(); + +The refcount is held by pdsc_adminq_post() for the duration of an +in-flight command, which can wait up to devcmd_timeout seconds +(PDS_CORE_DEVCMD_TIMEOUT is 5) for the hardware to complete. cpu_relax() +is not a reschedule point, so on a non-preemptible kernel this loop can +spin on the CPU for several seconds, starving other tasks on that core. + +Add cond_resched() to the loop so the waiter yields to other runnable +tasks while it polls, keeping cpu_relax() as the busy-wait hint between +checks. + +Fixes: 7e82a8745b95 ("pds_core: Prevent race issues involving the adminq") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Eric Joyner +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714201456.1776153-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c +index 985ef535e41583..276e61f043c5ec 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.c ++++ b/drivers/net/ethernet/amd/pds_core/core.c +@@ -530,6 +530,7 @@ static void pdsc_adminq_wait_and_dec_once_unused(struct pdsc *pdsc) + dev_dbg_ratelimited(pdsc->dev, "%s: adminq in use\n", + __func__); + cpu_relax(); ++ cond_resched(); + } + } + +-- +2.53.0 + diff --git a/queue-6.12/ppp-annotate-data-races-in-ppp_generic.patch b/queue-6.12/ppp-annotate-data-races-in-ppp_generic.patch new file mode 100644 index 0000000000..fadb900864 --- /dev/null +++ b/queue-6.12/ppp-annotate-data-races-in-ppp_generic.patch @@ -0,0 +1,233 @@ +From 6c199d994c80a4d98496ccade63323cfd65de591 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:16:05 +0000 +Subject: ppp: annotate data races in ppp_generic + +From: Eric Dumazet + +[ Upstream commit 543adf072165aaf2e3b635c0476204f9658ed3bf ] + +Several fields in struct ppp can be read or updated concurrently +from multiple CPUs without synchronization, causing data races: + +1. ppp->mru is read concurrently in ppp_receive_nonmp_frame() while + being updated via PPPIOCSMRU ioctl. Protect ppp->mru updates in + PPPIOCSMRU with ppp_recv_lock(ppp). + +2. PPPIOCGFLAGS reads ppp->flags, ppp->xstate, and ppp->rstate + unlocked. Wrap the read in ppp_lock(ppp) to get a consistent + snapshot. + +3. ppp->debug is updated via PPPIOCSDEBUG and read concurrently on + fast paths. Annotate reads with READ_ONCE() and writes with + WRITE_ONCE(). + +4. ppp->last_xmit and ppp->last_recv are updated on TX/RX data paths + and read via PPPIOCGIDLE32 / PPPIOCGIDLE64 ioctls. Annotate with + WRITE_ONCE() / READ_ONCE() and use max() to handle jiffies + subtraction. + +5. ppp->npmode[] is updated via PPPIOCSNPMODE and read on TX/RX + paths. Annotate with WRITE_ONCE() / READ_ONCE(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/20260722101605.2868548-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 50 ++++++++++++++++++++--------------- + 1 file changed, 28 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index f217f6dee38f10..5d6d69632c847a 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -813,7 +813,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case PPPIOCSMRU: + if (get_user(val, p)) + break; ++ ppp_recv_lock(ppp); + ppp->mru = val; ++ ppp_recv_unlock(ppp); + err = 0; + break; + +@@ -834,7 +836,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + + case PPPIOCGFLAGS: ++ ppp_lock(ppp); + val = ppp->flags | ppp->xstate | ppp->rstate; ++ ppp_unlock(ppp); + if (put_user(val, p)) + break; + err = 0; +@@ -858,7 +862,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case PPPIOCSDEBUG: + if (get_user(val, p)) + break; +- ppp->debug = val; ++ WRITE_ONCE(ppp->debug, val); + err = 0; + break; + +@@ -869,16 +873,16 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + + case PPPIOCGIDLE32: +- idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ; +- idle32.recv_idle = (jiffies - ppp->last_recv) / HZ; +- if (copy_to_user(argp, &idle32, sizeof(idle32))) ++ idle32.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ; ++ idle32.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ; ++ if (copy_to_user(argp, &idle32, sizeof(idle32))) + break; + err = 0; + break; + + case PPPIOCGIDLE64: +- idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ; +- idle64.recv_idle = (jiffies - ppp->last_recv) / HZ; ++ idle64.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ; ++ idle64.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ; + if (copy_to_user(argp, &idle64, sizeof(idle64))) + break; + err = 0; +@@ -919,7 +923,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + if (copy_to_user(argp, &npi, sizeof(npi))) + break; + } else { +- ppp->npmode[i] = npi.mode; ++ WRITE_ONCE(ppp->npmode[i], npi.mode); + /* we may be able to transmit more packets now (??) */ + netif_wake_queue(ppp->dev); + } +@@ -1454,7 +1458,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) + goto outf; + + /* Drop, accept or reject the packet */ +- switch (ppp->npmode[npi]) { ++ switch (READ_ONCE(ppp->npmode[npi])) { + case NPMODE_PASS: + break; + case NPMODE_QUEUE: +@@ -1769,7 +1773,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_OUTBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: outbound frame " + "not passed\n"); +@@ -1779,11 +1783,11 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + /* if this packet passes the active filter, record the time */ + if (!(ppp->active_filter && + bpf_prog_run(ppp->active_filter, skb) == 0)) +- ppp->last_xmit = jiffies; ++ WRITE_ONCE(ppp->last_xmit, jiffies); + skb_pull(skb, 2); + #else + /* for data packets, record the time */ +- ppp->last_xmit = jiffies; ++ WRITE_ONCE(ppp->last_xmit, jiffies); + #endif /* CONFIG_PPP_FILTER */ + } + +@@ -2159,7 +2163,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + noskb: + spin_unlock(&pch->downl); + err_linearize: +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); + ++ppp->dev->stats.tx_errors; + ++ppp->nxseq; +@@ -2505,7 +2509,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: inbound frame " + "not passed\n"); +@@ -2514,14 +2518,14 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + } + if (!(ppp->active_filter && + bpf_prog_run(ppp->active_filter, skb) == 0)) +- ppp->last_recv = jiffies; ++ WRITE_ONCE(ppp->last_recv, jiffies); + __skb_pull(skb, 2); + } else + #endif /* CONFIG_PPP_FILTER */ +- ppp->last_recv = jiffies; ++ WRITE_ONCE(ppp->last_recv, jiffies); + + if ((ppp->dev->flags & IFF_UP) == 0 || +- ppp->npmode[npi] != NPMODE_PASS) { ++ READ_ONCE(ppp->npmode[npi]) != NPMODE_PASS) { + kfree_skb(skb); + } else { + /* chop off protocol */ +@@ -2774,7 +2778,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + seq = seq_before(minseq, PPP_MP_CB(p)->sequence)? + minseq + 1: PPP_MP_CB(p)->sequence; + +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "lost frag %u..%u\n", + oldseq, seq-1); +@@ -2823,7 +2827,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + struct sk_buff *tmp2; + + skb_queue_reverse_walk_from_safe(list, p, tmp2) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "discarding frag %u\n", + PPP_MP_CB(p)->sequence); +@@ -2845,7 +2849,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + skb_queue_walk_safe(list, p, tmp) { + if (p == head) + break; +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "discarding frag %u\n", + PPP_MP_CB(p)->sequence); +@@ -2853,7 +2857,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + kfree_skb(p); + } + +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + " missed pkts %u..%u\n", + ppp->nextseq, +@@ -3163,7 +3167,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) + if (!ppp->rc_state) + break; + if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len, +- ppp->file.index, 0, ppp->mru, ppp->debug)) { ++ ppp->file.index, 0, ppp->mru, ++ READ_ONCE(ppp->debug))) { + ppp->rstate |= SC_DECOMP_RUN; + ppp->rstate &= ~(SC_DC_ERROR | SC_DC_FERROR); + } +@@ -3172,7 +3177,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) + if (!ppp->xc_state) + break; + if (ppp->xcomp->comp_init(ppp->xc_state, dp, len, +- ppp->file.index, 0, ppp->debug)) ++ ppp->file.index, 0, ++ READ_ONCE(ppp->debug))) + ppp->xstate |= SC_COMP_RUN; + } + break; +-- +2.53.0 + diff --git a/queue-6.12/ppp-convert-to-percpu-netstats.patch b/queue-6.12/ppp-convert-to-percpu-netstats.patch new file mode 100644 index 0000000000..bd8fd16e6c --- /dev/null +++ b/queue-6.12/ppp-convert-to-percpu-netstats.patch @@ -0,0 +1,137 @@ +From 6972c41647045fbbce3c089380e8fc7ea1e17c01 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 16:32:10 +0800 +Subject: ppp: convert to percpu netstats + +From: Qingfang Deng + +[ Upstream commit 1a3e9b7a6b09e8ab3d2af019e4a392622685855e ] + +Convert to percpu netstats to avoid lock contention when reading them. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20250610083211.909015-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 52 +++++++++++++---------------------- + 1 file changed, 19 insertions(+), 33 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 9599b67688432e..68cd438a5b5eb5 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -107,18 +107,6 @@ struct ppp_file { + #define PF_TO_PPP(pf) PF_TO_X(pf, struct ppp) + #define PF_TO_CHANNEL(pf) PF_TO_X(pf, struct channel) + +-/* +- * Data structure to hold primary network stats for which +- * we want to use 64 bit storage. Other network stats +- * are stored in dev->stats of the ppp strucute. +- */ +-struct ppp_link_stats { +- u64 rx_packets; +- u64 tx_packets; +- u64 rx_bytes; +- u64 tx_bytes; +-}; +- + /* + * Data structure describing one ppp unit. + * A ppp unit corresponds to a ppp network interface device +@@ -162,7 +150,6 @@ struct ppp { + struct bpf_prog *active_filter; /* filter for pkts to reset idle */ + #endif /* CONFIG_PPP_FILTER */ + struct net *ppp_net; /* the net we belong to */ +- struct ppp_link_stats stats64; /* 64 bit network stats */ + }; + + /* +@@ -1545,23 +1532,12 @@ ppp_net_siocdevprivate(struct net_device *dev, struct ifreq *ifr, + static void + ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) + { +- struct ppp *ppp = netdev_priv(dev); +- +- ppp_recv_lock(ppp); +- stats64->rx_packets = ppp->stats64.rx_packets; +- stats64->rx_bytes = ppp->stats64.rx_bytes; +- ppp_recv_unlock(ppp); +- +- ppp_xmit_lock(ppp); +- stats64->tx_packets = ppp->stats64.tx_packets; +- stats64->tx_bytes = ppp->stats64.tx_bytes; +- ppp_xmit_unlock(ppp); +- + stats64->rx_errors = dev->stats.rx_errors; + stats64->tx_errors = dev->stats.tx_errors; + stats64->rx_dropped = dev->stats.rx_dropped; + stats64->tx_dropped = dev->stats.tx_dropped; + stats64->rx_length_errors = dev->stats.rx_length_errors; ++ dev_fetch_sw_netstats(stats64, dev->tstats); + } + + static int ppp_dev_init(struct net_device *dev) +@@ -1659,6 +1635,7 @@ static void ppp_setup(struct net_device *dev) + dev->type = ARPHRD_PPP; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->priv_destructor = ppp_dev_priv_destructor; ++ dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; + netif_keep_dst(dev); + } + +@@ -1804,8 +1781,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + #endif /* CONFIG_PPP_FILTER */ + } + +- ++ppp->stats64.tx_packets; +- ppp->stats64.tx_bytes += skb->len - PPP_PROTO_LEN; ++ dev_sw_netstats_tx_add(ppp->dev, 1, skb->len - PPP_PROTO_LEN); + + switch (proto) { + case PPP_IP: +@@ -2483,8 +2459,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + break; + } + +- ++ppp->stats64.rx_packets; +- ppp->stats64.rx_bytes += skb->len - 2; ++ dev_sw_netstats_rx_add(ppp->dev, skb->len - PPP_PROTO_LEN); + + npi = proto_to_npindex(proto); + if (npi < 0) { +@@ -3312,14 +3287,25 @@ static void + ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) + { + struct slcompress *vj = ppp->vj; ++ int cpu; + + memset(st, 0, sizeof(*st)); +- st->p.ppp_ipackets = ppp->stats64.rx_packets; ++ for_each_possible_cpu(cpu) { ++ struct pcpu_sw_netstats *p = per_cpu_ptr(ppp->dev->tstats, cpu); ++ u64 rx_packets, rx_bytes, tx_packets, tx_bytes; ++ ++ rx_packets = u64_stats_read(&p->rx_packets); ++ rx_bytes = u64_stats_read(&p->rx_bytes); ++ tx_packets = u64_stats_read(&p->tx_packets); ++ tx_bytes = u64_stats_read(&p->tx_bytes); ++ ++ st->p.ppp_ipackets += rx_packets; ++ st->p.ppp_ibytes += rx_bytes; ++ st->p.ppp_opackets += tx_packets; ++ st->p.ppp_obytes += tx_bytes; ++ } + st->p.ppp_ierrors = ppp->dev->stats.rx_errors; +- st->p.ppp_ibytes = ppp->stats64.rx_bytes; +- st->p.ppp_opackets = ppp->stats64.tx_packets; + st->p.ppp_oerrors = ppp->dev->stats.tx_errors; +- st->p.ppp_obytes = ppp->stats64.tx_bytes; + if (!vj) + return; + st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; +-- +2.53.0 + diff --git a/queue-6.12/ppp-enable-tx-scatter-gather.patch b/queue-6.12/ppp-enable-tx-scatter-gather.patch new file mode 100644 index 0000000000..1c01959379 --- /dev/null +++ b/queue-6.12/ppp-enable-tx-scatter-gather.patch @@ -0,0 +1,115 @@ +From d232af909cc52bb1c695398dd5b6cd532a231400 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Jan 2026 09:29:02 +0800 +Subject: ppp: enable TX scatter-gather + +From: Qingfang Deng + +[ Upstream commit 42fcb213e58a7da33d5d2d7517b4e521025c68c3 ] + +PPP channels using chan->direct_xmit prepend the PPP header to a skb and +call dev_queue_xmit() directly. In this mode the skb does not need to be +linear, but the PPP netdevice currently does not advertise +scatter-gather features, causing unnecessary linearization and +preventing GSO. + +Enable NETIF_F_SG and NETIF_F_FRAGLIST on PPP devices. In case a linear +buffer is required (PPP compression, multilink, and channels without +direct_xmit), call skb_linearize() explicitly. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20260129012902.941-1-dqfext@gmail.com +Signed-off-by: Paolo Abeni +Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 30 +++++++++++++++++++++++++----- + 1 file changed, 25 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 68cd438a5b5eb5..f217f6dee38f10 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1636,6 +1636,8 @@ static void ppp_setup(struct net_device *dev) + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->priv_destructor = ppp_dev_priv_destructor; + dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; ++ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST; ++ dev->hw_features = dev->features; + netif_keep_dst(dev); + } + +@@ -1700,6 +1702,10 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb) + ppp->xcomp->comp_extra + ppp->dev->hard_header_len; + int compressor_skb_size = ppp->dev->mtu + + ppp->xcomp->comp_extra + PPP_HDRLEN; ++ ++ if (skb_linearize(skb)) ++ return NULL; ++ + new_skb = alloc_skb(new_skb_size, GFP_ATOMIC); + if (!new_skb) { + if (net_ratelimit()) +@@ -1787,6 +1793,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + case PPP_IP: + if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0) + break; ++ ++ if (skb_linearize(skb)) ++ goto drop; ++ + /* try to do VJ TCP header compression */ + new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2, + GFP_ATOMIC); +@@ -1884,19 +1894,26 @@ ppp_push(struct ppp *ppp) + } + + if ((ppp->flags & SC_MULTILINK) == 0) { ++ struct ppp_channel *chan; + /* not doing multilink: send it down the first channel */ + list = list->next; + pch = list_entry(list, struct channel, clist); + + spin_lock(&pch->downl); +- if (pch->chan) { +- if (pch->chan->ops->start_xmit(pch->chan, skb)) +- ppp->xmit_pending = NULL; +- } else { +- /* channel got unregistered */ ++ chan = pch->chan; ++ if (unlikely(!chan || (!chan->direct_xmit && skb_linearize(skb)))) { ++ /* channel got unregistered, or it requires a linear ++ * skb but linearization failed ++ */ + kfree_skb(skb); + ppp->xmit_pending = NULL; ++ goto out; + } ++ ++ if (chan->ops->start_xmit(chan, skb)) ++ ppp->xmit_pending = NULL; ++ ++out: + spin_unlock(&pch->downl); + return; + } +@@ -1981,6 +1998,8 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + return 0; /* can't take now, leave it in xmit_pending */ + + /* Do protocol field compression */ ++ if (skb_linearize(skb)) ++ goto err_linearize; + p = skb->data; + len = skb->len; + if (*p == 0 && mp_protocol_compress) { +@@ -2139,6 +2158,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + + noskb: + spin_unlock(&pch->downl); ++ err_linearize: + if (ppp->debug & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); + ++ppp->dev->stats.tx_errors; +-- +2.53.0 + diff --git a/queue-6.12/ppp-use-iff_no_queue-in-virtual-interfaces.patch b/queue-6.12/ppp-use-iff_no_queue-in-virtual-interfaces.patch new file mode 100644 index 0000000000..00fb619c6e --- /dev/null +++ b/queue-6.12/ppp-use-iff_no_queue-in-virtual-interfaces.patch @@ -0,0 +1,105 @@ +From d75d890bc99ed678c25c7f38f93fa1163e30e736 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 21:55:16 +0800 +Subject: ppp: use IFF_NO_QUEUE in virtual interfaces +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Qingfang Deng + +[ Upstream commit 95d0d094ba26432ec467e2260f4bf553053f1f8f ] + +For PPPoE, PPTP, and PPPoL2TP, the start_xmit() function directly +forwards packets to the underlying network stack and never returns +anything other than 1. So these interfaces do not require a qdisc, +and the IFF_NO_QUEUE flag should be set. + +Introduces a direct_xmit flag in struct ppp_channel to indicate when +IFF_NO_QUEUE should be applied. The flag is set in ppp_connect_channel() +for relevant protocols. + +While at it, remove the usused latency member from struct ppp_channel. + +Signed-off-by: Qingfang Deng +Reviewed-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20250301135517.695809-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 4 ++++ + drivers/net/ppp/pppoe.c | 1 + + drivers/net/ppp/pptp.c | 1 + + include/linux/ppp_channel.h | 3 +-- + net/l2tp/l2tp_ppp.c | 1 + + 5 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 9f787adef3eb38..9599b67688432e 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -3508,6 +3508,10 @@ ppp_connect_channel(struct channel *pch, int unit) + ret = -ENOTCONN; + goto outl; + } ++ if (pch->chan->direct_xmit) ++ ppp->dev->priv_flags |= IFF_NO_QUEUE; ++ else ++ ppp->dev->priv_flags &= ~IFF_NO_QUEUE; + spin_unlock_bh(&pch->downl); + if (pch->file.hdrlen > ppp->file.hdrlen) + ppp->file.hdrlen = pch->file.hdrlen; +diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c +index 937cf9b17f9aeb..944adf8b6e02b6 100644 +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -699,6 +699,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, + po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr) - 2; + po->chan.private = sk; + po->chan.ops = &pppoe_chan_ops; ++ po->chan.direct_xmit = true; + + error = ppp_register_net_channel(dev_net(dev), &po->chan); + if (error) { +diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c +index cec3bb22471b54..90737cb718928a 100644 +--- a/drivers/net/ppp/pptp.c ++++ b/drivers/net/ppp/pptp.c +@@ -469,6 +469,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, + po->chan.mtu -= PPTP_HEADER_OVERHEAD; + + po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header); ++ po->chan.direct_xmit = true; + error = ppp_register_channel(&po->chan); + if (error) { + pr_err("PPTP: failed to register PPP channel (%d)\n", error); +diff --git a/include/linux/ppp_channel.h b/include/linux/ppp_channel.h +index 45e6e427ceb8a0..f73fbea0dbc239 100644 +--- a/include/linux/ppp_channel.h ++++ b/include/linux/ppp_channel.h +@@ -42,8 +42,7 @@ struct ppp_channel { + int hdrlen; /* amount of headroom channel needs */ + void *ppp; /* opaque to channel */ + int speed; /* transfer rate (bytes/second) */ +- /* the following is not used at present */ +- int latency; /* overhead time in milliseconds */ ++ bool direct_xmit; /* no qdisc, xmit directly */ + }; + + #ifdef __KERNEL__ +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index bf78edee1ef8a7..f388bf9abf378d 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -796,6 +796,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, + po->chan.private = sk; + po->chan.ops = &pppol2tp_chan_ops; + po->chan.mtu = pppol2tp_tunnel_mtu(tunnel); ++ po->chan.direct_xmit = true; + + error = ppp_register_net_channel(sock_net(sk), &po->chan); + if (error) { +-- +2.53.0 + diff --git a/queue-6.12/rds-drop-incoming-messages-that-cross-network-namesp.patch b/queue-6.12/rds-drop-incoming-messages-that-cross-network-namesp.patch new file mode 100644 index 0000000000..5b7bba7e22 --- /dev/null +++ b/queue-6.12/rds-drop-incoming-messages-that-cross-network-namesp.patch @@ -0,0 +1,78 @@ +From fd505a9300700d0bd7a0808807439cd2d109953a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 19:43:14 -0700 +Subject: rds: drop incoming messages that cross network namespace boundaries + +From: Aldo Ariel Panzardo + +[ Upstream commit 5521ae71e32a8069ed4ca6e792179dc57bc43ab2 ] + +rds_find_bound() looks up the destination socket using a global +rhashtable keyed solely on (addr, port, scope_id). Network namespaces +are not part of the key, so a sender in netns A can deliver an incoming +message (inc) to a socket that lives in a different netns B. + +When this happens, inc->i_conn points to an rds_connection whose c_net +is netns A, but the receiving rs lives in netns B. Once the child +process that created netns A exits, cleanup_net() calls +rds_loop_exit_net() -> rds_loop_kill_conns() -> rds_conn_destroy(), +freeing that connection. If the survivor socket in netns B still holds +the inc, any subsequent dereference of inc->i_conn is a use-after-free. + +There are two dangerous sites in rds_clear_recv_queue(): + 1. inc->i_conn->c_lcong (offset 88 of freed rds_connection, size 200) + read via rds_recv_rcvbuf_delta() -- confirmed by KASAN. + 2. inc->i_conn->c_trans->inc_free(inc) (function pointer at offset 80) + called via rds_inc_put() when the inc refcount reaches zero -- same + race window, potential call-through-freed-object primitive. + +The bug is reachable from unprivileged user namespaces +(CLONE_NEWUSER + CLONE_NEWNET), available since Linux 3.8. + +Fix this by rejecting the delivery in rds_recv_incoming() when the +socket returned by rds_find_bound() belongs to a different network +namespace than the connection that carried the message. Use the +existing rds_conn_net() / sock_net() helpers and net_eq() for the +comparison. + +Fixes: c809195f5523 ("rds: clean up loopback rds_connections on netns deletion") +Signed-off-by: Aldo Ariel Panzardo +Reviewed-by: Allison Henderson +Tested-by: Allison Henderson +Signed-off-by: Allison Henderson +Link: https://patch.msgid.link/20260708024314.601139-1-achender@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/rds/recv.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/net/rds/recv.c b/net/rds/recv.c +index 5627f80013f8b1..bd9d00326e94fd 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -366,6 +366,21 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr, + goto out; + } + ++ /* ++ * rds_find_bound() uses a global (netns-agnostic) hash table. ++ * An RDS connection created in netns A can match a socket bound ++ * in the init netns, delivering inc cross-netns with inc->i_conn ++ * pointing into netns A. When cleanup_net() then frees that conn, ++ * any subsequent dereference of inc->i_conn is a use-after-free. ++ * Drop the inc if the receiving socket lives in a different netns. ++ */ ++ if (!net_eq(sock_net(rds_rs_to_sk(rs)), rds_conn_net(conn))) { ++ rds_stats_inc(s_recv_drop_no_sock); ++ rds_sock_put(rs); ++ rs = NULL; ++ goto out; ++ } ++ + /* Process extension headers */ + rds_recv_incoming_exthdrs(inc, rs); + +-- +2.53.0 + diff --git a/queue-6.12/rds-tcp-unregister-sysctl-before-tearing-down-listen.patch b/queue-6.12/rds-tcp-unregister-sysctl-before-tearing-down-listen.patch new file mode 100644 index 0000000000..dbb32e904b --- /dev/null +++ b/queue-6.12/rds-tcp-unregister-sysctl-before-tearing-down-listen.patch @@ -0,0 +1,64 @@ +From 64dd917739f541f5c92c88ebea43ad74dc5f2195 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Jul 2026 17:03:57 -0400 +Subject: rds: tcp: unregister sysctl before tearing down listen socket + +From: Cen Zhang (Microsoft) + +[ Upstream commit 167e54c703ccd4fa028feb568b0d1002020cff86 ] + +rds_tcp_exit_net() frees the per-netns RDS TCP listen socket via +rds_tcp_kill_sock() before unregistering the per-netns sysctl table. Since +rds_tcp_skbuf_handler() derives the netns from +rtn->rds_tcp_listen_sock->sk, a concurrent sysctl write can race with +netns teardown and dereference the freed socket/sk. + +KASAN reports the race as: + + BUG: KASAN: slab-use-after-free in rds_tcp_skbuf_handler+0x2aa/0x2e0 + rds_tcp_skbuf_handler net/rds/tcp.c:721 + proc_sys_call_handler fs/proc/proc_sysctl.c + vfs_write fs/read_write.c + __x64_sys_pwrite64 fs/read_write.c + +Fix this by unregistering the RDS TCP sysctl table before calling +rds_tcp_kill_sock(). unregister_net_sysctl_table() prevents new sysctl +handlers from starting and waits for in-flight handlers to finish, so +the listen socket can then be released safely. The fix was tested +against the linked reproducer. + +Fixes: 7f5611cbc487 ("rds: sysctl: rds_tcp_{rcv,snd}buf: avoid using current->nsproxy") +Reported-by: AutonomousCodeSecurity@microsoft.com +Link: https://lore.kernel.org/all/20260719203718.9680-1-blbllhy@gmail.com +Reviewed-by: Allison Henderson +Signed-off-by: Cen Zhang (Microsoft) +Link: https://patch.msgid.link/20260719210357.10179-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/rds/tcp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/rds/tcp.c b/net/rds/tcp.c +index b66dfcc3efaa0f..06a2d8d48bbacf 100644 +--- a/net/rds/tcp.c ++++ b/net/rds/tcp.c +@@ -637,13 +637,13 @@ static void __net_exit rds_tcp_exit_net(struct net *net) + { + struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid); + +- rds_tcp_kill_sock(net); +- + if (rtn->rds_tcp_sysctl) + unregister_net_sysctl_table(rtn->rds_tcp_sysctl); + + if (net != &init_net) + kfree(rtn->ctl_table); ++ ++ rds_tcp_kill_sock(net); + } + + static struct pernet_operations rds_tcp_net_ops = { +-- +2.53.0 + diff --git a/queue-6.12/regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch b/queue-6.12/regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch new file mode 100644 index 0000000000..e7d76e9a0a --- /dev/null +++ b/queue-6.12/regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch @@ -0,0 +1,60 @@ +From f08c55b7fd59c3bedba32229cb9c4e3c3b433d59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Jul 2026 02:05:59 +0100 +Subject: regulator: mt6358: use regmap helper to read fixed LDO calibration + +From: Daniel Golle + +[ Upstream commit 1d26f125501f3fbe6c259ab75bf6516299a0bf0e ] + +The "fixed" LDOs with output voltage calibration use +mt6358_get_buck_voltage_sel as their get_voltage_sel op, but the +MT6358_REG_FIXED and MT6366_REG_FIXED entries do not populate +da_vsel_reg/da_vsel_mask. The op therefore reads register 0x0 with a +zero mask and shifts the result by ffs(0) - 1 = -1, which is undefined +behaviour and gets flagged by UBSAN on every boot on MT6366 boards: + + UBSAN: shift-out-of-bounds in drivers/regulator/mt6358-regulator.c:384:38 + shift exponent -1 is negative + Call trace: + mt6358_get_buck_voltage_sel+0xc8/0x120 + regulator_get_voltage_rdev+0x70/0x170 + set_machine_constraints+0x504/0xc38 + regulator_register+0x324/0xc68 + +Besides the undefined shift, the returned selector is always 0, so the +actual calibration offset programmed in _ANA_CON0 is never +reported. + +The descriptor already carries the correct vsel_reg/vsel_mask (the +ANA_CON0 calibration field), matching the regulator_set_voltage_sel_regmap +op already in use. Read the selector back through +regulator_get_voltage_sel_regmap instead. + +Fixes: cf08fa74c716 ("regulator: mt6358: Add output voltage fine tuning to fixed regulators") +Signed-off-by: Daniel Golle +Reviewed-by: Chen-Yu Tsai +Tested-by: Chen-Yu Tsai +Link: https://patch.msgid.link/dcd98d81dede338c9bbb9700a9613c848b702e49.1784336005.git.daniel@makrotopia.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/mt6358-regulator.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c +index e4745f616cea3b..44bef0bdfdbe35 100644 +--- a/drivers/regulator/mt6358-regulator.c ++++ b/drivers/regulator/mt6358-regulator.c +@@ -492,7 +492,7 @@ static const struct regulator_ops mt6358_volt_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +- .get_voltage_sel = mt6358_get_buck_voltage_sel, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, +-- +2.53.0 + diff --git a/queue-6.12/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch b/queue-6.12/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch new file mode 100644 index 0000000000..c28e3313fc --- /dev/null +++ b/queue-6.12/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch @@ -0,0 +1,51 @@ +From 3658d52f5fa6fe2ee12289c2a8e87cb4ff15f45d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 09:55:32 +0800 +Subject: sctp: auth: verify auth requirement when auth_chunk is NULL + +From: Qing Luo + +[ Upstream commit 8e04823c120b376ef7dab14b60ebf6823aa16c14 ] + +sctp_auth_chunk_verify() returns true unconditionally when +chunk->auth_chunk is NULL, silently skipping authentication. +This is incorrect when: + +1. skb_clone() failed in the BH receive path, leaving auth_chunk + NULL. In sctp_endpoint_bh_rcv() asoc is NULL for new + connections, so the early sctp_auth_recv_cid() check cannot + catch this. + +2. No AUTH chunk precedes COOKIE-ECHO, so skb_clone() is never + called and auth_chunk remains NULL. + +Fix by checking sctp_auth_recv_cid() when auth_chunk is NULL: +if authentication is required, return false to drop the chunk; +otherwise continue normally. + +Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk") +Signed-off-by: Qing Luo +Acked-by: Xin Long +Link: https://patch.msgid.link/20260721015532.120157-2-l1138897701@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/sm_statefuns.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 96e92719ff4df3..818878f484a795 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -641,7 +641,7 @@ static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, + struct sctp_chunk auth; + + if (!chunk->auth_chunk) +- return true; ++ return !sctp_auth_recv_cid(chunk->chunk_hdr->type, asoc); + + /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo + * is supposed to be authenticated and we have to do delayed +-- +2.53.0 + diff --git a/queue-6.12/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch b/queue-6.12/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch new file mode 100644 index 0000000000..67972ddafe --- /dev/null +++ b/queue-6.12/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch @@ -0,0 +1,46 @@ +From a79558e64834b17291f0c0632322cc693c650875 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 03:20:21 +0000 +Subject: sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid + +From: HanQuan + +[ Upstream commit ff04b26794a16a8a879eb4fd2c02c2d6b03850e9 ] + +sctp_auth_ep_add_chunkid() uses SCTP_NUM_CHUNK_TYPES (20) as the +capacity limit for ep->auth_chunk_list, allowing it to hold up to +20 chunk entries (param_hdr.length up to 24). However, the copy +destination asoc->c.auth_chunks in struct sctp_cookie is only +SCTP_AUTH_MAX_CHUNKS (16) entries (20 bytes). When more than 16 +chunks are added, sctp_association_init() memcpy overflows the +destination by up to 4 bytes. + +Fix by using SCTP_AUTH_MAX_CHUNKS as the capacity limit, matching +the destination capacity. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Signed-off-by: HanQuan +Acked-by: Xin Long +Link: https://patch.msgid.link/20260713032021.3491702-1-zhoujian.zja@antgroup.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/auth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index c58fffc86a0c2d..8320764b16b928 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -766,7 +766,7 @@ int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) + /* Check if we can add this chunk to the array */ + param_len = ntohs(p->param_hdr.length); + nchunks = param_len - sizeof(struct sctp_paramhdr); +- if (nchunks == SCTP_NUM_CHUNK_TYPES) ++ if (nchunks == SCTP_AUTH_MAX_CHUNKS) + return -EINVAL; + + p->chunks[nchunks] = chunk_id; +-- +2.53.0 + diff --git a/queue-6.12/sctp-validate-stream-count-in-sctp_process_strreset_.patch b/queue-6.12/sctp-validate-stream-count-in-sctp_process_strreset_.patch new file mode 100644 index 0000000000..0911128c6a --- /dev/null +++ b/queue-6.12/sctp-validate-stream-count-in-sctp_process_strreset_.patch @@ -0,0 +1,80 @@ +From f415c25eaf64a28aa3a909cd15ef2f6edfc9bf54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 21:07:18 -0400 +Subject: sctp: validate stream count in sctp_process_strreset_inreq() + +From: Cen Zhang (Microsoft) + +[ Upstream commit 18ae07691d43183d270de8be9dc8e027906015d9 ] + +When processing a RESET_IN_REQUEST from a peer, +sctp_process_strreset_inreq() derives the stream count from the +parameter length but does not check whether the resulting +RESET_OUT_REQUEST would exceed SCTP_MAX_CHUNK_LEN. + +The OUT request header (sctp_strreset_outreq, 16 bytes) is 8 bytes +larger than the IN request header (sctp_strreset_inreq, 8 bytes). +Generally, the IP payload is bounded to 65535 bytes, so the stream +list cannot be large enough to trigger the overflow. However, on +interfaces with MTU > 65535 (e.g., loopback with IPv6 jumbograms), a +stream list that fits within the incoming IN parameter can cause a +__u16 overflow in sctp_make_strreset_req() when computing the OUT +request size, leading to an undersized skb allocation and a kernel +BUG: + + net/core/skbuff.c:207 skb_panic + net/core/skbuff.c:2625 skb_put + net/sctp/sm_make_chunk.c:1535 sctp_addto_chunk + net/sctp/sm_make_chunk.c:3695 sctp_make_strreset_req + net/sctp/stream.c:655 sctp_process_strreset_inreq + +The local setsockopt path validates the generated reset request size. +However, for an incoming-only reset, it accounts for the smaller IN +request even though the peer must generate an OUT request with the same +stream list. Such a request cannot be completed successfully by the +peer. + +Reject peer IN requests whose corresponding OUT request would exceed +SCTP_MAX_CHUNK_LEN. Also tighten the local check so it does not send an +IN request that would require an oversized OUT request from the peer. + +Fixes: 7f9d68ac944e ("sctp: implement sender-side procedures for SSN Reset Request Parameter") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/20260707203215.2752-1-blbllhy@gmail.com/ +Suggested-by: Xin Long +Signed-off-by: Cen Zhang (Microsoft) +Acked-by: Xin Long +Link: https://patch.msgid.link/20260710010718.20318-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/stream.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/stream.c b/net/sctp/stream.c +index e8922f350bafe6..0f81820c730bae 100644 +--- a/net/sctp/stream.c ++++ b/net/sctp/stream.c +@@ -308,7 +308,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc, + goto out; + + param_len += str_nums * sizeof(__u16) + +- sizeof(struct sctp_strreset_inreq); ++ (out ? sizeof(struct sctp_strreset_inreq) ++ : sizeof(struct sctp_strreset_outreq)); + } + + if (param_len > SCTP_MAX_CHUNK_LEN - +@@ -639,6 +640,9 @@ struct sctp_chunk *sctp_process_strreset_inreq( + + nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16); + str_p = inreq->list_of_streams; ++ if (nums * sizeof(__u16) + sizeof(struct sctp_strreset_outreq) > ++ SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_reconf_chunk)) ++ goto out; + for (i = 0; i < nums; i++) { + if (ntohs(str_p[i]) >= stream->outcnt) { + result = SCTP_STRRESET_ERR_WRONG_SSN; +-- +2.53.0 + diff --git a/queue-6.12/selftests-af_unix-add-user_ns-config.patch b/queue-6.12/selftests-af_unix-add-user_ns-config.patch new file mode 100644 index 0000000000..cc44989ee9 --- /dev/null +++ b/queue-6.12/selftests-af_unix-add-user_ns-config.patch @@ -0,0 +1,40 @@ +From 37bdea656bc5c1f62bd710fce2f271362e718a6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:41 +0200 +Subject: selftests: af_unix: add USER_NS config + +From: Matthieu Baerts (NGI0) + +[ Upstream commit f8b1abed736111f914b2c567d9a3db1f71e788e8 ] + +This is required to use unshare(CLONE_NEWUSER). + +This has not been seen on NIPA before, because the 'af_unix' tests are +executed with the 'net' ones, merging their config files. USER_NS is +present in tools/testing/selftests/net/config. + +This issue is visible when only the af_unix config is used on top of the +default one. This is the recommended way to execute selftest targets. + +Fixes: ac011361bd4f ("af_unix: Add test for sock_diag and UDIAG_SHOW_UID.") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-1-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/af_unix/config | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/net/af_unix/config b/tools/testing/selftests/net/af_unix/config +index 37368567768cc0..9c4fb9c31c9506 100644 +--- a/tools/testing/selftests/net/af_unix/config ++++ b/tools/testing/selftests/net/af_unix/config +@@ -1,3 +1,4 @@ + CONFIG_UNIX=y + CONFIG_AF_UNIX_OOB=y + CONFIG_UNIX_DIAG=m ++CONFIG_USER_NS=y +-- +2.53.0 + diff --git a/queue-6.12/selftests-openvswitch-add-config-file.patch b/queue-6.12/selftests-openvswitch-add-config-file.patch new file mode 100644 index 0000000000..bb26fb7065 --- /dev/null +++ b/queue-6.12/selftests-openvswitch-add-config-file.patch @@ -0,0 +1,59 @@ +From 8bc84922912a63d93b7ff758b03f232fcb0c31fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:42 +0200 +Subject: selftests: openvswitch: add config file + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 441a820ccef9af80a9ac5a4c85b9c396e595967c ] + +The kselftests doc mentions that a config file should be present "if a +test needs specific kernel config options enabled". This selftest +requires some kernel config, but no config file was provided. + +We could say that a sub-target could use the parent's config file, but +the kselftests doc doesn't mention anything about that. Plus the +net/openvswitch target is the only net target without a config file. + +Here is a new config file, which is a trimmed version of the net one, +with hopefully the minimal required kconfig on top of 'make defconfig'. + +The Fixes tag points to the introduction of the net/openvswitch target, +just to help validating this target on stable kernels. + +Fixes: 25f16c873fb1 ("selftests: add openvswitch selftest suite") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Eelco Chaudron +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-2-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/openvswitch/config | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + create mode 100644 tools/testing/selftests/net/openvswitch/config + +diff --git a/tools/testing/selftests/net/openvswitch/config b/tools/testing/selftests/net/openvswitch/config +new file mode 100644 +index 00000000000000..c659749cd086c7 +--- /dev/null ++++ b/tools/testing/selftests/net/openvswitch/config +@@ -0,0 +1,16 @@ ++CONFIG_GENEVE=m ++CONFIG_INET_DIAG=y ++CONFIG_IPV6=y ++CONFIG_NETFILTER=y ++CONFIG_NET_IPGRE=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_OVS=y ++CONFIG_OPENVSWITCH=m ++CONFIG_OPENVSWITCH_GENEVE=m ++CONFIG_OPENVSWITCH_GRE=m ++CONFIG_OPENVSWITCH_VXLAN=m ++CONFIG_PSAMPLE=m ++CONFIG_VETH=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VXLAN=m +-- +2.53.0 + diff --git a/queue-6.12/series b/queue-6.12/series index db6b2dc0e5..193c9516ab 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -133,3 +133,120 @@ crypto-rsa-pkcs1pad-don-t-warn-on-an-empty-digest.patch revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch risc-v-kvm-serialize-virtual-interrupt-pending-state.patch usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch +wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch +wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch +hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch +hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch +hwmon-gigabyte_waterforce-stop-device-io-before-call.patch +hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch +hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch +watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch +wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch +wifi-ath11k-flush-the-posted-write-after-writing-to-.patch +wifi-ath12k-flush-the-posted-write-after-writing-to-.patch +firewire-net-fix-fragmented-datagram-reassembly.patch +wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch +wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch +wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch +wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch +wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch +btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch +btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch +btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch +asoc-tas2781-bound-firmware-description-string-parsi.patch +alsa-hda-cs35l41-fix-null-pointer-dereference-in-cs3.patch +alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch +asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch +asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch +asoc-cs35l56-fix-potential-probe-deadlock.patch +asoc-cs35l56-use-complete_all-to-signal-init_complet.patch +wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch +wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch +usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch +drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch +hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch +hwmon-asus-ec-sensors-fix-ec-read-intervals.patch +hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch +smb-client-validate-dfs-referral-pathconsumed.patch +hwmon-occ-validate-poll-response-sensor-blocks.patch +regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch +bluetooth-btusb-validate-realtek-vendor-event-length.patch +netlink-specs-rt-link-convert-bridge-port-flag-attri.patch +net-packet-avoid-fanout-hook-re-registration-after-u.patch +bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch +rds-drop-incoming-messages-that-cross-network-namesp.patch +gtp-parse-extension-headers-before-reading-inner-pro.patch +dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch +dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch +iommu-amd-wait-for-completion-instead-of-returning-e.patch +wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch +nfp-check-resource-mutex-allocation.patch +wan-wanxl-only-reset-hardware-after-bar-mapping.patch +wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch +iommu-amd-bound-the-early-acpi-hid-map.patch +iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch +wifi-mac80211-recalculate-tim-when-a-station-enters-.patch +pds_core-reject-component-parameter-in-legacy-firmwa.patch +amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch +net-txgbe-fix-fdir-filter-leak-on-remove.patch +sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch +pds_core-fix-deadlock-between-reset-thread-and-remov.patch +pds_core-fix-use-after-free-on-workqueue-during-remo.patch +pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch +pds_core-order-completion-reads-after-the-ownership-.patch +pds_core-fix-auxiliary-device-add-del-races.patch +pds_core-check-for-workqueue-allocation-failure.patch +sctp-validate-stream-count-in-sctp_process_strreset_.patch +net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch +tls-device-push-pending-open-record-on-splice-eof.patch +selftests-af_unix-add-user_ns-config.patch +selftests-openvswitch-add-config-file.patch +gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch +nexthop-initialize-extack-in-nh_res_bucket_migrate.patch +tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch +wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch +wifi-mt76-mt7915-guard-he-capability-lookups.patch +wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch +wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch +wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch +wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch +wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch +wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch +ovl-fix-trusted-xattr-escape-prefix-matching.patch +amt-re-read-skb-header-pointers-after-every-pull.patch +amt-make-the-head-writable-before-rewriting-the-l2-h.patch +net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch +net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch +net-dpaa-fix-mode-setting.patch +sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch +vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch +iomap-correct-the-range-of-a-partial-dirty-clear.patch +tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch +drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch +net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch +net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch +net-stmmac-enable-the-mac-on-link-up-for-all-support.patch +net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch +octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch +ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch +ppp-use-iff_no_queue-in-virtual-interfaces.patch +ppp-convert-to-percpu-netstats.patch +ppp-enable-tx-scatter-gather.patch +ppp-annotate-data-races-in-ppp_generic.patch +hinic-remove-unused-ethtool-rss-user-configuration-b.patch +net-qrtr-restrict-socket-creation-to-the-initial-net.patch +dpll-add-clock-quality-level-attribute-and-op.patch +net-mlx5-dpll-add-clock-quality-level-op-implementat.patch +net-mlx5-remove-newline-at-the-end-of-a-netlink-erro.patch +net-mlx5-refactor-eeprom-query-error-handling-to-ret.patch +net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch +net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch +net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch +net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch +octeontx2-pf-tc-fix-egress-ratelimiting.patch +net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch +ice-allow-creating-vfs-when-config_ice_switchdev.patch +ice-fix-lag-recipe-to-profile-association.patch +rds-tcp-unregister-sysctl-before-tearing-down-listen.patch +net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch +bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch diff --git a/queue-6.12/smb-client-validate-dfs-referral-pathconsumed.patch b/queue-6.12/smb-client-validate-dfs-referral-pathconsumed.patch new file mode 100644 index 0000000000..8139140397 --- /dev/null +++ b/queue-6.12/smb-client-validate-dfs-referral-pathconsumed.patch @@ -0,0 +1,97 @@ +From 3244d33075ef583a7c1a31666693700ef21fad0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 13:25:23 +0800 +Subject: smb: client: validate DFS referral PathConsumed + +From: Yichong Chen + +[ Upstream commit f6f5ee2aa33b350c671721b965251c42cebb962e ] + +parse_dfs_referrals() validates that the response contains the fixed +referral entry array and, on for-next, the per-referral string offsets. +However, the response also contains a PathConsumed value that is later +used for DFS path parsing. + +If a malformed response provides a PathConsumed value larger than the +search name, later DFS parsing can advance beyond the end of the path. + +Validate PathConsumed against the search name length before storing it in +the parsed referral. + +Fixes: 4ecce920e13a ("CIFS: move DFS response parsing out of SMB1 code") +Reviewed-by: Paulo Alcantara (Red Hat) +Signed-off-by: Yichong Chen +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/misc.c | 34 +++++++++++++++++++++++++--------- + 1 file changed, 25 insertions(+), 9 deletions(-) + +diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c +index 713b95a2361145..ce8f3fdffc3bda 100644 +--- a/fs/smb/client/misc.c ++++ b/fs/smb/client/misc.c +@@ -954,6 +954,8 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + int i, rc = 0; + char *data_end; + struct dfs_referral_level_3 *ref; ++ unsigned int path_consumed; ++ size_t search_name_len; + + if (rsp_size < sizeof(*rsp)) { + cifs_dbg(VFS | ONCE, +@@ -1001,6 +1003,7 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + rc = -ENOMEM; + goto parse_DFS_referrals_exit; + } ++ search_name_len = strlen(searchName); + + /* collect necessary data from referrals */ + for (i = 0; i < *num_of_nodes; i++) { +@@ -1009,21 +1012,34 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + struct dfs_info3_param *node = (*target_nodes)+i; + + node->flags = le32_to_cpu(rsp->DFSFlags); ++ path_consumed = le16_to_cpu(rsp->PathConsumed); + if (is_unicode) { +- __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, +- GFP_KERNEL); +- if (tmp == NULL) { ++ size_t search_name_utf16_len = search_name_len * 2 + 2; ++ __le16 *tmp; ++ ++ if (path_consumed > search_name_utf16_len) { ++ rc = -EINVAL; ++ goto parse_DFS_referrals_exit; ++ } ++ ++ tmp = kmalloc(search_name_utf16_len, GFP_KERNEL); ++ if (!tmp) { + rc = -ENOMEM; + goto parse_DFS_referrals_exit; + } +- cifsConvertToUTF16((__le16 *) tmp, searchName, ++ cifsConvertToUTF16((__le16 *)tmp, searchName, + PATH_MAX, nls_codepage, remap); +- node->path_consumed = cifs_utf16_bytes(tmp, +- le16_to_cpu(rsp->PathConsumed), +- nls_codepage); ++ node->path_consumed = cifs_utf16_bytes(tmp, path_consumed, ++ nls_codepage); + kfree(tmp); +- } else +- node->path_consumed = le16_to_cpu(rsp->PathConsumed); ++ } else { ++ if (path_consumed > search_name_len) { ++ rc = -EINVAL; ++ goto parse_DFS_referrals_exit; ++ } ++ ++ node->path_consumed = path_consumed; ++ } + + node->server_type = le16_to_cpu(ref->ServerType); + node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); +-- +2.53.0 + diff --git a/queue-6.12/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch b/queue-6.12/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch new file mode 100644 index 0000000000..20f127a5e4 --- /dev/null +++ b/queue-6.12/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch @@ -0,0 +1,47 @@ +From 919da3248a2a86a683f1a9e331d4ce12e81e8b47 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:49:35 -0300 +Subject: tipc: fix infinite loop in __tipc_nl_compat_dumpit + +From: Helen Koike + +[ Upstream commit 22f8aa35964e8f2ab026578f45befc9605fd1b28 ] + +cmd->dumpit callback can return a negative errno, causing an infinite +loop due to the while(len) condition. As the loop never terminates, +genl_mutex is never released, and other tasks waiting on it starve in D +state. + +Check dumpit's return value, propagate it and jump to err_out on error. + +Reported-by: syzbot+85d0bec020d805014a3a@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=85d0bec020d805014a3a +Fixes: d0796d1ef63d ("tipc: convert legacy nl bearer dump to nl compat") +Signed-off-by: Helen Koike +Reviewed-by: Tung Nguyen +Link: https://patch.msgid.link/20260713204940.647668-1-koike@igalia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/netlink_compat.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c +index 079aebb16ed8ff..30e37c05a3f334 100644 +--- a/net/tipc/netlink_compat.c ++++ b/net/tipc/netlink_compat.c +@@ -222,6 +222,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, + int rem; + + len = (*cmd->dumpit)(buf, &cb); ++ if (len < 0) { ++ err = len; ++ goto err_out; ++ } + + nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) { + err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN, +-- +2.53.0 + diff --git a/queue-6.12/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch b/queue-6.12/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch new file mode 100644 index 0000000000..51dc722674 --- /dev/null +++ b/queue-6.12/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch @@ -0,0 +1,72 @@ +From 535eafce0a34b9e31b81ea30d9d5aa522041b746 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 00:15:41 -0400 +Subject: tipc: fix u16 MTU truncation in media and bearer MTU validation + +From: Cen Zhang (Microsoft) + +[ Upstream commit 9f29cd8a8e7901a2617c8064ce9f50fc67b97cb8 ] + +Both TIPC_NL_MEDIA_SET and TIPC_NL_BEARER_SET accept user-supplied +MTU values but only enforce a minimum bound, not a maximum. When a user +sets the MTU to a value exceeding U16_MAX (65535), it passes validation +but is silently truncated when assigned to u16 fields l->mtu and +l->advertised_mtu in tipc_link_create(). Values like 65536 (0x10000) +truncate to 0, causing a division by zero in tipc_link_set_queue_limits() +which computes TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE). Other overflowing +values (e.g. 65537-131071) produce small incorrect MTU values, resulting +in link malfunction behaviors. + +Crash stack (triggered as unprivileged user via user namespace): + + tipc_link_set_queue_limits net/tipc/link.c:2531 + tipc_link_create net/tipc/link.c:520 + tipc_node_check_dest net/tipc/node.c:1279 + tipc_disc_rcv net/tipc/discover.c:252 + tipc_rcv net/tipc/node.c:2129 + tipc_udp_recv net/tipc/udp_media.c:392 + +Two independent paths lack the upper bound check: +1. tipc_udp_mtu_bad() -- called from __tipc_nl_media_set() (MEDIA_SET) +2. inline check in __tipc_nl_bearer_set() at bearer.c:1160 (BEARER_SET) + +Fix both by rejecting MTU values above U16_MAX. + +Fixes: 901271e0403a ("tipc: implement configuration of UDP media MTU") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/CAB8m9WgETt0AjmFwE=F-CKjGXsK6_WDv0=kbYRcC8-noo+amnA@mail.gmail.com +Reviewed-by: Vadim Fedorenko +Signed-off-by: Cen Zhang (Microsoft) +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260714041541.307702-1-blbllhy@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tipc/netlink.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c +index 8336a9664703fe..1307dd1a961341 100644 +--- a/net/tipc/netlink.c ++++ b/net/tipc/netlink.c +@@ -113,12 +113,16 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { + }; + + /* Properties valid for media, bearer and link */ ++static const struct netlink_range_validation tipc_nl_mtu_range = { ++ .max = U16_MAX, ++}; ++ + const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { + [TIPC_NLA_PROP_UNSPEC] = { .type = NLA_UNSPEC }, + [TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 }, +- [TIPC_NLA_PROP_MTU] = { .type = NLA_U32 }, ++ [TIPC_NLA_PROP_MTU] = NLA_POLICY_FULL_RANGE(NLA_U32, &tipc_nl_mtu_range), + [TIPC_NLA_PROP_BROADCAST] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_BROADCAST_RATIO] = { .type = NLA_U32 } + }; +-- +2.53.0 + diff --git a/queue-6.12/tls-device-push-pending-open-record-on-splice-eof.patch b/queue-6.12/tls-device-push-pending-open-record-on-splice-eof.patch new file mode 100644 index 0000000000..af795d3215 --- /dev/null +++ b/queue-6.12/tls-device-push-pending-open-record-on-splice-eof.patch @@ -0,0 +1,56 @@ +From 67005bd16303a306c245cb7031f39966b67fae1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 16:44:36 -0600 +Subject: tls: device: push pending open record on splice EOF + +From: Rishikesh Jethwani + +[ Upstream commit eaa39f9f8ac8c1d032cd26b9cd572804e9d7683f ] + +On kTLS device-offload sockets, sendfile() with count > EOF can reach +->splice_eof() with a fully assembled but still-open TLS record left +pending. tls_device_splice_eof() only flushes partially sent records, +so an abrupt close() can drop the final record and the peer receives +a short file. + +Fix tls_device_splice_eof() to also push pending open records. +This matches the software path, where splice EOF already flushes +pending open records. + +Fixes: d4c1e80b0d1b ("tls/device: Use splice_eof() to flush") +Link: https://lore.kernel.org/netdev/CAMPsyauZ+jzG9AysO0FWv6ZY0kvCUpjX_U7o=oOjCuOQ87BCgg@mail.gmail.com/ +Reported-by: Nils Juenemann +Signed-off-by: Rishikesh Jethwani +Tested-by: Nils Juenemann +Link: https://patch.msgid.link/20260709224436.1608993-2-rjethwani@purestorage.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tls/tls_device.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c +index 5c6a4c9a2df755..942edc9b3157af 100644 +--- a/net/tls/tls_device.c ++++ b/net/tls/tls_device.c +@@ -594,13 +594,15 @@ void tls_device_splice_eof(struct socket *sock) + struct tls_context *tls_ctx = tls_get_ctx(sk); + struct iov_iter iter = {}; + +- if (!tls_is_partially_sent_record(tls_ctx)) ++ if (!tls_is_partially_sent_record(tls_ctx) && ++ !tls_is_pending_open_record(tls_ctx)) + return; + + mutex_lock(&tls_ctx->tx_lock); + lock_sock(sk); + +- if (tls_is_partially_sent_record(tls_ctx)) { ++ if (tls_is_partially_sent_record(tls_ctx) || ++ tls_is_pending_open_record(tls_ctx)) { + iov_iter_bvec(&iter, ITER_SOURCE, NULL, 0, 0); + tls_push_data(sk, &iter, 0, 0, TLS_RECORD_TYPE_DATA); + } +-- +2.53.0 + diff --git a/queue-6.12/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch b/queue-6.12/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch new file mode 100644 index 0000000000..ceba257b70 --- /dev/null +++ b/queue-6.12/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch @@ -0,0 +1,93 @@ +From ed83e58737ab2d8359086bb6f4b61feab5da9710 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 02:07:04 -0600 +Subject: usb: atm: ueagle-atm: reject descriptors that confuse probe and + disconnect + +From: Diego Fernando Mancera Gomez + +[ Upstream commit 71132cedd1ecbc4032d76e9928c18a10f7e39b80 ] + +uea_probe() distinguishes a pre-firmware device from a post-firmware one +using the USB id (UEA_IS_PREFIRM()), and stores a different object as the +interface data in each case: a 'struct completion' for a pre-firmware +device (to be waited on in .disconnect()), or a 'struct usbatm_data' for a +post-firmware one. + +uea_disconnect() instead tells the two apart by the number of interfaces +of the active configuration (a pre-firmware device exposes a single +interface, ADI930 has 2 and eagle has 3), and casts the interface data +accordingly. + +Because the two handlers use different criteria, a crafted device that +advertises a pre-firmware id together with a multi-interface descriptor +(or a post-firmware id with a single interface) makes them disagree: the +small 'struct completion' stored by uea_probe() is then passed to +usbatm_usb_disconnect(), which casts it to 'struct usbatm_data' and takes +instance->serialize, reading past the end of the allocation: + + BUG: KASAN: slab-out-of-bounds in __mutex_lock+0x152a/0x1b80 + Read of size 8 at addr ffff8880470e2c60 by task kworker/1:2/982 + ... + __mutex_lock+0x152a/0x1b80 + usbatm_usb_disconnect+0x70/0x820 + uea_disconnect+0x133/0x2c0 + usb_unbind_interface+0x1dd/0x9e0 + ... + which belongs to the cache kmalloc-96 of size 96 + The buggy address is located 0 bytes to the right of + allocated 96-byte region [ffff8880470e2c00, ffff8880470e2c60) + +Reject such inconsistent descriptors in uea_probe() so that both handlers +always make the same pre/post-firmware decision. + +Reported-by: syzbot+e62a973f8322b3bbe3ac@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e62a973f8322b3bbe3ac +Fixes: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()") +Signed-off-by: Diego Fernando Mancera Gomez +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260717080704.1264-1-diegomancera.dev@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/atm/ueagle-atm.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c +index cd53d36aa30748..dad42820814022 100644 +--- a/drivers/usb/atm/ueagle-atm.c ++++ b/drivers/usb/atm/ueagle-atm.c +@@ -2590,6 +2590,7 @@ static struct usbatm_driver uea_usbatm_driver = { + static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + { + struct usb_device *usb = interface_to_usbdev(intf); ++ bool single_iface = usb->config->desc.bNumInterfaces == 1; + int ret; + + uea_enters(usb); +@@ -2599,6 +2600,22 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + le16_to_cpu(usb->descriptor.bcdDevice), + chip_name[UEA_CHIP_VERSION(id)]); + ++ /* ++ * uea_probe() decides between the pre-firmware and post-firmware case ++ * from the USB id and stores a different object as interface data in ++ * each case: a struct completion for a pre-firmware device, a struct ++ * usbatm_data for a post-firmware one. uea_disconnect() instead tells ++ * the two apart by the number of interfaces (a pre-firmware device ++ * exposes a single interface, ADI930 has 2 and eagle has 3). A crafted ++ * device advertising a pre-firmware id together with a multi-interface ++ * descriptor (or the other way around) makes the two disagree, so that ++ * usbatm_usb_disconnect() treats the small completion object as a ++ * struct usbatm_data and reads out of bounds. Reject such inconsistent ++ * descriptors so both paths make the same decision. ++ */ ++ if (UEA_IS_PREFIRM(id) != single_iface) ++ return -ENODEV; ++ + usb_reset_device(usb); + + if (UEA_IS_PREFIRM(id)) { +-- +2.53.0 + diff --git a/queue-6.12/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch b/queue-6.12/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch new file mode 100644 index 0000000000..c756c1a9ed --- /dev/null +++ b/queue-6.12/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch @@ -0,0 +1,84 @@ +From 31dd595358762d7e9fedb15e08aaa6026ec3de2a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 07:09:15 -0700 +Subject: vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets + +From: Harshaka Narayana + +[ Upstream commit 34a71f5361fc3adb5b7138da78750b0d535a8252 ] + +vmxnet3_get_hdr_len() assumes gdesc->rcd.v4/v6/tcp always describe the +outer header, but for a Geneve-encapsulated packet the device can set +them based on the inner header instead, signalled by the +VMXNET3_RCD_HDR_INNER_SHIFT bit in the completion descriptor. Since the +function never skips the outer encapsulation, this mismatch triggers: + +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP), because the outer + protocol is UDP (Geneve), not TCP. +- BUG_ON(hdr.eth->h_proto != ...), when the tunnel's outer and inner + IP versions differ (e.g. outer IPv6/inner IPv4 or vice versa). + +Check VMXNET3_RCD_HDR_INNER_SHIFT up front and bail out, since the +function cannot locate the inner header it would need to parse. Also +convert the remaining BUG_ON()s in this function to return 0 +defensively. + +Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)") +Signed-off-by: Harshaka Narayana +Reviewed-by: Ronak Doshi +Reviewed-by: Sankararaman Jayaraman +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260713140915.3381715-1-harshaka.narayana@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c +index e1e472b3a301ef..538738231a5a95 100644 +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -1518,7 +1518,11 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + struct ipv6hdr *ipv6; + struct tcphdr *tcp; + } hdr; +- BUG_ON(gdesc->rcd.tcp == 0); ++ ++ /* v4/v6/tcp then describe the inner header, which we can't locate. */ ++ if ((le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT)) || ++ gdesc->rcd.tcp == 0) ++ return 0; + + maplen = skb_headlen(skb); + if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen)) +@@ -1532,15 +1536,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + + hdr.eth = eth_hdr(skb); + if (gdesc->rcd.v4) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)); ++ if (hdr.eth->h_proto != htons(ETH_P_IP) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)) ++ return 0; ++ + hdr.ptr += hlen; +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP); ++ if (hdr.ipv4->protocol != IPPROTO_TCP) ++ return 0; ++ + hlen = hdr.ipv4->ihl << 2; + hdr.ptr += hdr.ipv4->ihl << 2; + } else if (gdesc->rcd.v6) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)); ++ if (hdr.eth->h_proto != htons(ETH_P_IPV6) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)) ++ return 0; ++ + hdr.ptr += hlen; + /* Use an estimated value, since we also need to handle + * TSO case. +-- +2.53.0 + diff --git a/queue-6.12/wan-wanxl-only-reset-hardware-after-bar-mapping.patch b/queue-6.12/wan-wanxl-only-reset-hardware-after-bar-mapping.patch new file mode 100644 index 0000000000..5930379281 --- /dev/null +++ b/queue-6.12/wan-wanxl-only-reset-hardware-after-bar-mapping.patch @@ -0,0 +1,51 @@ +From 637704dc3dfd957461aa2a152e0e5a6e8a7a78a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:15 +0800 +Subject: wan: wanxl: Only reset hardware after BAR mapping + +From: Ruoyu Wang + +[ Upstream commit 91957b89da995607cb654b1f9a3c126ddbaee10f ] + +wanxl_pci_init_one() stores the freshly allocated card in driver data +before the PLX BAR is mapped. Several early probe failures then unwind +through wanxl_pci_remove_one(), including failure to allocate the coherent +status area or to restore the DMA mask. + +wanxl_pci_remove_one() unconditionally calls wanxl_reset(), and +wanxl_reset() dereferences card->plx. On those early failures card->plx +is still NULL, so the error path can dereference a NULL MMIO pointer. + +Only issue the hardware reset once the BAR mapping exists. The remaining +cleanup in wanxl_pci_remove_one() already checks whether later resources +were allocated. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ruoyu Wang +Link: https://patch.msgid.link/20260708143415.3169358-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/wan/wanxl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c +index 5a9e262188efe1..c38dd741401e13 100644 +--- a/drivers/net/wan/wanxl.c ++++ b/drivers/net/wan/wanxl.c +@@ -514,7 +514,8 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) + if (card->irq) + free_irq(card->irq, card); + +- wanxl_reset(card); ++ if (card->plx) ++ wanxl_reset(card); + + for (i = 0; i < RX_QUEUE_LENGTH; i++) + if (card->rx_skbs[i]) { +-- +2.53.0 + diff --git a/queue-6.12/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch b/queue-6.12/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch new file mode 100644 index 0000000000..76303b7338 --- /dev/null +++ b/queue-6.12/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch @@ -0,0 +1,48 @@ +From a98ee5910fe1d33f5000ba8e08ad8cbed716b5e5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:18:03 +0000 +Subject: watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() + +From: Tzung-Bi Shih + +[ Upstream commit 7362ba0f9c96ac3ad6a2ca3995bd9fc9a28a8661 ] + +When a watchdog governor is unregistered, it updates existing watchdog +devices that were using this governor by falling back to `default_gov`. + +If the governor being unregistered is currently set as `default_gov`, +the `default_gov` is never cleared. This leads to 2 use-after-free +issues: +1. New watchdog devices registered after this point will inherit the + dangling `default_gov`. +2. Existing watchdog devices using the unregistered governor will have + their `wdd->gov` reassigned to the dangling `default_gov`. + +Fix the UAF by clearing `default_gov` if it matches the governor being +unregistered. + +Fixes: da0d12ff2b82 ("watchdog: pretimeout: add panic pretimeout governor") +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20260707101803.3598173-1-tzungbi@kernel.org +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/watchdog_pretimeout.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c +index e5295c990fa1b8..787b6227b8ccc3 100644 +--- a/drivers/watchdog/watchdog_pretimeout.c ++++ b/drivers/watchdog/watchdog_pretimeout.c +@@ -165,6 +165,8 @@ void watchdog_unregister_governor(struct watchdog_governor *gov) + } + + spin_lock_irq(&pretimeout_lock); ++ if (default_gov == gov) ++ default_gov = NULL; + list_for_each_entry(p, &pretimeout_list, entry) + if (p->wdd->gov == gov) + p->wdd->gov = default_gov; +-- +2.53.0 + diff --git a/queue-6.12/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch b/queue-6.12/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch new file mode 100644 index 0000000000..fd8208a967 --- /dev/null +++ b/queue-6.12/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch @@ -0,0 +1,68 @@ +From bcf25cf76f5e975efd59e50e154064fe4e925415 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jun 2026 17:06:09 +0800 +Subject: wifi: ath11k: fix NULL pointer dereference in + ath11k_hal_srng_access_begin + +From: Gaole Zhang + +[ Upstream commit e8d85672dd7e2523f774caafba8f858384e18df7 ] + +In ATH11K_QMI_EVENT_FW_READY, ATH11K_FLAG_REGISTERED is set +unconditionally even when ath11k_core_qmi_firmware_ready() fails. +This leaves the driver in an inconsistent state where +initialization is considered complete although the firmware ready +handling did not finish successfully. During the subsequent SSR, +the driver enters the restart path based on this incorrect state +and dereferences uninitialized srng members, resulting in a NULL +pointer dereference. + +Call trace: + ath11k_hal_srng_access_begin+0xc/0x60 [ath11k] (P) + ath11k_ce_cleanup_pipes+0x17c/0x180 [ath11k] + ath11k_core_restart+0x40/0x168 [ath11k] + +Fix this by: +- skipping firmware_ready if ATH11K_FLAG_REGISTERED is already set +- setting ATH11K_FLAG_REGISTERED only when firmware_ready succeeds +- setting ATH11K_FLAG_QMI_FAIL and aborting the FW_READY handling +on error + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.2.0.c2-00204-QCAMSLSWPLZ-1 + +Fixes: 6fe62a8cec51c ("wifi: ath11k: Add cold boot calibration support on WCN6750") +Signed-off-by: Gaole Zhang +Reviewed-by: Baochen Qiang +Reviewed-by: Rameshkumar Sundaram +Link: https://patch.msgid.link/20260609090609.4041009-1-gaole.zhang@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/qmi.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index 3ffb7723b67318..0c2527d85532fa 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -3295,9 +3295,14 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) + clear_bit(ATH11K_FLAG_CRASH_FLUSH, + &ab->dev_flags); + clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); +- ath11k_core_qmi_firmware_ready(ab); +- set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); +- ++ if (!test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { ++ ret = ath11k_core_qmi_firmware_ready(ab); ++ if (ret) { ++ set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); ++ break; ++ } ++ set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); ++ } + break; + case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE: + break; +-- +2.53.0 + diff --git a/queue-6.12/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch b/queue-6.12/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch new file mode 100644 index 0000000000..cce517fb39 --- /dev/null +++ b/queue-6.12/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch @@ -0,0 +1,48 @@ +From d70ea04095a992f126fa3631ffd0b2427104e4b6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 May 2026 11:42:52 +0000 +Subject: wifi: ath11k: fix potential buffer underflow in + ath11k_hal_rx_msdu_list_get() + +From: Dmitry Morgun + +[ Upstream commit 7f11e70629650ff6ea140984e5ce188b775b2683 ] + +When the first entry in msdu_details has a zero buffer address, +the code accesses msdu_details[i - 1] with i == 0, causing a +buffer underflow. + +Fix similarly to ath12k_wifi7_hal_rx_msdu_list_get() by adding +a separate check for i == 0 before the main condition to prevent +the out-of-bounds access. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Dmitry Morgun +Reviewed-by: Rameshkumar Sundaram +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20260530114252.42615-1-d.morgun@ispras.ru +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 78b0fa8d4f3391..6cc252d00ef130 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -4614,6 +4614,9 @@ static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar, + msdu_details = &msdu_link->msdu_link[0]; + + for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) { ++ if (!i && FIELD_GET(BUFFER_ADDR_INFO0_ADDR, ++ msdu_details[i].buf_addr_info.info0) == 0) ++ break; + if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR, + msdu_details[i].buf_addr_info.info0) == 0) { + msdu_desc_info = &msdu_details[i - 1].rx_msdu_info; +-- +2.53.0 + diff --git a/queue-6.12/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch b/queue-6.12/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch new file mode 100644 index 0000000000..07e1ba312a --- /dev/null +++ b/queue-6.12/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch @@ -0,0 +1,60 @@ +From f891ca10a8779c7bb9e59c050e6d000d6497f562 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 16:16:48 +0200 +Subject: wifi: ath11k: Flush the posted write after writing to + PCIE_SOC_GLOBAL_RESET + +From: Manivannan Sadhasivam + +[ Upstream commit 0fe8010fc5b147607fc19ba010ba469afc95f35f ] + +ath11k_pci_soc_global_reset() tries to reset the device by writing to the +PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure +that the write gets flushed to the device before the delay. + +This may lead to the delay on the host to be insufficient, if the posted +write doesn't reach the device before the delay. + +So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and +before the delay. + +Compile tested only. + +Fixes: f3c603d412b3 ("ath11k: reset MHI during power down and power up") +Reported-by: Alex Williamson +Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Reviewed-by: Raj Kumar Bhagat +Link: https://patch.msgid.link/20260623141649.41087-1-manivannan.sadhasivam@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c +index eee83eb6b2c3c0..6b0e52a6fb89b6 100644 +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -197,6 +197,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) + val |= PCIE_SOC_GLOBAL_RESET_V; + + ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); + + /* TODO: exact time to sleep is uncertain */ + delay = 10; +@@ -206,6 +208,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) + val &= ~PCIE_SOC_GLOBAL_RESET_V; + + ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); + + mdelay(delay); + +-- +2.53.0 + diff --git a/queue-6.12/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch b/queue-6.12/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch new file mode 100644 index 0000000000..942a76e0bf --- /dev/null +++ b/queue-6.12/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch @@ -0,0 +1,62 @@ +From ed93700ebcd8d15a729ea98f2b03e7cb12f331c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 16:16:49 +0200 +Subject: wifi: ath12k: Flush the posted write after writing to + PCIE_SOC_GLOBAL_RESET + +From: Manivannan Sadhasivam + +[ Upstream commit 55f3aa06951cac78b0206bde961c8cf11929a27a ] + +ath12k_pci_soc_global_reset() tries to reset the device by writing to the +PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure +that the write gets flushed to the device before the delay. + +This may lead to the delay on the host to be insufficient, if the posted +write doesn't reach the device before the delay. + +So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and +before the delay. + +Compile tested only. +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1 + +Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") +Reported-by: Alex Williamson +Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Reviewed-by: Raj Kumar Bhagat +Tested-by: Raj Kumar Bhagat +Link: https://patch.msgid.link/20260623141649.41087-2-manivannan.sadhasivam@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c +index 0ac92a606cea0c..4ba0c1bb32341b 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -225,6 +225,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab) + val |= PCIE_SOC_GLOBAL_RESET_V; + + ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET); + + /* TODO: exact time to sleep is uncertain */ + delay = 10; +@@ -234,6 +236,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab) + val &= ~PCIE_SOC_GLOBAL_RESET_V; + + ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET); + + mdelay(delay); + +-- +2.53.0 + diff --git a/queue-6.12/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch b/queue-6.12/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch new file mode 100644 index 0000000000..f08aea19bb --- /dev/null +++ b/queue-6.12/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch @@ -0,0 +1,49 @@ +From f246b9f18288691851704bb891619744bed18c76 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:50:08 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware IE lengths in connect event + +From: Tristan Madani + +[ Upstream commit 6b47b29730de3232b919d8362749f6814c5f2a33 ] + +The firmware-controlled beacon_ie_len, assoc_req_len, and assoc_resp_len +fields in ath6kl_wmi_connect_event_rx() are not validated against the +buffer length. Their sum (up to 765) can exceed the actual WMI event +data, causing out-of-bounds reads during IE parsing and state corruption +of wmi->is_wmm_enabled. + +Add a check that the total IE length fits within the buffer. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20260421135009.348084-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index a572952dd4b903..447896b871c3e2 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -874,6 +874,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, + + ev = (struct wmi_connect_event *) datap; + ++ if (len < sizeof(*ev) + ev->beacon_ie_len + ++ ev->assoc_req_len + ev->assoc_resp_len) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, ++ "connect event: IE lengths %u+%u+%u exceed buffer %d\n", ++ ev->beacon_ie_len, ev->assoc_req_len, ++ ev->assoc_resp_len, len); ++ return -EINVAL; ++ } + if (vif->nw_type == AP_NETWORK) { + /* AP mode start/STA connected event */ + struct net_device *dev = vif->ndev; +-- +2.53.0 + diff --git a/queue-6.12/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch b/queue-6.12/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch new file mode 100644 index 0000000000..8dc9fbfb6c --- /dev/null +++ b/queue-6.12/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch @@ -0,0 +1,53 @@ +From 75cb351e30b113b5f9082d0667427e0418d41e19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jun 2026 23:29:07 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware num_msg in TX complete + handler + +From: Tristan Madani + +[ Upstream commit 3a21c89215cc18f1a97c5e5bfd1da6d4f3d44495 ] + +The firmware-controlled num_msg field (u8, 0-255) drives the loop in +ath6kl_wmi_tx_complete_event_rx() without validation against the buffer +length. This allows out-of-bounds reads of up to 1020 bytes past the +WMI event buffer when the firmware sends an inflated num_msg. + +Add a check that the buffer is large enough to hold the fixed struct +and the num_msg variable-length entries. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Link: https://patch.msgid.link/20260625232907.3620746-1-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index 3787b9fb007559..a572952dd4b903 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -484,6 +484,18 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) + + evt = (struct wmi_tx_complete_event *) datap; + ++ if (len < sizeof(*evt)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d\n", ++ len); ++ return -EINVAL; ++ } ++ ++ if (len < sizeof(*evt) + evt->num_msg * sizeof(struct tx_complete_msg_v1)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d for %u msgs\n", ++ len, evt->num_msg); ++ return -EINVAL; ++ } ++ + ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", + evt->num_msg, evt->msg_len, evt->msg_type); + +-- +2.53.0 + diff --git a/queue-6.12/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch b/queue-6.12/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch new file mode 100644 index 0000000000..49483b9a28 --- /dev/null +++ b/queue-6.12/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch @@ -0,0 +1,90 @@ +From 12911b8701f474b179fd1e40dba473d1fdb82b26 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 08:32:10 -0700 +Subject: wifi: ath9k: hif_usb: don't dereference hif_dev after re-arming + firmware request +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Cheng Yongkang + +[ Upstream commit dad9f96945d77ecd4708f730c06ef54dcd8cc057 ] + +ath9k_hif_request_firmware() re-arms an asynchronous firmware load via +request_firmware_nowait(), passing hif_dev as the completion context, and +then still dereferences hif_dev: + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", + hif_dev->fw_name); + +The re-armed callback ath9k_hif_usb_firmware_cb() runs on the "events" +workqueue and, when the firmware is missing, walks the retry chain into +ath9k_hif_usb_firmware_fail() -> complete_all(&hif_dev->fw_done). That +releases the wait_for_completion(&hif_dev->fw_done) in a concurrent +ath9k_hif_usb_disconnect(), which then kfree()s hif_dev. The trailing +dev_info() in the frame that re-armed the request can therefore read freed +memory (hif_dev->udev, the first field of struct hif_device_usb): + + BUG: KASAN: slab-use-after-free in ath9k_hif_request_firmware + Read of size 8 ... by task kworker/... + ath9k_hif_request_firmware + ath9k_hif_usb_firmware_cb drivers/net/wireless/ath/ath9k/hif_usb.c:1247 + request_firmware_work_func + Allocated by ...: + ath9k_hif_usb_probe drivers/net/wireless/ath/ath9k/hif_usb.c + Freed by ...: + ath9k_hif_usb_disconnect -> kfree drivers/net/wireless/ath/ath9k/hif_usb.c + +The fw_done barrier only makes disconnect wait for the firmware chain to +*terminate*; it does not protect the outer ath9k_hif_request_firmware() +frame that re-armed the request and keeps touching hif_dev afterwards. + +Drop the post-request dev_info(): it is the only use of hif_dev after the +async request is armed, and it is purely informational (the dev_err() on the +failure path runs only when request_firmware_nowait() did not arm a callback, +so hif_dev is still alive there). + +This was first reported by syzbot as a single, non-reproduced crash that was +later auto-obsoleted, and was independently rediscovered by the reFuzz fuzzer, +which produced a C reproducer (USB-gadget connect/disconnect of an ath9k_htc +device whose firmware download fails). The vulnerable code is unchanged and +still present in v7.1-rc6, where the slab-use-after-free reproduces under KASAN +once the (sub-microsecond) race window is widened. + +Fixes: e904cf6fe230 ("ath9k_htc: introduce support for different fw versions") +Reported-by: syzbot+50122cbc2874b1eb25b0@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=50122cbc2874b1eb25b0 +Signed-off-by: Cheng Yongkang +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260605153210.20471-1-1020691186@qq.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index 7265766cddbdeb..dbf94333664ec5 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -1225,15 +1225,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, + ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, + &hif_dev->udev->dev, GFP_KERNEL, + hif_dev, ath9k_hif_usb_firmware_cb); +- if (ret) { ++ if (ret) + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Async request for firmware %s failed\n", + hif_dev->fw_name); +- return ret; +- } +- +- dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", +- hif_dev->fw_name); + + return ret; + } +-- +2.53.0 + diff --git a/queue-6.12/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch b/queue-6.12/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch new file mode 100644 index 0000000000..95d314bce3 --- /dev/null +++ b/queue-6.12/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch @@ -0,0 +1,69 @@ +From e4c79c9bf9b15ab1ff9bb226de33331da06a2eb8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 May 2026 16:38:59 +0800 +Subject: wifi: brcmfmac: fix 802.1X-SHA256 call trace warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Shelley Yang + +[ Upstream commit 7cb34f6c4fe8a68af621d870abe63bfca2275dd6 ] + +Based on wpa_auth as 1x_256 mode, need to set up +"use_fwsup" with BRCMF_PROFILE_FWSUP_1X. +Or it will happen trace warning when call brcmf_cfg80211_set_pmk(). + +[ 4481.831101] ------------[ cut here ]------------ +[ 4481.831102] WARNING: CPU: 1 PID: 2997 at +drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:7242 brcmf_cfg80211_set_pmk+0x77/0xd0 [brcmfmac] +[...] +[ 4481.831202] Call Trace: +[ 4481.831204]   +[ 4481.831205]  nl80211_set_pmk+0x183/0x250 [cfg80211] +[ 4481.831233]  genl_family_rcv_msg_doit+0xea/0x150 +[ 4481.831237]  genl_rcv_msg+0x104/0x240 +[ 4481.831239]  ? cfg80211_probe_status+0x2c0/0x2c0 [cfg80211] +[ 4481.831257]  ? genl_family_rcv_msg_doit+0x150/0x150 +[ 4481.831259]  netlink_rcv_skb+0x4e/0x100 +[ 4481.831261]  genl_rcv+0x24/0x40 +[ 4481.831262]  netlink_unicast+0x236/0x380 +[ 4481.831264]  netlink_sendmsg+0x250/0x4b0 +[ 4481.831266]  sock_sendmsg+0x5c/0x70 +[ 4481.831269]  ____sys_sendmsg+0x236/0x2b0 +[ 4481.831271]  ? copy_msghdr_from_user+0x6d/0xa0 +[ 4481.831272]  ___sys_sendmsg+0x86/0xd0 +[ 4481.831274]  ? avc_has_perm+0x8c/0x1a0 +[ 4481.831276]  ? preempt_count_add+0x6a/0xa0 +[ 4481.831279]  ? sock_has_perm+0x82/0xa0 +[ 4481.831280]  __sys_sendmsg+0x57/0xa0 +[ 4481.831282]  do_syscall_64+0x38/0x90 +[ 4481.831284]  entry_SYSCALL_64_after_hwframe+0x63/0xcd +[ 4481.831286] RIP: 0033:0x7fd270d369b4 + +Fixes: 2526ff21aa77 ("brcmfmac: support 4-way handshake offloading for 802.1X") +Signed-off-by: Shelley Yang +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260525083859.581246-1-shelley.yang@infineon.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 2b8a85a7bf9eba..c3a3a081791095 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2122,7 +2122,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) + sme->crypto.akm_suites[0]); + return -EINVAL; + } +- } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { ++ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_1X_SHA256)) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + val = WPA2_AUTH_UNSPECIFIED; +-- +2.53.0 + diff --git a/queue-6.12/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch b/queue-6.12/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch new file mode 100644 index 0000000000..219d0c7010 --- /dev/null +++ b/queue-6.12/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch @@ -0,0 +1,48 @@ +From 683d68a61fe8d37102c5c49504720f153e356577 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:26 +0000 +Subject: wifi: carl9170: bound memcpy length in cmd callback to prevent OOB + read + +From: Tristan Madani + +[ Upstream commit 4cde55b2feff9504d1f993ab80e84e7ccb62791c ] + +When the firmware sends a command response with a length mismatch, +carl9170_cmd_callback() logs the mismatch and calls carl9170_restart() +but then falls through to memcpy(ar->readbuf, buffer + 4, len - 4). +Since len comes from the firmware and can exceed ar->readlen, this +copies more data than the readbuf was allocated for. + +Bound the memcpy to min(len - 4, ar->readlen) so that the response +is still completed -- avoiding repeated restarts from queued garbage -- +while preventing an overread past the response buffer. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-2-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 908c4c8b7f8256..9a25c2a540b95f 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -150,7 +150,8 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) + spin_lock(&ar->cmd_lock); + if (ar->readbuf) { + if (len >= 4) +- memcpy(ar->readbuf, buffer + 4, len - 4); ++ memcpy(ar->readbuf, buffer + 4, ++ min_t(u32, len - 4, ar->readlen)); + + ar->readbuf = NULL; + } +-- +2.53.0 + diff --git a/queue-6.12/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch b/queue-6.12/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch new file mode 100644 index 0000000000..593a8a39b1 --- /dev/null +++ b/queue-6.12/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch @@ -0,0 +1,46 @@ +From f0ae541c6a9fccded86ee665163768af23af29f7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:28 +0000 +Subject: wifi: carl9170: fix buffer overflow in rx_stream failover path + +From: Tristan Madani + +[ Upstream commit a1a21995c2e1cc2ca6b2226cfe4f5f018370182a ] + +The failover continuation in carl9170_rx_stream() copies the full tlen +from the second USB transfer instead of capping at rx_failover_missing +bytes. When both transfers are near maximum size, the total exceeds the +65535-byte failover SKB, triggering skb_over_panic. + +Limit the copy size to the missing byte count. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-4-tristmd@gmail.com +[Fix checkpatch CHECK:PARENTHESIS_ALIGNMENT] +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 9a25c2a540b95f..bda30b1f940459 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -918,7 +918,9 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) + } + } + +- skb_put_data(ar->rx_failover, tbuf, tlen); ++ skb_put_data(ar->rx_failover, tbuf, ++ min_t(unsigned int, tlen, ++ ar->rx_failover_missing)); + ar->rx_failover_missing -= tlen; + + if (ar->rx_failover_missing <= 0) { +-- +2.53.0 + diff --git a/queue-6.12/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch b/queue-6.12/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch new file mode 100644 index 0000000000..1a0b457f41 --- /dev/null +++ b/queue-6.12/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch @@ -0,0 +1,42 @@ +From fc1730af78aeb2bc3db3c56121b50069ef24382c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:27 +0000 +Subject: wifi: carl9170: fix OOB read from off-by-two in TX status handler + +From: Tristan Madani + +[ Upstream commit a3f42f1049ad80c65560d2b078ad426c3134f78d ] + +The bounds check in carl9170_tx_process_status() uses +`i > ((cmd->hdr.len / 2) + 1)` which is off by two, allowing +2 extra iterations past valid _tx_status entries when the firmware- +controlled hdr.ext exceeds hdr.len/2. Fix by using the correct +comparison `i >= (cmd->hdr.len / 2)`. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c +index 0226c31a6cae26..8280d264d5e2e8 100644 +--- a/drivers/net/wireless/ath/carl9170/tx.c ++++ b/drivers/net/wireless/ath/carl9170/tx.c +@@ -693,7 +693,7 @@ void carl9170_tx_process_status(struct ar9170 *ar, + unsigned int i; + + for (i = 0; i < cmd->hdr.ext; i++) { +- if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) { ++ if (WARN_ON(i >= (cmd->hdr.len / 2))) { + print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE, + (void *) cmd, cmd->hdr.len + 4); + break; +-- +2.53.0 + diff --git a/queue-6.12/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch b/queue-6.12/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch new file mode 100644 index 0000000000..55a82a6dda --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch @@ -0,0 +1,50 @@ +From f7cc020131e18a13ef496550e435d4067dbbf1a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:08 +0300 +Subject: wifi: iwlwifi: mvm: fix read in wake packet notification handler + +From: Shahar Tzarfati + +[ Upstream commit 9d7657aae8c1579584c67b0b66114a6a98db8b2f ] + +In iwl_mvm_wowlan_store_wake_pkt(), packet_len was initialized from +notif->wake_packet_length before the explicit check that len >= +sizeof(*notif). + +Move the assignment of packet_len to after the size check so that +notif->wake_packet_length is only accessed once the payload length +has been validated. + +Fixes: 219ed58feda9 ("wifi: iwlwifi: mvm: Add support for wowlan wake packet notification") +Signed-off-by: Shahar Tzarfati +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.99d5cf85a528.Ic4aa736011d4fe88e0cd19723d1d48bb24642198@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +index 817ddc7103af27..dd31b9b2cd39bf 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +@@ -3144,7 +3144,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, + struct iwl_wowlan_status_data *status, + u32 len) + { +- u32 data_size, packet_len = le32_to_cpu(notif->wake_packet_length); ++ u32 data_size, packet_len; + + if (len < sizeof(*notif)) { + IWL_ERR(mvm, "Invalid WoWLAN wake packet notification!\n"); +@@ -3163,6 +3163,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, + return -EIO; + } + ++ packet_len = le32_to_cpu(notif->wake_packet_length); + data_size = len - offsetof(struct iwl_wowlan_wake_pkt_notif, wake_packet); + + /* data_size got the padding from the notification, remove it. */ +-- +2.53.0 + diff --git a/queue-6.12/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch b/queue-6.12/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch new file mode 100644 index 0000000000..f1299b9d47 --- /dev/null +++ b/queue-6.12/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch @@ -0,0 +1,56 @@ +From de2938cf9c1a4b71807cb4dc818a56ccfca11c7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:04 +0300 +Subject: wifi: iwlwifi: mvm: validate SAR GEO response payload size + +From: Pagadala Yesu Anjaneyulu + +[ Upstream commit 408d7da38272ce48e2db79b8a9895999f94d7655 ] + +The SAR GEO command response is cast to +iwl_geo_tx_power_profiles_resp without verifying the payload length. +A malformed or unexpected firmware response can lead to reading an +invalid structure layout. + +Add an explicit size check before accessing the response data and +return -EIO when the payload size is wrong. + +Fixes: f604324eefec ("iwlwifi: remove iwl_validate_sar_geo_profile() export") +Signed-off-by: Pagadala Yesu Anjaneyulu +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.7e749b7d374a.I4ef54548bff6c6e7c7a57bee771ac12508aad677@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +index 2b9a684cf61d57..4bad012472e1e9 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +@@ -976,12 +976,22 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) + return ret; + } + ++ if (IWL_FW_CHECK(mvm, ++ iwl_rx_packet_payload_len(cmd.resp_pkt) != ++ sizeof(*resp), ++ "Wrong size for iwl_geo_tx_power_profiles_resp: %d\n", ++ iwl_rx_packet_payload_len(cmd.resp_pkt))) { ++ ret = -EIO; ++ goto out; ++ } ++ + resp = (void *)cmd.resp_pkt->data; + ret = le32_to_cpu(resp->profile_idx); + + if (WARN_ON(ret > BIOS_GEO_MAX_PROFILE_NUM)) + ret = -EIO; + ++out: + iwl_free_resp(&cmd); + return ret; + } +-- +2.53.0 + diff --git a/queue-6.12/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch b/queue-6.12/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch new file mode 100644 index 0000000000..964edd4bbf --- /dev/null +++ b/queue-6.12/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch @@ -0,0 +1,56 @@ +From d06efa55824b2d9fedd68c1cad2145d3f0fdd2e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:17:51 +1000 +Subject: wifi: mac80211: recalculate TIM when a station enters power save + +From: Andrew Pope + +[ Upstream commit a007a384c9eb17610f53a53e2f59944c31f1565a ] + +When an AP buffers frames for a station on its per-station TXQs and the +station subsequently enters power save, sta_ps_start() records the +buffered TIDs in txq_buffered_tids but does not update the TIM. The +station's TIM bit is only ever set when a further frame is buffered +while the station is already asleep +(ieee80211_tx_h_unicast_ps_buf() -> sta_info_recalc_tim()). + +If no further downlink frame arrives for that station the beacon +TIM never advertises the buffered traffic. A station relying on the +TIM then remains in doze indefinitely on top of a non-empty queue. Its +TXQs were removed from the scheduler's active list at PS entry, nothing +pages it, and the flow deadlocks until an unrelated event wakes the +station. + +Recalculate the TIM at the end of sta_ps_start(), so traffic +already buffered at PS entry is advertised immediately. +sta_info_recalc_tim() already consults txq_buffered_tids, which is +updated above, and is safe in this context (it is already called +from equivalent paths such as the tx handlers and +ieee80211_handle_filtered_frame()). + +Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation") +Signed-off-by: Andrew Pope +Link: https://patch.msgid.link/20260717011751.79524-1-andrew.pope@morsemicro.com +[add wifi: subject prefix] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 59070283839277..7e3bcd709c579b 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1595,6 +1595,8 @@ static void sta_ps_start(struct sta_info *sta) + else + clear_bit(tid, &sta->txq_buffered_tids); + } ++ ++ sta_info_recalc_tim(sta); + } + + static void sta_ps_end(struct sta_info *sta) +-- +2.53.0 + diff --git a/queue-6.12/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch b/queue-6.12/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch new file mode 100644 index 0000000000..f95311026e --- /dev/null +++ b/queue-6.12/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch @@ -0,0 +1,75 @@ +From 8d6c160028ef1e17daafaca1cb1bd92ae4898f59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 14:03:02 -0700 +Subject: wifi: mac80211: tear down new links on vif update error path + +From: Xiang Mei + +[ Upstream commit 952c02b33f56207a160421bcd61e7ac53c9c59ae ] + +When ieee80211_vif_update_links() adds new links it allocates a link +container for each and calls ieee80211_link_init() (which registers the +per-link debugfs files with file->private_data pointing into the container) +and ieee80211_link_setup(). If the subsequent drv_change_vif_links() fails, +the error path restores the old pointers and jumps to 'free', which frees +the new containers but never removes their debugfs entries or stops the +links. The debugfs files survive with file->private_data dangling at the +freed container, so a later open()+read() (e.g. link-1/txpower) +dereferences freed memory in ieee80211_if_read_link(), a use-after-free. + +The removal path already dismantles links correctly via +ieee80211_tear_down_links(), which removes each link's keys and debugfs +entries and calls ieee80211_link_stop(); the add path on the error branch +does not. Commit be1ba9ed221f ("wifi: mac80211: avoid weird state in error +path") hardened this same error path for the link-removal case +(new_links == 0) but left the newly-added links' teardown unaddressed. + +drv_change_vif_links() can fail at runtime on MLO drivers (internal +allocation / queue / firmware command failures). + +Remove the new links' debugfs entries and stop them before freeing. + + BUG: KASAN: slab-use-after-free in ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + Read of size 8 at addr ffff888011290000 by task exploit/145 + Call Trace: + ... + ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + short_proxy_read (fs/debugfs/file.c:373) + vfs_read (fs/read_write.c:572) + ksys_read (fs/read_write.c:716) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + ... + Oops: general protection fault, probably for non-canonical address 0xdffffc000000000a + RIP: 0010:ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + Kernel panic - not syncing: Fatal exception + +Fixes: 170cd6a66d9a ("wifi: mac80211: add netdev per-link debugfs data and driver hook") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/20260711210302.2098404-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/link.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/mac80211/link.c b/net/mac80211/link.c +index df303496914ca6..29813394bbff1c 100644 +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -379,6 +379,10 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata, + memcpy(sdata->link, old_data, sizeof(old_data)); + memcpy(sdata->vif.link_conf, old, sizeof(old)); + ieee80211_set_vif_links_bitmaps(sdata, old_links, dormant_links); ++ for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { ++ ieee80211_link_debugfs_remove(&links[link_id]->data); ++ ieee80211_link_stop(&links[link_id]->data); ++ } + /* and free (only) the newly allocated links */ + memset(to_free, 0, sizeof(links)); + goto free; +-- +2.53.0 + diff --git a/queue-6.12/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch b/queue-6.12/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..d23ca44579 --- /dev/null +++ b/queue-6.12/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,38 @@ +From 2e23a970d03a60fcd06a828c9163593fc02aabb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:24:59 +0200 +Subject: wifi: mt76: connac: fix possible NULL-pointer deref in + mt76_connac_mcu_uni_bss_he_tlv() + +From: Lorenzo Bianconi + +[ Upstream commit 2c1fb2335f5e3afb34f91bc07ecb63517c328090 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: d0e274af2f2e4 ("mt76: mt76_connac: create mcu library") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-1-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index 462b4a68c4f0f1..b1a7fbedffac5c 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -1435,6 +1435,8 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct bss_info_uni_he *he; + + cap = mt76_connac_get_he_phy_cap(phy, vif); ++ if (!cap) ++ return; + + he = (struct bss_info_uni_he *)tlv; + he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; +-- +2.53.0 + diff --git a/queue-6.12/wifi-mt76-mt7915-guard-he-capability-lookups.patch b/queue-6.12/wifi-mt76-mt7915-guard-he-capability-lookups.patch new file mode 100644 index 0000000000..1a6ebbdf49 --- /dev/null +++ b/queue-6.12/wifi-mt76-mt7915-guard-he-capability-lookups.patch @@ -0,0 +1,90 @@ +From 7ed16792587453ca6e127e51bd46a81f3bb5b39e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 23:53:32 +0800 +Subject: wifi: mt76: mt7915: guard HE capability lookups + +From: Ruoyu Wang + +[ Upstream commit 8e9db062654a388d0fa587acbeeae68dd33eba41 ] + +mt7915_mcu_bss_he_tlv() and mt7915_mcu_sta_bfer_tlv() both run after +checking HE support, then dereference the HE PHY capability returned by +mt76_connac_get_he_phy_cap(). That helper can return NULL when no +capability entry matches the vif type. + +Fetch the capability before appending the TLV and skip the HE-specific +setup when no matching capability is available. + +Fixes: e6d557a78b60 ("mt76: mt7915: rely on mt76_connac_get_phy utilities") +Signed-off-by: Ruoyu Wang +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260620155332.81120-1-ruoyuw560@gmail.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +index 2489364110d6eb..d622d7c7bee41c 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +@@ -551,6 +551,8 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!cap) ++ return; + + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he)); + +@@ -1133,13 +1135,12 @@ mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy, + } + + static void +-mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, +- struct mt7915_phy *phy, struct sta_rec_bf *bf) ++mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, ++ const struct ieee80211_sta_he_cap *vc, ++ struct sta_rec_bf *bf) + { + struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap; + struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; +- const struct ieee80211_sta_he_cap *vc = +- mt76_connac_get_he_phy_cap(phy->mt76, vif); + const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; + u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); + u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map); +@@ -1198,6 +1199,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_phy *phy = mvif->phy; ++ const struct ieee80211_sta_he_cap *vc = NULL; + int tx_ant = hweight8(phy->mt76->chainmask) - 1; + struct sta_rec_bf *bf; + struct tlv *tlv; +@@ -1216,6 +1218,12 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + if (!ebf && !dev->ibf) + return; + ++ if (sta->deflink.he_cap.has_he && ebf) { ++ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!vc) ++ return; ++ } ++ + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); + bf = (struct sta_rec_bf *)tlv; + +@@ -1224,7 +1232,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + * ht: iBF only, since mac80211 lacks of eBF support + */ + if (sta->deflink.he_cap.has_he && ebf) +- mt7915_mcu_sta_bfer_he(sta, vif, phy, bf); ++ mt7915_mcu_sta_bfer_he(sta, vc, bf); + else if (sta->deflink.vht_cap.vht_supported) + mt7915_mcu_sta_bfer_vht(sta, phy, bf, ebf); + else if (sta->deflink.ht_cap.ht_supported) +-- +2.53.0 + diff --git a/queue-6.12/wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch b/queue-6.12/wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch new file mode 100644 index 0000000000..84ed84c675 --- /dev/null +++ b/queue-6.12/wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch @@ -0,0 +1,55 @@ +From ecba5d434d1cf64ade31969d5e29ac2568a9c53a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jun 2026 11:10:16 -0500 +Subject: wifi: mt76: mt7925: fix crash in reset link replay + +From: Sean Wang + +[ Upstream commit bd8b2ec838184236c3fcbf738a926328836adf12 ] + +During reset recovery, mt7925_vif_connect_iter() replays firmware state +for links tracked in mvif->valid_links. After MLO link changes or MCU +timeout recovery, the driver bitmap can temporarily contain a link whose +mac80211 bss_conf has already gone away. + +This can pass a NULL bss_conf to mt76_connac_mcu_uni_add_dev(), matching +the crash where x1, the second argument, is NULL: + +pc : mt76_connac_mcu_uni_add_dev+0x8c/0x1f8 [mt76_connac_lib] +lr : mt7925_vif_connect_iter+0x9c/0x168 [mt7925_common] +x2 : ffffff80a77f6018 x1 : 0000000000000000 x0 : ffffff8099402080 +Call trace: +mt76_connac_mcu_uni_add_dev+0x8c/0x1f8 [mt76_connac_lib] +mt7925_vif_connect_iter+0x9c/0x168 [mt7925_common] +mt7925_mac_reset_work+0x264/0x2f8 [mt7925_common] + +Skip missing bss_conf entries before replaying the link. Non-MLO AP/STA +reset replay is unchanged because the helper still returns &vif->bss_conf +for the legacy link. + +Fixes: 14061994184d ("wifi: mt76: mt7925: add link handling in mt7925_vif_connect_iter") +Signed-off-by: Sean Wang +Link: https://patch.msgid.link/20260616161016.19346-1-sean.wang@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +index f01dbca6e9b9ca..9ed0c2655037a0 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +@@ -1285,6 +1285,9 @@ mt7925_vif_connect_iter(void *priv, u8 *mac, + + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + bss_conf = mt792x_vif_to_bss_conf(vif, i); ++ if (!bss_conf) ++ continue; ++ + mconf = mt792x_vif_to_link(mvif, i); + + mt76_connac_mcu_uni_add_dev(&dev->mphy, bss_conf, &mconf->mt76, +-- +2.53.0 + diff --git a/queue-6.12/wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch b/queue-6.12/wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..9a4eccf980 --- /dev/null +++ b/queue-6.12/wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,38 @@ +From d7e5b82f1de30440a6ca7d8df697c75a2c93c587 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:00 +0200 +Subject: wifi: mt76: mt7925: fix possible NULL-pointer deref in + mt7925_mcu_bss_he_tlv() + +From: Lorenzo Bianconi + +[ Upstream commit 8d1b6738c1ab48c086b17e7994034aca94258931 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: c948b5da6bbec ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-2-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +index 1f113a618515e8..1fc1116d9becca 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +@@ -2646,6 +2646,8 @@ mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, link_conf->vif); ++ if (!cap) ++ return; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he)); + +-- +2.53.0 + diff --git a/queue-6.12/wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch b/queue-6.12/wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch new file mode 100644 index 0000000000..aebe74bc5f --- /dev/null +++ b/queue-6.12/wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch @@ -0,0 +1,46 @@ +From 1528e8fc3560b19afc587197c1aec378a7cd9bc5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 15:55:39 +0800 +Subject: wifi: mt76: mt7925: guard link STA in decap offload + +From: Guangshuo Li + +[ Upstream commit 96ea44f2269f30364cffa054ee3a87e595bef0d4 ] + +mt7925_sta_set_decap_offload() iterates over the vif valid_links mask +when updating decap offload state for an MLO station. The station may not +have a link STA for every valid link of the vif, so mt792x_sta_to_link() +can return NULL for a link that belongs to the vif but not to the station. + +The function currently dereferences mlink before checking whether the +link WCID is ready. If mlink is NULL, setting or clearing +MT_WCID_FLAG_HDR_TRANS dereferences a NULL pointer. + +Skip links without a station link before touching mlink->wcid. + +Fixes: b859ad65309a ("wifi: mt76: mt7925: add link handling in mt7925_sta_set_decap_offload") +Signed-off-by: Guangshuo Li +Link: https://patch.msgid.link/20260708075539.726200-1-lgs201920130244@gmail.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c +index 98ec76cf2fe8b4..1dbc6d22b06661 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c +@@ -1583,6 +1583,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, + + mlink = mt792x_sta_to_link(msta, i); + ++ if (!mlink) ++ continue; ++ + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags); + else +-- +2.53.0 + diff --git a/queue-6.12/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch b/queue-6.12/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch new file mode 100644 index 0000000000..d9a4d328ba --- /dev/null +++ b/queue-6.12/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch @@ -0,0 +1,60 @@ +From 5b788664f041a3f4eb170011fbc9b89d9803ecd9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:01 +0200 +Subject: wifi: mt76: mt7996: check pointer returned by + mt76_connac_get_he_phy_cap() + +From: Lorenzo Bianconi + +[ Upstream commit e858cf6bf99880343348ff1e8c942aaff1d9d592 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: 98686cd21624c ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-3-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +index 54567a5893449e..5730980fdc64eb 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +@@ -798,6 +798,8 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!cap) ++ return; + + tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he)); + +@@ -1537,17 +1539,18 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, + { + struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap; + struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; +- const struct ieee80211_sta_he_cap *vc = +- mt76_connac_get_he_phy_cap(phy->mt76, vif); +- const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; + u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); + u8 nss_mcs = mt7996_mcu_get_sta_nss(mcs_map); ++ const struct ieee80211_he_cap_elem *ve; ++ const struct ieee80211_sta_he_cap *vc; + u8 snd_dim, sts; + ++ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif); + if (!vc) + return; + + bf->tx_mode = MT_PHY_TYPE_HE_SU; ++ ve = &vc->he_cap_elem; + + mt7996_mcu_sta_sounding_rate(bf); + +-- +2.53.0 + diff --git a/queue-6.12/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch b/queue-6.12/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..6a3d7410b3 --- /dev/null +++ b/queue-6.12/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,51 @@ +From 74efd98ce57c626338c457975eb405bb052d9f87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:02 +0200 +Subject: wifi: mt76: mt7996: fix possible NULL-pointer deref in + mt7996_mcu_sta_bfer_eht() + +From: Lorenzo Bianconi + +[ Upstream commit 2fffc472bec490c8357defcee9c075ca74467352 ] + +mt76_connac_get_eht_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: ba01944adee9f ("wifi: mt76: mt7996: add EHT beamforming support") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-4-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +index 5730980fdc64eb..a5693efee74b85 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +@@ -1604,14 +1604,18 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif, + struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap; + struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; + struct ieee80211_eht_mcs_nss_supp *eht_nss = &pc->eht_mcs_nss_supp; +- const struct ieee80211_sta_eht_cap *vc = +- mt76_connac_get_eht_phy_cap(phy->mt76, vif); +- const struct ieee80211_eht_cap_elem_fixed *ve = &vc->eht_cap_elem; + u8 nss_mcs = u8_get_bits(eht_nss->bw._80.rx_tx_mcs9_max_nss, + IEEE80211_EHT_MCS_NSS_RX) - 1; ++ const struct ieee80211_eht_cap_elem_fixed *ve; ++ const struct ieee80211_sta_eht_cap *vc; + u8 snd_dim, sts; + ++ vc = mt76_connac_get_eht_phy_cap(phy->mt76, vif); ++ if (!vc) ++ return; ++ + bf->tx_mode = MT_PHY_TYPE_EHT_MU; ++ ve = &vc->eht_cap_elem; + + mt7996_mcu_sta_sounding_rate(bf); + +-- +2.53.0 + diff --git a/queue-6.12/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch b/queue-6.12/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch new file mode 100644 index 0000000000..5e4ee0c8ed --- /dev/null +++ b/queue-6.12/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch @@ -0,0 +1,104 @@ +From f9d438597a36ac8ea0f1751afe10902b1681de38 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 22:57:11 +0900 +Subject: wifi: mwifiex: bound uAP association event IEs to the event buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit f0858bfc7d3cab411a447b88e3ef970e575032c9 ] + +mwifiex_process_uap_event() handles EVENT_UAP_STA_ASSOC by exposing the +(re)association request IEs that the firmware copies into the event: + + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - (u8 *)&event->frame_control; + sinfo->assoc_req_ies_len = le16_to_cpu(event->len) - (u16)len; + +event->len is supplied by the device firmware and is never validated, +and the subtraction is unchecked. assoc_req_ies points into +adapter->event_body[MAX_EVENT_SIZE], a fixed-size array embedded in the +kmalloc()'d struct mwifiex_adapter. + +On the ap_11n_enabled path mwifiex_set_sta_ht_cap() walks these IEs with +cfg80211_find_ie(), whose for_each_element() loop dereferences each +element header. A firmware-reported event->len larger than the bytes +actually received makes assoc_req_ies_len describe IEs that extend past +event_body, so the walk reads out of the adapter slab object, a +slab-out-of-bounds read (KASAN: slab-out-of-bounds in cfg80211_find_ie). +An event->len smaller than the header instead makes the int subtraction +negative, which wraps to a huge size_t when stored in assoc_req_ies_len. +The same length is handed to cfg80211_new_sta(), so a more modest +over-claim can also copy stale event_body bytes into the +NL80211_CMD_NEW_STATION notification. + +A malicious or malfunctioning mwifiex device (USB/SDIO/PCIe) can deliver +such an event while the interface is in AP/uAP mode. + +Validate event->len before use: reject a length that underflows the +header or that would place the IEs outside the event_body[] buffer the +event was copied into. event->len here is struct mwifiex_assoc_event.len, +a payload field internal to this event, not the transport frame length, +so it is validated in this handler rather than at the generic +MWIFIEX_TYPE_EVENT receive path, which only sees the event cause and the +transport frame length. The bound is against event_body[MAX_EVENT_SIZE] +rather than the actually-received length because the transports store the +event differently (USB and SDIO leave the 4-byte event header in +event_skb, PCIe strips it via skb_pull), whereas event_body is the single +fixed buffer all of them copy the event into. This is the event-path +analogue of the receive-path bounds checks added in commit 119585281617 +("wifi: mwifiex: Fix OOB and integer underflow when rx packets"). + +Fixes: e568634ae7ac ("mwifiex: add AP event handling framework") +Signed-off-by: HE WEI (ギカク) +Reviewed-by: Francesco Dolcini +Link: https://patch.msgid.link/20260715135711.34688-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + .../net/wireless/marvell/mwifiex/uap_event.c | 24 +++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c +index 58ef5020a46a73..c7383abf064f50 100644 +--- a/drivers/net/wireless/marvell/mwifiex/uap_event.c ++++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c +@@ -123,11 +123,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) + len = ETH_ALEN; + + if (len != -1) { ++ u16 evt_len = le16_to_cpu(event->len); ++ + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - + (u8 *)&event->frame_control; +- sinfo->assoc_req_ies_len = +- le16_to_cpu(event->len) - (u16)len; ++ ++ /* ++ * event->len is reported by the device firmware ++ * and is not otherwise validated. Reject a ++ * length that underflows the header, or that ++ * would place the association request IEs ++ * outside the fixed-size event_body[] buffer the ++ * event was copied into; otherwise the IE walk ++ * in mwifiex_set_sta_ht_cap() reads past ++ * event_body and out of the adapter slab object. ++ */ ++ if (evt_len < len || ++ (u8 *)&event->frame_control + evt_len > ++ adapter->event_body + MAX_EVENT_SIZE) { ++ mwifiex_dbg(adapter, ERROR, ++ "invalid STA assoc event length\n"); ++ kfree(sinfo); ++ return -1; ++ } ++ sinfo->assoc_req_ies_len = evt_len - (u16)len; + } + } + cfg80211_new_sta(priv->netdev, event->sta_addr, sinfo, +-- +2.53.0 + diff --git a/queue-6.18/alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch b/queue-6.18/alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch new file mode 100644 index 0000000000..3e1b40bb19 --- /dev/null +++ b/queue-6.18/alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch @@ -0,0 +1,60 @@ +From e54d8a630677ffab277355c924a1e59a046d5400 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:36:25 +0800 +Subject: ALSA: hda: cs35l41: validate and free ACPI mute object + +From: Guangshuo Li + +[ Upstream commit 3b597d24dc0455ae926f1053f97c2725038fc3cd ] + +cs35l41_get_acpi_mute_state() evaluates a _DSM method to get the ACPI +mute state and reads the first byte from the returned object. + +However, the returned ACPI object is owned by the caller and is never +freed after use, so each successful query leaks the _DSM result object. + +The code also assumes that the returned object is a buffer with at least +one byte. A malformed firmware response can return a different object +type or an empty buffer, and the direct ret->buffer.pointer dereference +can then access an invalid pointer. + +Use the typed _DSM helper, validate that the returned buffer contains at +least one byte, and free the ACPI object after reading it. + +Fixes: 447106e92a0c ("ALSA: hda: cs35l41: Support mute notifications for CS35L41 HDA") +Signed-off-by: Guangshuo Li +Link: https://patch.msgid.link/20260708113625.752913-1-lgs201920130244@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/hda/codecs/side-codecs/cs35l41_hda.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.c b/sound/hda/codecs/side-codecs/cs35l41_hda.c +index 438a19bd979bfe..de2fd6471f0598 100644 +--- a/sound/hda/codecs/side-codecs/cs35l41_hda.c ++++ b/sound/hda/codecs/side-codecs/cs35l41_hda.c +@@ -1437,10 +1437,19 @@ static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle + guid_parse(CS35L41_UUID, &guid); + + if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) { +- ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL); ++ ret = acpi_evaluate_dsm_typed(handle, &guid, 0, ++ CS35L41_DSM_GET_MUTE, NULL, ++ ACPI_TYPE_BUFFER); ++ + if (!ret) + return -EINVAL; ++ if (!ret->buffer.length || !ret->buffer.pointer) { ++ ACPI_FREE(ret); ++ return -EINVAL; ++ } ++ + mute = *ret->buffer.pointer; ++ ACPI_FREE(ret); + dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute); + } + +-- +2.53.0 + diff --git a/queue-6.18/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch b/queue-6.18/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch new file mode 100644 index 0000000000..05e6b9dead --- /dev/null +++ b/queue-6.18/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch @@ -0,0 +1,58 @@ +From 5c992cd31685a7e36ac112e29e02bf5690f24ecd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 15:20:06 +0530 +Subject: amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN + +From: Prashanth Kumar KR + +[ Upstream commit 4bf22afe53a1de4b44b04cf677fd5199089cbdff ] + +MAC_AUTO_SW (VR_MII_DIG_CTRL1 bit 9) enables automatic XPCS speed +mode switching after CL37 auto-negotiation and is only meaningful in +SGMII MAC mode. The original code unconditionally set this bit on +every call to xgbe_an37_set(), including when called from +xgbe_an37_disable() with enable=false. This left MAC_AUTO_SW=1 after +AN was disabled, causing the XPCS to autonomously switch speed from +stale AN state during subsequent mode changes, breaking SGMII speed +negotiation on 1G copper SFP modules. + +Patrick: This was breaking negotiation for all 1G SFP modules, +not just copper modules. + +Fixes: 42fd432fe6d3 ("amd-xgbe: align CL37 AN sequence as per databook") +Reported-by: Patrick Oppenlander +Link: https://lore.kernel.org/netdev/CAEg67GmFS0Q4oSZkz8zWdOzckSth9_vBPiOy6a7-d697C2w2Xg@mail.gmail.com +Signed-off-by: Prashanth Kumar KR +Tested-by: Patrick Oppenlander +Link: https://patch.msgid.link/20260709095006.3683940-1-prashanthkumar.k.r@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index 7675bb98f02956..c2d22fdb6c1829 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -267,9 +267,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, + + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); + +- reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); +- reg |= XGBE_VEND2_MAC_AUTO_SW; +- XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ if (pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) { ++ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); ++ if (enable) ++ reg |= XGBE_VEND2_MAC_AUTO_SW; ++ else ++ reg &= ~XGBE_VEND2_MAC_AUTO_SW; ++ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ } + } + + static void xgbe_an37_restart(struct xgbe_prv_data *pdata) +-- +2.53.0 + diff --git a/queue-6.18/amt-make-the-head-writable-before-rewriting-the-l2-h.patch b/queue-6.18/amt-make-the-head-writable-before-rewriting-the-l2-h.patch new file mode 100644 index 0000000000..335fac5df3 --- /dev/null +++ b/queue-6.18/amt-make-the-head-writable-before-rewriting-the-l2-h.patch @@ -0,0 +1,67 @@ +From 44ac58f4359f03a928937ed680ace8f3969d5707 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:19:34 -0400 +Subject: amt: make the head writable before rewriting the L2 header + +From: Michael Bommarito + +[ Upstream commit 53969d704fa5b7c1751e277fac96bfc22b435eac ] + +amt_multicast_data_handler(), amt_membership_query_handler() and +amt_update_handler() rewrite the ethernet header of the decapsulated skb +in place (eth->h_proto, eth->h_dest and, for the query, also +eth->h_source) before handing it up the stack. The skb head may be +shared, for example when a packet tap has cloned it on the underlay +interface, so writing through it corrupts the other reader's copy. + +Call skb_cow_head() before the rewrite so the head is private. It is +placed before the pointers into the head are (re-)derived, so a +reallocation caused by the copy is picked up by those derivations. + +Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") +Signed-off-by: Michael Bommarito +Reviewed-by: Simon Horman +Reviewed-by: Taehee Yoo +Link: https://patch.msgid.link/20260711151934.2955226-3-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/amt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/amt.c b/drivers/net/amt.c +index 76e0ab70d8273d..cddcad172bbce0 100644 +--- a/drivers/net/amt.c ++++ b/drivers/net/amt.c +@@ -2320,6 +2320,9 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + skb_reset_mac_header(skb); + skb_pull(skb, sizeof(*eth)); + ++ if (skb_cow_head(skb, 0)) ++ return true; ++ + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + iph = ip_hdr(skb); +@@ -2396,6 +2399,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_network_header(skb); + eth = eth_hdr(skb); + ether_addr_copy(h_source, oeth->h_source); ++ if (skb_cow_head(skb, 0)) ++ return true; + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + +@@ -2521,6 +2526,9 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + ++ if (skb_cow_head(skb, 0)) ++ return true; ++ + iph = ip_hdr(skb); + if (iph->version == 4) { + if (ip_mc_check_igmp(skb)) { +-- +2.53.0 + diff --git a/queue-6.18/amt-re-read-skb-header-pointers-after-every-pull.patch b/queue-6.18/amt-re-read-skb-header-pointers-after-every-pull.patch new file mode 100644 index 0000000000..3dc966e94c --- /dev/null +++ b/queue-6.18/amt-re-read-skb-header-pointers-after-every-pull.patch @@ -0,0 +1,367 @@ +From a84d50db9382d83c177bac03f648536b5ad9aa11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:19:33 -0400 +Subject: amt: re-read skb header pointers after every pull + +From: Michael Bommarito + +[ Upstream commit 3656a79f94c471827a08f2cacce5f94ad5e52c24 ] + +Several AMT receive and transmit paths cache a pointer into the skb head +(ip_hdr(), ipv6_hdr(), eth_hdr() or the AMT message header) and then call +a helper that can reallocate that head before the cached pointer is used +again. pskb_may_pull(), ip_mc_may_pull(), ipv6_mc_may_pull(), +iptunnel_pull_header(), ip_mc_check_igmp() and ipv6_mc_check_mld() can all +free the old head and move the data, so a pointer taken before the call +dangles afterwards and the later access is a use-after-free of the freed +head. + +The affected sites are: + + amt_rcv() caches ip_hdr() before amt_parse_type() pulls, then reads + iph->saddr. + + amt_dev_xmit() caches ip_hdr()/ipv6_hdr() before ip_mc_check_igmp()/ + ipv6_mc_check_mld() and pskb_may_pull(), then reads the group address. + + amt_multicast_data_handler() caches eth_hdr() before pskb_may_pull(), + then writes the L2 header. + + amt_membership_query_handler() caches the AMT header, the outer and + inner eth_hdr() and ip_hdr() before iptunnel_pull_header() and several + pulls, then reads and writes them. + + amt_igmpv3_report_handler() and amt_mldv2_report_handler() cache + ip_hdr()/ipv6_hdr() and the current group record and read the record + count from the report header inside the record loop, across the + *_mc_may_pull() calls. + + amt_update_handler() caches ip_hdr() and the AMT membership-update + header before pskb_may_pull(), iptunnel_pull_header(), + ip_mc_check_igmp() and the report handler, then reads iph->daddr and + amtmu->nonce / amtmu->response_mac. + +Fix each site by either snapshotting the scalar that is used after the +pull before the first pull runs, or re-deriving the header pointer from +the skb after the last pull that can move the head. Values that are +stable across the pull (source and group address, the response MAC and +nonce, the record count, the outer source MAC) are snapshotted; pointers +that are written through or read repeatedly are re-derived. + +Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") +Signed-off-by: Michael Bommarito +Reviewed-by: Simon Horman +Reviewed-by: Taehee Yoo +Link: https://patch.msgid.link/20260711151934.2955226-2-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/amt.c | 79 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 55 insertions(+), 24 deletions(-) + +diff --git a/drivers/net/amt.c b/drivers/net/amt.c +index e4d1aa26d7bbd7..76e0ab70d8273d 100644 +--- a/drivers/net/amt.c ++++ b/drivers/net/amt.c +@@ -1211,7 +1211,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + data = true; + } + v6 = false; +- group.ip4 = iph->daddr; ++ group.ip4 = ip_hdr(skb)->daddr; + #if IS_ENABLED(CONFIG_IPV6) + } else if (iph->version == 6) { + ip6h = ipv6_hdr(skb); +@@ -1235,7 +1235,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + data = true; + } + v6 = true; +- group.ip6 = ip6h->daddr; ++ group.ip6 = ipv6_hdr(skb)->daddr; + #endif + } else { + dev->stats.tx_errors++; +@@ -1278,12 +1278,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash], + node) { + if (!v6) { +- if (gnode->group_addr.ip4 == iph->daddr) ++ if (gnode->group_addr.ip4 == group.ip4) + goto found; + #if IS_ENABLED(CONFIG_IPV6) + } else { + if (ipv6_addr_equal(&gnode->group_addr.ip6, +- &ip6h->daddr)) ++ &group.ip6)) + goto found; + #endif + } +@@ -2000,14 +2000,18 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb, + struct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb); + int len = skb_transport_offset(skb) + sizeof(*ihrv3); + void *zero_grec = (void *)&igmpv3_zero_grec; +- struct iphdr *iph = ip_hdr(skb); + struct amt_group_node *gnode; + union amt_addr group, host; + struct igmpv3_grec *grec; ++ __be32 saddr; + u16 nsrcs; ++ u16 ngrec; + int i; + +- for (i = 0; i < ntohs(ihrv3->ngrec); i++) { ++ saddr = ip_hdr(skb)->saddr; ++ ngrec = ntohs(ihrv3->ngrec); ++ ++ for (i = 0; i < ngrec; i++) { + len += sizeof(*grec); + if (!ip_mc_may_pull(skb, len)) + break; +@@ -2019,10 +2023,13 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb, + if (!ip_mc_may_pull(skb, len)) + break; + ++ grec = (void *)(skb->data + len - sizeof(*grec) - ++ nsrcs * sizeof(__be32)); ++ + memset(&group, 0, sizeof(union amt_addr)); + group.ip4 = grec->grec_mca; + memset(&host, 0, sizeof(union amt_addr)); +- host.ip4 = iph->saddr; ++ host.ip4 = saddr; + gnode = amt_lookup_group(tunnel, &group, &host, false); + if (!gnode) { + gnode = amt_add_group(amt, tunnel, &group, &host, +@@ -2162,14 +2169,18 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb, + struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb); + int len = skb_transport_offset(skb) + sizeof(*mld2r); + void *zero_grec = (void *)&mldv2_zero_grec; +- struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct amt_group_node *gnode; + union amt_addr group, host; + struct mld2_grec *grec; ++ struct in6_addr saddr; + u16 nsrcs; ++ u16 ngrec; + int i; + +- for (i = 0; i < ntohs(mld2r->mld2r_ngrec); i++) { ++ saddr = ipv6_hdr(skb)->saddr; ++ ngrec = ntohs(mld2r->mld2r_ngrec); ++ ++ for (i = 0; i < ngrec; i++) { + len += sizeof(*grec); + if (!ipv6_mc_may_pull(skb, len)) + break; +@@ -2181,10 +2192,13 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb, + if (!ipv6_mc_may_pull(skb, len)) + break; + ++ grec = (void *)(skb->data + len - sizeof(*grec) - ++ nsrcs * sizeof(struct in6_addr)); ++ + memset(&group, 0, sizeof(union amt_addr)); + group.ip6 = grec->grec_mca; + memset(&host, 0, sizeof(union amt_addr)); +- host.ip6 = ip6h->saddr; ++ host.ip6 = saddr; + gnode = amt_lookup_group(tunnel, &group, &host, true); + if (!gnode) { + gnode = amt_add_group(amt, tunnel, &group, &host, +@@ -2305,7 +2319,6 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + skb_push(skb, sizeof(*eth)); + skb_reset_mac_header(skb); + skb_pull(skb, sizeof(*eth)); +- eth = eth_hdr(skb); + + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; +@@ -2315,6 +2328,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!ipv4_is_multicast(iph->daddr)) + return true; + skb->protocol = htons(ETH_P_IP); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IP); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) +@@ -2328,6 +2342,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!ipv6_addr_is_multicast(&ip6h->daddr)) + return true; + skb->protocol = htons(ETH_P_IPV6); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IPV6); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif +@@ -2351,10 +2366,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + struct sk_buff *skb) + { + struct amt_header_membership_query *amtmq; +- struct igmpv3_query *ihv3; + struct ethhdr *eth, *oeth; ++ struct igmpv3_query *ihv3; ++ u8 h_source[ETH_ALEN]; + struct iphdr *iph; + int hdr_size, len; ++ u64 response_mac; + + hdr_size = sizeof(*amtmq) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) +@@ -2367,6 +2384,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + if (amtmq->nonce != amt->nonce) + return true; + ++ response_mac = amtmq->response_mac; ++ + hdr_size -= sizeof(*eth); + if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false)) + return true; +@@ -2376,6 +2395,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_pull(skb, sizeof(*eth)); + skb_reset_network_header(skb); + eth = eth_hdr(skb); ++ ether_addr_copy(h_source, oeth->h_source); + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + +@@ -2388,6 +2408,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + sizeof(*ihv3))) + return true; + ++ iph = ip_hdr(skb); + if (!ipv4_is_multicast(iph->daddr)) + return true; + +@@ -2395,10 +2416,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS); + WRITE_ONCE(amt->ready4, true); +- amt->mac = amtmq->response_mac; ++ amt->mac = response_mac; + amt->req_cnt = 0; + amt->qi = ihv3->qqic; + skb->protocol = htons(ETH_P_IP); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IP); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) +@@ -2421,10 +2443,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS); + WRITE_ONCE(amt->ready6, true); +- amt->mac = amtmq->response_mac; ++ amt->mac = response_mac; + amt->req_cnt = 0; + amt->qi = mld2q->mld2q_qqic; + skb->protocol = htons(ETH_P_IPV6); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IPV6); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif +@@ -2432,7 +2455,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + return true; + } + +- ether_addr_copy(eth->h_source, oeth->h_source); ++ ether_addr_copy(eth->h_source, h_source); + skb->pkt_type = PACKET_MULTICAST; + skb->ip_summed = CHECKSUM_NONE; + len = skb->len; +@@ -2455,8 +2478,11 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + struct ethhdr *eth; + struct iphdr *iph; + int len, hdr_size; ++ u64 response_mac; ++ __be32 saddr; ++ __be32 nonce; + +- iph = ip_hdr(skb); ++ saddr = ip_hdr(skb)->saddr; + + hdr_size = sizeof(*amtmu) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) +@@ -2466,15 +2492,18 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + if (amtmu->reserved || amtmu->version) + return true; + ++ nonce = amtmu->nonce; ++ response_mac = amtmu->response_mac; ++ + if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false)) + return true; + + skb_reset_network_header(skb); + + list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) { +- if (tunnel->ip4 == iph->saddr) { +- if ((amtmu->nonce == tunnel->nonce && +- amtmu->response_mac == tunnel->mac)) { ++ if (tunnel->ip4 == saddr) { ++ if ((nonce == tunnel->nonce && ++ response_mac == tunnel->mac)) { + mod_delayed_work(amt_wq, &tunnel->gc_wq, + msecs_to_jiffies(amt_gmi(amt)) + * 3); +@@ -2508,6 +2537,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + eth = eth_hdr(skb); + skb->protocol = htons(ETH_P_IP); + eth->h_proto = htons(ETH_P_IP); ++ iph = ip_hdr(skb); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) + } else if (iph->version == 6) { +@@ -2527,6 +2557,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + eth = eth_hdr(skb); + skb->protocol = htons(ETH_P_IPV6); + eth->h_proto = htons(ETH_P_IPV6); ++ ip6h = ipv6_hdr(skb); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif + } else { +@@ -2772,7 +2803,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb) + static int amt_rcv(struct sock *sk, struct sk_buff *skb) + { + struct amt_dev *amt; +- struct iphdr *iph; ++ __be32 saddr; + int type; + bool err; + +@@ -2785,7 +2816,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + } + + skb->dev = amt->dev; +- iph = ip_hdr(skb); ++ saddr = ip_hdr(skb)->saddr; + type = amt_parse_type(skb); + if (type == -1) { + err = true; +@@ -2795,7 +2826,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + if (amt->mode == AMT_MODE_GATEWAY) { + switch (type) { + case AMT_MSG_ADVERTISEMENT: +- if (iph->saddr != amt->discovery_ip) { ++ if (saddr != amt->discovery_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +@@ -2807,7 +2838,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + } + goto out; + case AMT_MSG_MULTICAST_DATA: +- if (iph->saddr != amt->remote_ip) { ++ if (saddr != amt->remote_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +@@ -2818,7 +2849,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + else + goto out; + case AMT_MSG_MEMBERSHIP_QUERY: +- if (iph->saddr != amt->remote_ip) { ++ if (saddr != amt->remote_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +-- +2.53.0 + diff --git a/queue-6.18/arm64-correct-value-returned-by-esr_elx_fsc_addrsz_n.patch b/queue-6.18/arm64-correct-value-returned-by-esr_elx_fsc_addrsz_n.patch new file mode 100644 index 0000000000..360220f6c2 --- /dev/null +++ b/queue-6.18/arm64-correct-value-returned-by-esr_elx_fsc_addrsz_n.patch @@ -0,0 +1,39 @@ +From 51f8fe72f48cda33f5134e66518997159f06583b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 14:48:35 +0100 +Subject: arm64: Correct value returned by ESR_ELx_FSC_ADDRSZ_nL() + +From: Steven Price + +[ Upstream commit b877075d0baa22c225842c2f19e3ea0a9cbcbe39 ] + +Address size fault, level -1 is encoded as 0b101001 or 0x29 according to +the Arm ARM. Correct the value to match the spec. This also matches the +offset of "level -1 address size fault" in the fault_info array in +fault.c. + +Fixes: fb8a3eba9c81 ("KVM: arm64: Only read HPFAR_EL2 when value is architecturally valid") +Signed-off-by: Steven Price +Reviewed-by: Marc Zyngier +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/esr.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h +index e1deed82446450..31058567eee465 100644 +--- a/arch/arm64/include/asm/esr.h ++++ b/arch/arm64/include/asm/esr.h +@@ -130,7 +130,7 @@ + * Annoyingly, the negative levels for Address size faults aren't laid out + * contiguously (or in the desired order) + */ +-#define ESR_ELx_FSC_ADDRSZ_nL(n) ((n) == -1 ? 0x25 : 0x2C) ++#define ESR_ELx_FSC_ADDRSZ_nL(n) ((n) == -1 ? 0x29 : 0x2C) + #define ESR_ELx_FSC_ADDRSZ_L(n) ((n) < 0 ? ESR_ELx_FSC_ADDRSZ_nL(n) : \ + (ESR_ELx_FSC_ADDRSZ + (n))) + +-- +2.53.0 + diff --git a/queue-6.18/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch b/queue-6.18/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch new file mode 100644 index 0000000000..0efd5ede0d --- /dev/null +++ b/queue-6.18/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch @@ -0,0 +1,72 @@ +From ea70a63897dff3e5191c9569b24b2fc8b0bf3adf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 18:06:20 +0800 +Subject: ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI + +From: Shengjiu Wang + +[ Upstream commit 0b604e886ece11b71c4daaeccc512c784b89b014 ] + +The bt-sco-pcm-wb DAI uses the same stream_name strings as bt-sco-pcm +("Playback" and "Capture"). This causes duplicate DAPM AIF widget +names within the same component, leading to debugfs warnings: + + debugfs: 'Playback' already exists in 'dapm' + debugfs: 'Capture' already exists in 'dapm' + +Give the wideband DAI distinct stream names ("WB Playback" and +"WB Capture") and add corresponding DAPM AIF widgets and routes for +them. + +Fixes: 5947e1b4992e ("ASoC: bt-sco: extend rate and add a general compatible string") +Assisted-by: VeroCoder:claude-sonnet-4-5 +Signed-off-by: Shengjiu Wang +Link: https://patch.msgid.link/20260715100620.1387159-1-shengjiu.wang@oss.nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/bt-sco.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c +index 3afcef2dfa3529..c0bf45b76cb8c5 100644 +--- a/sound/soc/codecs/bt-sco.c ++++ b/sound/soc/codecs/bt-sco.c +@@ -17,11 +17,17 @@ static const struct snd_soc_dapm_widget bt_sco_widgets[] = { + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0, + SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_IN("BT_SCO_RX_WB", "WB Playback", 0, ++ SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("BT_SCO_TX_WB", "WB Capture", 0, ++ SND_SOC_NOPM, 0, 0), + }; + + static const struct snd_soc_dapm_route bt_sco_routes[] = { + { "BT_SCO_TX", NULL, "RX" }, + { "TX", NULL, "BT_SCO_RX" }, ++ { "BT_SCO_TX_WB", NULL, "RX" }, ++ { "TX", NULL, "BT_SCO_RX_WB" }, + }; + + static struct snd_soc_dai_driver bt_sco_dai[] = { +@@ -45,14 +51,14 @@ static struct snd_soc_dai_driver bt_sco_dai[] = { + { + .name = "bt-sco-pcm-wb", + .playback = { +- .stream_name = "Playback", ++ .stream_name = "WB Playback", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { +- .stream_name = "Capture", ++ .stream_name = "WB Capture", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, +-- +2.53.0 + diff --git a/queue-6.18/asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch b/queue-6.18/asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch new file mode 100644 index 0000000000..9e0fd327aa --- /dev/null +++ b/queue-6.18/asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch @@ -0,0 +1,61 @@ +From 8369266cf5113d3659f8f0b99fd4c36a7eecd6d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 May 2026 17:11:23 +0100 +Subject: ASoC: cs35l56: Don't use devres to unregister component + +From: Richard Fitzgerald + +[ Upstream commit bee87cf0f1248c0f20710d7a79df41fe892d9f88 ] + +Manually call snd_soc_unregister_component() from cs35l56_remove() +instead of using devres cleanup. This ensures that the component is +destroyed before cs35l56_remove() starts cleanup of anything the +component code could be using. + +Devres cleanup happens after the driver remove() callback, so if +snd_soc_register_component() is used, it will not be destroyed until +after cs35l56_remove() has returned. But there is some cleanup that +must be done in cs35l56_remove(), or wrapped in a custom devres +cleanup handler to ensure correct ordering. The simplest option is +to call snd_soc_unregister_component() at the start of cs35l56_remove(). + +Fixes: e49611252900 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Closes: https://sashiko.dev/#/patchset/20260501103002.2843735-1-rf%40opensource.cirrus.com +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260505161124.3621000-2-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Stable-dep-of: 93c2a8ea2454 ("ASoC: cs35l56: Fix potential probe() deadlock") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index 7b57ef2336ea8d..0f40af6606a426 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -1437,9 +1437,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + goto err; + } + +- ret = devm_snd_soc_register_component(cs35l56->base.dev, +- &soc_component_dev_cs35l56, +- cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); ++ ret = snd_soc_register_component(cs35l56->base.dev, ++ &soc_component_dev_cs35l56, ++ cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); + if (ret < 0) { + dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n"); + goto err_remove_wm_adsp; +@@ -1541,6 +1541,8 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_init, "SND_SOC_CS35L56_CORE"); + + void cs35l56_remove(struct cs35l56_private *cs35l56) + { ++ snd_soc_unregister_component(cs35l56->base.dev); ++ + cs35l56->base.init_done = false; + + /* +-- +2.53.0 + diff --git a/queue-6.18/asoc-cs35l56-fix-potential-probe-deadlock.patch b/queue-6.18/asoc-cs35l56-fix-potential-probe-deadlock.patch new file mode 100644 index 0000000000..2983901590 --- /dev/null +++ b/queue-6.18/asoc-cs35l56-fix-potential-probe-deadlock.patch @@ -0,0 +1,111 @@ +From 5342d92f3fab551df39c91563ce920b424cb58cb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 14:20:44 +0100 +Subject: ASoC: cs35l56: Fix potential probe() deadlock + +From: Richard Fitzgerald + +[ Upstream commit 93c2a8ea2454b7b14eb378a58cad8a83c0ffc903 ] + +On I2C/SPI call cs35l56_init() before calling +snd_soc_register_component() to prevent the potential for a deadlock +on init_completion. + +For most buses all the hardware would be ready when probe() returns, +but on SoundWire, probe() must return before the SoundWire bus driver +will enumerate the device. All access to the registers must be deferred +until the driver receives an ATTACHED notification. But anything that +could return -EPROBE_DEFER must be called during probe, and that includes +snd_soc_register_component(). Because of that, on SoundWire the ASoC +component can be created before the registers are accssible, so +cs35l56_component_probe() waits for init_completion to signal that the +registers are accessible. + +On I2C/SPI this 2-stage startup isn't required so their probe() +functions simply called cs35l56_common_probe() and then cs35l56_init(). +The problem with this was that snd_soc_register_component() was still +called early. If this triggered ASoC to create the card, ASoC would call +cs35l56_component_probe() which waits on init_completion - but this would +be running inside the cs35l56 driver probe() so blocking it from reaching +the code that signals init_completion, causing a deadlock. + +Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Reported-by: Salman S. Tahir +Closes: https://lore.kernel.org/linux-sound/95c21574-97d5-4311-9263-9e174d22d22c@opensource.cirrus.com/T/#u +Tested-by: Salman S. Tahir +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260716132045.1469156-2-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56-i2c.c | 4 +--- + sound/soc/codecs/cs35l56-spi.c | 4 +--- + sound/soc/codecs/cs35l56.c | 15 +++++++++++++++ + 3 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c +index 0492ddc4102d80..8259714d8b2692 100644 +--- a/sound/soc/codecs/cs35l56-i2c.c ++++ b/sound/soc/codecs/cs35l56-i2c.c +@@ -55,9 +55,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client) + if (ret != 0) + return ret; + +- ret = cs35l56_init(cs35l56); +- if (ret == 0) +- ret = cs35l56_irq_request(&cs35l56->base, client->irq); ++ ret = cs35l56_irq_request(&cs35l56->base, client->irq); + if (ret < 0) + cs35l56_remove(cs35l56); + +diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c +index 9bc9b7c98390dc..b1eb924a5b6ccf 100644 +--- a/sound/soc/codecs/cs35l56-spi.c ++++ b/sound/soc/codecs/cs35l56-spi.c +@@ -44,9 +44,7 @@ static int cs35l56_spi_probe(struct spi_device *spi) + if (ret != 0) + return ret; + +- ret = cs35l56_init(cs35l56); +- if (ret == 0) +- ret = cs35l56_irq_request(&cs35l56->base, spi->irq); ++ ret = cs35l56_irq_request(&cs35l56->base, spi->irq); + if (ret < 0) + cs35l56_remove(cs35l56); + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index 0f40af6606a426..f8468b3ae593a1 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -1437,6 +1437,16 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + goto err; + } + ++ /* ++ * On SoundWire the cs35l56_init() cannot be run until after the ++ * device has been enumerated by the SoundWire core. ++ */ ++ if (!cs35l56->sdw_peripheral) { ++ ret = cs35l56_init(cs35l56); ++ if (ret) ++ goto err_remove_wm_adsp; ++ } ++ + ret = snd_soc_register_component(cs35l56->base.dev, + &soc_component_dev_cs35l56, + cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); +@@ -1451,6 +1461,11 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + wm_adsp2_remove(&cs35l56->dsp); + + err: ++ if (pm_runtime_enabled(cs35l56->base.dev)) { ++ pm_runtime_dont_use_autosuspend(cs35l56->base.dev); ++ pm_runtime_disable(cs35l56->base.dev); ++ } ++ + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); + regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + +-- +2.53.0 + diff --git a/queue-6.18/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch b/queue-6.18/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch new file mode 100644 index 0000000000..f28fa3dcfb --- /dev/null +++ b/queue-6.18/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch @@ -0,0 +1,57 @@ +From 29d82e4febba6258874d11f124fbf5a8ddee1c61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 14:20:45 +0100 +Subject: ASoC: cs35l56: Use complete_all() to signal init_completion + +From: Richard Fitzgerald + +[ Upstream commit e0bffb63a2eda0af82ed7e6357ac67c2db990c21 ] + +In cs35l56_init() use complete_all() to signal init_completion instead +of complete(). + +cs35l56_init() was signaling init_completion using the complete() function. +This only releases ONE waiter. + +If cs35l56_component_probe() was called multiple times the first time +would consume that one signal, then future calls would timeout waiting for +the completion. This could happen if: + + - The component is probed, removed, then probed again without the cs35l56 + module being removed. + + - A call to component_probe() returns an error and ASoC calls it again + later. + +It should use complete_all() so that after it has been signaled it will +allow any code that waits on it to continue immediately. + +The one case where the driver must wait for initialization to run again is +when waiting for a reboot after firmware download, and here the code +correctly calls reinit_completion() first. + +Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260716132045.1469156-3-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index f8468b3ae593a1..e3334b2d845323 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -1548,7 +1548,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56) + return dev_err_probe(cs35l56->base.dev, ret, "Failed to write ASP1_CONTROL3\n"); + + cs35l56->base.init_done = true; +- complete(&cs35l56->init_completion); ++ complete_all(&cs35l56->init_completion); + + return 0; + } +-- +2.53.0 + diff --git a/queue-6.18/asoc-sun4i-codec-set-quirks.playback_only-for-h616-c.patch b/queue-6.18/asoc-sun4i-codec-set-quirks.playback_only-for-h616-c.patch new file mode 100644 index 0000000000..9888c2a575 --- /dev/null +++ b/queue-6.18/asoc-sun4i-codec-set-quirks.playback_only-for-h616-c.patch @@ -0,0 +1,39 @@ +From 3b1c9ccafb31281d560e5a7eef43768733bc8c3d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:33:03 +0800 +Subject: ASoC: sun4i-codec: Set quirks.playback_only for H616 codec + +From: Chen-Yu Tsai + +[ Upstream commit d9e96f859de3ea3e99bce927a988449a1816483c ] + +The H616 codec does not have capture capabilities. Set the +.playback_only quirks flag to denote this. + +This was somehow missing from the original driver patch, even though +the patch prior to it in the series added this quirk. + +Fixes: 9155c321a1d0 ("ASoC: sun4i-codec: support allwinner H616 codec") +Signed-off-by: Chen-Yu Tsai +Link: https://patch.msgid.link/20260714113304.270224-1-wens@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sunxi/sun4i-codec.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c +index 93733ff2e32a03..3b92318e18ba6f 100644 +--- a/sound/soc/sunxi/sun4i-codec.c ++++ b/sound/soc/sunxi/sun4i-codec.c +@@ -2236,6 +2236,7 @@ static const struct sun4i_codec_quirks sun50i_h616_codec_quirks = { + .reg_dac_fifoc = REG_FIELD(SUN50I_H616_CODEC_DAC_FIFOC, 0, 31), + .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA, + .has_reset = true, ++ .playback_only = true, + .dma_max_burst = SUN4I_DMA_MAX_BURST, + }; + +-- +2.53.0 + diff --git a/queue-6.18/asoc-tas2781-bound-firmware-description-string-parsi.patch b/queue-6.18/asoc-tas2781-bound-firmware-description-string-parsi.patch new file mode 100644 index 0000000000..042611e084 --- /dev/null +++ b/queue-6.18/asoc-tas2781-bound-firmware-description-string-parsi.patch @@ -0,0 +1,153 @@ +From b65fc944d143aa3859e83d9c07e0a88e08dca276 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:45:39 +0800 +Subject: ASoC: tas2781: bound firmware description string parsing + +From: Pengpeng Hou + +[ Upstream commit bc889dfcea9294a1eae7f8e2f3573a90764ae4d0 ] + +The TAS2781 firmware parser reads several variable-length description +strings with strlen() before checking that the string terminator is +present inside the firmware blob. A malformed firmware image without a +NUL terminator can therefore make the parser walk past the end of the +firmware buffer before the later size checks run. + +Add a small bounded string-length helper and use it for all description +fields that are parsed from the firmware buffer. Keep the existing size +checks for the fixed bytes that follow each string. + +Fixes: 915f5eadebd2 ("ASoC: tas2781: firmware lib") +Signed-off-by: Pengpeng Hou +Link: https://patch.msgid.link/20260706144540.93929-1-pengpeng@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2781-fmwlib.c | 63 ++++++++++++++++++++++++++++--- + 1 file changed, 57 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c +index 78fd0a5dc6f22e..2f6522f76df9b3 100644 +--- a/sound/soc/codecs/tas2781-fmwlib.c ++++ b/sound/soc/codecs/tas2781-fmwlib.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1082,13 +1083,42 @@ static int tasdevice_load_block_kernel( + return 0; + } + ++static int tasdevice_fw_strnlen(const struct firmware *fmw, int offset) ++{ ++ const u8 *start; ++ const u8 *nul; ++ size_t remaining; ++ size_t len; ++ ++ if (offset < 0 || offset >= fmw->size) ++ return -EINVAL; ++ ++ start = fmw->data + offset; ++ remaining = fmw->size - offset; ++ nul = memchr(start, '\0', remaining); ++ if (!nul) ++ return -EINVAL; ++ ++ len = nul - start; ++ if (len > INT_MAX) ++ return -EOVERFLOW; ++ ++ return len; ++} ++ + static int fw_parse_variable_hdr(struct tasdevice_priv + *tas_priv, struct tasdevice_dspfw_hdr *fw_hdr, + const struct firmware *fmw, int offset) + { + const unsigned char *buf = fmw->data; +- int len = strlen((char *)&buf[offset]); ++ int len; + ++ len = tasdevice_fw_strnlen(fmw, offset); ++ if (len < 0) { ++ dev_err(tas_priv->dev, "%s: Description error\n", __func__); ++ offset = len; ++ goto out; ++ } + len++; + + if (offset + len + 8 > fmw->size) { +@@ -1220,7 +1250,12 @@ static int fw_parse_data(struct tasdevice_fw *tas_fmw, + memcpy(img_data->name, &data[offset], 64); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_fmw->dev, "%s: Description error\n", __func__); ++ offset = n; ++ goto out; ++ } + n++; + if (offset + n + 2 > fmw->size) { + dev_err(tas_fmw->dev, "%s: Description error\n", __func__); +@@ -1293,7 +1328,12 @@ static int fw_parse_program_data(struct tasdevice_priv *tas_priv, + } + offset += 64; + +- n = strlen((char *)&buf[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + /* skip '\0' and 5 unused bytes */ + n += 6; + if (offset + n > fmw->size) { +@@ -1356,7 +1396,12 @@ static int fw_parse_configuration_data( + memcpy(config->name, &data[offset], 64); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + n += 15; + if (offset + n > fmw->size) { + dev_err(tas_priv->dev, "Description err\n"); +@@ -2038,7 +2083,8 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, + { + struct tasdevice_calibration *calibration; + unsigned char *data = (unsigned char *)fmw->data; +- unsigned int i, n; ++ unsigned int i; ++ int n; + + if (offset + 2 > fmw->size) { + dev_err(tas_priv->dev, "%s: Calibrations error\n", __func__); +@@ -2070,7 +2116,12 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, + calibration = &(tas_fmw->calibrations[i]); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + /* skip '\0' and 2 unused bytes */ + n += 3; + if (offset + n > fmw->size) { +-- +2.53.0 + diff --git a/queue-6.18/bluetooth-btusb-validate-realtek-vendor-event-length.patch b/queue-6.18/bluetooth-btusb-validate-realtek-vendor-event-length.patch new file mode 100644 index 0000000000..e14bd51fd5 --- /dev/null +++ b/queue-6.18/bluetooth-btusb-validate-realtek-vendor-event-length.patch @@ -0,0 +1,48 @@ +From 794b12b99903e6cc7be8398a3cae54785b030491 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:47:17 +0800 +Subject: Bluetooth: btusb: validate Realtek vendor event length + +From: Pengpeng Hou + +[ Upstream commit df541cd485ff80a5ddc579d99687bc7506df9851 ] + +btusb_recv_event_realtek() reads the event code at data[0] and the Realtek +subevent code at data[2] before deciding whether to consume a vendor event +as a coredump. + +For example, the two-byte event ff 00 contains a complete vendor-event +header declaring zero parameters. The old classifier still reads a +nonexistent third byte and can misclassify the event as a coredump if the +adjacent byte is 0x34. + +Require the HCI event header and first parameter to be present before +inspecting the Realtek subevent code. Short events continue through the +normal HCI receive path, which owns their protocol validation. + +Fixes: 044014ce85a1 ("Bluetooth: btrtl: Add Realtek devcoredump support") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index b9e5adecfed609..fea3cb502a4e03 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2716,7 +2716,9 @@ static int btusb_setup_realtek(struct hci_dev *hdev) + + static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb) + { +- if (skb->data[0] == HCI_VENDOR_PKT && skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) { ++ if (skb->len >= HCI_EVENT_HDR_SIZE + 1 && ++ skb->data[0] == HCI_VENDOR_PKT && ++ skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) { + struct rtk_dev_coredump_hdr hdr = { + .code = RTK_DEVCOREDUMP_CODE_MEMDUMP, + }; +-- +2.53.0 + diff --git a/queue-6.18/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch b/queue-6.18/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch new file mode 100644 index 0000000000..5f279dd418 --- /dev/null +++ b/queue-6.18/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch @@ -0,0 +1,75 @@ +From 2023c7cb0857c74cf344260e9687ae3dd31b3ff8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 09:06:22 +0800 +Subject: bonding: fix devconf_all NULL dereference when IPv6 is disabled + +From: Zhaolong Zhang + +[ Upstream commit 1c975de3343cdef506f2eecc833cc1f14b0401c4 ] + +When booting with the 'ipv6.disable=1' parameter, the devconf_all is +never initialized because inet6_init() exits before addrconf_init() is +called which initializes it. bond_send_validate(), however, will still +call bond_ns_send_all() even ipv6 is indeed disabled. It will lead to +NULL derefence of net->ipv6.devconf_all in ip6_pol_route(). + + BUG: kernel NULL pointer dereference, address: 000000000000000c + [...] + Workqueue: bond0 bond_arp_monitor [bonding] + RIP: 0010:ip6_pol_route+0x69/0x480 + [...] + Call Trace: + + ? srso_return_thunk+0x5/0x5f + ? __pfx_ip6_pol_route_output+0x10/0x10 + fib6_rule_lookup+0xfe/0x260 + ? wakeup_preempt+0x8a/0x90 + ? srso_return_thunk+0x5/0x5f + ? srso_return_thunk+0x5/0x5f + ? sched_balance_rq+0x369/0x810 + ip6_route_output_flags+0xd7/0x170 + bond_ns_send_all+0xde/0x280 [bonding] + bond_ab_arp_probe+0x296/0x320 [bonding] + ? srso_return_thunk+0x5/0x5f + bond_activebackup_arp_mon+0xb4/0x2c0 [bonding] + process_one_work+0x196/0x370 + worker_thread+0x1af/0x320 + ? srso_return_thunk+0x5/0x5f + ? __pfx_worker_thread+0x10/0x10 + kthread+0xe3/0x120 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x199/0x260 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Fix this by adding ipv6_mod_enabled() condition check in the caller. + +Fixes: 4e24be018eb9 ("bonding: add new parameter ns_targets") +Signed-off-by: Qianheng Peng +Signed-off-by: Zhaolong Zhang +Reviewed-by: Hangbin Liu +Link: https://patch.msgid.link/20260707010622.487333-1-zhangzl2013@126.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index e38cae22fe025e..52af663e12e0c1 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -3422,7 +3422,8 @@ static void bond_send_validate(struct bonding *bond, struct slave *slave) + { + bond_arp_send_all(bond, slave); + #if IS_ENABLED(CONFIG_IPV6) +- bond_ns_send_all(bond, slave); ++ if (likely(ipv6_mod_enabled())) ++ bond_ns_send_all(bond, slave); + #endif + } + +-- +2.53.0 + diff --git a/queue-6.18/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch b/queue-6.18/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch new file mode 100644 index 0000000000..650a806960 --- /dev/null +++ b/queue-6.18/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch @@ -0,0 +1,79 @@ +From ca38df115bb779a08c1bbaa6717db09f861e343d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jul 2026 18:38:56 +0800 +Subject: bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() + +From: Chengfeng Ye + +[ Upstream commit 2d66a033864e27ab8d5e44cb36f31d9d2413bee4 ] + +tcp_bpf_sendmsg() keeps msg_tx across sk_stream_wait_memory(), which +drops and reacquires the socket lock. Its error path tries to decide +whether msg_tx names the local temporary message by comparing it with +the current value of psock->cork. + +This comparison is unsafe when two threads send on the same socket: + + Thread A Thread B + msg_tx = psock->cork + sk_msg_alloc() fails + sk_stream_wait_memory() + releases the socket lock acquires the socket lock + completes the cork + psock->cork = NULL + frees the cork + reacquires the socket lock + msg_tx != psock->cork + sk_msg_free(msg_tx) + +The stale cork is therefore mistaken for the local temporary message +and freed again. KASAN reported: + + BUG: KASAN: slab-use-after-free in sk_msg_free+0x49/0x50 + Read of size 4 at addr ffff88810c908800 by task poc/90 + Call Trace: + sk_msg_free+0x49/0x50 + tcp_bpf_sendmsg+0x14f5/0x1cc0 + __sys_sendto+0x32c/0x3a0 + __x64_sys_sendto+0xdb/0x1b0 + Allocated by task 89: + __kasan_kmalloc+0x8f/0xa0 + tcp_bpf_sendmsg+0x16b3/0x1cc0 + Freed by task 91: + __kasan_slab_free+0x43/0x70 + kfree+0x131/0x3c0 + tcp_bpf_sendmsg+0xec3/0x1cc0 + +msg_tx can only name the stack-local tmp or the shared cork. Check for +tmp directly so a changed psock->cork cannot turn a shared message into +an apparent local one. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Chengfeng Ye +Reviewed-by: Emil Tsalapatis +Reviewed-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/87fr18lmzo.fsf%40cloudflare.com/ +Link: https://lore.kernel.org/netdev/20260719161630.2901208-1-nicoyip.dev%40gmail.com/ [v1] +Link: https://patch.msgid.link/20260724103856.3399001-1-nicoyip.dev@gmail.com +Signed-off-by: Eduard Zingerman +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 7a3f0b244c8fc8..c27e797eff275a 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -589,7 +589,7 @@ static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + wait_for_memory: + err = sk_stream_wait_memory(sk, &timeo); + if (err) { +- if (msg_tx && msg_tx != psock->cork) ++ if (msg_tx == &tmp) + sk_msg_free(sk, msg_tx); + goto out_err; + } +-- +2.53.0 + diff --git a/queue-6.18/bpf-tcp-fix-double-sock-release-on-batch-realloc.patch b/queue-6.18/bpf-tcp-fix-double-sock-release-on-batch-realloc.patch new file mode 100644 index 0000000000..b13d740a94 --- /dev/null +++ b/queue-6.18/bpf-tcp-fix-double-sock-release-on-batch-realloc.patch @@ -0,0 +1,70 @@ +From 66a3760eaf32b93a5421395d0a7f0b62c116bb1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:32:30 +0000 +Subject: bpf: tcp: fix double sock release on batch realloc + +From: Xiang Mei (Microsoft) + +[ Upstream commit 980a813452754f8001704744e92f7aa697c53dd3 ] + +bpf_iter_tcp_batch() releases the current batch via +bpf_iter_tcp_put_batch(), which drops the socket refs and rewrites +each slot with the socket cookie, then grows the batch. cur_sk/end_sk +are kept for bpf_iter_tcp_resume(), but on realloc failure the function +returns ERR_PTR() before resume runs, leaving cur_sk < end_sk over +slots that now hold cookies rather than sock pointers. +bpf_iter_tcp_seq_stop() then calls bpf_iter_tcp_put_batch() again and +dereferences a cookie as a struct sock. + +Empty the batch on the failure path so stop() does not release it +again. The sockets were already freed by the first +bpf_iter_tcp_put_batch(), so nothing leaks, and a later read() rescans +the bucket from the start instead of skipping it. The sibling +GFP_NOWAIT failure path still holds real socket references and is left +for stop() to release. + + BUG: KASAN: null-ptr-deref in __sock_gen_cookie + Read of size 8 at addr 0000000000000059 by task exploit + ... + __sock_gen_cookie (net/core/sock_diag.c:28) + bpf_iter_tcp_put_batch (net/ipv4/tcp_ipv4.c:2918) + bpf_iter_tcp_seq_stop (net/ipv4/tcp_ipv4.c:3270) + bpf_seq_read (kernel/bpf/bpf_iter.c:205) + vfs_read (fs/read_write.c:572) + ksys_read (fs/read_write.c:716) + do_syscall_64 + entry_SYSCALL_64_after_hwframe + Kernel panic - not syncing: Fatal exception + +Fixes: cdec67a489d4 ("bpf: tcp: Make sure iter->batch always contains a full bucket snapshot") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Eric Dumazet +Reviewed-by: Jordan Rife +Link: https://patch.msgid.link/20260713233230.3553593-1-xmei5@asu.edu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_ipv4.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index a1ed4fa264836d..7efb49f9e5b3bf 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -3284,8 +3284,11 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq) + bpf_iter_tcp_put_batch(iter); + err = bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2, + GFP_USER); +- if (err) ++ if (err) { ++ iter->cur_sk = 0; ++ iter->end_sk = 0; + return ERR_PTR(err); ++ } + + sk = bpf_iter_tcp_resume(seq); + if (!sk) +-- +2.53.0 + diff --git a/queue-6.18/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch b/queue-6.18/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch new file mode 100644 index 0000000000..a7bd27123f --- /dev/null +++ b/queue-6.18/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch @@ -0,0 +1,55 @@ +From fde8c8966c0ffd4d2040ba0cfafb0f8c1fd01b48 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jun 2026 18:39:07 +0800 +Subject: btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8 + +From: You-Kai Zheng + +[ Upstream commit b95181f3929ff98949fa9460ca93eccebbf2d7fc ] + +The variable-sized buffer buf in struct btrfs_ioctl_search_args_v2 is +declared as __u64[], but it holds a packed byte stream of search results, +where all offsets into the buffer are in bytes. + +Declaring buf as __u64[] makes it easy for user space to write incorrect +pointer arithmetic: adding a byte offset directly to a __u64 pointer +scales the offset by 8, landing at byte position offset*8 instead of +offset. + +This recently caused an infinite loop in btrfs-progs: the accessor read +all-zero data from misaddressed items, which fed zeroed search keys back +into the ioctl loop and spun forever. The issue was worked around at the +time by disabling TREE_SEARCH_V2 entirely in btrfs-progs (d73e69824854: +"btrfs-progs: temporarily disable usage of v2 of search tree ioctl"). + +The kernel side already treats buf as a byte buffer, so change the +declaration to __u8[] to match the actual semantics and prevent similar +misuse in user space. The change is ABI compatible: both the structure size +and alignment are unchanged. + +Fixes: cc68a8a5a433 ("btrfs: new ioctl TREE_SEARCH_V2") +Reviewed-by: Qu Wenruo +Signed-off-by: You-Kai Zheng +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + include/uapi/linux/btrfs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h +index 8e710bbb688e04..fb89c5c37eb045 100644 +--- a/include/uapi/linux/btrfs.h ++++ b/include/uapi/linux/btrfs.h +@@ -597,7 +597,7 @@ struct btrfs_ioctl_search_args_v2 { + __u64 buf_size; /* in - size of buffer + * out - on EOVERFLOW: needed size + * to store item */ +- __u64 buf[]; /* out - found items */ ++ __u8 buf[]; /* out - found items */ + }; + + /* With a @src_length of zero, the range from @src_offset->EOF is cloned! */ +-- +2.53.0 + diff --git a/queue-6.18/btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch b/queue-6.18/btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch new file mode 100644 index 0000000000..a04d74f599 --- /dev/null +++ b/queue-6.18/btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch @@ -0,0 +1,62 @@ +From 625ff33d364df69f82283aa013b861f44a3b5568 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jun 2026 12:58:05 -0700 +Subject: btrfs: don't propagate EXTENT_FLAG_LOGGING to split extent maps + +From: Leo Martins + +[ Upstream commit 5eff4d5b17fa1950e80bfd1ba43dc0699e61a644 ] + +When btrfs_drop_extent_map_range() splits an extent map, the new split +maps inherit the original map's flags through a local 'flags' variable. +Commit f86f7a75e2fb ("btrfs: use the flags of an extent map to identify +the compression type") changed the EXTENT_FLAG_LOGGING clearing to +operate on em->flags instead of that local 'flags' copy, so a split of +an extent map that is currently being logged wrongly inherits +EXTENT_FLAG_LOGGING. + +The flag is then never cleared on the split, and when it is freed while +still on the inode's modified_extents list (for example by the extent +map shrinker) it trips the WARN_ON(!list_empty(&em->list)) in +btrfs_free_extent_map() and leads to a use-after-free. + +Clear EXTENT_FLAG_LOGGING from the local 'flags' copy used for the +splits and only clear EXTENT_FLAG_PINNED from em->flags, restoring the +behaviour prior to f86f7a75e2fb. + +CC: Jeff Layton +Link: https://lore.kernel.org/all/20260629-btrfs-skip-logging-v1-1-4e3a28c1acaf@kernel.org/ +Fixes: f86f7a75e2fb ("btrfs: use the flags of an extent map to identify the compression type") +Reviewed-by: Jeff Layton +Reviewed-by: Filipe Manana +Signed-off-by: Leo Martins +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_map.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c +index 7e38c23a0c1cb6..21eb104ee2aefb 100644 +--- a/fs/btrfs/extent_map.c ++++ b/fs/btrfs/extent_map.c +@@ -854,13 +854,13 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, + goto next; + } + +- flags = em->flags; + /* + * In case we split the extent map, we want to preserve the + * EXTENT_FLAG_LOGGING flag on our extent map, but we don't want + * it on the new extent maps. + */ +- em->flags &= ~(EXTENT_FLAG_PINNED | EXTENT_FLAG_LOGGING); ++ flags = em->flags & ~EXTENT_FLAG_LOGGING; ++ em->flags &= ~EXTENT_FLAG_PINNED; + modified = !list_empty(&em->list); + + /* +-- +2.53.0 + diff --git a/queue-6.18/btrfs-fix-u32-to-s64-type-conversion-in-dirty_metada.patch b/queue-6.18/btrfs-fix-u32-to-s64-type-conversion-in-dirty_metada.patch new file mode 100644 index 0000000000..909c2be81d --- /dev/null +++ b/queue-6.18/btrfs-fix-u32-to-s64-type-conversion-in-dirty_metada.patch @@ -0,0 +1,62 @@ +From 0367bcdd3d56ffad6371bbdbd0e9568419c6ab1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Jun 2026 15:08:43 +0800 +Subject: btrfs: fix u32 to s64 type conversion in dirty_metadata_bytes + accounting + +From: Dave Chen + +[ Upstream commit 8b5a09ceb61b18b1f0797cd30a549d7dc85d8d50 ] + +The percpu_counter dirty_metadata_bytes is updated by negating eb->len +and passing it to percpu_counter_add_batch(), whose amount parameter is +s64. Since commit 84cda1a6087d ("btrfs: cache folio size and shift in +extent_buffer"), eb->len is u32. The u32 result of -eb->len, when +widened to the s64 parameter, becomes a large positive value instead of +the intended negative value. For eb->len == 16384 the counter adds ++4294950912 instead of subtracting 16384. + +The counter therefore grows on every metadata writeback instead of +shrinking by the extent buffer size, permanently exceeding +BTRFS_DIRTY_METADATA_THRESH and causing __btrfs_btree_balance_dirty() +to trigger balance_dirty_pages_ratelimited() unconditionally, adding +unnecessary writeback pressure. + +Cast eb->len to s64 before negation at both call sites so the +subtraction is performed in signed 64-bit arithmetic. + +Reviewed-by: Filipe Manana +Fixes: 84cda1a6087d ("btrfs: cache folio size and shift in extent_buffer") +Signed-off-by: Dave Chen +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_io.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index f955b4003d4246..80fc2d59bfeb86 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -1949,7 +1949,7 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e + + btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, +- -eb->len, ++ -(s64)eb->len, + fs_info->dirty_metadata_batch); + ret = true; + } else { +@@ -3731,7 +3731,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, + return; + + buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); +- percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, ++ percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -(s64)eb->len, + fs_info->dirty_metadata_batch); + + for (int i = 0; i < num_extent_folios(eb); i++) { +-- +2.53.0 + diff --git a/queue-6.18/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch b/queue-6.18/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch new file mode 100644 index 0000000000..2b9d276a8e --- /dev/null +++ b/queue-6.18/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch @@ -0,0 +1,47 @@ +From 819709000fd8c1fb8f8f5ce41b016a698f1a03f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 03:17:28 +0000 +Subject: btrfs: free mapping node on duplicate reloc root insert + +From: Guanghui Yang <3497809730@qq.com> + +[ Upstream commit 6a8269b6459ed870a8156c106a0f597383907872 ] + +__add_reloc_root() allocates a mapping_node before inserting it into +rc->reloc_root_tree. If rb_simple_insert() finds an existing entry, it +returns the existing rb_node and leaves the newly allocated node unlinked. + +The error path then returns -EEXIST without freeing the new node. Since +the node was never inserted into reloc_root_tree, the later cleanup in +put_reloc_control() cannot find it either. + +Free the newly allocated node before returning -EEXIST. + +The callers currently assert that -EEXIST should not happen, so this is a +defensive cleanup for an unexpected duplicate insert path. If the path is +ever reached, the local allocation should still be released. + +Fixes: 57a304cfd43b ("btrfs: do not panic in __add_reloc_root") +Reviewed-by: Qu Wenruo +Signed-off-by: Guanghui Yang <3497809730@qq.com> +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 86430435d3acc7..80e5de6736e829 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -496,6 +496,7 @@ static int __add_reloc_root(struct btrfs_root *root) + btrfs_err(fs_info, + "Duplicate root found for start=%llu while inserting into relocation tree", + node->bytenr); ++ kfree(node); + return -EEXIST; + } + +-- +2.53.0 + diff --git a/queue-6.18/cred-add-scoped_with_kernel_creds.patch b/queue-6.18/cred-add-scoped_with_kernel_creds.patch new file mode 100644 index 0000000000..8e29a7cc14 --- /dev/null +++ b/queue-6.18/cred-add-scoped_with_kernel_creds.patch @@ -0,0 +1,48 @@ +From 47873951a173c57c83ee281a02097def67a06593 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Nov 2025 00:12:43 +0100 +Subject: cred: add scoped_with_kernel_creds() + +From: Christian Brauner + +[ Upstream commit ae40e6c65791f47c76cc14d0cce2707fe6053f72 ] + +Add a new cleanup class for override creds. We can make use of this in a +bunch of places going forward. + +Based on this scoped_with_kernel_creds() that can be used to temporarily +assume kernel credentials for specific tasks such as firmware loading, +or coredump socket connections. At no point will the caller interact +with the kernel credentials directly. + +Link: https://patch.msgid.link/20251103-work-creds-init_cred-v1-4-cb3ec8711a6a@kernel.org +Reviewed-by: Jens Axboe +Signed-off-by: Christian Brauner +Stable-dep-of: a1e0eb8f55cf ("ovl: check access to copy_file_range source with src mounter creds") +Signed-off-by: Sasha Levin +--- + include/linux/cred.h | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/include/linux/cred.h b/include/linux/cred.h +index 89ae50ad2acea9..6225c0cef3d779 100644 +--- a/include/linux/cred.h ++++ b/include/linux/cred.h +@@ -180,6 +180,14 @@ static inline const struct cred *revert_creds(const struct cred *revert_cred) + return rcu_replace_pointer(current->cred, revert_cred, 1); + } + ++DEFINE_CLASS(override_creds, ++ const struct cred *, ++ revert_creds(_T), ++ override_creds(override_cred), const struct cred *override_cred) ++ ++#define scoped_with_kernel_creds() \ ++ scoped_class(override_creds, __UNIQUE_ID(cred), kernel_cred()) ++ + /** + * get_cred_many - Get references on a set of credentials + * @cred: The credentials to reference +-- +2.53.0 + diff --git a/queue-6.18/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch b/queue-6.18/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..68a8c78cc5 --- /dev/null +++ b/queue-6.18/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,48 @@ +From 55d6bbb11d7b379936ae83a92acc83f5b49c3197 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:17:37 +0800 +Subject: dpaa2-eth: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit b4b201cc93ff70150853aba03e14d314d1980ca0 ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The Ethernet connect path stores that +device in mac->mc_dev and keeps it for the lifetime of the connected MAC +object. + +However, the disconnect path only disconnects and closes the MAC before +freeing the dpaa2_mac object. It does not drop the endpoint device +reference stored in mac->mc_dev, so every successful connect leaks that +device reference when the MAC is later disconnected. + +Drop the endpoint device reference after closing the MAC and before +freeing the dpaa2_mac object. + +Fixes: 719479230893 ("dpaa2-eth: add MAC/PHY support through phylink") +Signed-off-by: Guangshuo Li +Reviewed-by: Ioana Ciornei +Reviewed-by: Ioana Ciornei +Link: https://patch.msgid.link/20260708111738.750391-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index 18d86badd6ea73..6fd478572ef8ff 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -4732,6 +4732,7 @@ static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-6.18/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch b/queue-6.18/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..5826571079 --- /dev/null +++ b/queue-6.18/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,46 @@ +From 2d09ccd7df121b5768edcf3276b4cc8988aa5354 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:10:25 +0800 +Subject: dpaa2-switch: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit 4c1eabbef7a1707635652e956e39db1269c3af2b ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The switch port connect path stores +that device in mac->mc_dev and keeps it for the lifetime of the connected +MAC object. + +However, the disconnect path only closes the MAC and frees the dpaa2_mac +object. It does not drop the endpoint device reference stored in +mac->mc_dev, so every successful connect leaks that device reference when +the MAC is later disconnected. + +Drop the endpoint device reference before freeing the dpaa2_mac object. + +Fixes: 84cba72956fd ("dpaa2-switch: integrate the MAC endpoint support") +Signed-off-by: Guangshuo Li +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708111025.749311-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +index 789a46f6938eea..846300b77e8acc 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +@@ -1511,6 +1511,7 @@ static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-6.18/drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch b/queue-6.18/drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch new file mode 100644 index 0000000000..727b44bfcb --- /dev/null +++ b/queue-6.18/drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch @@ -0,0 +1,42 @@ +From cf52c8df33c66120358a107cf7734698854ba063 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 11:05:21 +0000 +Subject: drivers/virt: pkvm: Fix end calculation in mmio_guard_ioremap_hook() + +From: Mostafa Saleh + +[ Upstream commit 62c740f823a8e47ffe56e45a7472c27cf988e2f6 ] + +Sashiko (locally) reports a logical issues in mmio_guard_ioremap_hook() + +mmio_guard_ioremap_hook() attempts to handle unaligned addresses and +sizes. However, aligning the start address before adding the size, might +shift the end to the page before. + +Fixes: 0f1269495800 ("drivers/virt: pkvm: Intercept ioremap using pKVM MMIO_GUARD hypercall") +Signed-off-by: Mostafa Saleh +Reviewed-by: Catalin Marinas +Tested-by: Aneesh Kumar K.V (Arm) +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c +index 4230b817a80bd8..d66291def0f408 100644 +--- a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c ++++ b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c +@@ -82,8 +82,8 @@ static int mmio_guard_ioremap_hook(phys_addr_t phys, size_t size, + if (protval != PROT_DEVICE_nGnRE && protval != PROT_DEVICE_nGnRnE) + return 0; + ++ end = PAGE_ALIGN(phys + size); + phys = PAGE_ALIGN_DOWN(phys); +- end = phys + PAGE_ALIGN(size); + + while (phys < end) { + const int func_id = ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_FUNC_ID; +-- +2.53.0 + diff --git a/queue-6.18/drm-panel-s6e3ha8-fix-unmet-dependency-on-drm_displa.patch b/queue-6.18/drm-panel-s6e3ha8-fix-unmet-dependency-on-drm_displa.patch new file mode 100644 index 0000000000..934092243d --- /dev/null +++ b/queue-6.18/drm-panel-s6e3ha8-fix-unmet-dependency-on-drm_displa.patch @@ -0,0 +1,43 @@ +From 306c4d47cdadabfe7a80f504e207d57116e0289e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 01:15:14 +0100 +Subject: drm/panel: s6e3ha8: fix unmet dependency on DRM_DISPLAY_HELPER + +From: Julian Braha + +[ Upstream commit 3667bc164849fee4f1b18b182bdfe643f758ca17 ] + +Currently, DRM_PANEL_SAMSUNG_S6E3HA8 selects DRM_DISPLAY_DSC_HELPER +without ensuring its dependency, DRM_DISPLAY_HELPER, is enabled, +causing an unmet dependency. + +Let's select DRM_DISPLAY_HELPER as other similar options do. + +This unmet dependency bug was found by kconfirm, a static analysis tool +for Kconfig. + +Fixes: fd3b2c5f40a1 ("drm/panel: s6e3ha8: select CONFIG_DRM_DISPLAY_DSC_HELPER") +Signed-off-by: Julian Braha +Reviewed-by: Neil Armstrong +Signed-off-by: Neil Armstrong +Link: https://patch.msgid.link/20260712001514.2318597-1-julianbraha@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig +index 1516c6fa265db7..7354dc85a6aa70 100644 +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -814,6 +814,7 @@ config DRM_PANEL_SAMSUNG_S6E3HA8 + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE ++ select DRM_DISPLAY_HELPER + select DRM_DISPLAY_DSC_HELPER + help + Say Y or M here if you want to enable support for the +-- +2.53.0 + diff --git a/queue-6.18/drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch b/queue-6.18/drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch new file mode 100644 index 0000000000..f5045e1fe5 --- /dev/null +++ b/queue-6.18/drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch @@ -0,0 +1,108 @@ +From c6a2b859d4825578f478c3ef140b3f8ad0bae854 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 17:07:43 +0200 +Subject: drm/tests: shmem: Set DMA mask to 64-bit in drm_gem_shmem +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit b04a248cfa6cfa1e7dc9ce91cb1eb88b1a70dd69 ] + +drm_gem_shmem_test_purge [1] and drm_gem_shmem_test_get_pages_sgt [2] +intermittently fail on ppc64le and s390x CI systems with a DMA address +overflow: + + DMA addr 0x0000000100307000+4096 overflow (mask ffffffff, bus limit 0) + WARNING: kernel/dma/direct.h:114 dma_direct_map_sg+0x778/0x920 + + drm_gem_shmem_test_purge: ASSERTION FAILED at + drivers/gpu/drm/tests/drm_gem_shmem_test.c:330 + Expected sgt is not error, but is: -5 + +The call chain leading to the failure is: + + drm_gem_shmem_test_purge() / drm_gem_shmem_test_get_pages_sgt() + drm_gem_shmem_get_pages_sgt() + drm_gem_shmem_get_pages_sgt_locked() [drm_gem_shmem_helper.c] + dma_map_sgtable() [mapping.c] + __dma_map_sg_attrs() + dma_direct_map_sg() [direct.c] + dma_direct_map_phys() [kernel/dma/direct.h] + dma_capable() Checks addr against DMA mask + -> FAILS: addr > 0xFFFFFFFF + +The root cause is that KUnit devices are initialized with a 32-bit DMA +mask (DMA_BIT_MASK(32)) in lib/kunit/device.c. On ppc64le and s390x +systems with physical memory above 4GB, page allocations can land at +addresses that exceed this mask. When drm_gem_shmem_get_pages_sgt() +attempts to DMA-map these pages via dma_map_sgtable(), the DMA layer +rejects the mapping because the physical address overflows the 32-bit +mask. + +The failure is intermittent because pages may or may not be allocated +above 4GB on any given run depend on memory pressure. + +Fix by setting a 64-bit DMA mask on the device before calling +drm_gem_shmem_get_pages_sgt() for all tests, following the same pattern +already used in drm_gem_shmem_test_obj_create_private(). + +[1] https://s3.amazonaws.com/arr-cki-prod-trusted-artifacts/trusted-artifacts/2643976103/test_s390x/15128551935/artifacts/jobwatch/logs/recipes/21561049/tasks/220716793/results/1014626315/logs/dmesg.log +[2] https://s3.amazonaws.com/arr-cki-prod-trusted-artifacts/trusted-artifacts/2643976103/test_ppc64le/15128551933/artifacts/jobwatch/logs/recipes/21561041/tasks/220716705/results/1014628163/logs/dmesg.log + +Fixes: 93032ae634d4 ("drm/test: add a test suite for GEM objects backed by shmem") +Closes: https://datawarehouse.cki-project.org/issue/5345 +Closes: https://datawarehouse.cki-project.org/issue/3184 +Assisted-by: Claude:claude-4.6-opus +Reviewed-by: Thomas Zimmermann +Signed-off-by: José Expósito +Link: https://patch.msgid.link/20260703150808.3832-1-jose.exposito89@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/tests/drm_gem_shmem_test.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/tests/drm_gem_shmem_test.c b/drivers/gpu/drm/tests/drm_gem_shmem_test.c +index 4b459f21acfd95..b1fa287892fb81 100644 +--- a/drivers/gpu/drm/tests/drm_gem_shmem_test.c ++++ b/drivers/gpu/drm/tests/drm_gem_shmem_test.c +@@ -95,13 +95,9 @@ static void drm_gem_shmem_test_obj_create_private(struct kunit *test) + sg_init_one(sgt->sgl, buf, TEST_SIZE); + + /* +- * Set the DMA mask to 64-bits and map the sgtables +- * otherwise drm_gem_shmem_free will cause a warning +- * on debug kernels. ++ * Map the sgtables otherwise drm_gem_shmem_free will cause a warning on ++ * debug kernels. + */ +- ret = dma_set_mask(drm_dev->dev, DMA_BIT_MASK(64)); +- KUNIT_ASSERT_EQ(test, ret, 0); +- + ret = dma_map_sgtable(drm_dev->dev, sgt, DMA_BIDIRECTIONAL, 0); + KUNIT_ASSERT_EQ(test, ret, 0); + +@@ -352,11 +348,19 @@ static int drm_gem_shmem_test_init(struct kunit *test) + { + struct device *dev; + struct drm_device *drm_dev; ++ int ret; + + /* Allocate a parent device */ + dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + ++ /* ++ * Set the DMA mask to 64-bits to avoid intermittent failures calling ++ * drm_gem_shmem_get_pages_sgt(). ++ */ ++ ret = dma_set_mask(dev, DMA_BIT_MASK(64)); ++ KUNIT_ASSERT_EQ(test, ret, 0); ++ + /* + * The DRM core will automatically initialize the GEM core and create + * a DRM Memory Manager object which provides an address space pool +-- +2.53.0 + diff --git a/queue-6.18/drm-xe-i2c-allow-per-domain-unique-id.patch b/queue-6.18/drm-xe-i2c-allow-per-domain-unique-id.patch new file mode 100644 index 0000000000..64998783bb --- /dev/null +++ b/queue-6.18/drm-xe-i2c-allow-per-domain-unique-id.patch @@ -0,0 +1,58 @@ +From 95f4ee5c253b663c735a12df34b49d57cd2f7823 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:04:38 +0530 +Subject: drm/xe/i2c: Allow per domain unique id +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Raag Jadav + +[ Upstream commit 5d8ed6b64220ad629aade5f174e3f690c37435f9 ] + +PCI bus, device and function can be same for devices existing across +different domains. Allow per domain unique identifier while registering +platform device to prevent name conflict. + +Fixes: f0e53aadd702 ("drm/xe: Support for I2C attached MCUs") +Signed-off-by: Raag Jadav +Reviewed-by: Heikki Krogerus +Link: https://patch.msgid.link/20260721113438.651100-1-raag.jadav@intel.com +Signed-off-by: Matt Roper +(cherry picked from commit a79f6abc8b516b5bd906e2eca8121e3549ee163f) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_i2c.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_i2c.c b/drivers/gpu/drm/xe/xe_i2c.c +index 48dfcb41fa08c1..2788dc6510d6ac 100644 +--- a/drivers/gpu/drm/xe/xe_i2c.c ++++ b/drivers/gpu/drm/xe/xe_i2c.c +@@ -94,18 +94,21 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c) + struct platform_device *pdev; + struct fwnode_handle *fwnode; + int ret; ++ u32 id; + + fwnode = fwnode_create_software_node(xe_i2c_adapter_properties, NULL); + if (IS_ERR(fwnode)) + return PTR_ERR(fwnode); + ++ id = (pci_domain_nr(pci->bus) << 16) | pci_dev_id(pci); ++ + /* + * Not using platform_device_register_full() here because we don't have + * a handle to the platform_device before it returns. xe_i2c_notifier() + * uses that handle, but it may be called before + * platform_device_register_full() is done. + */ +- pdev = platform_device_alloc(adapter_name, pci_dev_id(pci)); ++ pdev = platform_device_alloc(adapter_name, id); + if (!pdev) { + ret = -ENOMEM; + goto err_fwnode_remove; +-- +2.53.0 + diff --git a/queue-6.18/drm-xe-vm-fix-svm-leak-on-resv-obj-alloc-failure-in-.patch b/queue-6.18/drm-xe-vm-fix-svm-leak-on-resv-obj-alloc-failure-in-.patch new file mode 100644 index 0000000000..c912664b51 --- /dev/null +++ b/queue-6.18/drm-xe-vm-fix-svm-leak-on-resv-obj-alloc-failure-in-.patch @@ -0,0 +1,75 @@ +From 5f9125c5594cf68a9e59525cd435f0361a622a55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 20:55:14 +0000 +Subject: drm/xe/vm: Fix SVM leak on resv obj alloc failure in xe_vm_create() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Shuicheng Lin + +[ Upstream commit d2c6800ad1802bed72a6de1416536737f114f1d6 ] + +Commit 9e9787414882 ("drm/xe/userptr: replace xe_hmm with gpusvm") made +xe_svm_init() unconditional in xe_vm_create() and extended it to also +initialize a "simple" gpusvm state for non-fault-mode VMs. The matching +xe_svm_fini() call in xe_vm_close_and_put() was updated to run +unconditionally, but the error unwind path in xe_vm_create() was not. + +On the drm_gpuvm_resv_object_alloc() failure path, xe_svm_init() has +already succeeded but xe_svm_fini() is only called when +XE_VM_FLAG_FAULT_MODE is set. For non-fault-mode VMs this leaves +vm->svm.gpusvm partially initialized and leaks the resources allocated +by drm_gpusvm_init(). + +For fault-mode VMs, xe_svm_init() additionally acquires the pagemap +owner via drm_pagemap_acquire_owner() and the pagemaps via +xe_svm_get_pagemaps(). Those resources are released by xe_svm_close(), +not xe_svm_fini(). On the same error path, xe_svm_close() is not +called either, so fault-mode VMs leak the pagemap owner and pagemaps. + +Fix both leaks: + +- Call xe_svm_fini() unconditionally on the err_svm_fini path, matching + the unconditional xe_svm_init() call. Move the vm->size = 0 + assignment out of the conditional so the xe_vm_is_closed() assert in + xe_svm_fini() (and xe_svm_close()) holds for both modes. + +- Call xe_svm_close() for fault-mode VMs before xe_svm_fini(), matching + the ordering used in xe_vm_close_and_put(). + +Fixes: 9e9787414882 ("drm/xe/userptr: replace xe_hmm with gpusvm") +Cc: Matthew Auld +Assisted-by: Claude:claude-opus-4.7 +Reviewed-by: Matthew Brost +Link: https://patch.msgid.link/20260721205516.4058959-2-shuicheng.lin@intel.com +Signed-off-by: Shuicheng Lin +(cherry picked from commit ca2a3587d577ba764e0fe628fb676244fc33ddd4) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_vm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c +index 8f7b8f2da06bac..b00da90e399135 100644 +--- a/drivers/gpu/drm/xe/xe_vm.c ++++ b/drivers/gpu/drm/xe/xe_vm.c +@@ -1626,10 +1626,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef) + return ERR_PTR(err); + + err_svm_fini: +- if (flags & XE_VM_FLAG_FAULT_MODE) { +- vm->size = 0; /* close the vm */ +- xe_svm_fini(vm); +- } ++ vm->size = 0; /* close the vm */ ++ if (flags & XE_VM_FLAG_FAULT_MODE) ++ xe_svm_close(vm); ++ xe_svm_fini(vm); + err_no_resv: + mutex_destroy(&vm->snap_mutex); + for_each_tile(tile, xe, id) +-- +2.53.0 + diff --git a/queue-6.18/filemap-add-helper-to-look-up-dirty-folios-in-a-rang.patch b/queue-6.18/filemap-add-helper-to-look-up-dirty-folios-in-a-rang.patch new file mode 100644 index 0000000000..872fd03eae --- /dev/null +++ b/queue-6.18/filemap-add-helper-to-look-up-dirty-folios-in-a-rang.patch @@ -0,0 +1,116 @@ +From aec6e23a1a570aabdd254804b6985f1679aff1bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Oct 2025 09:46:35 -0400 +Subject: filemap: add helper to look up dirty folios in a range + +From: Brian Foster + +[ Upstream commit f8d98072feee32722086ddae4f288b6c45ae4330 ] + +Add a new filemap_get_folios_dirty() helper to look up existing dirty +folios in a range and add them to a folio_batch. This is to support +optimization of certain iomap operations that only care about dirty +folios in a target range. For example, zero range only zeroes the subset +of dirty pages over unwritten mappings, seek hole/data may use similar +logic in the future, etc. + +Note that the helper is intended for use under internal fs locks. +Therefore it trylocks folios in order to filter out clean folios. +This loosely follows the logic from filemap_range_has_writeback(). + +Signed-off-by: Brian Foster +Reviewed-by: Christoph Hellwig +Reviewed-by: Darrick J. Wong +Signed-off-by: Christian Brauner +Stable-dep-of: 7a6fd6b21d7e ("iomap: fix incorrect did_zero setting in iomap_zero_iter()") +Signed-off-by: Sasha Levin +--- + include/linux/pagemap.h | 2 ++ + mm/filemap.c | 58 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 60 insertions(+) + +diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h +index 09b581c1d878d3..7274a86b487170 100644 +--- a/include/linux/pagemap.h ++++ b/include/linux/pagemap.h +@@ -977,6 +977,8 @@ unsigned filemap_get_folios_contig(struct address_space *mapping, + pgoff_t *start, pgoff_t end, struct folio_batch *fbatch); + unsigned filemap_get_folios_tag(struct address_space *mapping, pgoff_t *start, + pgoff_t end, xa_mark_t tag, struct folio_batch *fbatch); ++unsigned filemap_get_folios_dirty(struct address_space *mapping, ++ pgoff_t *start, pgoff_t end, struct folio_batch *fbatch); + + struct folio *read_cache_folio(struct address_space *, pgoff_t index, + filler_t *filler, struct file *file); +diff --git a/mm/filemap.c b/mm/filemap.c +index 7c26e3735f1bb4..7c599eedf4da6c 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2372,6 +2372,64 @@ unsigned filemap_get_folios_tag(struct address_space *mapping, pgoff_t *start, + } + EXPORT_SYMBOL(filemap_get_folios_tag); + ++/** ++ * filemap_get_folios_dirty - Get a batch of dirty folios ++ * @mapping: The address_space to search ++ * @start: The starting folio index ++ * @end: The final folio index (inclusive) ++ * @fbatch: The batch to fill ++ * ++ * filemap_get_folios_dirty() works exactly like filemap_get_folios(), except ++ * the returned folios are presumed to be dirty or undergoing writeback. Dirty ++ * state is presumed because we don't block on folio lock nor want to miss ++ * folios. Callers that need to can recheck state upon locking the folio. ++ * ++ * This may not return all dirty folios if the batch gets filled up. ++ * ++ * Return: The number of folios found. ++ * Also update @start to be positioned for traversal of the next folio. ++ */ ++unsigned filemap_get_folios_dirty(struct address_space *mapping, pgoff_t *start, ++ pgoff_t end, struct folio_batch *fbatch) ++{ ++ XA_STATE(xas, &mapping->i_pages, *start); ++ struct folio *folio; ++ ++ rcu_read_lock(); ++ while ((folio = find_get_entry(&xas, end, XA_PRESENT)) != NULL) { ++ if (xa_is_value(folio)) ++ continue; ++ if (folio_trylock(folio)) { ++ bool clean = !folio_test_dirty(folio) && ++ !folio_test_writeback(folio); ++ folio_unlock(folio); ++ if (clean) { ++ folio_put(folio); ++ continue; ++ } ++ } ++ if (!folio_batch_add(fbatch, folio)) { ++ unsigned long nr = folio_nr_pages(folio); ++ *start = folio->index + nr; ++ goto out; ++ } ++ } ++ /* ++ * We come here when there is no folio beyond @end. We take care to not ++ * overflow the index @start as it confuses some of the callers. This ++ * breaks the iteration when there is a folio at index -1 but that is ++ * already broke anyway. ++ */ ++ if (end == (pgoff_t)-1) ++ *start = (pgoff_t)-1; ++ else ++ *start = end + 1; ++out: ++ rcu_read_unlock(); ++ ++ return folio_batch_count(fbatch); ++} ++ + /* + * CD/DVDs are error prone. When a medium error occurs, the driver may fail + * a _large_ part of the i/o request. Imagine the worst scenario: +-- +2.53.0 + diff --git a/queue-6.18/firewire-net-fix-fragmented-datagram-reassembly.patch b/queue-6.18/firewire-net-fix-fragmented-datagram-reassembly.patch new file mode 100644 index 0000000000..c55958dcdf --- /dev/null +++ b/queue-6.18/firewire-net-fix-fragmented-datagram-reassembly.patch @@ -0,0 +1,99 @@ +From 74b8c1440d8052e5f9c6c903ef5dda12a3718a20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 23:04:54 +0800 +Subject: firewire: net: Fix fragmented datagram reassembly + +From: Ruoyu Wang + +[ Upstream commit d52a13adbb8ccbab99cd3bad36804e87d8b5c052 ] + +fwnet_frag_new() keeps a sorted list of received fragments for a partial +datagram. When a new fragment is adjacent to an existing fragment, the +code checks whether the new fragment also closes the gap to the next or +previous list entry. + +Those neighbor lookups currently assume that the current fragment always +has a real next or previous fragment. At a list edge, the next or +previous entry is the list head, not a struct fwnet_fragment_info. + +The gap checks also compare against the old edge of the current fragment +instead of the edge after adding the new fragment. As a result, a +fragment that bridges two existing ranges may leave two adjacent ranges +unmerged, so fwnet_pd_is_complete() can miss a complete datagram. + +Check for the list head before looking up the neighboring fragment, and +compare the neighbor against the new fragment's far edge when deciding +whether to merge all three ranges. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: c76acec6d551 ("firewire: add IPv4 support") +Signed-off-by: Ruoyu Wang +Link: https://lore.kernel.org/r/20260707150454.2265951-1-ruoyuw560@gmail.com +Signed-off-by: Takashi Sakamoto +Signed-off-by: Sasha Levin +--- + drivers/firewire/net.c | 39 +++++++++++++++++++++------------------ + 1 file changed, 21 insertions(+), 18 deletions(-) + +diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c +index e8294540895507..354c81409946a9 100644 +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -298,31 +298,34 @@ static struct fwnet_fragment_info *fwnet_frag_new( + if (fi->offset + fi->len == offset) { + /* The new fragment can be tacked on to the end */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.next, +- struct fwnet_fragment_info, fi_link); +- if (fi->offset + fi->len == fi2->offset) { +- /* glue fragments together */ +- fi->len += len + fi2->len; +- list_del(&fi2->fi_link); +- kfree(fi2); +- } else { +- fi->len += len; ++ if (!list_is_last(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_next_entry(fi, fi_link); ++ if (offset + len == fi2->offset) { ++ /* glue fragments together */ ++ fi->len += len + fi2->len; ++ list_del(&fi2->fi_link); ++ kfree(fi2); ++ ++ return fi; ++ } + } ++ fi->len += len; + + return fi; + } + if (offset + len == fi->offset) { + /* The new fragment can be tacked on to the beginning */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.prev, +- struct fwnet_fragment_info, fi_link); +- if (fi2->offset + fi2->len == fi->offset) { +- /* glue fragments together */ +- fi2->len += fi->len + len; +- list_del(&fi->fi_link); +- kfree(fi); +- +- return fi2; ++ if (!list_is_first(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_prev_entry(fi, fi_link); ++ if (fi2->offset + fi2->len == offset) { ++ /* glue fragments together */ ++ fi2->len += fi->len + len; ++ list_del(&fi->fi_link); ++ kfree(fi); ++ ++ return fi2; ++ } + } + fi->offset = offset; + fi->len += len; +-- +2.53.0 + diff --git a/queue-6.18/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch b/queue-6.18/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch new file mode 100644 index 0000000000..709a544e41 --- /dev/null +++ b/queue-6.18/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch @@ -0,0 +1,58 @@ +From ddec75a9e1e4aaea05c00191e174e901f08168cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 23:07:24 +0000 +Subject: gtp: check skb_pull_data() return in gtp1u_send_echo_resp() + +From: Xiang Mei (Microsoft) + +[ Upstream commit cd170f051dba9ac146fabcd1b91726487c0cb9fa ] + +gtp1u_send_echo_resp() ignores skb_pull_data()'s return value. Its +caller gtp1u_udp_encap_recv() only guarantees 16 bytes (udphdr + +gtp1_header), but the pull requests 20 (gtp1_header_long + udphdr). For +a 16-19 byte echo request the pull fails and returns NULL without +advancing skb->data; execution continues, and the following skb_push() +plus the IP header pushed by iptunnel_xmit() move skb->data below +skb->head, tripping skb_under_panic(). + +Fix it by dropping the packet when skb_pull_data() fails. + + skbuff: skb_under_panic: ... + kernel BUG at net/core/skbuff.c:214! + Call Trace: + skb_push (net/core/skbuff.c:2648) + iptunnel_xmit (net/ipv4/ip_tunnel_core.c:82) + gtp_encap_recv (drivers/net/gtp.c:701 drivers/net/gtp.c:808 drivers/net/gtp.c:920) + udp_queue_rcv_one_skb (net/ipv4/udp.c:2388) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 9af41cc33471 ("gtp: Implement GTP echo response") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Link: https://patch.msgid.link/20260710230724.942574-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/gtp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index 937d913ce5c334..98614d0b390b8c 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -669,8 +669,9 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb) + return -1; + + /* pull GTP and UDP headers */ +- skb_pull_data(skb, +- sizeof(struct gtp1_header_long) + sizeof(struct udphdr)); ++ if (!skb_pull_data(skb, sizeof(struct gtp1_header_long) + ++ sizeof(struct udphdr))) ++ return -1; + + gtp_pkt = skb_push(skb, sizeof(struct gtp1u_packet)); + memset(gtp_pkt, 0, sizeof(struct gtp1u_packet)); +-- +2.53.0 + diff --git a/queue-6.18/gtp-parse-extension-headers-before-reading-inner-pro.patch b/queue-6.18/gtp-parse-extension-headers-before-reading-inner-pro.patch new file mode 100644 index 0000000000..499e9aa150 --- /dev/null +++ b/queue-6.18/gtp-parse-extension-headers-before-reading-inner-pro.patch @@ -0,0 +1,67 @@ +From c9bdc4876b87cc87696a11bfb0c54dc6c1715545 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:22:44 +0800 +Subject: gtp: parse extension headers before reading inner protocol + +From: Zhixing Chen + +[ Upstream commit 96e37e2f618e931aa97af95e707dcdfb1ec41264 ] + +GTPv1-U packets may carry a chain of extension headers before the inner +IP packet. The receive path already parses and skips these extension +headers, but it currently reads the inner protocol before doing so. + +As a result, the first extension header byte is interpreted as the inner +IP version. Packets with extension headers are then dropped before PDP +lookup. + +Parse the extension header chain before calling gtp_inner_proto(), so the +inner protocol is read from the actual inner IP header. + +Fixes: c75fc0b9e5be ("gtp: identify tunnel via GTP device + GTP version + TEID + family") +Signed-off-by: Zhixing Chen +Link: https://patch.msgid.link/20260708042244.120898-1-running910@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/gtp.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index 2f8626c3824d6b..937d913ce5c334 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -826,13 +826,17 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) + if (!pskb_may_pull(skb, hdrlen)) + return -1; + ++ gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); ++ ++ if (gtp1->flags & GTP1_F_EXTHDR && ++ gtp_parse_exthdrs(skb, &hdrlen) < 0) ++ return -1; ++ + if (gtp_inner_proto(skb, hdrlen, &inner_proto) < 0) { + netdev_dbg(gtp->dev, "GTP packet does not encapsulate an IP packet\n"); + return -1; + } + +- gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); +- + pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid), + gtp_proto_to_family(inner_proto)); + if (!pctx) { +@@ -840,10 +844,6 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) + return 1; + } + +- if (gtp1->flags & GTP1_F_EXTHDR && +- gtp_parse_exthdrs(skb, &hdrlen) < 0) +- return -1; +- + return gtp_rx(pctx, skb, hdrlen, gtp->role, inner_proto); + } + +-- +2.53.0 + diff --git a/queue-6.18/hinic-remove-unused-ethtool-rss-user-configuration-b.patch b/queue-6.18/hinic-remove-unused-ethtool-rss-user-configuration-b.patch new file mode 100644 index 0000000000..81896fe908 --- /dev/null +++ b/queue-6.18/hinic-remove-unused-ethtool-rss-user-configuration-b.patch @@ -0,0 +1,83 @@ +From f8aab1f9990c9db72300ab6c8a711d323e6dd1b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:53:53 +0800 +Subject: hinic: remove unused ethtool RSS user configuration buffers + +From: Chenguang Zhao + +[ Upstream commit fe0c002928c6749b7f4a726f6f600f6dd70280ea ] + +rss_indir_user and rss_hkey_user are allocated and filled in +__set_rss_rxfh() when the user configures RSS via ethtool, but +nothing ever reads them. hinic_get_rxfh() fetches the state from +the device, and the hardware is programmed from the original +indir/key arguments. These buffers only leaked on driver unload. + +Drop the unused allocations, memcpys, and struct fields. + +Fixes: 4fdc51bb4e92 ("hinic: add support for rss parameters with ethtool") +Signed-off-by: Chenguang Zhao +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260722025353.328179-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/huawei/hinic/hinic_dev.h | 2 -- + .../net/ethernet/huawei/hinic/hinic_ethtool.c | 21 ------------------- + 2 files changed, 23 deletions(-) + +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +index 52ea97c818b8ec..d9ab94910a2a79 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h ++++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +@@ -104,8 +104,6 @@ struct hinic_dev { + u16 num_rss; + u16 rss_limit; + struct hinic_rss_type rss_type; +- u8 *rss_hkey_user; +- s32 *rss_indir_user; + struct hinic_intr_coal_info *rx_intr_coalesce; + struct hinic_intr_coal_info *tx_intr_coalesce; + struct hinic_sriov_info sriov_info; +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +index e9f338e9dbe7ae..cd4c295ec7aeb3 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c ++++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +@@ -1064,17 +1064,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + int err; + + if (indir) { +- if (!nic_dev->rss_indir_user) { +- nic_dev->rss_indir_user = +- kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE, +- GFP_KERNEL); +- if (!nic_dev->rss_indir_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_indir_user, indir, +- sizeof(u32) * HINIC_RSS_INDIR_SIZE); +- + err = hinic_rss_set_indir_tbl(nic_dev, + nic_dev->rss_tmpl_idx, indir); + if (err) +@@ -1082,16 +1071,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + } + + if (key) { +- if (!nic_dev->rss_hkey_user) { +- nic_dev->rss_hkey_user = +- kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL); +- +- if (!nic_dev->rss_hkey_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE); +- + err = hinic_rss_set_template_tbl(nic_dev, + nic_dev->rss_tmpl_idx, key); + if (err) +-- +2.53.0 + diff --git a/queue-6.18/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch b/queue-6.18/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch new file mode 100644 index 0000000000..877832132f --- /dev/null +++ b/queue-6.18/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch @@ -0,0 +1,42 @@ +From a6e91b23fdd5bb1f386db68a265f903cd9c97e4b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 15:05:05 +0200 +Subject: hwmon: (asus-ec-sensors) add missed handle for ENOMEM + +From: Eugene Shalygin + +[ Upstream commit 9813c1f49efeadbcb17e4a41972350ac783f9cac ] + +Add missing return value check in the setup function. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260712130602.1256700-2-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index 52986b64881eab..13fd212ad40407 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -1353,9 +1353,11 @@ static int asus_ec_probe(struct platform_device *pdev) + if (!nr_count[type]) + continue; + +- asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, +- nr_count[type], type, +- hwmon_attributes[type]); ++ status = asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, ++ nr_count[type], type, ++ hwmon_attributes[type]); ++ if (status) ++ return status; + *ptr_asus_ec_ci++ = asus_ec_hwmon_chan++; + } + +-- +2.53.0 + diff --git a/queue-6.18/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch b/queue-6.18/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch new file mode 100644 index 0000000000..222c43023f --- /dev/null +++ b/queue-6.18/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch @@ -0,0 +1,60 @@ +From 053405cb2ec9c8c7107be39fc9effc17b125ddbd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 13:05:03 +0200 +Subject: hwmon: (asus-ec-sensors) fix EC read intervals + +From: Eugene Shalygin + +[ Upstream commit 60710b2af13b81da71b429d3f8b19dd70310729d ] + +Take INITIAL_JIFFIES into account when setting up next update time. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260712110650.1240071-2-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index aac4706cd437fe..52986b64881eab 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -870,7 +870,7 @@ struct ec_sensors_data { + /* sorted list of unique register banks */ + u8 banks[ASUS_EC_MAX_BANK + 1]; + /* in jiffies */ +- unsigned long last_updated; ++ u64 next_update; + struct lock_data lock_data; + /* number of board EC sensors */ + u8 nr_sensors; +@@ -1139,13 +1139,12 @@ static int get_cached_value_or_update(const struct device *dev, + int sensor_index, + struct ec_sensors_data *state, s32 *value) + { +- if (time_after(jiffies, state->last_updated + HZ)) { ++ if (time_after64(get_jiffies_64(), state->next_update)) { + if (update_ec_sensors(dev, state)) { + dev_err(dev, "update_ec_sensors() failure\n"); + return -EIO; + } +- +- state->last_updated = jiffies; ++ state->next_update = get_jiffies_64() + HZ; + } + + *value = state->sensors[sensor_index].cached_value; +@@ -1263,6 +1262,7 @@ static int asus_ec_probe(struct platform_device *pdev) + if (!ec_data) + return -ENOMEM; + ++ ec_data->next_update = INITIAL_JIFFIES; + dev_set_drvdata(dev, ec_data); + ec_data->board_info = pboard_info; + +-- +2.53.0 + diff --git a/queue-6.18/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch b/queue-6.18/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch new file mode 100644 index 0000000000..eb35f5855d --- /dev/null +++ b/queue-6.18/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch @@ -0,0 +1,37 @@ +From 9ff18ada75750a5638ebff55247a0132db51910f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 09:42:07 +0200 +Subject: hwmon: (asus-ec-sensors) fix looping over banks while reading from EC + +From: Eugene Shalygin + +[ Upstream commit e741d13cc2abfc6fccebe2008057aa52e285223e ] + +Do not assume there are only bank 0 and bank 1 available, just use '!=' +for bank comparison. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260711074217.554656-1-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index 95c50d3a788ce7..aac4706cd437fe 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -1050,7 +1050,7 @@ static int asus_ec_block_read(const struct device *dev, + } + for (ireg = 0; ireg < ec->nr_registers; ireg++) { + reg_bank = register_bank(ec->registers[ireg]); +- if (reg_bank < bank) { ++ if (reg_bank != bank) { + continue; + } + ec_read(register_index(ec->registers[ireg]), +-- +2.53.0 + diff --git a/queue-6.18/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch b/queue-6.18/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch new file mode 100644 index 0000000000..8e28da8f06 --- /dev/null +++ b/queue-6.18/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch @@ -0,0 +1,41 @@ +From 6ca618b40617dcc112b46f78f04f2027952466ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 17:52:54 -0700 +Subject: hwmon: (corsair-cpro) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 94c87871b051d7ad758828a805215a2ec194512a ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 40c3a44542257 ("hwmon: add Corsair Commander Pro driver") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-cpro.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c +index b7b911f8359c7f..71e48b3bba60f0 100644 +--- a/drivers/hwmon/corsair-cpro.c ++++ b/drivers/hwmon/corsair-cpro.c +@@ -645,6 +645,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) + + out_hw_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.18/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch b/queue-6.18/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..5f3798bb0d --- /dev/null +++ b/queue-6.18/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,89 @@ +From 2582fe899182e47d54c023d40e758d8b2fae9a00 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Apr 2026 12:12:26 +0800 +Subject: hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop + +From: Edward Adam Davis + +[ Upstream commit 9ab8656548cd737b98d0b19c4253aff8d68e97f4 ] + +hid_hw_stop() does not stop the device IO. + +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +corsairpsu_probe(). If the probe operation fails after "io start" has +been initiated, this race condition will result in a uaf vulnerability +[1]. + +CPU0 CPU1 +==== ==== +corsairpsu_probe() + hid_device_io_start() + ... unlock driver_input_lock + hid_hw_stop() + kfree(hidraw) __hid_input_report() + ... acquire driver_input_lock + hid_report_raw_event() + hidraw_report_event() + ... access hidraw's list_lock // trigger uaf + +Consequently, when corsairpsu_probe() fails and hid_hw_stop() needs to +be executed, the io_started flag is first cleared while holding the +driver_input_lock to prevent potential race conditions involving input +reports. + +[1] +BUG: KASAN: slab-use-after-free in rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56 +Call Trace: + hidraw_report_event+0x5d/0x3a0 drivers/hid/hidraw.c:577 + hid_report_raw_event+0x311/0x1730 drivers/hid/hid-core.c:2076 + __hid_input_report drivers/hid/hid-core.c:2152 [inline] + hid_input_report+0x44e/0x580 drivers/hid/hid-core.c:2174 + hid_irq_in+0x47e/0x6d0 drivers/hid/usbhid/hid-core.c:286 + __usb_hcd_giveback_urb+0x3b3/0x5e0 drivers/usb/core/hcd.c:1657 + dummy_timer+0x8a9/0x47d0 drivers/usb/gadget/udc/dummy_hcd.c:2005 + +Allocated by task 10: + hidraw_connect+0x57/0x430 drivers/hid/hidraw.c:606 + hid_connect+0x5bf/0x19d0 drivers/hid/hid-core.c:2277 + hid_hw_start+0xa8/0x120 drivers/hid/hid-core.c:2387 + corsairpsu_probe+0xd9/0x3c0 drivers/hwmon/corsair-psu.c:782 + +Freed by task 10: + hidraw_disconnect+0x4f/0x60 drivers/hid/hidraw.c:662 + hid_disconnect drivers/hid/hid-core.c:2362 [inline] + hid_hw_stop+0x101/0x1e0 drivers/hid/hid-core.c:2407 + corsairpsu_probe+0x327/0x3c0 drivers/hwmon/corsair-psu.c:826 + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Fixes: d115b51e0e56 ("hwmon: add Corsair PSU HID controller driver") +Reported-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9eebf5f6544c5e873858 +Tested-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Link: https://lore.kernel.org/r/tencent_BB7C33EB9EA41B7B4B5F1B8B25C0BA13BB08@qq.com +[groeck: Updated subject and description; + call hid_device_io_stop() only if IO has been started] +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-psu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c +index ea28c9219507ad..4681af6843596b 100644 +--- a/drivers/hwmon/corsair-psu.c ++++ b/drivers/hwmon/corsair-psu.c +@@ -831,6 +831,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id + + fail_and_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + fail_and_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.18/hwmon-gigabyte_waterforce-stop-device-io-before-call.patch b/queue-6.18/hwmon-gigabyte_waterforce-stop-device-io-before-call.patch new file mode 100644 index 0000000000..c0bbbc4203 --- /dev/null +++ b/queue-6.18/hwmon-gigabyte_waterforce-stop-device-io-before-call.patch @@ -0,0 +1,51 @@ +From 98225355d6db08c2ecc72462bd2600d0d3fb32be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 17:59:10 -0700 +Subject: hwmon: (gigabyte_waterforce) Stop device IO before calling + hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit ff0c5c53d08274e200b48a4d53aa078265e873cb ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 42ac68e3d4ba0 ("hwmon: Add driver for Gigabyte AORUS Waterforce AIO coolers") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/gigabyte_waterforce.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/hwmon/gigabyte_waterforce.c b/drivers/hwmon/gigabyte_waterforce.c +index 27487e215bddff..4eea05f8b569c2 100644 +--- a/drivers/hwmon/gigabyte_waterforce.c ++++ b/drivers/hwmon/gigabyte_waterforce.c +@@ -371,13 +371,15 @@ static int waterforce_probe(struct hid_device *hdev, const struct hid_device_id + if (IS_ERR(priv->hwmon_dev)) { + ret = PTR_ERR(priv->hwmon_dev); + hid_err(hdev, "hwmon registration failed with %d\n", ret); +- goto fail_and_close; ++ goto fail_and_io_stop; + } + + waterforce_debugfs_init(priv); + + return 0; + ++fail_and_io_stop: ++ hid_device_io_stop(hdev); + fail_and_close: + hid_hw_close(hdev); + fail_and_stop: +-- +2.53.0 + diff --git a/queue-6.18/hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch b/queue-6.18/hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch new file mode 100644 index 0000000000..0b4354ed71 --- /dev/null +++ b/queue-6.18/hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch @@ -0,0 +1,59 @@ +From fa6687d2a9ca6d0b839b8767a8162f4de1fb6f68 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:01:58 -0700 +Subject: hwmon: (nzxt-kraken3) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit f151d0143ac4e086f92f52328ebdbdc50933d8ef ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: f3b4b146eb107 ("hwmon: Add driver for NZXT Kraken X and Z series AIO CPU coolers") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/nzxt-kraken3.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/hwmon/nzxt-kraken3.c b/drivers/hwmon/nzxt-kraken3.c +index d00409bcab93ad..05525406c5fbb5 100644 +--- a/drivers/hwmon/nzxt-kraken3.c ++++ b/drivers/hwmon/nzxt-kraken3.c +@@ -948,7 +948,7 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id + ret = kraken3_init_device(hdev); + if (ret < 0) { + hid_err(hdev, "device init failed with %d\n", ret); +- goto fail_and_close; ++ goto fail_and_stop_io; + } + + ret = kraken3_get_fw_ver(hdev); +@@ -960,13 +960,15 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id + if (IS_ERR(priv->hwmon_dev)) { + ret = PTR_ERR(priv->hwmon_dev); + hid_err(hdev, "hwmon registration failed with %d\n", ret); +- goto fail_and_close; ++ goto fail_and_stop_io; + } + + kraken3_debugfs_init(priv, device_name); + + return 0; + ++fail_and_stop_io: ++ hid_device_io_stop(hdev); + fail_and_close: + hid_hw_close(hdev); + fail_and_stop: +-- +2.53.0 + diff --git a/queue-6.18/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch b/queue-6.18/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..69ba4a10fb --- /dev/null +++ b/queue-6.18/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,42 @@ +From 2605801844754f7a62dbe80ae661e6f67b7ebf45 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:00:32 -0700 +Subject: hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 59d104b54b0b42e30fd2a68d24ee5c49dcc54d1e ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 53e68c20aeb1e ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/nzxt-smart2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c +index 58ef9fa0184be4..e2316c46629d61 100644 +--- a/drivers/hwmon/nzxt-smart2.c ++++ b/drivers/hwmon/nzxt-smart2.c +@@ -768,7 +768,7 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev, + + out_hw_close: + hid_hw_close(hdev); +- ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.18/hwmon-occ-validate-poll-response-sensor-blocks.patch b/queue-6.18/hwmon-occ-validate-poll-response-sensor-blocks.patch new file mode 100644 index 0000000000..90f04db73c --- /dev/null +++ b/queue-6.18/hwmon-occ-validate-poll-response-sensor-blocks.patch @@ -0,0 +1,118 @@ +From fdcd9d3b58cbe70b12c48fc636bc2dd1f69dc352 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:58:26 +0800 +Subject: hwmon: occ: validate poll response sensor blocks + +From: Pengpeng Hou + +[ Upstream commit 70e76e700fc6c46afb4e17aec099a1ea089b4a22 ] + +The OCC poll response parser walks a counted list of sensor data blocks. +It used the static backing-array capacity as the parse boundary, but a +transport response makes only data_length bytes current and valid. A +truncated response can therefore make the parser consume a block header or +block extent outside the current response. + +Use data_length as the parent boundary, prove the fixed poll header and +each current block header before reading them, and prove the complete block +before advancing. Keep parsed sensor metadata local until the complete +response has passed validation, then publish it. Propagate +malformed-response errors before publishing the OCC as active. + +Fixes: aa195fe49b03 ("hwmon (occ): Parse OCC poll response") +Signed-off-by: Pengpeng Hou +Link: https://lore.kernel.org/r/20260720115826.14813-1-pengpeng@iscas.ac.cn +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/common.c | 38 ++++++++++++++++++++++++++++++-------- + 1 file changed, 30 insertions(+), 8 deletions(-) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index e18e80e832fd3f..175208d712b06e 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -1052,32 +1052,49 @@ static int occ_setup_sensor_attrs(struct occ *occ) + } + + /* only need to do this once at startup, as OCC won't change sensors on us */ +-static void occ_parse_poll_response(struct occ *occ) ++static int occ_parse_poll_response(struct occ *occ) + { + unsigned int i, old_offset, offset = 0, size = 0; ++ u16 data_length; + struct occ_sensor *sensor; +- struct occ_sensors *sensors = &occ->sensors; ++ struct occ_sensors parsed = {}; ++ struct occ_sensors *sensors = &parsed; + struct occ_response *resp = &occ->resp; + struct occ_poll_response *poll = + (struct occ_poll_response *)&resp->data[0]; + struct occ_poll_response_header *header = &poll->header; + struct occ_sensor_data_block *block = &poll->block; + ++ data_length = get_unaligned_be16(&resp->data_length); ++ if (data_length < sizeof(*header) || data_length > OCC_RESP_DATA_BYTES) { ++ dev_err(occ->bus_dev, "invalid OCC poll response length %u\n", ++ data_length); ++ return -EMSGSIZE; ++ } ++ + dev_info(occ->bus_dev, "OCC found, code level: %.16s\n", + header->occ_code_level); + + for (i = 0; i < header->num_sensor_data_blocks; ++i) { + block = (struct occ_sensor_data_block *)((u8 *)block + offset); ++ if (size + sizeof(*header) + sizeof(block->header) > ++ data_length) { ++ dev_err(occ->bus_dev, ++ "truncated OCC sensor block header\n"); ++ return -EMSGSIZE; ++ } ++ + old_offset = offset; + offset = (block->header.num_sensors * + block->header.sensor_length) + sizeof(block->header); +- size += offset; + + /* validate all the length/size fields */ +- if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) { +- dev_warn(occ->bus_dev, "exceeded response buffer\n"); +- return; ++ if (size + sizeof(*header) + offset > data_length) { ++ dev_err(occ->bus_dev, ++ "exceeded OCC poll response length\n"); ++ return -EMSGSIZE; + } ++ size += offset; + + dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n", + old_offset, offset - 1, block->header.eye_catcher, +@@ -1107,6 +1124,9 @@ static void occ_parse_poll_response(struct occ *occ) + + dev_dbg(occ->bus_dev, "Max resp size: %u+%zd=%zd\n", size, + sizeof(*header), size + sizeof(*header)); ++ occ->sensors = parsed; ++ ++ return 0; + } + + int occ_active(struct occ *occ, bool active) +@@ -1138,10 +1158,12 @@ int occ_active(struct occ *occ, bool active) + goto unlock; + } + +- occ->active = true; + occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; +- occ_parse_poll_response(occ); ++ rc = occ_parse_poll_response(occ); ++ if (rc) ++ goto unlock; + ++ occ->active = true; + rc = occ_setup_sensor_attrs(occ); + if (rc) { + dev_err(occ->bus_dev, +-- +2.53.0 + diff --git a/queue-6.18/ice-allow-creating-vfs-when-config_ice_switchdev.patch b/queue-6.18/ice-allow-creating-vfs-when-config_ice_switchdev.patch new file mode 100644 index 0000000000..409199612c --- /dev/null +++ b/queue-6.18/ice-allow-creating-vfs-when-config_ice_switchdev.patch @@ -0,0 +1,90 @@ +From 5e51785e7344260f88841c1cd5f4f81ea94a766d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:53:23 -0700 +Subject: ice: allow creating VFs when !CONFIG_ICE_SWITCHDEV + +From: Vincent Chen + +[ Upstream commit 99d0f42b0e5c57e4c02070a908aaff082881293a ] + +Currently ice_eswitch_attach_vf() is called unconditionally in +ice_start_vfs(), which causes VF creation to fail when CONFIG_ICE_SWITCHDEV +is not defined. + +Fix this by adding switchdev mode checks at the call sites before +calling ice_eswitch_attach_vf(), consistent with how +ice_eswitch_attach_sf() is already handled in ice_devlink_port_new(). +This is similar to commit aacca7a83b97 ("ice: allow creating VFs for +!CONFIG_NET_SWITCHDEV") which fixed the same issue for the previous +ice_eswitch_configure() API. + +Fixes: 415db8399d06 ("ice: make representor code generic") +Signed-off-by: Vincent Chen +Reviewed-by: Aleksandr Loktionov +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260717185340.3595286-2-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_eswitch.c | 3 --- + drivers/net/ethernet/intel/ice/ice_sriov.c | 14 ++++++++------ + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 3 ++- + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c +index c30e27bbfe6e25..b069e6c514fb12 100644 +--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c ++++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c +@@ -512,9 +512,6 @@ int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf) + struct ice_repr *repr; + int err; + +- if (!ice_is_eswitch_mode_switchdev(pf)) +- return 0; +- + repr = ice_repr_create_vf(vf); + if (IS_ERR(repr)) + return PTR_ERR(repr); +diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c +index 843e82fd3bf936..6a0b724e46f9ac 100644 +--- a/drivers/net/ethernet/intel/ice/ice_sriov.c ++++ b/drivers/net/ethernet/intel/ice/ice_sriov.c +@@ -484,12 +484,14 @@ static int ice_start_vfs(struct ice_pf *pf) + goto teardown; + } + +- retval = ice_eswitch_attach_vf(pf, vf); +- if (retval) { +- dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d", +- vf->vf_id, retval); +- ice_vf_vsi_release(vf); +- goto teardown; ++ if (ice_is_eswitch_mode_switchdev(pf)) { ++ retval = ice_eswitch_attach_vf(pf, vf); ++ if (retval) { ++ dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d", ++ vf->vf_id, retval); ++ ice_vf_vsi_release(vf); ++ goto teardown; ++ } + } + + set_bit(ICE_VF_STATE_INIT, vf->vf_states); +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +index 4f86412a9c0c3a..bab968b05540b1 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +@@ -812,7 +812,8 @@ void ice_reset_all_vfs(struct ice_pf *pf) + } + ice_vf_post_vsi_rebuild(vf); + +- ice_eswitch_attach_vf(pf, vf); ++ if (ice_is_eswitch_mode_switchdev(pf)) ++ ice_eswitch_attach_vf(pf, vf); + + mutex_unlock(&vf->cfg_lock); + } +-- +2.53.0 + diff --git a/queue-6.18/ice-fix-lag-recipe-to-profile-association.patch b/queue-6.18/ice-fix-lag-recipe-to-profile-association.patch new file mode 100644 index 0000000000..2ffc7494e3 --- /dev/null +++ b/queue-6.18/ice-fix-lag-recipe-to-profile-association.patch @@ -0,0 +1,49 @@ +From 7a355a2d3cba8f4b9f5b58010516e9a8ece03d6a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:53:28 -0700 +Subject: ice: fix LAG recipe to profile association + +From: Marcin Szycik + +[ Upstream commit d6da9b7d48599db078aea6144997a381f8d90d45 ] + +ice_init_lag() associates recipes to profiles, assuming that Link +Aggregation-related profiles will always have profile ID lower than 70 +(ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER). This value seems arbitrary and +might not always be valid for some versions of DDP package, i.e. LAG +profiles may have profile ID greater than 70. This would lead to +misconfigured switch and LAG not working properly. + +Fix it by checking up to maximum profile ID. + +Fixes: 1e0f9881ef79 ("ice: Flesh out implementation of support for SRIOV on bonded interface") +Signed-off-by: Marcin Szycik +Reviewed-by: Michal Swiatkowski +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Dave Ertman +Reviewed-by: Simon Horman +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260717185340.3595286-7-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_lag.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c +index aebf8e08a297be..e8ab36d0f11d82 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lag.c ++++ b/drivers/net/ethernet/intel/ice/ice_lag.c +@@ -2624,7 +2624,7 @@ int ice_init_lag(struct ice_pf *pf) + goto free_lport_res; + + /* associate recipes to profiles */ +- for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) { ++ for (n = 0; n < ICE_MAX_NUM_PROFILES; n++) { + err = ice_aq_get_recipe_to_profile(&pf->hw, n, + &recipe_bits, NULL); + if (err) +-- +2.53.0 + diff --git a/queue-6.18/ice-prevent-tstamp-ring-allocation-for-non-pf-vsi-ty.patch b/queue-6.18/ice-prevent-tstamp-ring-allocation-for-non-pf-vsi-ty.patch new file mode 100644 index 0000000000..7f8698ba37 --- /dev/null +++ b/queue-6.18/ice-prevent-tstamp-ring-allocation-for-non-pf-vsi-ty.patch @@ -0,0 +1,62 @@ +From 1ad3460a83f43a4ef952affecca52a95056144e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:53:32 -0700 +Subject: ice: prevent tstamp ring allocation for non-PF VSI types + +From: Paul Greenwalt + +[ Upstream commit 144539bbfd3cea1ab0fb6f5216d6004c1f4f029b ] + +The pf->txtime_txqs bitmap tracks which Tx queues have ETF (Earliest +TxTime First) offload enabled. This bitmap is indexed by queue number +and is set by ice_offload_txtime(), which only operates on PF VSI +queues. + +However, ice_is_txtime_ena() does not check the VSI type before +consulting the bitmap. When ETF offload is enabled on PF Tx queue 0, +bit 0 is set in pf->txtime_txqs. During a subsequent PCI reset +rebuild, the CTRL VSI's Tx queue 0 is reconfigured and +ice_is_txtime_ena() is called for that ring. Since it only checks +pf->txtime_txqs by queue index without distinguishing VSI type, it +finds bit 0 set and returns true, matching the PF VSI's ETF queue, +not the CTRL VSI's. This causes ice_vsi_cfg_txq() to spuriously +allocate a tstamp_ring for the CTRL VSI ring. + +Since CTRL VSI rings have no associated netdev, ice_clean_tx_ring() +takes an early return at the !netdev check before reaching +ice_free_tx_tstamp_ring(), leaking the allocation. Each PCI reset +leaks one 64-byte tstamp_ring. + +Fix this by restricting ice_is_txtime_ena() to return true only for +PF VSI rings, since txtime_txqs is only meaningful for PF VSI queues. + +Fixes: ccde82e90946 ("ice: add E830 Earliest TxTime First Offload support") +Signed-off-by: Paul Greenwalt +Reviewed-by: Przemek Kitszel +Reviewed-by: Aleksandr Loktionov +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260717185340.3595286-11-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 6886188043764c..fc4eae0a00cd3b 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -765,6 +765,9 @@ static inline bool ice_is_txtime_ena(const struct ice_tx_ring *ring) + struct ice_vsi *vsi = ring->vsi; + struct ice_pf *pf = vsi->back; + ++ if (vsi->type != ICE_VSI_PF) ++ return false; ++ + return test_bit(ring->q_index, pf->txtime_txqs); + } + +-- +2.53.0 + diff --git a/queue-6.18/iomap-correct-the-range-of-a-partial-dirty-clear.patch b/queue-6.18/iomap-correct-the-range-of-a-partial-dirty-clear.patch new file mode 100644 index 0000000000..6fed95d2c6 --- /dev/null +++ b/queue-6.18/iomap-correct-the-range-of-a-partial-dirty-clear.patch @@ -0,0 +1,60 @@ +From fad824e1bd14fff43164b7468db5aae350267d0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:23:21 +0800 +Subject: iomap: correct the range of a partial dirty clear + +From: Zhang Yi + +[ Upstream commit 88c26515313169806a412a362b32a1eca53d21bd ] + +The block range calculation in ifs_clear_range_dirty() is incorrect when +partially clearing a range in a folio. We cannot clear the dirty bit of +the first block or the last block if the start or end offset is not +blocksize-aligned. This has not yet caused any issues since we always +clear a whole folio in iomap_writeback_folio(). + +Fix this by rounding up the first block to blocksize alignment, and +calculate the last block by rounding down (using truncation). Correct +the nr_blks calculation accordingly. + +Fixes: 4ce02c679722 ("iomap: Add per-block dirty state tracking to improve performance") +Signed-off-by: Zhang Yi +Link: https://patch.msgid.link/20260714082325.325163-2-yi.zhang@huaweicloud.com +Reviewed-by: Joanne Koong +Reviewed-by: "Darrick J. Wong" +Reviewed-by: Christoph Hellwig +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/iomap/buffered-io.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index c0fa6acf19375b..734854f864fd1e 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -127,13 +127,17 @@ static void ifs_clear_range_dirty(struct folio *folio, + { + struct inode *inode = folio->mapping->host; + unsigned int blks_per_folio = i_blocks_per_folio(inode, folio); +- unsigned int first_blk = (off >> inode->i_blkbits); +- unsigned int last_blk = (off + len - 1) >> inode->i_blkbits; +- unsigned int nr_blks = last_blk - first_blk + 1; ++ unsigned int first_blk = round_up(off, i_blocksize(inode)) >> ++ inode->i_blkbits; ++ unsigned int last_blk = (off + len) >> inode->i_blkbits; + unsigned long flags; + ++ if (first_blk >= last_blk) ++ return; ++ + spin_lock_irqsave(&ifs->state_lock, flags); +- bitmap_clear(ifs->state, first_blk + blks_per_folio, nr_blks); ++ bitmap_clear(ifs->state, first_blk + blks_per_folio, ++ last_blk - first_blk); + spin_unlock_irqrestore(&ifs->state_lock, flags); + } + +-- +2.53.0 + diff --git a/queue-6.18/iomap-fix-incorrect-did_zero-setting-in-iomap_zero_i.patch b/queue-6.18/iomap-fix-incorrect-did_zero-setting-in-iomap_zero_i.patch new file mode 100644 index 0000000000..fb76455634 --- /dev/null +++ b/queue-6.18/iomap-fix-incorrect-did_zero-setting-in-iomap_zero_i.patch @@ -0,0 +1,78 @@ +From dc1bc967ff7cbb370829ef90f2cba281e33b99f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:23:23 +0800 +Subject: iomap: fix incorrect did_zero setting in iomap_zero_iter() + +From: Zhang Yi + +[ Upstream commit 7a6fd6b21d7e1737b40de1a210acf9e6a1e4d59e ] + +The did_zero output parameter was unconditionally set after the loop, +which is incorrect. It should only be set when the zeroing operation +actually completes, not when IOMAP_F_STALE is set or when +IOMAP_F_FOLIO_BATCH is set but !folio causes the loop to break early, +or when iomap_iter_advance() returns an error. + +This causes did_zero to be incorrectly set when zeroing a clean +unwritten extent because the loop exits early without actually zeroing +any data. + +Fix it by using a local variable to track whether any folio was actually +zeroed, and only set did_zero after the loop if zeroing happened. + +Fixes: 98eb8d95025b ("iomap: set did_zero to true when zeroing successfully") +Signed-off-by: Zhang Yi +Link: https://patch.msgid.link/20260714082325.325163-4-yi.zhang@huaweicloud.com +Reviewed-by: "Darrick J. Wong" +Reviewed-by: Christoph Hellwig +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/iomap/buffered-io.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index d856093db9d278..43c69b606e20fb 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -1458,6 +1458,7 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + const struct iomap_write_ops *write_ops) + { + u64 bytes = iomap_length(iter); ++ bool zeroed = false; + int status; + + do { +@@ -1476,6 +1477,8 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + /* a NULL folio means we're done with a folio batch */ + if (!folio) { + status = iomap_iter_advance_full(iter); ++ if (status) ++ return status; + break; + } + +@@ -1486,6 +1489,7 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + bytes); + + folio_zero_range(folio, offset, bytes); ++ zeroed = true; + folio_mark_accessed(folio); + + ret = iomap_write_end(iter, bytes, bytes, folio); +@@ -1495,10 +1499,10 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + + status = iomap_iter_advance(iter, bytes); + if (status) +- break; ++ return status; + } while ((bytes = iomap_length(iter)) > 0); + +- if (did_zero) ++ if (did_zero && zeroed) + *did_zero = true; + return status; + } +-- +2.53.0 + diff --git a/queue-6.18/iomap-optional-zero-range-dirty-folio-processing.patch b/queue-6.18/iomap-optional-zero-range-dirty-folio-processing.patch new file mode 100644 index 0000000000..b4d78aecd3 --- /dev/null +++ b/queue-6.18/iomap-optional-zero-range-dirty-folio-processing.patch @@ -0,0 +1,241 @@ +From 888665737ba5355d21889fb98178599eaffcda8b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Oct 2025 09:46:37 -0400 +Subject: iomap: optional zero range dirty folio processing + +From: Brian Foster + +[ Upstream commit 395ed1ef0012e1bb1e4050e84ba0173b3623112a ] + +The only way zero range can currently process unwritten mappings +with dirty pagecache is to check whether the range is dirty before +mapping lookup and then flush when at least one underlying mapping +is unwritten. This ordering is required to prevent iomap lookup from +racing with folio writeback and reclaim. + +Since zero range can skip ranges of unwritten mappings that are +clean in cache, this operation can be improved by allowing the +filesystem to provide a set of dirty folios that require zeroing. In +turn, rather than flush or iterate file offsets, zero range can +iterate on folios in the batch and advance over clean or uncached +ranges in between. + +Add a folio_batch in struct iomap and provide a helper for +filesystems to populate the batch at lookup time. Update the folio +lookup path to return the next folio in the batch, if provided, and +advance the iter if the folio starts beyond the current offset. + +Signed-off-by: Brian Foster +Reviewed-by: Christoph Hellwig +Reviewed-by: Darrick J. Wong +Signed-off-by: Christian Brauner +Stable-dep-of: 7a6fd6b21d7e ("iomap: fix incorrect did_zero setting in iomap_zero_iter()") +Signed-off-by: Sasha Levin +--- + fs/iomap/buffered-io.c | 90 +++++++++++++++++++++++++++++++++++++++--- + fs/iomap/iter.c | 6 +++ + include/linux/iomap.h | 4 ++ + 3 files changed, 95 insertions(+), 5 deletions(-) + +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index 66d16483df4441..d856093db9d278 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -790,6 +790,28 @@ static struct folio *__iomap_get_folio(struct iomap_iter *iter, + if (!mapping_large_folio_support(iter->inode->i_mapping)) + len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos)); + ++ if (iter->fbatch) { ++ struct folio *folio = folio_batch_next(iter->fbatch); ++ ++ if (!folio) ++ return NULL; ++ ++ /* ++ * The folio mapping generally shouldn't have changed based on ++ * fs locks, but be consistent with filemap lookup and retry ++ * the iter if it does. ++ */ ++ folio_lock(folio); ++ if (unlikely(folio->mapping != iter->inode->i_mapping)) { ++ iter->iomap.flags |= IOMAP_F_STALE; ++ folio_unlock(folio); ++ return NULL; ++ } ++ ++ folio_get(folio); ++ return folio; ++ } ++ + if (write_ops && write_ops->get_folio) + return write_ops->get_folio(iter, pos, len); + return iomap_get_folio(iter, pos, len); +@@ -850,6 +872,8 @@ static int iomap_write_begin(struct iomap_iter *iter, + int status = 0; + + len = min_not_zero(len, *plen); ++ *foliop = NULL; ++ *plen = 0; + + if (fatal_signal_pending(current)) + return -EINTR; +@@ -858,6 +882,15 @@ static int iomap_write_begin(struct iomap_iter *iter, + if (IS_ERR(folio)) + return PTR_ERR(folio); + ++ /* ++ * No folio means we're done with a batch. We still have range to ++ * process so return and let the caller iterate and refill the batch. ++ */ ++ if (!folio) { ++ WARN_ON_ONCE(!iter->fbatch); ++ return 0; ++ } ++ + /* + * Now we have a locked folio, before we do anything with it we need to + * check that the iomap we have cached is not stale. The inode extent +@@ -878,6 +911,22 @@ static int iomap_write_begin(struct iomap_iter *iter, + } + } + ++ /* ++ * The folios in a batch may not be contiguous. If we've skipped ++ * forward, advance the iter to the pos of the current folio. If the ++ * folio starts beyond the end of the mapping, it may have been trimmed ++ * since the lookup for whatever reason. Return a NULL folio to ++ * terminate the op. ++ */ ++ if (folio_pos(folio) > iter->pos) { ++ len = min_t(u64, folio_pos(folio) - iter->pos, ++ iomap_length(iter)); ++ status = iomap_iter_advance(iter, len); ++ len = iomap_length(iter); ++ if (status || !len) ++ goto out_unlock; ++ } ++ + pos = iomap_trim_folio_range(iter, folio, poffset, &len); + + if (srcmap->type == IOMAP_INLINE) +@@ -1424,6 +1473,12 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + if (iter->iomap.flags & IOMAP_F_STALE) + break; + ++ /* a NULL folio means we're done with a folio batch */ ++ if (!folio) { ++ status = iomap_iter_advance_full(iter); ++ break; ++ } ++ + /* warn about zeroing folios beyond eof that won't write back */ + WARN_ON_ONCE(folio_pos(folio) > iter->inode->i_size); + +@@ -1448,6 +1503,26 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + return status; + } + ++loff_t ++iomap_fill_dirty_folios( ++ struct iomap_iter *iter, ++ loff_t offset, ++ loff_t length) ++{ ++ struct address_space *mapping = iter->inode->i_mapping; ++ pgoff_t start = offset >> PAGE_SHIFT; ++ pgoff_t end = (offset + length - 1) >> PAGE_SHIFT; ++ ++ iter->fbatch = kmalloc(sizeof(struct folio_batch), GFP_KERNEL); ++ if (!iter->fbatch) ++ return offset + length; ++ folio_batch_init(iter->fbatch); ++ ++ filemap_get_folios_dirty(mapping, &start, end, iter->fbatch); ++ return (start << PAGE_SHIFT); ++} ++EXPORT_SYMBOL_GPL(iomap_fill_dirty_folios); ++ + int + iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero, + const struct iomap_ops *ops, +@@ -1477,7 +1552,7 @@ iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero, + * flushing on partial eof zeroing, special case it to zero the + * unaligned start portion if already dirty in pagecache. + */ +- if (off && ++ if (!iter.fbatch && off && + filemap_range_needs_writeback(mapping, pos, pos + plen - 1)) { + iter.len = plen; + while ((ret = iomap_iter(&iter, ops)) > 0) +@@ -1494,13 +1569,18 @@ iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero, + * if dirty and the fs returns a mapping that might convert on + * writeback. + */ +- range_dirty = filemap_range_needs_writeback(inode->i_mapping, +- iter.pos, iter.pos + iter.len - 1); ++ range_dirty = filemap_range_needs_writeback(mapping, iter.pos, ++ iter.pos + iter.len - 1); + while ((ret = iomap_iter(&iter, ops)) > 0) { + const struct iomap *srcmap = iomap_iter_srcmap(&iter); + +- if (srcmap->type == IOMAP_HOLE || +- srcmap->type == IOMAP_UNWRITTEN) { ++ if (WARN_ON_ONCE(iter.fbatch && ++ srcmap->type != IOMAP_UNWRITTEN)) ++ return -EIO; ++ ++ if (!iter.fbatch && ++ (srcmap->type == IOMAP_HOLE || ++ srcmap->type == IOMAP_UNWRITTEN)) { + s64 status; + + if (range_dirty) { +diff --git a/fs/iomap/iter.c b/fs/iomap/iter.c +index 91d2024e00da4e..8692e5e41c6df6 100644 +--- a/fs/iomap/iter.c ++++ b/fs/iomap/iter.c +@@ -8,6 +8,12 @@ + + static inline void iomap_iter_reset_iomap(struct iomap_iter *iter) + { ++ if (iter->fbatch) { ++ folio_batch_release(iter->fbatch); ++ kfree(iter->fbatch); ++ iter->fbatch = NULL; ++ } ++ + iter->status = 0; + memset(&iter->iomap, 0, sizeof(iter->iomap)); + memset(&iter->srcmap, 0, sizeof(iter->srcmap)); +diff --git a/include/linux/iomap.h b/include/linux/iomap.h +index 4469b2318b08e5..53428ce1262f4e 100644 +--- a/include/linux/iomap.h ++++ b/include/linux/iomap.h +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + struct address_space; + struct fiemap_extent_info; +@@ -241,6 +242,7 @@ struct iomap_iter { + unsigned flags; + struct iomap iomap; + struct iomap srcmap; ++ struct folio_batch *fbatch; + void *private; + }; + +@@ -347,6 +349,8 @@ bool iomap_dirty_folio(struct address_space *mapping, struct folio *folio); + int iomap_file_unshare(struct inode *inode, loff_t pos, loff_t len, + const struct iomap_ops *ops, + const struct iomap_write_ops *write_ops); ++loff_t iomap_fill_dirty_folios(struct iomap_iter *iter, loff_t offset, ++ loff_t length); + int iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, + bool *did_zero, const struct iomap_ops *ops, + const struct iomap_write_ops *write_ops, void *private); +-- +2.53.0 + diff --git a/queue-6.18/iomap-remove-pos-len-bug_on-to-after-folio-lookup.patch b/queue-6.18/iomap-remove-pos-len-bug_on-to-after-folio-lookup.patch new file mode 100644 index 0000000000..4ddc2a3276 --- /dev/null +++ b/queue-6.18/iomap-remove-pos-len-bug_on-to-after-folio-lookup.patch @@ -0,0 +1,50 @@ +From 4d107f5c44def02149e841a1ec3d01fecaf1601d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Oct 2025 09:46:36 -0400 +Subject: iomap: remove pos+len BUG_ON() to after folio lookup + +From: Brian Foster + +[ Upstream commit 49590716be886cc3cbbac10964eac551cfe570b2 ] + +The bug checks at the top of iomap_write_begin() assume the pos/len +reflect exactly the next range to process. This may no longer be the +case once the get folio path is able to process a folio batch from +the filesystem. On top of that, len is already trimmed to within the +iomap/srcmap by iomap_length(), so these checks aren't terribly +useful. Remove the unnecessary BUG_ON() checks. + +Signed-off-by: Brian Foster +Reviewed-by: Christoph Hellwig +Reviewed-by: Darrick J. Wong +Signed-off-by: Christian Brauner +Stable-dep-of: 7a6fd6b21d7e ("iomap: fix incorrect did_zero setting in iomap_zero_iter()") +Signed-off-by: Sasha Levin +--- + fs/iomap/buffered-io.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index db7d448e282cab..66d16483df4441 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -844,15 +844,12 @@ static int iomap_write_begin(struct iomap_iter *iter, + size_t *poffset, u64 *plen) + { + const struct iomap *srcmap = iomap_iter_srcmap(iter); +- loff_t pos = iter->pos; ++ loff_t pos; + u64 len = min_t(u64, SIZE_MAX, iomap_length(iter)); + struct folio *folio; + int status = 0; + + len = min_not_zero(len, *plen); +- BUG_ON(pos + len > iter->iomap.offset + iter->iomap.length); +- if (srcmap != &iter->iomap) +- BUG_ON(pos + len > srcmap->offset + srcmap->length); + + if (fatal_signal_pending(current)) + return -EINTR; +-- +2.53.0 + diff --git a/queue-6.18/iomap-simplify-iomap_iter_advance.patch b/queue-6.18/iomap-simplify-iomap_iter_advance.patch new file mode 100644 index 0000000000..da7efe57c4 --- /dev/null +++ b/queue-6.18/iomap-simplify-iomap_iter_advance.patch @@ -0,0 +1,320 @@ +From bd84ab5a21131b9541edf97d08e897fb7557d6aa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Sep 2025 14:42:50 -0700 +Subject: iomap: simplify iomap_iter_advance() + +From: Joanne Koong + +[ Upstream commit ca82a7ea2299b4586af1f77daee66ee781202320 ] + +Most callers of iomap_iter_advance() do not need the remaining length +returned. Get rid of the extra iomap_length() call that +iomap_iter_advance() does. + +Signed-off-by: Joanne Koong +Reviewed-by: Brian Foster +Reviewed-by: Christoph Hellwig +Signed-off-by: Christian Brauner +Stable-dep-of: 7a6fd6b21d7e ("iomap: fix incorrect did_zero setting in iomap_zero_iter()") +Signed-off-by: Sasha Levin +--- + fs/dax.c | 30 ++++++++++++------------------ + fs/iomap/buffered-io.c | 18 +++++++++--------- + fs/iomap/direct-io.c | 6 +++--- + fs/iomap/iter.c | 14 +++++--------- + fs/iomap/seek.c | 8 ++++---- + include/linux/iomap.h | 6 ++---- + 6 files changed, 35 insertions(+), 47 deletions(-) + +diff --git a/fs/dax.c b/fs/dax.c +index 516f995a988c8f..38fae11ee41912 100644 +--- a/fs/dax.c ++++ b/fs/dax.c +@@ -1507,7 +1507,7 @@ static int dax_zero_iter(struct iomap_iter *iter, bool *did_zero) + + /* already zeroed? we're done. */ + if (srcmap->type == IOMAP_HOLE || srcmap->type == IOMAP_UNWRITTEN) +- return iomap_iter_advance(iter, &length); ++ return iomap_iter_advance(iter, length); + + /* + * invalidate the pages whose sharing state is to be changed +@@ -1536,10 +1536,10 @@ static int dax_zero_iter(struct iomap_iter *iter, bool *did_zero) + if (ret < 0) + return ret; + +- ret = iomap_iter_advance(iter, &length); ++ ret = iomap_iter_advance(iter, length); + if (ret) + return ret; +- } while (length > 0); ++ } while ((length = iomap_length(iter)) > 0); + + if (did_zero) + *did_zero = true; +@@ -1597,7 +1597,7 @@ static int dax_iomap_iter(struct iomap_iter *iomi, struct iov_iter *iter) + + if (iomap->type == IOMAP_HOLE || iomap->type == IOMAP_UNWRITTEN) { + done = iov_iter_zero(min(length, end - pos), iter); +- return iomap_iter_advance(iomi, &done); ++ return iomap_iter_advance(iomi, done); + } + } + +@@ -1681,12 +1681,12 @@ static int dax_iomap_iter(struct iomap_iter *iomi, struct iov_iter *iter) + xfer = dax_copy_to_iter(dax_dev, pgoff, kaddr, + map_len, iter); + +- length = xfer; +- ret = iomap_iter_advance(iomi, &length); ++ ret = iomap_iter_advance(iomi, xfer); + if (!ret && xfer == 0) + ret = -EFAULT; + if (xfer < map_len) + break; ++ length = iomap_length(iomi); + } + dax_read_unlock(id); + +@@ -1919,10 +1919,8 @@ static vm_fault_t dax_iomap_pte_fault(struct vm_fault *vmf, unsigned long *pfnp, + ret |= VM_FAULT_MAJOR; + } + +- if (!(ret & VM_FAULT_ERROR)) { +- u64 length = PAGE_SIZE; +- iter.status = iomap_iter_advance(&iter, &length); +- } ++ if (!(ret & VM_FAULT_ERROR)) ++ iter.status = iomap_iter_advance(&iter, PAGE_SIZE); + } + + if (iomap_errp) +@@ -2034,10 +2032,8 @@ static vm_fault_t dax_iomap_pmd_fault(struct vm_fault *vmf, unsigned long *pfnp, + continue; /* actually breaks out of the loop */ + + ret = dax_fault_iter(vmf, &iter, pfnp, &xas, &entry, true); +- if (ret != VM_FAULT_FALLBACK) { +- u64 length = PMD_SIZE; +- iter.status = iomap_iter_advance(&iter, &length); +- } ++ if (ret != VM_FAULT_FALLBACK) ++ iter.status = iomap_iter_advance(&iter, PMD_SIZE); + } + + unlock_entry: +@@ -2163,7 +2159,6 @@ static int dax_range_compare_iter(struct iomap_iter *it_src, + const struct iomap *smap = &it_src->iomap; + const struct iomap *dmap = &it_dest->iomap; + loff_t pos1 = it_src->pos, pos2 = it_dest->pos; +- u64 dest_len; + void *saddr, *daddr; + int id, ret; + +@@ -2196,10 +2191,9 @@ static int dax_range_compare_iter(struct iomap_iter *it_src, + dax_read_unlock(id); + + advance: +- dest_len = len; +- ret = iomap_iter_advance(it_src, &len); ++ ret = iomap_iter_advance(it_src, len); + if (!ret) +- ret = iomap_iter_advance(it_dest, &dest_len); ++ ret = iomap_iter_advance(it_dest, len); + return ret; + + out_unlock: +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index 734854f864fd1e..db7d448e282cab 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -405,7 +405,7 @@ static int iomap_readpage_iter(struct iomap_iter *iter, + ret = iomap_read_inline_data(iter, folio); + if (ret) + return ret; +- return iomap_iter_advance(iter, &length); ++ return iomap_iter_advance(iter, length); + } + + /* zero post-eof blocks as the page may be mapped */ +@@ -466,7 +466,7 @@ static int iomap_readpage_iter(struct iomap_iter *iter, + * iteration. + */ + length = pos - iter->pos + plen; +- return iomap_iter_advance(iter, &length); ++ return iomap_iter_advance(iter, length); + } + + static int iomap_read_folio_iter(struct iomap_iter *iter, +@@ -1070,7 +1070,7 @@ static int iomap_write_iter(struct iomap_iter *iter, struct iov_iter *i, + } + } else { + total_written += written; +- iomap_iter_advance(iter, &written); ++ iomap_iter_advance(iter, written); + } + } while (iov_iter_count(i) && iomap_length(iter)); + +@@ -1339,7 +1339,7 @@ static int iomap_unshare_iter(struct iomap_iter *iter, + int status; + + if (!iomap_want_unshare_iter(iter)) +- return iomap_iter_advance(iter, &bytes); ++ return iomap_iter_advance(iter, bytes); + + do { + struct folio *folio; +@@ -1363,10 +1363,10 @@ static int iomap_unshare_iter(struct iomap_iter *iter, + + balance_dirty_pages_ratelimited(iter->inode->i_mapping); + +- status = iomap_iter_advance(iter, &bytes); ++ status = iomap_iter_advance(iter, bytes); + if (status) + break; +- } while (bytes > 0); ++ } while ((bytes = iomap_length(iter)) > 0); + + return status; + } +@@ -1441,10 +1441,10 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + if (WARN_ON_ONCE(!ret)) + return -EIO; + +- status = iomap_iter_advance(iter, &bytes); ++ status = iomap_iter_advance(iter, bytes); + if (status) + break; +- } while (bytes > 0); ++ } while ((bytes = iomap_length(iter)) > 0); + + if (did_zero) + *did_zero = true; +@@ -1555,7 +1555,7 @@ static int iomap_folio_mkwrite_iter(struct iomap_iter *iter, + folio_mark_dirty(folio); + } + +- return iomap_iter_advance(iter, &length); ++ return iomap_iter_advance(iter, length); + } + + vm_fault_t iomap_page_mkwrite(struct vm_fault *vmf, const struct iomap_ops *ops, +diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c +index e73c71f39bd45f..2e86b5c5280bed 100644 +--- a/fs/iomap/direct-io.c ++++ b/fs/iomap/direct-io.c +@@ -511,7 +511,7 @@ static int iomap_dio_bio_iter(struct iomap_iter *iter, struct iomap_dio *dio) + /* Undo iter limitation to current extent */ + iov_iter_reexpand(dio->submit.iter, orig_count - copied); + if (copied) +- return iomap_iter_advance(iter, &copied); ++ return iomap_iter_advance(iter, copied); + return ret; + } + +@@ -522,7 +522,7 @@ static int iomap_dio_hole_iter(struct iomap_iter *iter, struct iomap_dio *dio) + dio->size += length; + if (!length) + return -EFAULT; +- return iomap_iter_advance(iter, &length); ++ return iomap_iter_advance(iter, length); + } + + static int iomap_dio_inline_iter(struct iomap_iter *iomi, struct iomap_dio *dio) +@@ -557,7 +557,7 @@ static int iomap_dio_inline_iter(struct iomap_iter *iomi, struct iomap_dio *dio) + dio->size += copied; + if (!copied) + return -EFAULT; +- return iomap_iter_advance(iomi, &copied); ++ return iomap_iter_advance(iomi, copied); + } + + static int iomap_dio_iter(struct iomap_iter *iter, struct iomap_dio *dio) +diff --git a/fs/iomap/iter.c b/fs/iomap/iter.c +index cef77ca0c20bcc..91d2024e00da4e 100644 +--- a/fs/iomap/iter.c ++++ b/fs/iomap/iter.c +@@ -13,17 +13,13 @@ static inline void iomap_iter_reset_iomap(struct iomap_iter *iter) + memset(&iter->srcmap, 0, sizeof(iter->srcmap)); + } + +-/* +- * Advance the current iterator position and output the length remaining for the +- * current mapping. +- */ +-int iomap_iter_advance(struct iomap_iter *iter, u64 *count) ++/* Advance the current iterator position and decrement the remaining length */ ++int iomap_iter_advance(struct iomap_iter *iter, u64 count) + { +- if (WARN_ON_ONCE(*count > iomap_length(iter))) ++ if (WARN_ON_ONCE(count > iomap_length(iter))) + return -EIO; +- iter->pos += *count; +- iter->len -= *count; +- *count = iomap_length(iter); ++ iter->pos += count; ++ iter->len -= count; + return 0; + } + +diff --git a/fs/iomap/seek.c b/fs/iomap/seek.c +index 56db2dd4b10ddb..6cbc587c93dab2 100644 +--- a/fs/iomap/seek.c ++++ b/fs/iomap/seek.c +@@ -16,13 +16,13 @@ static int iomap_seek_hole_iter(struct iomap_iter *iter, + *hole_pos = mapping_seek_hole_data(iter->inode->i_mapping, + iter->pos, iter->pos + length, SEEK_HOLE); + if (*hole_pos == iter->pos + length) +- return iomap_iter_advance(iter, &length); ++ return iomap_iter_advance(iter, length); + return 0; + case IOMAP_HOLE: + *hole_pos = iter->pos; + return 0; + default: +- return iomap_iter_advance(iter, &length); ++ return iomap_iter_advance(iter, length); + } + } + +@@ -59,12 +59,12 @@ static int iomap_seek_data_iter(struct iomap_iter *iter, + + switch (iter->iomap.type) { + case IOMAP_HOLE: +- return iomap_iter_advance(iter, &length); ++ return iomap_iter_advance(iter, length); + case IOMAP_UNWRITTEN: + *hole_pos = mapping_seek_hole_data(iter->inode->i_mapping, + iter->pos, iter->pos + length, SEEK_DATA); + if (*hole_pos < 0) +- return iomap_iter_advance(iter, &length); ++ return iomap_iter_advance(iter, length); + return 0; + default: + *hole_pos = iter->pos; +diff --git a/include/linux/iomap.h b/include/linux/iomap.h +index 73dceabc21c8c7..4469b2318b08e5 100644 +--- a/include/linux/iomap.h ++++ b/include/linux/iomap.h +@@ -245,7 +245,7 @@ struct iomap_iter { + }; + + int iomap_iter(struct iomap_iter *iter, const struct iomap_ops *ops); +-int iomap_iter_advance(struct iomap_iter *iter, u64 *count); ++int iomap_iter_advance(struct iomap_iter *iter, u64 count); + + /** + * iomap_length_trim - trimmed length of the current iomap iteration +@@ -282,9 +282,7 @@ static inline u64 iomap_length(const struct iomap_iter *iter) + */ + static inline int iomap_iter_advance_full(struct iomap_iter *iter) + { +- u64 length = iomap_length(iter); +- +- return iomap_iter_advance(iter, &length); ++ return iomap_iter_advance(iter, iomap_length(iter)); + } + + /** +-- +2.53.0 + diff --git a/queue-6.18/iommu-amd-bound-the-early-acpi-hid-map.patch b/queue-6.18/iommu-amd-bound-the-early-acpi-hid-map.patch new file mode 100644 index 0000000000..2d03247225 --- /dev/null +++ b/queue-6.18/iommu-amd-bound-the-early-acpi-hid-map.patch @@ -0,0 +1,45 @@ +From e0be55c54fd1d1779c4201f2703c616a380324e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:46:13 +0800 +Subject: iommu/amd: Bound the early ACPI HID map + +From: Pengpeng Hou + +[ Upstream commit fb80117fddb5b477218dc99bb53911b72c3847f8 ] + +The ivrs_acpihid command-line parser appends entries to a fixed +four-element early_acpihid_map array. Unlike the sibling IOAPIC and HPET +parsers, it does not reject a fifth entry before incrementing the map size. + +Check the capacity at the common found label before parsing the HID and +UID or writing the entry. + +Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter") +Signed-off-by: Pengpeng Hou +Reviewed-by: Ankit Soni +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/init.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index 32175daa3dd8a1..69170146d44217 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -3860,6 +3860,12 @@ static int __init parse_ivrs_acpihid(char *str) + return 1; + + found: ++ if (early_acpihid_map_size == EARLY_MAP_SIZE) { ++ pr_err("Early ACPI HID map overflow - ignoring ivrs_acpihid%s\n", ++ str); ++ return 1; ++ } ++ + p = acpiid; + hid = strsep(&p, ":"); + uid = p; +-- +2.53.0 + diff --git a/queue-6.18/iommu-amd-wait-for-completion-instead-of-returning-e.patch b/queue-6.18/iommu-amd-wait-for-completion-instead-of-returning-e.patch new file mode 100644 index 0000000000..9ee3785999 --- /dev/null +++ b/queue-6.18/iommu-amd-wait-for-completion-instead-of-returning-e.patch @@ -0,0 +1,95 @@ +From 47ddb616708eca520879b93c5758e9d2c5c24d61 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 22:16:22 +0800 +Subject: iommu/amd: Wait for completion instead of returning early in + iommu_completion_wait() + +From: Guanghui Feng + +[ Upstream commit 1e75a8255f11c81fb07e81e5029cfd75804350a0 ] + +need_sync is a per-IOMMU flag shared by all domains and devices behind +that IOMMU. It is set whenever a command is queued with sync == true and +cleared when a completion-wait (CWAIT) command is queued. However, a +cleared need_sync only means that a covering CWAIT has been queued, not +that all previously queued commands have actually completed in hardware. + +iommu_completion_wait() read need_sync locklessly and returned early +when it was false. This breaks the "block until all previously queued +commands have completed" contract in a multi-CPU scenario: + + CPU2: queue inv-B => need_sync = true + CPU1: queue CWAIT(N); need_sync = false; then wait_on_sem(N) + CPU2: read need_sync == false => return 0 (no wait!) + +CPU2 returns without waiting for any sequence number even though its +inv-B may not have completed yet (CWAIT(N), queued after inv-B, has not +been signaled). CPU2 then proceeds to, for example, free page-table +pages while the IOMMU can still walk stale translations, opening a +use-after-free window. This is a logical race in the meaning of the +flag, not a memory-visibility issue, so barriers alone do not help. + +Fix it without losing the optimization of avoiding redundant CWAIT +commands: take iommu->lock before testing need_sync, and when it is +false do not return early but wait for the last allocated sequence +number (cmd_sem_val). Since need_sync == false implies no sync command +was queued after the last CWAIT, that CWAIT is FIFO-ordered after every +not-yet-completed command, so waiting for its sequence number guarantees +all prior commands (possibly queued by another CPU) have completed. The +common path with pending work is unchanged and no extra hardware command +is issued. + +Signed-off-by: Guanghui Feng +Fixes: 815b33fdc279 ("x86/amd-iommu: Cleanup completion-wait handling") +Reviewed-by: Vasant Hegde +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/iommu.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c +index c458eec8a5bba8..12302647e26759 100644 +--- a/drivers/iommu/amd/iommu.c ++++ b/drivers/iommu/amd/iommu.c +@@ -1408,11 +1408,23 @@ static int iommu_completion_wait(struct amd_iommu *iommu) + int ret; + u64 data; + +- if (!iommu->need_sync) +- return 0; +- + raw_spin_lock_irqsave(&iommu->lock, flags); + ++ if (!iommu->need_sync) { ++ /* ++ * No command has been queued since the last completion-wait. ++ * A concurrent CPU may have already queued that CWAIT and ++ * cleared need_sync; need_sync == false only means a covering ++ * CWAIT is queued, not that all prior commands have completed. ++ * Wait for the last allocated sequence number so that any ++ * command queued before this call (possibly on another CPU) ++ * is guaranteed to have completed before returning. ++ */ ++ data = iommu->cmd_sem_val; ++ raw_spin_unlock_irqrestore(&iommu->lock, flags); ++ return wait_on_sem(iommu, data); ++ } ++ + data = get_cmdsem_val(iommu); + build_completion_wait(&cmd, iommu, data); + +@@ -1422,9 +1434,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu) + if (ret) + return ret; + +- ret = wait_on_sem(iommu, data); +- +- return ret; ++ return wait_on_sem(iommu, data); + } + + static void domain_flush_complete(struct protection_domain *domain) +-- +2.53.0 + diff --git a/queue-6.18/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch b/queue-6.18/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch new file mode 100644 index 0000000000..1493f82e1d --- /dev/null +++ b/queue-6.18/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch @@ -0,0 +1,43 @@ +From 2b4a8212d056f4a7f68360dc4dcdec86d31ddc1e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:34:10 +0800 +Subject: iommu/intel: Fix out-of-bounds memset in dmar_latency_disable() + +From: Li RongQing + +[ Upstream commit 754f8efe45f87e3a9c6871b645b2f9d46d1b407b ] + +dmar_latency_disable() intends to zero out only the single +latency_statistic entry for the given type, but the memset size was +computed as sizeof(*lstat) * DMAR_LATENCY_NUM, which clears the entire +array starting from &lstat[type]. + +When type > 0, this writes beyond the end of the allocated array, +corrupting adjacent memory. + +Fix by using sizeof(*lstat) to clear only the target entry. + +Fixes: 55ee5e67a59a ("iommu/vt-d: Add common code for dmar latency performance monitors") +Signed-off-by: Li RongQing +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/perf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/intel/perf.c b/drivers/iommu/intel/perf.c +index dceeadc3ee7cdd..6afb55073e9f10 100644 +--- a/drivers/iommu/intel/perf.c ++++ b/drivers/iommu/intel/perf.c +@@ -63,7 +63,7 @@ void dmar_latency_disable(struct intel_iommu *iommu, enum latency_type type) + return; + + spin_lock_irqsave(&latency_lock, flags); +- memset(&lstat[type], 0, sizeof(*lstat) * DMAR_LATENCY_NUM); ++ memset(&lstat[type], 0, sizeof(*lstat)); + spin_unlock_irqrestore(&latency_lock, flags); + } + +-- +2.53.0 + diff --git a/queue-6.18/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch b/queue-6.18/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch new file mode 100644 index 0000000000..0a986d2001 --- /dev/null +++ b/queue-6.18/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch @@ -0,0 +1,88 @@ +From 88bc860ffc4836ded97ee51925b42ee887785d37 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:42:36 +0000 +Subject: ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup + +From: Eric Dumazet + +[ Upstream commit 853e164c2b321f0711361bc23505aaeb7dc432c3 ] + +When Linux forwards a packet and needs to generate an ICMP error, +icmp_route_lookup() performs a reverse-path relookup. For non-local +destinations, it performs a decoy lookup to find the expected egress +interface (rt2->dst.dev) before validating the path with ip_route_input(). + +Currently, the decoy flow structure (fl4_2) only sets .daddr = fl4_dec.saddr, +leaving .saddr, .flowi4_dscp, .flowi4_proto, .flowi4_mark, .flowi4_oif, +.fl4_sport, .fl4_dport, and .flowi4_uid zeroed out. + +When policy routing rules (such as ip rule add from $SRC lookup 100, or +dscp/fwmark/ipproto/port rules, or VRF bindings) are configured: +1. The decoy lookup fails to match the policy rule because saddr and other + key flow selectors are missing in fl4_2. +2. It resolves a route using the default table instead, returning an incorrect + egress netdev. +3. Passing the wrong netdev to ip_route_input() causes strict reverse-path + filtering (rp_filter=1) to fail, logging false-positive "martian source" + warnings and causing the relookup to fail. + +Fix this by initializing fl4_2 from fl4_dec and: +- Swapping source/destination IP addresses. +- Swapping L4 ports for transport protocols with ports (TCP, UDP, SCTP, DCCP) + so port-based policy routing matches correctly. Non-port protocols (such as + ICMP or GRE) leave the flowi_uli union fields intact to prevent corruption. +- Setting .flowi4_oif = l3mdev_master_ifindex(route_lookup_dev) to ensure + VRF routing tables are respected. +- Setting .flowi4_flags |= FLOWI_FLAG_ANYSRC to allow output route lookups + for non-local source IP addresses. +- Using __ip_route_output_key() instead of ip_route_output_key() for fl4_2 + so that raw FIB routing is used without triggering spurious XFRM policy + lookups on the decoy flow (the actual XFRM lookup is performed later using + fl4_dec). + +Fixes: 415b3334a21a ("icmp: Fix regression in nexthop resolution during replies.") +Reported-by: Muhammad Ziad +Closes: https://lore.kernel.org/netdev/CAOAwikA60AYKdFr_UDLyja3oU4hqyAE7uFZWqum5uRdaQsgRYg@mail.gmail.com/ +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260722104236.2938082-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index fc0a93f43313d1..691d7b076c620c 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -539,11 +539,23 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4, + if (IS_ERR(rt2)) + err = PTR_ERR(rt2); + } else { +- struct flowi4 fl4_2 = {}; ++ struct flowi4 fl4_2 = fl4_dec; + unsigned long orefdst; + +- fl4_2.daddr = fl4_dec.saddr; +- rt2 = ip_route_output_key(net, &fl4_2); ++ swap(fl4_2.daddr, fl4_2.saddr); ++ switch (fl4_2.flowi4_proto) { ++ case IPPROTO_TCP: ++ case IPPROTO_UDP: ++ case IPPROTO_SCTP: ++ case IPPROTO_DCCP: ++ swap(fl4_2.fl4_sport, fl4_2.fl4_dport); ++ break; ++ } ++ ++ fl4_2.flowi4_oif = l3mdev_master_ifindex(route_lookup_dev); ++ fl4_2.flowi4_flags |= FLOWI_FLAG_ANYSRC; ++ ++ rt2 = __ip_route_output_key(net, &fl4_2); + if (IS_ERR(rt2)) { + err = PTR_ERR(rt2); + goto relookup_failed; +-- +2.53.0 + diff --git a/queue-6.18/ipv6-change-allocation-flags-to-match-rcu_read_lock-.patch b/queue-6.18/ipv6-change-allocation-flags-to-match-rcu_read_lock-.patch new file mode 100644 index 0000000000..6732b11775 --- /dev/null +++ b/queue-6.18/ipv6-change-allocation-flags-to-match-rcu_read_lock-.patch @@ -0,0 +1,69 @@ +From 6647dec2e5daca4c1dbb91a056a0ce476eb890da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Jul 2026 13:57:59 +0300 +Subject: ipv6: Change allocation flags to match rcu_read_lock section + requirements + +From: Nikola Z. Ivanov + +[ Upstream commit 313a123e1fca8827bb463db1f4bb211309764563 ] + +Since the call to __ip6_del_rt_siblings has been converted under +rcu read lock and it only has one call point +we should no longer block or yield. + +Our stack trace from the syzbot reproducer looks as follows: + +__ip6_del_rt_siblings + rtnl_notify (Here we pass gfp_any() -> GFP_KERNEL) + nlmsg_notify + nlmsg_multicast + nlmsg_multicast_filtered + netlink_broadcast_filtered (GFP_KERNEL passed from earlier) + +netlink_broadcast_filtered can yield if GFP_KERNEL +is passed, which we do not want to happen. + +Fix this by changing the allocation flag of rtnl_notify. + +Also change the flag passed to nlmsg_new. Even though it +is not related to the syzbot generated bug it still falls +under the same requirements. + +Reported-by: syzbot+84d4a405ed798b40c96d@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=84d4a405ed798b40c96d +Fixes: bd11ff421d36 ("ipv6: Get rid of RTNL for SIOCDELRT and RTM_DELROUTE.") +Signed-off-by: Nikola Z. Ivanov +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260719105759.558050-1-zlatistiv@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/route.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index ef66a3c86febbf..a45747bfb31a06 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -4011,7 +4011,7 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg) + struct fib6_node *fn; + + /* prefer to send a single notification with all hops */ +- skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any()); ++ skb = nlmsg_new(rt6_nlmsg_size(rt), GFP_ATOMIC); + if (skb) { + u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0; + +@@ -4067,7 +4067,7 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg) + + if (skb) { + rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE, +- info->nlh, gfp_any()); ++ info->nlh, GFP_ATOMIC); + } + return err; + } +-- +2.53.0 + diff --git a/queue-6.18/ksmbd-validate-compound-request-size-before-reading-.patch-18864 b/queue-6.18/ksmbd-validate-compound-request-size-before-reading-.patch-18864 new file mode 100644 index 0000000000..1c9d66a925 --- /dev/null +++ b/queue-6.18/ksmbd-validate-compound-request-size-before-reading-.patch-18864 @@ -0,0 +1,69 @@ +From 2dfad88ad7f4d242e768910e27e636f8fb524a20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 21:55:10 +0000 +Subject: ksmbd: validate compound request size before reading StructureSize2 + +From: Xiang Mei (Microsoft) + +[ Upstream commit 15b38176fd1530372905c602fde51fe89ec8c877 ] + +When ksmbd validates a compound (chained) SMB2 request, +ksmbd_smb2_check_message() reads pdu->StructureSize2 without first +checking that the compound element is large enough to contain it. +StructureSize2 is a 2-byte field at offset 64 +(__SMB2_HEADER_STRUCTURE_SIZE) from the start of each element. + +The compound-walking logic only guarantees that a full 64-byte SMB2 +header is present for the trailing element: when NextCommand is 0, len is +reduced to the number of bytes remaining after next_smb2_rcv_hdr_off. A +remote client can craft a compound request whose last element has exactly +64 bytes, so the 2-byte StructureSize2 read at offset 64 extends one byte +past the receive buffer, producing a slab-out-of-bounds read. + + BUG: KASAN: slab-out-of-bounds in ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + Read of size 2 at addr ffff888012ae31ac by task kworker/0:1/14 + The buggy address is located 172 bytes inside of allocated 173-byte region + Workqueue: ksmbd-io handle_ksmbd_work + Call Trace: + ... + kasan_report (mm/kasan/report.c:595) + ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402) + handle_ksmbd_work (fs/smb/server/server.c:119) + process_one_work (kernel/workqueue.c:3314) + worker_thread (kernel/workqueue.c:3397) + kthread (kernel/kthread.c:436) + ret_from_fork (arch/x86/kernel/process.c:158) + ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Reject any compound element that is too small to hold StructureSize2 +before dereferencing it. + +Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2misc.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c +index b11d854d3fcfba..e07d9aad4319c5 100644 +--- a/fs/smb/server/smb2misc.c ++++ b/fs/smb/server/smb2misc.c +@@ -405,6 +405,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work) + return 1; + } + ++ if (len < __SMB2_HEADER_STRUCTURE_SIZE + sizeof(__le16)) { ++ ksmbd_debug(SMB, "Message is too small for StructureSize2\n"); ++ return 1; ++ } ++ + if (smb2_req_struct_sizes[command] != pdu->StructureSize2) { + if (!(command == SMB2_OPLOCK_BREAK_HE && + (le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 || +-- +2.53.0 + diff --git a/queue-6.18/mctp-check-register_netdevice_notifier-error-in-mctp.patch b/queue-6.18/mctp-check-register_netdevice_notifier-error-in-mctp.patch new file mode 100644 index 0000000000..429136156f --- /dev/null +++ b/queue-6.18/mctp-check-register_netdevice_notifier-error-in-mctp.patch @@ -0,0 +1,43 @@ +From 81ff54038f181f5d602ec15117124776e9e4e3d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 15:25:18 +0800 +Subject: mctp: check register_netdevice_notifier() error in mctp_device_init() + +From: Minhong He + +[ Upstream commit d9a33cadc70a94c1582f65e6042e81027cd200c6 ] + +mctp_device_init() handles errors from rtnl_af_register() and +rtnl_register_many(), but ignores the return value of +register_netdevice_notifier(). If notifier registration fails, init can +still return success while the module is only partially initialized. + +Check the notifier registration error and fail module init early. + +Fixes: 583be982d934 ("mctp: Add device handling and netlink interface") +Signed-off-by: Minhong He +Link: https://patch.msgid.link/20260720072518.112614-1-heminhong@kylinos.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/mctp/device.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/mctp/device.c b/net/mctp/device.c +index 04c5570bacff69..7861d83aaad263 100644 +--- a/net/mctp/device.c ++++ b/net/mctp/device.c +@@ -536,7 +536,9 @@ int __init mctp_device_init(void) + { + int err; + +- register_netdevice_notifier(&mctp_dev_nb); ++ err = register_netdevice_notifier(&mctp_dev_nb); ++ if (err) ++ return err; + + err = rtnl_af_register(&mctp_af_ops); + if (err) +-- +2.53.0 + diff --git a/queue-6.18/net-airoha-fix-dma-direction-for-npu-mailbox-buffer.patch b/queue-6.18/net-airoha-fix-dma-direction-for-npu-mailbox-buffer.patch new file mode 100644 index 0000000000..0bd20f7fbd --- /dev/null +++ b/queue-6.18/net-airoha-fix-dma-direction-for-npu-mailbox-buffer.patch @@ -0,0 +1,73 @@ +From 0858f737d9eef702c0c84732e2bbb080f2613f27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:35:29 +0800 +Subject: net: airoha: Fix DMA direction for NPU mailbox buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Wayen Yan + +[ Upstream commit 6f884eb87a79e0c482baef2ad96c96b81d024235 ] + +airoha_npu_send_msg() always maps the mailbox buffer with DMA_TO_DEVICE, +but some callers expect the NPU to write response data back into the +same buffer: + +- airoha_npu_wlan_msg_get() (NPU_OP_GET): NPU writes response into + the buffer, then the caller reads it via memcpy() +- airoha_npu_ppe_stats_setup() (NPU_OP_SET): NPU writes back + npu_stats_addr field in the response + +On non-cache-coherent architectures like EN7581 (Cortex-A53 without +hardware cache coherency for NPU DMA), DMA_TO_DEVICE unmap is a no-op +— it does not invalidate the CPU cache. If the NPU-written cache line +is still present in the CPU cache when the caller reads the buffer, +the CPU observes stale data instead of the NPU response. + +This is a timing-sensitive bug: small mailbox buffers (~24 bytes) +typically fit in a single cache line and may survive in the cache +until the caller reads them, producing silent data corruption rather +than a crash. The bug is more likely to trigger when the caller reads +the response immediately after dma_unmap_single() without intervening +cache-evicting operations. + +Fix by using DMA_BIDIRECTIONAL for both map and unmap, which ensures +dma_unmap_single() invalidates the CPU cache on non-coherent systems. +The mailbox buffers are small so there is no performance concern. + +Fixes: c52918744ee1e49cea86622a2633b9782446428f ("net: airoha: npu: Move memory allocation in airoha_npu_send_msg() caller") +Signed-off-by: Wayen Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/178351055214.98729.11403147818632027428@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/airoha/airoha_npu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c +index 8c883f2b2d36b7..d6547834d3c783 100644 +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -154,7 +154,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, + dma_addr_t dma_addr; + int ret; + +- dma_addr = dma_map_single(npu->dev, p, size, DMA_TO_DEVICE); ++ dma_addr = dma_map_single(npu->dev, p, size, DMA_BIDIRECTIONAL); + ret = dma_mapping_error(npu->dev, dma_addr); + if (ret) + return ret; +@@ -177,7 +177,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, + + spin_unlock_bh(&npu->cores[core].lock); + +- dma_unmap_single(npu->dev, dma_addr, size, DMA_TO_DEVICE); ++ dma_unmap_single(npu->dev, dma_addr, size, DMA_BIDIRECTIONAL); + + return ret; + } +-- +2.53.0 + diff --git a/queue-6.18/net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch b/queue-6.18/net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch new file mode 100644 index 0000000000..3a9f77ed77 --- /dev/null +++ b/queue-6.18/net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch @@ -0,0 +1,47 @@ +From 2b0b3864125a3d7051091524734081c7fd31fe18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 13:22:28 +0200 +Subject: net: airoha: fix ETS channel derivation in + airoha_tc_setup_qdisc_ets() + +From: Lorenzo Bianconi + +[ Upstream commit 649ea07fc25a17aa51bff710baac1ab161022a7c ] + +Derive the hardware QoS channel from opt->parent instead of opt->handle +in airoha_tc_setup_qdisc_ets(). The ETS qdisc handle is either +user-specified or auto-allocated by qdisc_alloc_handle() and bears no +relation to the HTB leaf classid that identifies the hardware channel. +HTB derives the channel from TC_H_MIN(opt->classid), and ETS is always +attached as a child of an HTB leaf, so its opt->parent matches that +classid. Using opt->handle instead can cause two ETS qdiscs on different +HTB leaves to collide on the same hardware channel, corrupting scheduler +configuration and stats. + +Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support") +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260720-airoha-ets-handle-fix-v2-1-6f7129ddc06f@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/airoha/airoha_eth.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c +index 5efd03c2deea77..64ab34e37c36f9 100644 +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2326,8 +2326,7 @@ static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port, + if (opt->parent == TC_H_ROOT) + return -EINVAL; + +- channel = TC_H_MAJ(opt->handle) >> 16; +- channel = channel % AIROHA_NUM_QOS_CHANNELS; ++ channel = TC_H_MIN(opt->parent) % AIROHA_NUM_QOS_CHANNELS; + + switch (opt->command) { + case TC_ETS_REPLACE: +-- +2.53.0 + diff --git a/queue-6.18/net-airoha-fix-potential-use-after-free-in-airoha_pp.patch b/queue-6.18/net-airoha-fix-potential-use-after-free-in-airoha_pp.patch new file mode 100644 index 0000000000..d720daab3e --- /dev/null +++ b/queue-6.18/net-airoha-fix-potential-use-after-free-in-airoha_pp.patch @@ -0,0 +1,49 @@ +From 8c2707b6d9cbe728cccdecfeea27b90cfb9f1367 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:16:16 +0800 +Subject: net: airoha: Fix potential use-after-free in airoha_ppe_deinit() + +From: Wayen Yan + +[ Upstream commit 2484568a335cd7bda951c75b3a7d95ea36161ae7 ] + +airoha_ppe_deinit() replaces the NPU pointer with NULL via +rcu_replace_pointer() but does not wait for existing RCU readers +to exit before calling ppe_deinit() and airoha_npu_put(). This can +cause a use-after-free if a reader in an RCU read-side critical +section still holds a reference to the NPU when it is freed. + +The init path (airoha_ppe_init) already calls synchronize_rcu() +after rcu_assign_pointer(), but the deinit path introduced in +commit 6abcf751bc08 ("net: airoha: Fix schedule while atomic in +airoha_ppe_deinit()") omitted the matching barrier when switching +from rcu_read_lock()/rcu_dereference() to rcu_replace_pointer(). + +Add synchronize_rcu() before ppe_deinit() to ensure all existing +RCU readers have completed before the NPU resources are released. + +Fixes: 6abcf751bc084804a9e5b3051442e8a2ce67f48a ("net: airoha: Fix schedule while atomic in airoha_ppe_deinit()") +Signed-off-by: Wayen Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/178351022574.97989.6880403520276841703@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c +index 798839aa1010b8..8defd194568f25 100644 +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1575,6 +1575,7 @@ void airoha_ppe_deinit(struct airoha_eth *eth) + npu = rcu_replace_pointer(eth->npu, NULL, + lockdep_is_held(&flow_offload_mutex)); + if (npu) { ++ synchronize_rcu(); + npu->ops.ppe_deinit(npu); + airoha_npu_put(npu); + } +-- +2.53.0 + diff --git a/queue-6.18/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch b/queue-6.18/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch new file mode 100644 index 0000000000..3687245db7 --- /dev/null +++ b/queue-6.18/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch @@ -0,0 +1,149 @@ +From 44fabbb2ec567728dac8cbc409f25f64c7ed9977 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:09:21 +0300 +Subject: net: bridge: vlan: fix vlan range dumps starting with pvid + +From: Nikolay Aleksandrov + +[ Upstream commit 43171c97e4714bf601b468401b37732244639c21 ] + +There is a bug in all range dumps that rely on br_vlan_can_enter_range() +when the PVID is a range starting VLAN, all following VLANs that match +its flags can enter the range, but when the range is filled in only the +PVID VLAN is dumped and the rest of the range is discarded because +br_vlan_fill_vids() checks for the PVID flag. Since the PVID VLAN can +be only one, we need to break ranges around it, the best way to do that +consistently for all is to alter br_vlan_can_enter_range() to take into +account the PVID and return false to break the range when it's matched. + +Before the fix: +$ ip l add br0 type bridge vlan_filtering 1 +$ ip l add dumdum type dummy +$ ip l set dumdum master br0 +$ ip l set br0 up +$ ip l set dumdum up +$ bridge vlan add dev dumdum vid 1 pvid untagged master +$ bridge vlan add dev dumdum vid 2 untagged master +$ bridge vlan show dev dumdum # use legacy dump to show all vlans +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged + +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + +VLAN 2 is missing, and if there are more matching VLANs afterwards +they'd be missing too. + +After the fix: +[ same setup steps ] +$ bridge vlan show dev dumdum +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + 2 Egress Untagged + state forwarding mcast_router 1 + +Fixes: 0ab558795184 ("net: bridge: vlan: add rtm range support") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260721140922.682265-2-razor@blackwall.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_netlink_tunnel.c | 3 ++- + net/bridge/br_private.h | 6 ++++-- + net/bridge/br_vlan.c | 10 ++++++---- + net/bridge/br_vlan_options.c | 3 +-- + 4 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/net/bridge/br_netlink_tunnel.c b/net/bridge/br_netlink_tunnel.c +index 71a12da30004c7..a713668ea34f0e 100644 +--- a/net/bridge/br_netlink_tunnel.c ++++ b/net/bridge/br_netlink_tunnel.c +@@ -271,7 +271,8 @@ static void __vlan_tunnel_handle_range(const struct net_bridge_port *p, + if (!*v_start) + goto out_init; + +- if (v && curr_change && br_vlan_can_enter_range(v, *v_end)) { ++ if (v && curr_change && ++ br_vlan_can_enter_range(v, *v_end, br_get_pvid(vg))) { + *v_end = v; + return; + } +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index b9b2981c484149..2b451f3f72a6ad 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1613,7 +1613,8 @@ void br_vlan_notify(const struct net_bridge *br, + u16 vid, u16 vid_range, + int cmd); + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end); ++ const struct net_bridge_vlan *range_end, ++ u16 pvid); + + void br_vlan_fill_forward_path_pvid(struct net_bridge *br, + struct net_device_path_ctx *ctx, +@@ -1860,7 +1861,8 @@ static inline void br_vlan_notify(const struct net_bridge *br, + } + + static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { + return true; + } +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index ce72b837ff8ee9..a4ba725ad1dff4 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1977,9 +1977,11 @@ void br_vlan_notify(const struct net_bridge *br, + + /* check if v_curr can enter a range ending in range_end */ + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { +- return v_curr->vid - range_end->vid == 1 && ++ return v_curr->vid != pvid && range_end->vid != pvid && ++ v_curr->vid - range_end->vid == 1 && + range_end->flags == v_curr->flags && + br_vlan_opts_eq_range(v_curr, range_end); + } +@@ -2061,8 +2063,8 @@ static int br_vlan_dump_dev(const struct net_device *dev, + idx += range_end->vid - range_start->vid + 1; + + range_start = v; +- } else if (dump_stats || v->vid == pvid || +- !br_vlan_can_enter_range(v, range_end)) { ++ } else if (dump_stats || ++ !br_vlan_can_enter_range(v, range_end, pvid)) { + u16 vlan_flags = br_vlan_flags(range_start, pvid); + + if (!br_vlan_fill_vids(skb, range_start->vid, +diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c +index 8fa89b04ee942d..4a736e005bad7e 100644 +--- a/net/bridge/br_vlan_options.c ++++ b/net/bridge/br_vlan_options.c +@@ -310,8 +310,7 @@ int br_vlan_process_options(const struct net_bridge *br, + continue; + } + +- if (v->vid == pvid || +- !br_vlan_can_enter_range(v, curr_end)) { ++ if (!br_vlan_can_enter_range(v, curr_end, pvid)) { + br_vlan_notify(br, p, curr_start->vid, + curr_end->vid, RTM_NEWVLAN); + curr_start = v; +-- +2.53.0 + diff --git a/queue-6.18/net-call-net_enable_timestamp-before-failure-in-sk_c.patch b/queue-6.18/net-call-net_enable_timestamp-before-failure-in-sk_c.patch new file mode 100644 index 0000000000..48a70e015a --- /dev/null +++ b/queue-6.18/net-call-net_enable_timestamp-before-failure-in-sk_c.patch @@ -0,0 +1,59 @@ +From 807dec7667c8ca4c02a5ef207bd071dfbe0b69c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 18:31:40 +0000 +Subject: net: Call net_enable_timestamp() before failure in sk_clone(). + +From: Kuniyuki Iwashima + +[ Upstream commit d50557779257a00162411e3048d82971ff1f644c ] + +When sk_clone() fails, sk_destruct() is called for the new socket. + +If the parent socket has SK_FLAGS_TIMESTAMP in sk->sk_flags, +net_disable_timestamp() is called for the child socket even though +net_enable_timestamp() is not called for it. + +Let's call net_enable_timestamp() before any failure path in +sk_clone(). + +Fixes: 704da560c0a0 ("tcp: update the netstamp_needed counter when cloning sockets") +Reported-by: Sashiko +Closes: https://lore.kernel.org/all/20260709032007.9E4D61F000E9@smtp.kernel.org/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Willem de Bruijn +Reviewed-by: Jason Xing +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260709183315.965751-3-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/sock.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/core/sock.c b/net/core/sock.c +index 9803926942c559..5a658606c50e8a 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -2527,6 +2527,9 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) + + RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL); + ++ if (sock_needs_netstamp(sk) && newsk->sk_flags & SK_FLAGS_TIMESTAMP) ++ net_enable_timestamp(); ++ + rcu_read_lock(); + filter = rcu_dereference(sk->sk_filter); + if (filter != NULL) +@@ -2575,9 +2578,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) + + if (newsk->sk_prot->sockets_allocated) + sk_sockets_allocated_inc(newsk); +- +- if (sock_needs_netstamp(sk) && newsk->sk_flags & SK_FLAGS_TIMESTAMP) +- net_enable_timestamp(); + out: + return newsk; + free: +-- +2.53.0 + diff --git a/queue-6.18/net-dpaa-fix-mode-setting.patch b/queue-6.18/net-dpaa-fix-mode-setting.patch new file mode 100644 index 0000000000..e156027811 --- /dev/null +++ b/queue-6.18/net-dpaa-fix-mode-setting.patch @@ -0,0 +1,81 @@ +From 6b215f64a1419c08c687cc56c784550436dca110 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 15:20:29 +0200 +Subject: net: dpaa: fix mode setting + +From: Michael Walle + +[ Upstream commit da2c6bcc5e30b1496ac587785dcacf6e849eb6ef ] + +Before converting to the phylink interface, the init function would have +set a non-reserved I/F mode in the maccfg2 register. After converting to +phylink, 0 is written as mode, which is a reserved value (although it's +the hardware default). Without a valid mode, a SGMII link is never +established between the MAC and the PHY and thus .link_up() is never +called which could set the correct mode according to the actual speed. + +Fix it by setting the maximum speed of the phy_interface_t in use in +.mac_config() - just like the driver did before the phylink conversion. + +Fixes: 5d93cfcf7360 ("net: dpaa: Convert to phylink") +Suggested-by: Sean Anderson +Signed-off-by: Michael Walle +Reviewed-by: Sean Anderson +Reviewed-by: Sean Anderson +Link: https://patch.msgid.link/20260717132401.2653252-1-mwalle@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/freescale/fman/fman_dtsec.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +index 51402dff72c5ff..52f13b61bc6993 100644 +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +@@ -900,22 +900,28 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, + { + struct mac_device *mac_dev = fman_config_to_mac(config); + struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs; +- u32 tmp; ++ u32 ecntrl, maccfg2; ++ ++ maccfg2 = ioread32be(®s->maccfg2); ++ maccfg2 &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); + + switch (state->interface) { + case PHY_INTERFACE_MODE_RMII: +- tmp = DTSEC_ECNTRL_RMM; ++ ecntrl = DTSEC_ECNTRL_RMM; ++ maccfg2 |= MACCFG2_NIBBLE_MODE; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: +- tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; ++ ecntrl = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; ++ maccfg2 |= MACCFG2_BYTE_MODE; + break; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: +- tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; ++ ecntrl = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; ++ maccfg2 |= MACCFG2_BYTE_MODE; + break; + default: + dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n", +@@ -923,7 +929,8 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, + return; + } + +- iowrite32be(tmp, ®s->ecntrl); ++ iowrite32be(ecntrl, ®s->ecntrl); ++ iowrite32be(maccfg2, ®s->maccfg2); + } + + static void dtsec_link_up(struct phylink_config *config, struct phy_device *phy, +-- +2.53.0 + diff --git a/queue-6.18/net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch b/queue-6.18/net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch new file mode 100644 index 0000000000..5a3a0c67d9 --- /dev/null +++ b/queue-6.18/net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch @@ -0,0 +1,92 @@ +From d5ac78814a7157ba24b922b071c10b23b42868fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:09:45 +0800 +Subject: net: gre: fix lltx regression for GRE tunnels with SEQ/CSUM + +From: Yun Zhou + +[ Upstream commit 675ed582c1aa4d919dd535490de08c015005c653 ] + +Before commit 00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to +dev->lltx"), NETIF_F_LLTX was set unconditionally in both +__gre_tunnel_init() and ip6gre_tnl_init_features() alongside +GRE_FEATURES: + + dev->features |= GRE_FEATURES | NETIF_F_LLTX; + +When that commit converted NETIF_F_LLTX to the dev->lltx flag, it +placed 'dev->lltx = true' after the SEQ/CSUM early returns instead +of before them. This causes GRE/GRETAP/ip6gre tunnels with SEQ or +CSUM+encap to lose lockless TX, reintroducing _xmit_lock acquisition +around their ndo_start_xmit. Since GRE xmit re-enters the stack via +ip_tunnel_xmit(), holding _xmit_lock risks ABBA deadlock with the +underlay device. + + CPU0 CPU1 + ---- ---- + lock(&qdisc_xmit_lock_key#6); + lock(&qdisc_xmit_lock_key#3); + lock(&qdisc_xmit_lock_key#6); + lock(&qdisc_xmit_lock_key#3); + +Fix by moving dev->lltx = true before the early returns in both +functions, restoring the original unconditional behavior. + +Fixes: 00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to dev->lltx") +Signed-off-by: Yun Zhou +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260713150945.1779628-1-yun.zhou@windriver.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_gre.c | 4 ++-- + net/ipv6/ip6_gre.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index 879d37c557fafb..300b802125db27 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -1017,6 +1017,8 @@ static void __gre_tunnel_init(struct net_device *dev) + dev->features |= GRE_FEATURES; + dev->hw_features |= GRE_FEATURES; + ++ dev->lltx = true; ++ + /* TCP offload with GRE SEQ is not supported, nor can we support 2 + * levels of outer headers requiring an update. + */ +@@ -1028,8 +1030,6 @@ static void __gre_tunnel_init(struct net_device *dev) + + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; +- +- dev->lltx = true; + } + + static int ipgre_tunnel_init(struct net_device *dev) +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 75961c4ebcdd22..58b473c157c820 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -1454,6 +1454,8 @@ static void ip6gre_tnl_init_features(struct net_device *dev) + dev->features |= GRE6_FEATURES; + dev->hw_features |= GRE6_FEATURES; + ++ dev->lltx = true; ++ + /* TCP offload with GRE SEQ is not supported, nor can we support 2 + * levels of outer headers requiring an update. + */ +@@ -1465,8 +1467,6 @@ static void ip6gre_tnl_init_features(struct net_device *dev) + + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; +- +- dev->lltx = true; + } + + static int ip6gre_tunnel_init_common(struct net_device *dev) +-- +2.53.0 + diff --git a/queue-6.18/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch b/queue-6.18/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch new file mode 100644 index 0000000000..b6bb96e4ee --- /dev/null +++ b/queue-6.18/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch @@ -0,0 +1,56 @@ +From 11c10d8043fcb90fb78901f7aaefa7f058811636 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 10:12:40 +0000 +Subject: net: hsr: fix memory leak on slave unregistration by removing synced + VLANs + +From: Eric Dumazet + +[ Upstream commit dcf15eaf5641812f1cfc5e96537380132a7da89d ] + +When an HSR master device is brought UP, it auto-adds VLAN 0 via +vlan_vid0_add(), which propagates VID 0 to its slave devices (slave A and B). + +If a slave device is later unregistered while HSR is active (e.g., during +netns cleanup or interface destruction), hsr_del_port() is called to +detach the slave port from the HSR master. However, hsr_del_port() currently +does not delete the VLAN IDs that were synced to the slave device by HSR. + +As a result, the slave device retains a refcount on VID 0 (and any other +synced VLANs). When the slave device is destroyed, its vlan_info / +vlan_vid_info structure remains allocated, leading to a memory leak. + +Fix this by calling vlan_vids_del_by_dev(port->dev, master->dev) in +hsr_del_port() before unlinking slave A or slave B ports, matching the +propagation logic in hsr_ndo_vlan_rx_add_vid() / hsr_ndo_vlan_rx_kill_vid() +and the cleanup behavior in bonding and team drivers. + +Fixes: 1a8a63a5305e ("net: hsr: Add VLAN CTAG filter support") +Reported-by: syzbot+456957213f32970c0762@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/6a4cb6ca.57639fcc.86d58.000b.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Fernando Fernandez Mancera +Reviewed-by: Felix Maurer +Link: https://patch.msgid.link/20260721101240.995597-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_slave.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c +index afe06ba00ea447..474f44f1ee88ce 100644 +--- a/net/hsr/hsr_slave.c ++++ b/net/hsr/hsr_slave.c +@@ -242,6 +242,8 @@ void hsr_del_port(struct hsr_port *port) + netdev_rx_handler_unregister(port->dev); + if (!port->hsr->fwd_offloaded) + dev_set_promiscuity(port->dev, -1); ++ if (port->type == HSR_PT_SLAVE_A || port->type == HSR_PT_SLAVE_B) ++ vlan_vids_del_by_dev(port->dev, master->dev); + netdev_upper_dev_unlink(port->dev, master->dev); + eth_hw_addr_set(port->dev, port->original_macaddress); + } +-- +2.53.0 + diff --git a/queue-6.18/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch b/queue-6.18/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch new file mode 100644 index 0000000000..d63c36b7d6 --- /dev/null +++ b/queue-6.18/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch @@ -0,0 +1,48 @@ +From 3f0096f0602c1c090efc1205192a88afa6a9d039 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 22:32:30 +0800 +Subject: net: ipv6: fix dif and sdif mismatch in raw6_icmp_error + +From: Li RongQing + +[ Upstream commit 440e274da4d1b93c7df2cb0ce893c3009dd4db55 ] + +In raw6_icmp_error(), raw_v6_match() is called with inet6_iif(skb) passed +to both the 'dif' and 'sdif' arguments. This is a copy-paste or typo error, +as the last argument should represent the secondary interface index (sdif). + +This mismatch breaks ICMPv6 error handling for IPv6 raw sockets in VRF +(Virtual Routing and Forwarding) environments. When a raw socket is bound +to a VRF master device, raw_v6_match() fails to find a match because it is +not given the correct sdif value, causing the socket to miss relevant +ICMPv6 error notifications. + +Fix this by properly passing inet6_sdif(skb) as the last argument to +raw_v6_match(). + +Fixes: 5108ab4bf446fa ("net: ipv6: add second dif to raw socket lookups") +Signed-off-by: Li RongQing +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260717143230.1836-1-lirongqing@baidu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/raw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index c534848933ee64..6cb8e32a3061f2 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -348,7 +348,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data; + + if (!raw_v6_match(net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr, +- inet6_iif(skb), inet6_iif(skb))) ++ inet6_iif(skb), inet6_sdif(skb))) + continue; + rawv6_err(sk, skb, type, code, inner_offset, info); + } +-- +2.53.0 + diff --git a/queue-6.18/net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch b/queue-6.18/net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch new file mode 100644 index 0000000000..2b823b8cbc --- /dev/null +++ b/queue-6.18/net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch @@ -0,0 +1,68 @@ +From 88c8875d4ce326d029d986fa693ccdf505d65444 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 16:25:17 +0900 +Subject: net: mctp i3c: clean up notifier and buses if driver register fails + +From: Myeonghun Pak + +[ Upstream commit 03d1057305ef17ac3f5936ac1580bc9a1a826e14 ] + +mctp_i3c_mod_init() registers the I3C bus notifier and then walks the +existing buses with i3c_for_each_bus_locked(mctp_i3c_bus_add_new, NULL) +before registering the I3C device driver. If i3c_driver_register() +fails, the function returns the error directly, leaving the notifier +registered and every mctp_i3c_bus object created for the existing buses +allocated. The notifier is left pointing into the module that failed to +load and the bus list is leaked. + +Mirror the module exit path on this failure: unregister the notifier and +tear down the buses that were added before returning the error. + +This issue was identified during our ongoing static-analysis research while +reviewing kernel code. + +Fixes: c8755b29b58e ("mctp i3c: MCTP I3C driver") +Co-developed-by: Ijae Kim +Signed-off-by: Ijae Kim +Signed-off-by: Myeonghun Pak +Acked-by: Jeremy Kerr +Link: https://patch.msgid.link/20260715072517.13216-1-mhun512@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/mctp/mctp-i3c.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c +index c678f79aa35611..c5d0bc517fea99 100644 +--- a/drivers/net/mctp/mctp-i3c.c ++++ b/drivers/net/mctp/mctp-i3c.c +@@ -731,18 +731,21 @@ static __init int mctp_i3c_mod_init(void) + int rc; + + rc = i3c_register_notifier(&mctp_i3c_notifier); +- if (rc < 0) { +- i3c_driver_unregister(&mctp_i3c_driver); ++ if (rc < 0) + return rc; +- } + + i3c_for_each_bus_locked(mctp_i3c_bus_add_new, NULL); + + rc = i3c_driver_register(&mctp_i3c_driver); + if (rc < 0) +- return rc; ++ goto err_unregister_notifier; + + return 0; ++ ++err_unregister_notifier: ++ i3c_unregister_notifier(&mctp_i3c_notifier); ++ mctp_i3c_bus_remove_all(); ++ return rc; + } + + static __exit void mctp_i3c_mod_exit(void) +-- +2.53.0 + diff --git a/queue-6.18/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch b/queue-6.18/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch new file mode 100644 index 0000000000..1c67f60c5f --- /dev/null +++ b/queue-6.18/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch @@ -0,0 +1,51 @@ +From e4c95bb9498d732597e708bb0c3fd345fb051fcd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:33:06 +0300 +Subject: net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule + +From: Yael Chemla + +[ Upstream commit d12956d083eb70f2c6d72711aebaf8c2ce21e170 ] + +esw_egress_acl_vlan_create() hardcodes num_dest=0 in its +mlx5_add_flow_rules() call. When invoked from the non-bond path +fwd_dest is NULL and num_dest=0 is correct. When invoked from +esw_acl_egress_ofld_rules_create() during a bond event, fwd_dest is +non-NULL and flow_act.action carries MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, +but _mlx5_add_flow_rules() rejects a non-NULL dest pointer paired with +dest_num<=0 and returns -EINVAL. The error propagates as +"configure slave vport egress fwd, err(-22)". The passive vport's egress +ACL table ends up with its flow groups allocated but no FTEs, so +prio-tagged packets are not popped and bond failover is broken on +prio_tag_required devices. + +Fix by passing fwd_dest ? 1 : 0 as num_dest to match the actual number +of destinations supplied. + +Fixes: bf773dc0e6d5 ("net/mlx5: E-Switch, Introduce APIs to enable egress acl forward-to-vport rule") +Signed-off-by: Yael Chemla +Reviewed-by: Cosmin Ratiu +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20260717073306.1242399-1-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +index 3ce455c2535c40..53f064ebd1c181 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +@@ -71,7 +71,7 @@ int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw, + flow_act.action = flow_action; + vport->egress.allowed_vlan = + mlx5_add_flow_rules(vport->egress.acl, spec, +- &flow_act, fwd_dest, 0); ++ &flow_act, fwd_dest, fwd_dest ? 1 : 0); + if (IS_ERR(vport->egress.allowed_vlan)) { + err = PTR_ERR(vport->egress.allowed_vlan); + esw_warn(esw->dev, +-- +2.53.0 + diff --git a/queue-6.18/net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch b/queue-6.18/net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch new file mode 100644 index 0000000000..a0a241a3f8 --- /dev/null +++ b/queue-6.18/net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch @@ -0,0 +1,93 @@ +From ca776879b1a083b5a60a43154bd826fbf87dc0eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:23:38 +0300 +Subject: net/mlx5: Fix MCIA register buffer overflow on 32 dword reads + +From: Gal Pressman + +[ Upstream commit 11c057d23465c7a5817a7284c896d19d54c0b616 ] + +The MCIA register can return up to 32 dwords (128 bytes) when the device +advertises the mcia_32dwords capability, but struct +mlx5_ifc_mcia_reg_bits only defines dword_0..11, leaving room for just +12 dwords (48 bytes) of data. + +mlx5_query_mcia() clamps the read size to mlx5_mcia_max_bytes() and then +memcpy()s that many bytes out of the register, potentially reading past +the end of the 'out' buffer. On kernels built with FORTIFY_SOURCE this +is caught as a buffer overflow while reading the module EEPROM via +ethtool: + + detected buffer overflow in memcpy + kernel BUG at lib/string_helpers.c:1048! + RIP: 0010:fortify_panic+0x13/0x20 + Call Trace: + mlx5_query_mcia.isra.0+0x200/0x210 [mlx5_core] + mlx5_query_module_eeprom_by_page+0x4a/0xa0 [mlx5_core] + mlx5e_get_module_eeprom_by_page+0xbb/0x120 [mlx5_core] + eeprom_prepare_data+0xf3/0x170 + ethnl_default_doit+0xf1/0x3b0 + +Extend the mcia_reg layout to 32 dwords. + +Fixes: 271907ee2f29 ("net/mlx5: Query the maximum MCIA register read size from firmware") +Signed-off-by: Gal Pressman +Reviewed-by: Alex Lazar +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20260717072338.1240582-1-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/port.c | 4 ++-- + include/linux/mlx5/mlx5_ifc.h | 13 +------------ + 2 files changed, 3 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c +index 5fa06f69943dff..d25713ce65b6d8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c +@@ -314,7 +314,7 @@ static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num, + return -EIO; + } + +- ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); ++ ptr = MLX5_ADDR_OF(mcia_reg, out, dwords); + + *module_id = ptr[0]; + +@@ -397,7 +397,7 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev, + if (*status) + return -EIO; + +- ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); ++ ptr = MLX5_ADDR_OF(mcia_reg, out, dwords); + memcpy(data, ptr, size); + + return size; +diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h +index 1b0b36aa2a767a..61257b866fb24e 100644 +--- a/include/linux/mlx5/mlx5_ifc.h ++++ b/include/linux/mlx5/mlx5_ifc.h +@@ -12141,18 +12141,7 @@ struct mlx5_ifc_mcia_reg_bits { + + u8 reserved_at_60[0x20]; + +- u8 dword_0[0x20]; +- u8 dword_1[0x20]; +- u8 dword_2[0x20]; +- u8 dword_3[0x20]; +- u8 dword_4[0x20]; +- u8 dword_5[0x20]; +- u8 dword_6[0x20]; +- u8 dword_7[0x20]; +- u8 dword_8[0x20]; +- u8 dword_9[0x20]; +- u8 dword_10[0x20]; +- u8 dword_11[0x20]; ++ u8 dwords[0x400]; + }; + + struct mlx5_ifc_dcbx_param_bits { +-- +2.53.0 + diff --git a/queue-6.18/net-mlx5-refactor-eeprom-query-error-handling-to-ret.patch b/queue-6.18/net-mlx5-refactor-eeprom-query-error-handling-to-ret.patch new file mode 100644 index 0000000000..d9fec050e6 --- /dev/null +++ b/queue-6.18/net-mlx5-refactor-eeprom-query-error-handling-to-ret.patch @@ -0,0 +1,235 @@ +From e3e93de8d61d2688bb695b68f3e4d98ee2cf71da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 23:42:05 +0200 +Subject: net/mlx5: Refactor EEPROM query error handling to return status + separately + +From: Gal Pressman + +[ Upstream commit 2e4c44b12f4da60d3e8dcbc1ccf38bb28a878050 ] + +Matthew and Jakub reported [1] issues where inventory automation tools +are calling EEPROM query repeatedly on a port that doesn't have an SFP +connected, resulting in millions of error prints. + +Move MCIA register status extraction from the query functions to the +callers, allowing use of extack reporting instead of a dmesg print when +using the netlink API. + +[1] https://lore.kernel.org/netdev/20251028194011.39877-1-mattc@purestorage.com/ + +Cc: Matthew W Carlis +Signed-off-by: Gal Pressman +Reviewed-by: Jianbo Liu +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/1763415729-1238421-2-git-send-email-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 11c057d23465 ("net/mlx5: Fix MCIA register buffer overflow on 32 dword reads") +Signed-off-by: Sasha Levin +--- + .../ethernet/mellanox/mlx5/core/en_ethtool.c | 19 +++++----- + .../ethernet/mellanox/mlx5/core/mlx5_core.h | 4 +-- + .../net/ethernet/mellanox/mlx5/core/port.c | 35 +++++++++---------- + 3 files changed, 30 insertions(+), 28 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +index 893e1380a7c973..8a07b9e8dc3861 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +@@ -2027,7 +2027,7 @@ static int mlx5e_get_module_info(struct net_device *netdev, + int size_read = 0; + u8 data[4] = {0}; + +- size_read = mlx5_query_module_eeprom(dev, 0, 2, data); ++ size_read = mlx5_query_module_eeprom(dev, 0, 2, data, NULL); + if (size_read < 2) + return -EIO; + +@@ -2069,6 +2069,7 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + int offset = ee->offset; + int size_read; ++ u8 status = 0; + int i = 0; + + if (!ee->len) +@@ -2078,15 +2079,15 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev, + + while (i < ee->len) { + size_read = mlx5_query_module_eeprom(mdev, offset, ee->len - i, +- data + i); +- ++ data + i, &status); + if (!size_read) + /* Done reading */ + return 0; + + if (size_read < 0) { +- netdev_err(priv->netdev, "%s: mlx5_query_eeprom failed:0x%x\n", +- __func__, size_read); ++ netdev_err(netdev, ++ "%s: mlx5_query_eeprom failed:0x%x, status %u\n", ++ __func__, size_read, status); + return size_read; + } + +@@ -2106,6 +2107,7 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev, + struct mlx5_core_dev *mdev = priv->mdev; + u8 *data = page_data->data; + int size_read; ++ u8 status = 0; + int i = 0; + + if (!page_data->length) +@@ -2119,7 +2121,8 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev, + query.page = page_data->page; + while (i < page_data->length) { + query.size = page_data->length - i; +- size_read = mlx5_query_module_eeprom_by_page(mdev, &query, data + i); ++ size_read = mlx5_query_module_eeprom_by_page(mdev, &query, ++ data + i, &status); + + /* Done reading, return how many bytes was read */ + if (!size_read) +@@ -2128,8 +2131,8 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev, + if (size_read < 0) { + NL_SET_ERR_MSG_FMT_MOD( + extack, +- "Query module eeprom by page failed, read %u bytes, err %d", +- i, size_read); ++ "Query module eeprom by page failed, read %u bytes, err %d, status %u", ++ i, size_read, status); + return size_read; + } + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +index 09c544bdf70da9..e08903d002a10b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +@@ -358,11 +358,11 @@ int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable); + void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported, + bool *enabled); + int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, +- u16 offset, u16 size, u8 *data); ++ u16 offset, u16 size, u8 *data, u8 *status); + int + mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev, + struct mlx5_module_eeprom_query_params *params, +- u8 *data); ++ u8 *data, u8 *status); + + int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out); + int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c +index 876e648c91ba8b..5fa06f69943dff 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c +@@ -289,11 +289,11 @@ int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num) + } + + static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num, +- u8 *module_id) ++ u8 *module_id, u8 *status) + { + u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {}; + u32 out[MLX5_ST_SZ_DW(mcia_reg)]; +- int err, status; ++ int err; + u8 *ptr; + + MLX5_SET(mcia_reg, in, i2c_device_address, MLX5_I2C_ADDR_LOW); +@@ -308,12 +308,12 @@ static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num, + if (err) + return err; + +- status = MLX5_GET(mcia_reg, out, status); +- if (status) { +- mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n", +- status); ++ if (MLX5_GET(mcia_reg, out, status)) { ++ if (status) ++ *status = MLX5_GET(mcia_reg, out, status); + return -EIO; + } ++ + ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); + + *module_id = ptr[0]; +@@ -370,13 +370,14 @@ static int mlx5_mcia_max_bytes(struct mlx5_core_dev *dev) + } + + static int mlx5_query_mcia(struct mlx5_core_dev *dev, +- struct mlx5_module_eeprom_query_params *params, u8 *data) ++ struct mlx5_module_eeprom_query_params *params, ++ u8 *data, u8 *status) + { + u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {}; + u32 out[MLX5_ST_SZ_DW(mcia_reg)]; +- int status, err; + void *ptr; + u16 size; ++ int err; + + size = min_t(int, params->size, mlx5_mcia_max_bytes(dev)); + +@@ -392,12 +393,9 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev, + if (err) + return err; + +- status = MLX5_GET(mcia_reg, out, status); +- if (status) { +- mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n", +- status); ++ *status = MLX5_GET(mcia_reg, out, status); ++ if (*status) + return -EIO; +- } + + ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); + memcpy(data, ptr, size); +@@ -406,7 +404,7 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev, + } + + int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, +- u16 offset, u16 size, u8 *data) ++ u16 offset, u16 size, u8 *data, u8 *status) + { + struct mlx5_module_eeprom_query_params query = {0}; + u8 module_id; +@@ -416,7 +414,8 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, + if (err) + return err; + +- err = mlx5_query_module_id(dev, query.module_number, &module_id); ++ err = mlx5_query_module_id(dev, query.module_number, &module_id, ++ status); + if (err) + return err; + +@@ -442,12 +441,12 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev, + query.size = size; + query.offset = offset; + +- return mlx5_query_mcia(dev, &query, data); ++ return mlx5_query_mcia(dev, &query, data, status); + } + + int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev, + struct mlx5_module_eeprom_query_params *params, +- u8 *data) ++ u8 *data, u8 *status) + { + int err; + +@@ -461,7 +460,7 @@ int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev, + return -EINVAL; + } + +- return mlx5_query_mcia(dev, params, data); ++ return mlx5_query_mcia(dev, params, data, status); + } + + static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc, +-- +2.53.0 + diff --git a/queue-6.18/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch b/queue-6.18/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch new file mode 100644 index 0000000000..5eb38ddd3b --- /dev/null +++ b/queue-6.18/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch @@ -0,0 +1,46 @@ +From ede41831cd3920a09559c811545d1b7743f1d077 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:25 +0300 +Subject: net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation + +From: Alexei Lazar + +[ Upstream commit 9173e1d3c7c7d49a71eee813091f9e834ec7cee5 ] + +Credit Based (CB) TSA is not supported by the mlx5 driver, so reject +any configurations that specify it. + +Fixes: 08fb1dacdd76 ("net/mlx5e: Support DCBNL IEEE ETS") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-3-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index fbd84ab8d61e70..20db77552545e8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -309,6 +309,14 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev, + } + } + ++ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { ++ if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_CB_SHAPER) { ++ netdev_err(netdev, ++ "Failed to validate ETS: CB Shaper is not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ + /* Validate Bandwidth Sum */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { +-- +2.53.0 + diff --git a/queue-6.18/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch b/queue-6.18/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch new file mode 100644 index 0000000000..9ad87a7f6f --- /dev/null +++ b/queue-6.18/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch @@ -0,0 +1,53 @@ +From 2f4f4f4364227369f8e9d614cf7ea4749bf96f87 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:24 +0300 +Subject: net/mlx5e: Report zero bandwidth for non-ETS traffic classes + +From: Alexei Lazar + +[ Upstream commit ffb1873b2df11945b8c395e859169248675c91c5 ] + +The IEEE 802.1Qaz standard defines that bandwidth allocation percentages +only apply to Enhanced Transmission Selection (ETS) traffic classes. +For STRICT and VENDOR transmission selection algorithms, bandwidth +percentage values are not applicable. + +Currently for non-ETS 100 bandwidth is being reported for all traffic +classes in the get operation due to hardware limitation, regardless of +their TSA type. + +Fix this by reporting 0 for non-ETS traffic classes. + +Fixes: 820c2c5e773d ("net/mlx5e: Read ETS settings directly from firmware") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-2-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index cf8f14ce4cd50d..fbd84ab8d61e70 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -158,6 +158,13 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, + } + memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa)); + ++ /* Report 0 for non ETS TSA */ ++ for (i = 0; i < ets->ets_cap; i++) { ++ if (ets->tc_tx_bw[i] == MLX5E_MAX_BW_ALLOC && ++ priv->dcbx.tc_tsa[i] != IEEE_8021QAZ_TSA_ETS) ++ ets->tc_tx_bw[i] = 0; ++ } ++ + return err; + } + +-- +2.53.0 + diff --git a/queue-6.18/net-packet-avoid-fanout-hook-re-registration-after-u.patch b/queue-6.18/net-packet-avoid-fanout-hook-re-registration-after-u.patch new file mode 100644 index 0000000000..b3ccea31d4 --- /dev/null +++ b/queue-6.18/net-packet-avoid-fanout-hook-re-registration-after-u.patch @@ -0,0 +1,61 @@ +From c3c1f435942bb53002deba8b321ebeef8cff35c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:44:37 +0000 +Subject: net/packet: avoid fanout hook re-registration after unregister + +From: David Lee + +[ Upstream commit 50aff80475abd3533eef4320477037e6fcc6b56e ] + +packet_set_ring() temporarily detaches a socket from packet delivery while +reconfiguring its ring. It records the previous running state, clears +po->num, unregisters the protocol hook when needed, drops po->bind_lock, +and later restores po->num and re-registers the hook from the saved +was_running value. + +That unlocked window can race with NETDEV_UNREGISTER. The notifier can +observe the socket as not running, skip __unregister_prot_hook(), and +invalidate the per-socket binding by setting po->ifindex to -1 and clearing +po->prot_hook.dev. A one-member fanout group can still retain its shared +fanout hook device pointer. When packet_set_ring() resumes, re-registering +solely from the stale was_running state can re-add the fanout hook after +the device has been unregistered. + +Treat po->ifindex == -1 as an invalidated binding after reacquiring +po->bind_lock. This is distinct from ifindex 0, the normal +unbound/wildcard state: ifindex -1 marks an existing device binding that +was invalidated when the device was unregistered. Restore po->num as +before, but do not re-register the hook if device unregister already +detached the socket. + +Fixes: dc99f600698d ("packet: Add fanout support.") +Link: https://lore.kernel.org/netdev/20260701113947.23180-1-david.lee@trailofbits.com/ +Signed-off-by: David Lee +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260707104440.833129-1-david.lee@trailofbits.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 8b3961fba750b9..2989f1481aef45 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -4561,7 +4561,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + + spin_lock(&po->bind_lock); + WRITE_ONCE(po->num, num); +- if (was_running) ++ /* ++ * NETDEV_UNREGISTER may have invalidated the binding while bind_lock ++ * was dropped above. Do not re-add a fanout hook to a dead device. ++ */ ++ if (was_running && READ_ONCE(po->ifindex) != -1) + register_prot_hook(sk); + + spin_unlock(&po->bind_lock); +-- +2.53.0 + diff --git a/queue-6.18/net-phy-marvell-fix-return-code.patch b/queue-6.18/net-phy-marvell-fix-return-code.patch new file mode 100644 index 0000000000..5552689988 --- /dev/null +++ b/queue-6.18/net-phy-marvell-fix-return-code.patch @@ -0,0 +1,37 @@ +From 3b0fb6664aebae41b5c2debf74f71a522a4f903f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 14:06:27 +0200 +Subject: net: phy: marvell: fix return code + +From: Michael Walle + +[ Upstream commit 7d8ca62d6a9ef593780161586b4efc811ac094fe ] + +Return the correct error code, not the value written to the register. + +Fixes: a219912e0fec ("net: phy: marvell: implement config_inband() method") +Signed-off-by: Michael Walle +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260706120637.1947685-1-mwalle@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/marvell.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c +index c248c90510ae51..f191b8c4321887 100644 +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -753,7 +753,7 @@ static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes) + err = phy_modify(phydev, MII_M1111_PHY_EXT_SR, + MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr); + if (err < 0) +- return extsr; ++ return err; + + return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR, + BMCR_ANENABLE, bmcr); +-- +2.53.0 + diff --git a/queue-6.18/net-qrtr-restrict-socket-creation-to-the-initial-net.patch b/queue-6.18/net-qrtr-restrict-socket-creation-to-the-initial-net.patch new file mode 100644 index 0000000000..ed6f728d83 --- /dev/null +++ b/queue-6.18/net-qrtr-restrict-socket-creation-to-the-initial-net.patch @@ -0,0 +1,63 @@ +From c34ffd7123b45979399cc891ad1a33daa18b3fa3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 12:43:19 -0300 +Subject: net: qrtr: restrict socket creation to the initial network namespace + +From: Aldo Ariel Panzardo + +[ Upstream commit 3b536db8fb32da9e9c62f2bb45e2e319331f0426 ] + +QRTR keeps its entire port and node state in module-global variables +that are not partitioned per network namespace: qrtr_local_nid is a +single global node id (always 1) and qrtr_ports is a single global +xarray. qrtr_port_lookup() and qrtr_local_enqueue() operate on that +global state with no network-namespace check, and qrtr_create() places +no restriction on the namespace a socket is created in. + +As a result an unprivileged process that creates an AF_QIPCRTR socket +in a separate network namespace, e.g. via +unshare(CLONE_NEWUSER | CLONE_NEWNET), can send QRTR datagrams - +including control-plane messages such as QRTR_TYPE_NEW_SERVER - to QRTR +sockets owned by another namespace, and vice versa. The receiving +socket sees such a message as coming from node id 1, indistinguishable +from a legitimate local client, breaking the isolation that network +namespaces are expected to provide. + +QRTR is a transport to global hardware endpoints (the modem and other +remote processors) and has no per-namespace semantics; its in-kernel +name service already creates its socket in init_net only. Confine the +socket family to the initial network namespace, as other +non-namespace-aware socket families do (see llc_ui_create() and the +ieee802154 socket code). + +Fixes: bdabad3e363d ("net: Add Qualcomm IPC router") +Signed-off-by: Aldo Ariel Panzardo +Link: https://patch.msgid.link/20260716154319.3297699-1-qwe.aldo@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/qrtr/af_qrtr.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c +index 305523cebe3baa..fcd24a7df3f00d 100644 +--- a/net/qrtr/af_qrtr.c ++++ b/net/qrtr/af_qrtr.c +@@ -1261,6 +1261,14 @@ static int qrtr_create(struct net *net, struct socket *sock, + if (sock->type != SOCK_DGRAM) + return -EPROTOTYPE; + ++ /* QRTR keeps its port and node state in module-global variables that ++ * are not partitioned per network namespace, and the in-kernel name ++ * service only operates in init_net. Confine the family to init_net so ++ * a socket in another namespace cannot reach the global control plane. ++ */ ++ if (!net_eq(net, &init_net)) ++ return -EAFNOSUPPORT; ++ + sk = sk_alloc(net, AF_QIPCRTR, GFP_KERNEL, &qrtr_proto, kern); + if (!sk) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-6.18/net-stmmac-cores-remove-many-xxx_shift-definitions.patch b/queue-6.18/net-stmmac-cores-remove-many-xxx_shift-definitions.patch new file mode 100644 index 0000000000..952a7e87f8 --- /dev/null +++ b/queue-6.18/net-stmmac-cores-remove-many-xxx_shift-definitions.patch @@ -0,0 +1,1154 @@ +From 61e7a0e4a2738843c0b081b5b6e0c68d2e116cc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Jan 2026 17:36:40 +0000 +Subject: net: stmmac: cores: remove many xxx_SHIFT definitions + +From: Russell King (Oracle) + +[ Upstream commit 8409495bf6c907a5bc9632464dbdd8fb619f9ceb ] + +We have many xxx_SHIFT definitions along side their corresponding +xxx_MASK definitions for the various cores. Manually using the +shift and mask can be error prone, as shown with the dwmac4 RXFSTS +fix patch. + +Convert sites that use xxx_SHIFT and xxx_MASK directly to use +FIELD_GET(), FIELD_PREP(), and u32_replace_bits() as appropriate. + +Signed-off-by: Russell King (Oracle) +Link: https://patch.msgid.link/E1vdtw8-00000002Gtu-0Hyu@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Stable-dep-of: 9fcf274d93af ("net: stmmac: xgmac: fix l4 filter port overwrite on register update") +Signed-off-by: Sasha Levin +--- + .../ethernet/stmicro/stmmac/dwmac-loongson.c | 5 +- + .../ethernet/stmicro/stmmac/dwmac-socfpga.c | 5 +- + .../net/ethernet/stmicro/stmmac/dwmac100.h | 9 +-- + .../net/ethernet/stmicro/stmmac/dwmac1000.h | 16 +--- + .../ethernet/stmicro/stmmac/dwmac1000_core.c | 21 +++--- + .../ethernet/stmicro/stmmac/dwmac1000_dma.c | 16 ++-- + .../ethernet/stmicro/stmmac/dwmac100_core.c | 2 +- + .../ethernet/stmicro/stmmac/dwmac100_dma.c | 3 +- + drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 49 ++++-------- + .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 25 +++---- + .../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 40 +++++----- + .../net/ethernet/stmicro/stmmac/dwmac4_dma.h | 11 +-- + .../net/ethernet/stmicro/stmmac/dwmac4_lib.c | 2 +- + .../net/ethernet/stmicro/stmmac/dwmac_dma.h | 10 +-- + .../net/ethernet/stmicro/stmmac/dwmac_lib.c | 10 +-- + .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 31 ++------ + .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 21 +++--- + .../ethernet/stmicro/stmmac/dwxgmac2_dma.c | 75 ++++++++----------- + 18 files changed, 129 insertions(+), 222 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +index ab431bf9b25f29..e6bce3a433a789 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +@@ -209,9 +209,8 @@ static void loongson_dwmac_dma_init_channel(struct stmmac_priv *priv, + value |= DMA_BUS_MODE_MAXPBL; + + value |= DMA_BUS_MODE_USP; +- value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK); +- value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT); +- value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); ++ value = u32_replace_bits(value, txpbl, DMA_BUS_MODE_PBL_MASK); ++ value = u32_replace_bits(value, rxpbl, DMA_BUS_MODE_RPBL_MASK); + + /* Set the Fixed burst mode */ + if (dma_cfg->fixed_burst) +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +index d8c49083ada21c..e40d0d69630375 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +@@ -367,9 +367,8 @@ static int smtg_crosststamp(ktime_t *device, struct system_counterval_t *system, + .use_nsecs = false, + }; + +- num_snapshot = (readl(ioaddr + XGMAC_TIMESTAMP_STATUS) & +- XGMAC_TIMESTAMP_ATSNS_MASK) >> +- XGMAC_TIMESTAMP_ATSNS_SHIFT; ++ num_snapshot = FIELD_GET(XGMAC_TIMESTAMP_ATSNS_MASK, ++ readl(ioaddr + XGMAC_TIMESTAMP_STATUS)); + + /* Repeat until the timestamps are from the FIFO last segment */ + for (i = 0; i < num_snapshot; i++) { +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h +index 7ab791c8d355fb..eae929955ad780 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100.h ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100.h +@@ -59,8 +59,7 @@ + #define MAC_CORE_INIT (MAC_CONTROL_HBD) + + /* MAC FLOW CTRL defines */ +-#define MAC_FLOW_CTRL_PT_MASK 0xffff0000 /* Pause Time Mask */ +-#define MAC_FLOW_CTRL_PT_SHIFT 16 ++#define MAC_FLOW_CTRL_PT_MASK GENMASK(31, 16) /* Pause Time Mask */ + #define MAC_FLOW_CTRL_PASS 0x00000004 /* Pass Control Frames */ + #define MAC_FLOW_CTRL_ENABLE 0x00000002 /* Flow Control Enable */ + #define MAC_FLOW_CTRL_PAUSE 0x00000001 /* Flow Control Busy ... */ +@@ -76,10 +75,8 @@ + /* DMA Bus Mode register defines */ + #define DMA_BUS_MODE_DBO 0x00100000 /* Descriptor Byte Ordering */ + #define DMA_BUS_MODE_BLE 0x00000080 /* Big Endian/Little Endian */ +-#define DMA_BUS_MODE_PBL_MASK 0x00003f00 /* Programmable Burst Len */ +-#define DMA_BUS_MODE_PBL_SHIFT 8 +-#define DMA_BUS_MODE_DSL_MASK 0x0000007c /* Descriptor Skip Length */ +-#define DMA_BUS_MODE_DSL_SHIFT 2 /* (in DWORDS) */ ++#define DMA_BUS_MODE_PBL_MASK GENMASK(13, 8) /* Programmable Burst Len */ ++#define DMA_BUS_MODE_DSL_MASK GENMASK(6, 2) /* Descriptor Skip Length */ + #define DMA_BUS_MODE_BAR_BUS 0x00000002 /* Bar-Bus Arbitration */ + #define DMA_BUS_MODE_DEFAULT 0x00000000 + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +index 0c011a47d5a3e9..12c82235c1d7e8 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000.h +@@ -77,7 +77,6 @@ enum power_event { + /* SGMII/RGMII status register */ + #define GMAC_RGSMIIIS_LNKMODE BIT(0) + #define GMAC_RGSMIIIS_SPEED GENMASK(2, 1) +-#define GMAC_RGSMIIIS_SPEED_SHIFT 1 + #define GMAC_RGSMIIIS_LNKSTS BIT(3) + #define GMAC_RGSMIIIS_JABTO BIT(4) + #define GMAC_RGSMIIIS_FALSECARDET BIT(5) +@@ -134,8 +133,7 @@ enum inter_frame_gap { + #define GMAC_MII_ADDR_WRITE 0x00000002 /* MII Write */ + #define GMAC_MII_ADDR_BUSY 0x00000001 /* MII Busy */ + /* GMAC FLOW CTRL defines */ +-#define GMAC_FLOW_CTRL_PT_MASK 0xffff0000 /* Pause Time Mask */ +-#define GMAC_FLOW_CTRL_PT_SHIFT 16 ++#define GMAC_FLOW_CTRL_PT_MASK GENMASK(31, 16) /* Pause Time Mask */ + #define GMAC_FLOW_CTRL_UP 0x00000008 /* Unicast pause frame enable */ + #define GMAC_FLOW_CTRL_RFE 0x00000004 /* Rx Flow Control Enable */ + #define GMAC_FLOW_CTRL_TFE 0x00000002 /* Tx Flow Control Enable */ +@@ -148,7 +146,6 @@ enum inter_frame_gap { + #define GMAC_DEBUG_TWCSTS BIT(22) /* MTL Tx FIFO Write Controller */ + /* MTL Tx FIFO Read Controller Status */ + #define GMAC_DEBUG_TRCSTS_MASK GENMASK(21, 20) +-#define GMAC_DEBUG_TRCSTS_SHIFT 20 + #define GMAC_DEBUG_TRCSTS_IDLE 0 + #define GMAC_DEBUG_TRCSTS_READ 1 + #define GMAC_DEBUG_TRCSTS_TXW 2 +@@ -156,7 +153,6 @@ enum inter_frame_gap { + #define GMAC_DEBUG_TXPAUSED BIT(19) /* MAC Transmitter in PAUSE */ + /* MAC Transmit Frame Controller Status */ + #define GMAC_DEBUG_TFCSTS_MASK GENMASK(18, 17) +-#define GMAC_DEBUG_TFCSTS_SHIFT 17 + #define GMAC_DEBUG_TFCSTS_IDLE 0 + #define GMAC_DEBUG_TFCSTS_WAIT 1 + #define GMAC_DEBUG_TFCSTS_GEN_PAUSE 2 +@@ -164,13 +160,11 @@ enum inter_frame_gap { + /* MAC GMII or MII Transmit Protocol Engine Status */ + #define GMAC_DEBUG_TPESTS BIT(16) + #define GMAC_DEBUG_RXFSTS_MASK GENMASK(9, 8) /* MTL Rx FIFO Fill-level */ +-#define GMAC_DEBUG_RXFSTS_SHIFT 8 + #define GMAC_DEBUG_RXFSTS_EMPTY 0 + #define GMAC_DEBUG_RXFSTS_BT 1 + #define GMAC_DEBUG_RXFSTS_AT 2 + #define GMAC_DEBUG_RXFSTS_FULL 3 + #define GMAC_DEBUG_RRCSTS_MASK GENMASK(6, 5) /* MTL Rx FIFO Read Controller */ +-#define GMAC_DEBUG_RRCSTS_SHIFT 5 + #define GMAC_DEBUG_RRCSTS_IDLE 0 + #define GMAC_DEBUG_RRCSTS_RDATA 1 + #define GMAC_DEBUG_RRCSTS_RSTAT 2 +@@ -178,7 +172,6 @@ enum inter_frame_gap { + #define GMAC_DEBUG_RWCSTS BIT(4) /* MTL Rx FIFO Write Controller Active */ + /* MAC Receive Frame Controller FIFO Status */ + #define GMAC_DEBUG_RFCFCSTS_MASK GENMASK(2, 1) +-#define GMAC_DEBUG_RFCFCSTS_SHIFT 1 + /* MAC GMII or MII Receive Protocol Engine Status */ + #define GMAC_DEBUG_RPESTS BIT(0) + +@@ -188,8 +181,7 @@ enum inter_frame_gap { + #define DMA_BUS_MODE_DSL_MASK 0x0000007c /* Descriptor Skip Length */ + #define DMA_BUS_MODE_DSL_SHIFT 2 /* (in DWORDS) */ + /* Programmable burst length (passed thorugh platform)*/ +-#define DMA_BUS_MODE_PBL_MASK 0x00003f00 /* Programmable Burst Len */ +-#define DMA_BUS_MODE_PBL_SHIFT 8 ++#define DMA_BUS_MODE_PBL_MASK GENMASK(13, 8) /* Programmable Burst Len */ + #define DMA_BUS_MODE_ATDS 0x00000080 /* Alternate Descriptor Size */ + + enum rx_tx_priority_ratio { +@@ -200,8 +192,7 @@ enum rx_tx_priority_ratio { + + #define DMA_BUS_MODE_FB 0x00010000 /* Fixed burst */ + #define DMA_BUS_MODE_MB 0x04000000 /* Mixed burst */ +-#define DMA_BUS_MODE_RPBL_MASK 0x007e0000 /* Rx-Programmable Burst Len */ +-#define DMA_BUS_MODE_RPBL_SHIFT 17 ++#define DMA_BUS_MODE_RPBL_MASK GENMASK(22, 17) /* Rx-Programmable Burst Len */ + #define DMA_BUS_MODE_USP 0x00800000 + #define DMA_BUS_MODE_MAXPBL 0x01000000 + #define DMA_BUS_MODE_AAL 0x02000000 +@@ -321,7 +312,6 @@ enum rtc_control { + /* PTP and timestamping registers */ + + #define GMAC3_X_ATSNS GENMASK(29, 25) +-#define GMAC3_X_ATSNS_SHIFT 25 + + #define GMAC_PTP_TCR_ATSFC BIT(24) + #define GMAC_PTP_TCR_ATSEN0 BIT(25) +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +index 2c5ee59c320864..5bf717188c92df 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +@@ -240,7 +240,7 @@ static void dwmac1000_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, + + if (duplex) { + pr_debug("\tduplex mode: PAUSE %d\n", pause_time); +- flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT); ++ flow |= FIELD_PREP(GMAC_FLOW_CTRL_PT_MASK, pause_time); + } + + writel(flow, ioaddr + GMAC_FLOW_CTRL); +@@ -386,8 +386,8 @@ static void dwmac1000_debug(struct stmmac_priv *priv, void __iomem *ioaddr, + if (value & GMAC_DEBUG_TWCSTS) + x->mmtl_fifo_ctrl++; + if (value & GMAC_DEBUG_TRCSTS_MASK) { +- u32 trcsts = (value & GMAC_DEBUG_TRCSTS_MASK) +- >> GMAC_DEBUG_TRCSTS_SHIFT; ++ u32 trcsts = FIELD_GET(GMAC_DEBUG_TRCSTS_MASK, value); ++ + if (trcsts == GMAC_DEBUG_TRCSTS_WRITE) + x->mtl_tx_fifo_read_ctrl_write++; + else if (trcsts == GMAC_DEBUG_TRCSTS_TXW) +@@ -400,8 +400,7 @@ static void dwmac1000_debug(struct stmmac_priv *priv, void __iomem *ioaddr, + if (value & GMAC_DEBUG_TXPAUSED) + x->mac_tx_in_pause++; + if (value & GMAC_DEBUG_TFCSTS_MASK) { +- u32 tfcsts = (value & GMAC_DEBUG_TFCSTS_MASK) +- >> GMAC_DEBUG_TFCSTS_SHIFT; ++ u32 tfcsts = FIELD_GET(GMAC_DEBUG_TFCSTS_MASK, value); + + if (tfcsts == GMAC_DEBUG_TFCSTS_XFER) + x->mac_tx_frame_ctrl_xfer++; +@@ -415,8 +414,7 @@ static void dwmac1000_debug(struct stmmac_priv *priv, void __iomem *ioaddr, + if (value & GMAC_DEBUG_TPESTS) + x->mac_gmii_tx_proto_engine++; + if (value & GMAC_DEBUG_RXFSTS_MASK) { +- u32 rxfsts = (value & GMAC_DEBUG_RXFSTS_MASK) +- >> GMAC_DEBUG_RRCSTS_SHIFT; ++ u32 rxfsts = FIELD_GET(GMAC_DEBUG_RXFSTS_MASK, value); + + if (rxfsts == GMAC_DEBUG_RXFSTS_FULL) + x->mtl_rx_fifo_fill_level_full++; +@@ -428,8 +426,7 @@ static void dwmac1000_debug(struct stmmac_priv *priv, void __iomem *ioaddr, + x->mtl_rx_fifo_fill_level_empty++; + } + if (value & GMAC_DEBUG_RRCSTS_MASK) { +- u32 rrcsts = (value & GMAC_DEBUG_RRCSTS_MASK) >> +- GMAC_DEBUG_RRCSTS_SHIFT; ++ u32 rrcsts = FIELD_GET(GMAC_DEBUG_RRCSTS_MASK, value); + + if (rrcsts == GMAC_DEBUG_RRCSTS_FLUSH) + x->mtl_rx_fifo_read_ctrl_flush++; +@@ -443,8 +440,8 @@ static void dwmac1000_debug(struct stmmac_priv *priv, void __iomem *ioaddr, + if (value & GMAC_DEBUG_RWCSTS) + x->mtl_rx_fifo_ctrl_active++; + if (value & GMAC_DEBUG_RFCFCSTS_MASK) +- x->mac_rx_frame_ctrl_fifo = (value & GMAC_DEBUG_RFCFCSTS_MASK) +- >> GMAC_DEBUG_RFCFCSTS_SHIFT; ++ x->mac_rx_frame_ctrl_fifo = FIELD_GET(GMAC_DEBUG_RFCFCSTS_MASK, ++ value); + if (value & GMAC_DEBUG_RPESTS) + x->mac_gmii_rx_proto_engine++; + } +@@ -540,7 +537,7 @@ void dwmac1000_timestamp_interrupt(struct stmmac_priv *priv) + if (!(priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN)) + return; + +- num_snapshot = (ts_status & GMAC3_X_ATSNS) >> GMAC3_X_ATSNS_SHIFT; ++ num_snapshot = FIELD_GET(GMAC3_X_ATSNS, ts_status); + + for (i = 0; i < num_snapshot; i++) { + read_lock_irqsave(&priv->ptp_lock, flags); +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +index 118a22406a2e93..cacbf6d4365c71 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c +@@ -29,13 +29,10 @@ static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi) + if (axi->axi_xit_frm) + value |= DMA_AXI_LPI_XIT_FRM; + +- value &= ~DMA_AXI_WR_OSR_LMT; +- value |= (axi->axi_wr_osr_lmt & DMA_AXI_WR_OSR_LMT_MASK) << +- DMA_AXI_WR_OSR_LMT_SHIFT; +- +- value &= ~DMA_AXI_RD_OSR_LMT; +- value |= (axi->axi_rd_osr_lmt & DMA_AXI_RD_OSR_LMT_MASK) << +- DMA_AXI_RD_OSR_LMT_SHIFT; ++ value = u32_replace_bits(value, axi->axi_wr_osr_lmt, ++ DMA_AXI_WR_OSR_LMT); ++ value = u32_replace_bits(value, axi->axi_rd_osr_lmt, ++ DMA_AXI_RD_OSR_LMT); + + /* Depending on the UNDEF bit the Master AXI will perform any burst + * length according to the BLEN programmed (by default all BLEN are +@@ -88,9 +85,8 @@ static void dwmac1000_dma_init_channel(struct stmmac_priv *priv, + if (dma_cfg->pblx8) + value |= DMA_BUS_MODE_MAXPBL; + value |= DMA_BUS_MODE_USP; +- value &= ~(DMA_BUS_MODE_PBL_MASK | DMA_BUS_MODE_RPBL_MASK); +- value |= (txpbl << DMA_BUS_MODE_PBL_SHIFT); +- value |= (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); ++ value = u32_replace_bits(value, txpbl, DMA_BUS_MODE_PBL_MASK); ++ value = u32_replace_bits(value, rxpbl, DMA_BUS_MODE_RPBL_MASK); + + /* Set the Fixed burst mode */ + if (dma_cfg->fixed_burst) +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c +index 14e847c0e1a91d..dbc0c1019ed5e8 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c +@@ -132,7 +132,7 @@ static void dwmac100_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, + unsigned int flow = MAC_FLOW_CTRL_ENABLE; + + if (duplex) +- flow |= (pause_time << MAC_FLOW_CTRL_PT_SHIFT); ++ flow |= FIELD_PREP(MAC_FLOW_CTRL_PT_MASK, pause_time); + writel(flow, ioaddr + MAC_FLOW_CTRL); + } + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +index 82957db47c9911..12b2bf2d739ab9 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c +@@ -22,7 +22,8 @@ static void dwmac100_dma_init(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg) + { + /* Enable Application Access by writing to DMA CSR0 */ +- writel(DMA_BUS_MODE_DEFAULT | (dma_cfg->pbl << DMA_BUS_MODE_PBL_SHIFT), ++ writel(DMA_BUS_MODE_DEFAULT | ++ FIELD_PREP(DMA_BUS_MODE_PBL_MASK, dma_cfg->pbl), + ioaddr + DMA_BUS_MODE); + + /* Mask interrupts by writing to CSR7 */ +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h +index 3dec1a264cf609..7a6609185fd0c9 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h +@@ -95,7 +95,7 @@ + + /* MAC Flow Control TX */ + #define GMAC_TX_FLOW_CTRL_TFE BIT(1) +-#define GMAC_TX_FLOW_CTRL_PT_SHIFT 16 ++#define GMAC_TX_FLOW_CTRL_PT_MASK GENMASK(31, 16) + + /* MAC Interrupt bitmap*/ + #define GMAC_INT_RGSMIIS BIT(0) +@@ -145,23 +145,19 @@ enum power_event { + + /* MAC Debug bitmap */ + #define GMAC_DEBUG_TFCSTS_MASK GENMASK(18, 17) +-#define GMAC_DEBUG_TFCSTS_SHIFT 17 + #define GMAC_DEBUG_TFCSTS_IDLE 0 + #define GMAC_DEBUG_TFCSTS_WAIT 1 + #define GMAC_DEBUG_TFCSTS_GEN_PAUSE 2 + #define GMAC_DEBUG_TFCSTS_XFER 3 + #define GMAC_DEBUG_TPESTS BIT(16) + #define GMAC_DEBUG_RFCFCSTS_MASK GENMASK(2, 1) +-#define GMAC_DEBUG_RFCFCSTS_SHIFT 1 + #define GMAC_DEBUG_RPESTS BIT(0) + + /* MAC config */ + #define GMAC_CONFIG_ARPEN BIT(31) + #define GMAC_CONFIG_SARC GENMASK(30, 28) +-#define GMAC_CONFIG_SARC_SHIFT 28 + #define GMAC_CONFIG_IPC BIT(27) + #define GMAC_CONFIG_IPG GENMASK(26, 24) +-#define GMAC_CONFIG_IPG_SHIFT 24 + #define GMAC_CONFIG_2K BIT(22) + #define GMAC_CONFIG_ACS BIT(20) + #define GMAC_CONFIG_BE BIT(18) +@@ -169,7 +165,6 @@ enum power_event { + #define GMAC_CONFIG_JE BIT(16) + #define GMAC_CONFIG_PS BIT(15) + #define GMAC_CONFIG_FES BIT(14) +-#define GMAC_CONFIG_FES_SHIFT 14 + #define GMAC_CONFIG_DM BIT(13) + #define GMAC_CONFIG_LM BIT(12) + #define GMAC_CONFIG_DCRS BIT(9) +@@ -178,11 +173,9 @@ enum power_event { + + /* MAC extended config */ + #define GMAC_CONFIG_EIPG GENMASK(29, 25) +-#define GMAC_CONFIG_EIPG_SHIFT 25 + #define GMAC_CONFIG_EIPG_EN BIT(24) + #define GMAC_CONFIG_HDSMS GENMASK(22, 20) +-#define GMAC_CONFIG_HDSMS_SHIFT 20 +-#define GMAC_CONFIG_HDSMS_256 (0x2 << GMAC_CONFIG_HDSMS_SHIFT) ++#define GMAC_CONFIG_HDSMS_256 FIELD_PREP_CONST(GMAC_CONFIG_HDSMS, 0x2) + + /* MAC HW features0 bitmap */ + #define GMAC_HW_FEAT_SAVLANINS BIT(27) +@@ -245,7 +238,6 @@ enum power_event { + + /* MAC HW ADDR regs */ + #define GMAC_HI_DCS GENMASK(18, 16) +-#define GMAC_HI_DCS_SHIFT 16 + #define GMAC_HI_REG_AE BIT(31) + + /* L3/L4 Filters regs */ +@@ -260,7 +252,6 @@ enum power_event { + #define GMAC_L3SAM0 BIT(2) + #define GMAC_L3PEN0 BIT(0) + #define GMAC_L4DP0 GENMASK(31, 16) +-#define GMAC_L4DP0_SHIFT 16 + #define GMAC_L4SP0 GENMASK(15, 0) + + /* MAC Timestamp Status */ +@@ -317,39 +308,32 @@ static inline u32 mtl_chanx_base_addr(const struct dwmac4_addrs *addrs, + #define MTL_OP_MODE_TSF BIT(1) + + #define MTL_OP_MODE_TQS_MASK GENMASK(24, 16) +-#define MTL_OP_MODE_TQS_SHIFT 16 + +-#define MTL_OP_MODE_TTC_MASK 0x70 +-#define MTL_OP_MODE_TTC_SHIFT 4 +- +-#define MTL_OP_MODE_TTC_32 0 +-#define MTL_OP_MODE_TTC_64 (1 << MTL_OP_MODE_TTC_SHIFT) +-#define MTL_OP_MODE_TTC_96 (2 << MTL_OP_MODE_TTC_SHIFT) +-#define MTL_OP_MODE_TTC_128 (3 << MTL_OP_MODE_TTC_SHIFT) +-#define MTL_OP_MODE_TTC_192 (4 << MTL_OP_MODE_TTC_SHIFT) +-#define MTL_OP_MODE_TTC_256 (5 << MTL_OP_MODE_TTC_SHIFT) +-#define MTL_OP_MODE_TTC_384 (6 << MTL_OP_MODE_TTC_SHIFT) +-#define MTL_OP_MODE_TTC_512 (7 << MTL_OP_MODE_TTC_SHIFT) ++#define MTL_OP_MODE_TTC_MASK GENMASK(6, 4) ++#define MTL_OP_MODE_TTC_32 FIELD_PREP(MTL_OP_MODE_TTC_MASK, 0) ++#define MTL_OP_MODE_TTC_64 FIELD_PREP(MTL_OP_MODE_TTC_MASK, 1) ++#define MTL_OP_MODE_TTC_96 FIELD_PREP(MTL_OP_MODE_TTC_MASK, 2) ++#define MTL_OP_MODE_TTC_128 FIELD_PREP(MTL_OP_MODE_TTC_MASK, 3) ++#define MTL_OP_MODE_TTC_192 FIELD_PREP(MTL_OP_MODE_TTC_MASK, 4) ++#define MTL_OP_MODE_TTC_256 FIELD_PREP(MTL_OP_MODE_TTC_MASK, 5) ++#define MTL_OP_MODE_TTC_384 FIELD_PREP(MTL_OP_MODE_TTC_MASK, 6) ++#define MTL_OP_MODE_TTC_512 FIELD_PREP(MTL_OP_MODE_TTC_MASK, 7) + + #define MTL_OP_MODE_RQS_MASK GENMASK(29, 20) +-#define MTL_OP_MODE_RQS_SHIFT 20 + + #define MTL_OP_MODE_RFD_MASK GENMASK(19, 14) +-#define MTL_OP_MODE_RFD_SHIFT 14 + + #define MTL_OP_MODE_RFA_MASK GENMASK(13, 8) +-#define MTL_OP_MODE_RFA_SHIFT 8 + + #define MTL_OP_MODE_EHFC BIT(7) + #define MTL_OP_MODE_DIS_TCP_EF BIT(6) + + #define MTL_OP_MODE_RTC_MASK GENMASK(1, 0) +-#define MTL_OP_MODE_RTC_SHIFT 0 + +-#define MTL_OP_MODE_RTC_32 (1 << MTL_OP_MODE_RTC_SHIFT) +-#define MTL_OP_MODE_RTC_64 0 +-#define MTL_OP_MODE_RTC_96 (2 << MTL_OP_MODE_RTC_SHIFT) +-#define MTL_OP_MODE_RTC_128 (3 << MTL_OP_MODE_RTC_SHIFT) ++#define MTL_OP_MODE_RTC_32 FIELD_PREP(MTL_OP_MODE_RTC_MASK, 1) ++#define MTL_OP_MODE_RTC_64 FIELD_PREP(MTL_OP_MODE_RTC_MASK, 0) ++#define MTL_OP_MODE_RTC_96 FIELD_PREP(MTL_OP_MODE_RTC_MASK, 2) ++#define MTL_OP_MODE_RTC_128 FIELD_PREP(MTL_OP_MODE_RTC_MASK, 3) + + /* MTL ETS Control register */ + #define MTL_ETS_CTRL_BASE_ADDR 0x00000d10 +@@ -454,7 +438,6 @@ static inline u32 mtl_low_credx_base_addr(const struct dwmac4_addrs *addrs, + + /* MTL debug: Tx FIFO Read Controller Status */ + #define MTL_DEBUG_TRCSTS_MASK GENMASK(2, 1) +-#define MTL_DEBUG_TRCSTS_SHIFT 1 + #define MTL_DEBUG_TRCSTS_IDLE 0 + #define MTL_DEBUG_TRCSTS_READ 1 + #define MTL_DEBUG_TRCSTS_TXW 2 +@@ -469,7 +452,6 @@ static inline u32 mtl_low_credx_base_addr(const struct dwmac4_addrs *addrs, + #define MTL_DEBUG_RXFSTS_AT 2 + #define MTL_DEBUG_RXFSTS_FULL 3 + #define MTL_DEBUG_RRCSTS_MASK GENMASK(2, 1) +-#define MTL_DEBUG_RRCSTS_SHIFT 1 + #define MTL_DEBUG_RRCSTS_IDLE 0 + #define MTL_DEBUG_RRCSTS_RDATA 1 + #define MTL_DEBUG_RRCSTS_RSTAT 2 +@@ -523,7 +505,6 @@ static inline u32 mtl_low_credx_base_addr(const struct dwmac4_addrs *addrs, + #define GMAC_PHYIF_CTRLSTATUS_SMIDRXS BIT(4) + #define GMAC_PHYIF_CTRLSTATUS_LNKMOD BIT(16) + #define GMAC_PHYIF_CTRLSTATUS_SPEED GENMASK(18, 17) +-#define GMAC_PHYIF_CTRLSTATUS_SPEED_SHIFT 17 + #define GMAC_PHYIF_CTRLSTATUS_LNKSTS BIT(19) + #define GMAC_PHYIF_CTRLSTATUS_JABTO BIT(20) + #define GMAC_PHYIF_CTRLSTATUS_FALSECARDET BIT(21) +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +index 8a19df7b05775d..1f61177ece453c 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +@@ -572,8 +572,8 @@ static void dwmac4_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, + flow = GMAC_TX_FLOW_CTRL_TFE; + + if (duplex) +- flow |= +- (pause_time << GMAC_TX_FLOW_CTRL_PT_SHIFT); ++ flow |= FIELD_PREP(GMAC_TX_FLOW_CTRL_PT_MASK, ++ pause_time); + + writel(flow, ioaddr + GMAC_QX_TX_FLOW_CTRL(queue)); + } +@@ -691,8 +691,8 @@ static void dwmac4_debug(struct stmmac_priv *priv, void __iomem *ioaddr, + if (value & MTL_DEBUG_TWCSTS) + x->mmtl_fifo_ctrl++; + if (value & MTL_DEBUG_TRCSTS_MASK) { +- u32 trcsts = (value & MTL_DEBUG_TRCSTS_MASK) +- >> MTL_DEBUG_TRCSTS_SHIFT; ++ u32 trcsts = FIELD_GET(MTL_DEBUG_TRCSTS_MASK, value); ++ + if (trcsts == MTL_DEBUG_TRCSTS_WRITE) + x->mtl_tx_fifo_read_ctrl_write++; + else if (trcsts == MTL_DEBUG_TRCSTS_TXW) +@@ -723,8 +723,7 @@ static void dwmac4_debug(struct stmmac_priv *priv, void __iomem *ioaddr, + x->mtl_rx_fifo_fill_level_empty++; + } + if (value & MTL_DEBUG_RRCSTS_MASK) { +- u32 rrcsts = (value & MTL_DEBUG_RRCSTS_MASK) >> +- MTL_DEBUG_RRCSTS_SHIFT; ++ u32 rrcsts = FIELD_GET(MTL_DEBUG_RRCSTS_MASK, value); + + if (rrcsts == MTL_DEBUG_RRCSTS_FLUSH) + x->mtl_rx_fifo_read_ctrl_flush++; +@@ -743,8 +742,7 @@ static void dwmac4_debug(struct stmmac_priv *priv, void __iomem *ioaddr, + value = readl(ioaddr + GMAC_DEBUG); + + if (value & GMAC_DEBUG_TFCSTS_MASK) { +- u32 tfcsts = (value & GMAC_DEBUG_TFCSTS_MASK) +- >> GMAC_DEBUG_TFCSTS_SHIFT; ++ u32 tfcsts = FIELD_GET(GMAC_DEBUG_TFCSTS_MASK, value); + + if (tfcsts == GMAC_DEBUG_TFCSTS_XFER) + x->mac_tx_frame_ctrl_xfer++; +@@ -758,8 +756,8 @@ static void dwmac4_debug(struct stmmac_priv *priv, void __iomem *ioaddr, + if (value & GMAC_DEBUG_TPESTS) + x->mac_gmii_tx_proto_engine++; + if (value & GMAC_DEBUG_RFCFCSTS_MASK) +- x->mac_rx_frame_ctrl_fifo = (value & GMAC_DEBUG_RFCFCSTS_MASK) +- >> GMAC_DEBUG_RFCFCSTS_SHIFT; ++ x->mac_rx_frame_ctrl_fifo = FIELD_GET(GMAC_DEBUG_RFCFCSTS_MASK, ++ value); + if (value & GMAC_DEBUG_RPESTS) + x->mac_gmii_rx_proto_engine++; + } +@@ -780,8 +778,7 @@ static void dwmac4_sarc_configure(void __iomem *ioaddr, int val) + { + u32 value = readl(ioaddr + GMAC_CONFIG); + +- value &= ~GMAC_CONFIG_SARC; +- value |= val << GMAC_CONFIG_SARC_SHIFT; ++ value = u32_replace_bits(value, val, GMAC_CONFIG_SARC); + + writel(value, ioaddr + GMAC_CONFIG); + } +@@ -889,9 +886,9 @@ static int dwmac4_config_l4_filter(struct mac_device_info *hw, u32 filter_no, + writel(value, ioaddr + GMAC_L3L4_CTRL(filter_no)); + + if (sa) { +- value = match & GMAC_L4SP0; ++ value = FIELD_PREP(GMAC_L4SP0, match); + } else { +- value = (match << GMAC_L4DP0_SHIFT) & GMAC_L4DP0; ++ value = FIELD_PREP(GMAC_L4DP0, match); + } + + writel(value, ioaddr + GMAC_L4_ADDR(filter_no)); +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +index d87a8b595e6a3b..d17bcc31a89c96 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +@@ -28,13 +28,10 @@ static void dwmac4_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi) + if (axi->axi_xit_frm) + value |= DMA_AXI_LPI_XIT_FRM; + +- value &= ~DMA_AXI_WR_OSR_LMT; +- value |= (axi->axi_wr_osr_lmt & DMA_AXI_OSR_MAX) << +- DMA_AXI_WR_OSR_LMT_SHIFT; +- +- value &= ~DMA_AXI_RD_OSR_LMT; +- value |= (axi->axi_rd_osr_lmt & DMA_AXI_OSR_MAX) << +- DMA_AXI_RD_OSR_LMT_SHIFT; ++ value = u32_replace_bits(value, axi->axi_wr_osr_lmt, ++ DMA_AXI_WR_OSR_LMT); ++ value = u32_replace_bits(value, axi->axi_rd_osr_lmt, ++ DMA_AXI_RD_OSR_LMT); + + /* Depending on the UNDEF bit the Master AXI will perform any burst + * length according to the BLEN programmed (by default all BLEN are +@@ -79,7 +76,7 @@ static void dwmac4_dma_init_rx_chan(struct stmmac_priv *priv, + u32 rxpbl = dma_cfg->rxpbl ?: dma_cfg->pbl; + + value = readl(ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan)); +- value = value | (rxpbl << DMA_BUS_MODE_RPBL_SHIFT); ++ value = value | FIELD_PREP(DMA_BUS_MODE_RPBL_MASK, rxpbl); + writel(value, ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan)); + + if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && likely(dma_cfg->eame)) +@@ -100,7 +97,7 @@ static void dwmac4_dma_init_tx_chan(struct stmmac_priv *priv, + u32 txpbl = dma_cfg->txpbl ?: dma_cfg->pbl; + + value = readl(ioaddr + DMA_CHAN_TX_CONTROL(dwmac4_addrs, chan)); +- value = value | (txpbl << DMA_BUS_MODE_PBL_SHIFT); ++ value = value | FIELD_PREP(DMA_BUS_MODE_PBL, txpbl); + + /* Enable OSP to get best performance */ + value |= DMA_CONTROL_OSP; +@@ -175,10 +172,9 @@ static void dwmac4_dma_init(void __iomem *ioaddr, + + value = readl(ioaddr + DMA_BUS_MODE); + +- if (dma_cfg->multi_msi_en) { +- value &= ~DMA_BUS_MODE_INTM_MASK; +- value |= (DMA_BUS_MODE_INTM_MODE1 << DMA_BUS_MODE_INTM_SHIFT); +- } ++ if (dma_cfg->multi_msi_en) ++ value = u32_replace_bits(value, DMA_BUS_MODE_INTM_MODE1, ++ DMA_BUS_MODE_INTM_MASK); + + if (dma_cfg->dche) + value |= DMA_BUS_MODE_DCHE; +@@ -288,7 +284,7 @@ static void dwmac4_dma_rx_chan_op_mode(struct stmmac_priv *priv, + } + + mtl_rx_op &= ~MTL_OP_MODE_RQS_MASK; +- mtl_rx_op |= rqs << MTL_OP_MODE_RQS_SHIFT; ++ mtl_rx_op |= FIELD_PREP(MTL_OP_MODE_RQS_MASK, rqs); + + /* Enable flow control only if each channel gets 4 KiB or more FIFO and + * only if channel is not an AVB channel. +@@ -319,11 +315,10 @@ static void dwmac4_dma_rx_chan_op_mode(struct stmmac_priv *priv, + break; + } + +- mtl_rx_op &= ~MTL_OP_MODE_RFD_MASK; +- mtl_rx_op |= rfd << MTL_OP_MODE_RFD_SHIFT; +- +- mtl_rx_op &= ~MTL_OP_MODE_RFA_MASK; +- mtl_rx_op |= rfa << MTL_OP_MODE_RFA_SHIFT; ++ mtl_rx_op = u32_replace_bits(mtl_rx_op, rfd, ++ MTL_OP_MODE_RFD_MASK); ++ mtl_rx_op = u32_replace_bits(mtl_rx_op, rfa, ++ MTL_OP_MODE_RFA_MASK); + } + + writel(mtl_rx_op, ioaddr + MTL_CHAN_RX_OP_MODE(dwmac4_addrs, channel)); +@@ -378,8 +373,8 @@ static void dwmac4_dma_tx_chan_op_mode(struct stmmac_priv *priv, + mtl_tx_op |= MTL_OP_MODE_TXQEN; + else + mtl_tx_op |= MTL_OP_MODE_TXQEN_AV; +- mtl_tx_op &= ~MTL_OP_MODE_TQS_MASK; +- mtl_tx_op |= tqs << MTL_OP_MODE_TQS_SHIFT; ++ ++ mtl_tx_op = u32_replace_bits(mtl_tx_op, tqs, MTL_OP_MODE_TQS_MASK); + + writel(mtl_tx_op, ioaddr + MTL_CHAN_TX_OP_MODE(dwmac4_addrs, channel)); + } +@@ -520,8 +515,7 @@ static void dwmac4_set_bfsize(struct stmmac_priv *priv, void __iomem *ioaddr, + const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; + u32 value = readl(ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan)); + +- value &= ~DMA_RBSZ_MASK; +- value |= (bfsize << DMA_RBSZ_SHIFT) & DMA_RBSZ_MASK; ++ value = u32_replace_bits(value, bfsize, DMA_RBSZ_MASK); + + writel(value, ioaddr + DMA_CHAN_RX_CONTROL(dwmac4_addrs, chan)); + } +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h +index 4f980dcd395823..7573ca2db352da 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h +@@ -27,15 +27,13 @@ + /* DMA Bus Mode bitmap */ + #define DMA_BUS_MODE_DCHE BIT(19) + #define DMA_BUS_MODE_INTM_MASK GENMASK(17, 16) +-#define DMA_BUS_MODE_INTM_SHIFT 16 + #define DMA_BUS_MODE_INTM_MODE1 0x1 + #define DMA_BUS_MODE_SFT_RESET BIT(0) + + /* DMA SYS Bus Mode bitmap */ + #define DMA_BUS_MODE_SPH BIT(24) + #define DMA_BUS_MODE_PBL BIT(16) +-#define DMA_BUS_MODE_PBL_SHIFT 16 +-#define DMA_BUS_MODE_RPBL_SHIFT 16 ++#define DMA_BUS_MODE_RPBL_MASK GENMASK(21, 16) + #define DMA_BUS_MODE_MB BIT(14) + #define DMA_BUS_MODE_FB BIT(0) + +@@ -59,13 +57,7 @@ + #define DMA_AXI_EN_LPI BIT(31) + #define DMA_AXI_LPI_XIT_FRM BIT(30) + #define DMA_AXI_WR_OSR_LMT GENMASK(27, 24) +-#define DMA_AXI_WR_OSR_LMT_SHIFT 24 + #define DMA_AXI_RD_OSR_LMT GENMASK(19, 16) +-#define DMA_AXI_RD_OSR_LMT_SHIFT 16 +- +-#define DMA_AXI_OSR_MAX 0xf +-#define DMA_AXI_MAX_OSR_LIMIT ((DMA_AXI_OSR_MAX << DMA_AXI_WR_OSR_LMT_SHIFT) | \ +- (DMA_AXI_OSR_MAX << DMA_AXI_RD_OSR_LMT_SHIFT)) + + #define DMA_SYS_BUS_MB BIT(14) + #define DMA_AXI_1KBBE BIT(13) +@@ -146,7 +138,6 @@ static inline u32 dma_chanx_base_addr(const struct dwmac4_addrs *addrs, + /* DMA Rx Channel X Control register defines */ + #define DMA_CONTROL_SR BIT(0) + #define DMA_RBSZ_MASK GENMASK(14, 1) +-#define DMA_RBSZ_SHIFT 1 + + /* Interrupt status per channel */ + #define DMA_CHAN_STATUS_REB GENMASK(21, 19) +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +index 57c03d49177447..c098047a3bff8a 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c +@@ -234,7 +234,7 @@ void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6], + * bit that has no effect on the High Reg 0 where the bit 31 (MO) + * is RO. + */ +- data |= (STMMAC_CHAN0 << GMAC_HI_DCS_SHIFT); ++ data |= FIELD_PREP(GMAC_HI_DCS, STMMAC_CHAN0); + writel(data | GMAC_HI_REG_AE, ioaddr + high); + data = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; + writel(data, ioaddr + low); +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +index 5d9c18f5bbf587..14cfe0de3327ae 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h +@@ -59,11 +59,7 @@ static inline u32 dma_chan_base_addr(u32 base, u32 chan) + #define DMA_AXI_EN_LPI BIT(31) + #define DMA_AXI_LPI_XIT_FRM BIT(30) + #define DMA_AXI_WR_OSR_LMT GENMASK(23, 20) +-#define DMA_AXI_WR_OSR_LMT_SHIFT 20 +-#define DMA_AXI_WR_OSR_LMT_MASK 0xf + #define DMA_AXI_RD_OSR_LMT GENMASK(19, 16) +-#define DMA_AXI_RD_OSR_LMT_SHIFT 16 +-#define DMA_AXI_RD_OSR_LMT_MASK 0xf + + #define DMA_AXI_OSR_MAX 0xf + #define DMA_AXI_MAX_OSR_LIMIT ((DMA_AXI_OSR_MAX << DMA_AXI_WR_OSR_LMT_SHIFT) | \ +@@ -132,10 +128,8 @@ static inline u32 dma_chan_base_addr(u32 base, u32 chan) + #define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */ + #define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */ + #define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */ +-#define DMA_STATUS_TS_MASK 0x00700000 /* Transmit Process State */ +-#define DMA_STATUS_TS_SHIFT 20 +-#define DMA_STATUS_RS_MASK 0x000e0000 /* Receive Process State */ +-#define DMA_STATUS_RS_SHIFT 17 ++#define DMA_STATUS_TS_MASK GENMASK(22, 20) /* Transmit Process State */ ++#define DMA_STATUS_RS_MASK GENMASK(19, 17) /* Receive Process State */ + #define DMA_STATUS_NIS 0x00010000 /* Normal Interrupt Summary */ + #define DMA_STATUS_AIS 0x00008000 /* Abnormal Interrupt Summary */ + #define DMA_STATUS_ERI 0x00004000 /* Early Receive Interrupt */ +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +index 467f1a05747ecf..2e979f07566500 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +@@ -92,10 +92,7 @@ void dwmac_dma_stop_rx(struct stmmac_priv *priv, void __iomem *ioaddr, u32 chan) + #ifdef DWMAC_DMA_DEBUG + static void show_tx_process_state(unsigned int status) + { +- unsigned int state; +- state = (status & DMA_STATUS_TS_MASK) >> DMA_STATUS_TS_SHIFT; +- +- switch (state) { ++ switch (FIELD_GET(DMA_STATUS_TS_MASK, status)) { + case 0: + pr_debug("- TX (Stopped): Reset or Stop command\n"); + break; +@@ -123,10 +120,7 @@ static void show_tx_process_state(unsigned int status) + + static void show_rx_process_state(unsigned int status) + { +- unsigned int state; +- state = (status & DMA_STATUS_RS_MASK) >> DMA_STATUS_RS_SHIFT; +- +- switch (state) { ++ switch (FIELD_GET(DMA_STATUS_RS_MASK, status)) { + case 0: + pr_debug("- RX (Stopped): Reset or Stop command\n"); + break; +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +index e48cfa05000c07..67e2d539c33853 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +@@ -24,17 +24,15 @@ + #define XGMAC_CONFIG_SS_2500 (0x6 << XGMAC_CONFIG_SS_OFF) + #define XGMAC_CONFIG_SS_10_MII (0x7 << XGMAC_CONFIG_SS_OFF) + #define XGMAC_CONFIG_SARC GENMASK(22, 20) +-#define XGMAC_CONFIG_SARC_SHIFT 20 + #define XGMAC_CONFIG_JD BIT(16) + #define XGMAC_CONFIG_TE BIT(0) + #define XGMAC_CORE_INIT_TX (XGMAC_CONFIG_JD) + #define XGMAC_RX_CONFIG 0x00000004 + #define XGMAC_CONFIG_ARPEN BIT(31) + #define XGMAC_CONFIG_GPSL GENMASK(29, 16) +-#define XGMAC_CONFIG_GPSL_SHIFT 16 + #define XGMAC_CONFIG_HDSMS GENMASK(14, 12) + #define XGMAC_CONFIG_HDSMS_SHIFT 12 +-#define XGMAC_CONFIG_HDSMS_256 (0x2 << XGMAC_CONFIG_HDSMS_SHIFT) ++#define XGMAC_CONFIG_HDSMS_256 FIELD_PREP(XGMAC_CONFIG_HDSMS, 0x2) + #define XGMAC_CONFIG_S2KP BIT(11) + #define XGMAC_CONFIG_LM BIT(10) + #define XGMAC_CONFIG_IPC BIT(9) +@@ -44,8 +42,10 @@ + #define XGMAC_CONFIG_CST BIT(2) + #define XGMAC_CONFIG_ACS BIT(1) + #define XGMAC_CONFIG_RE BIT(0) +-#define XGMAC_CORE_INIT_RX (XGMAC_CONFIG_GPSLCE | XGMAC_CONFIG_WD | \ +- (XGMAC_JUMBO_LEN << XGMAC_CONFIG_GPSL_SHIFT)) ++#define XGMAC_CORE_INIT_RX (XGMAC_CONFIG_GPSLCE | \ ++ XGMAC_CONFIG_WD | \ ++ FIELD_PREP(XGMAC_CONFIG_GPSL, \ ++ XGMAC_JUMBO_LEN)) + #define XGMAC_PACKET_FILTER 0x00000008 + #define XGMAC_FILTER_RA BIT(31) + #define XGMAC_FILTER_IPFE BIT(20) +@@ -90,7 +90,6 @@ + #define XGMAC_INT_DEFAULT_EN (XGMAC_LPIIE | XGMAC_PMTIE) + #define XGMAC_Qx_TX_FLOW_CTRL(x) (0x00000070 + (x) * 4) + #define XGMAC_PT GENMASK(31, 16) +-#define XGMAC_PT_SHIFT 16 + #define XGMAC_TFE BIT(1) + #define XGMAC_RX_FLOW_CTRL 0x00000090 + #define XGMAC_RFE BIT(0) +@@ -180,12 +179,11 @@ + #define XGMAC_ADDR_MAX 32 + #define XGMAC_AE BIT(31) + #define XGMAC_DCS GENMASK(19, 16) +-#define XGMAC_DCS_SHIFT 16 + #define XGMAC_ADDRx_LOW(x) (0x00000304 + (x) * 0x8) + #define XGMAC_L3L4_ADDR_CTRL 0x00000c00 + #define XGMAC_IDDR GENMASK(16, 8) +-#define XGMAC_IDDR_SHIFT 8 +-#define XGMAC_IDDR_FNUM 4 ++#define XGMAC_IDDR_FNUM_MASK GENMASK(7, 4) /* FNUM within IDDR */ ++#define XGMAC_IDDR_REG_MASK GENMASK(3, 0) /* REG within IDDR */ + #define XGMAC_TT BIT(1) + #define XGMAC_XB BIT(0) + #define XGMAC_L3L4_DATA 0x00000c04 +@@ -204,7 +202,6 @@ + #define XGMAC_L3PEN0 BIT(0) + #define XGMAC_L4_ADDR 0x1 + #define XGMAC_L4DP0 GENMASK(31, 16) +-#define XGMAC_L4DP0_SHIFT 16 + #define XGMAC_L4SP0 GENMASK(15, 0) + #define XGMAC_L3_ADDR0 0x4 + #define XGMAC_L3_ADDR1 0x5 +@@ -224,7 +221,6 @@ + #define XGMAC_RSS_DATA 0x00000c8c + #define XGMAC_TIMESTAMP_STATUS 0x00000d20 + #define XGMAC_TIMESTAMP_ATSNS_MASK GENMASK(29, 25) +-#define XGMAC_TIMESTAMP_ATSNS_SHIFT 25 + #define XGMAC_TXTSC BIT(15) + #define XGMAC_TXTIMESTAMP_NSEC 0x00000d30 + #define XGMAC_TXTSSTSLO GENMASK(30, 0) +@@ -290,13 +286,9 @@ + #define XGMAC_DPP_DISABLE BIT(0) + #define XGMAC_MTL_TXQ_OPMODE(x) (0x00001100 + (0x80 * (x))) + #define XGMAC_TQS GENMASK(25, 16) +-#define XGMAC_TQS_SHIFT 16 + #define XGMAC_Q2TCMAP GENMASK(10, 8) +-#define XGMAC_Q2TCMAP_SHIFT 8 + #define XGMAC_TTC GENMASK(6, 4) +-#define XGMAC_TTC_SHIFT 4 + #define XGMAC_TXQEN GENMASK(3, 2) +-#define XGMAC_TXQEN_SHIFT 2 + #define XGMAC_TSF BIT(1) + #define XGMAC_MTL_TCx_ETS_CONTROL(x) (0x00001110 + (0x80 * (x))) + #define XGMAC_MTL_TCx_QUANTUM_WEIGHT(x) (0x00001118 + (0x80 * (x))) +@@ -310,16 +302,12 @@ + #define XGMAC_ETS (0x2 << 0) + #define XGMAC_MTL_RXQ_OPMODE(x) (0x00001140 + (0x80 * (x))) + #define XGMAC_RQS GENMASK(25, 16) +-#define XGMAC_RQS_SHIFT 16 + #define XGMAC_EHFC BIT(7) + #define XGMAC_RSF BIT(5) + #define XGMAC_RTC GENMASK(1, 0) +-#define XGMAC_RTC_SHIFT 0 + #define XGMAC_MTL_RXQ_FLOW_CONTROL(x) (0x00001150 + (0x80 * (x))) + #define XGMAC_RFD GENMASK(31, 17) +-#define XGMAC_RFD_SHIFT 17 + #define XGMAC_RFA GENMASK(15, 1) +-#define XGMAC_RFA_SHIFT 1 + #define XGMAC_MTL_QINTEN(x) (0x00001170 + (0x80 * (x))) + #define XGMAC_RXOIE BIT(16) + #define XGMAC_MTL_QINT_STATUS(x) (0x00001174 + (0x80 * (x))) +@@ -333,9 +321,7 @@ + #define XGMAC_SWR BIT(0) + #define XGMAC_DMA_SYSBUS_MODE 0x00003004 + #define XGMAC_WR_OSR_LMT GENMASK(29, 24) +-#define XGMAC_WR_OSR_LMT_SHIFT 24 + #define XGMAC_RD_OSR_LMT GENMASK(21, 16) +-#define XGMAC_RD_OSR_LMT_SHIFT 16 + #define XGMAC_EN_LPI BIT(15) + #define XGMAC_LPI_XIT_PKT BIT(14) + #define XGMAC_AAL BIT(12) +@@ -377,15 +363,12 @@ + #define XGMAC_DMA_CH_TX_CONTROL(x) (0x00003104 + (0x80 * (x))) + #define XGMAC_EDSE BIT(28) + #define XGMAC_TxPBL GENMASK(21, 16) +-#define XGMAC_TxPBL_SHIFT 16 + #define XGMAC_TSE BIT(12) + #define XGMAC_OSP BIT(4) + #define XGMAC_TXST BIT(0) + #define XGMAC_DMA_CH_RX_CONTROL(x) (0x00003108 + (0x80 * (x))) + #define XGMAC_RxPBL GENMASK(21, 16) +-#define XGMAC_RxPBL_SHIFT 16 + #define XGMAC_RBSZ GENMASK(14, 1) +-#define XGMAC_RBSZ_SHIFT 1 + #define XGMAC_RXST BIT(0) + #define XGMAC_DMA_CH_TxDESC_HADDR(x) (0x00003110 + (0x80 * (x))) + #define XGMAC_DMA_CH_TxDESC_LADDR(x) (0x00003114 + (0x80 * (x))) +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +index 00e929bf280bae..2c10302f53abe4 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +@@ -376,7 +376,7 @@ static void dwxgmac2_flow_ctrl(struct mac_device_info *hw, unsigned int duplex, + u32 value = XGMAC_TFE; + + if (duplex) +- value |= pause_time << XGMAC_PT_SHIFT; ++ value |= FIELD_PREP(XGMAC_PT, pause_time); + + writel(value, ioaddr + XGMAC_Qx_TX_FLOW_CTRL(i)); + } +@@ -1233,8 +1233,7 @@ static void dwxgmac2_sarc_configure(void __iomem *ioaddr, int val) + { + u32 value = readl(ioaddr + XGMAC_TX_CONFIG); + +- value &= ~XGMAC_CONFIG_SARC; +- value |= val << XGMAC_CONFIG_SARC_SHIFT; ++ value = u32_replace_bits(value, val, XGMAC_CONFIG_SARC); + + writel(value, ioaddr + XGMAC_TX_CONFIG); + } +@@ -1254,14 +1253,16 @@ static int dwxgmac2_filter_read(struct mac_device_info *hw, u32 filter_no, + u8 reg, u32 *data) + { + void __iomem *ioaddr = hw->pcsr; +- u32 value; ++ u32 value, iddr; + int ret; + + ret = dwxgmac2_filter_wait(hw); + if (ret) + return ret; + +- value = ((filter_no << XGMAC_IDDR_FNUM) | reg) << XGMAC_IDDR_SHIFT; ++ iddr = FIELD_PREP(XGMAC_IDDR_FNUM_MASK, filter_no) | ++ FIELD_PREP(XGMAC_IDDR_REG_MASK, reg); ++ value = FIELD_PREP(XGMAC_IDDR, iddr); + value |= XGMAC_TT | XGMAC_XB; + writel(value, ioaddr + XGMAC_L3L4_ADDR_CTRL); + +@@ -1277,7 +1278,7 @@ static int dwxgmac2_filter_write(struct mac_device_info *hw, u32 filter_no, + u8 reg, u32 data) + { + void __iomem *ioaddr = hw->pcsr; +- u32 value; ++ u32 value, iddr; + int ret; + + ret = dwxgmac2_filter_wait(hw); +@@ -1286,7 +1287,9 @@ static int dwxgmac2_filter_write(struct mac_device_info *hw, u32 filter_no, + + writel(data, ioaddr + XGMAC_L3L4_DATA); + +- value = ((filter_no << XGMAC_IDDR_FNUM) | reg) << XGMAC_IDDR_SHIFT; ++ iddr = FIELD_PREP(XGMAC_IDDR_FNUM_MASK, filter_no) | ++ FIELD_PREP(XGMAC_IDDR_REG_MASK, reg); ++ value = FIELD_PREP(XGMAC_IDDR, iddr); + value |= XGMAC_XB; + writel(value, ioaddr + XGMAC_L3L4_ADDR_CTRL); + +@@ -1395,13 +1398,13 @@ static int dwxgmac2_config_l4_filter(struct mac_device_info *hw, u32 filter_no, + return ret; + + if (sa) { +- value = match & XGMAC_L4SP0; ++ value = FIELD_PREP(XGMAC_L4SP0, match); + + ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value); + if (ret) + return ret; + } else { +- value = (match << XGMAC_L4DP0_SHIFT) & XGMAC_L4DP0; ++ value = FIELD_PREP(XGMAC_L4DP0, match); + + ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value); + if (ret) +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +index 4d6bb995d8d84c..964ce2d7331696 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c +@@ -55,8 +55,7 @@ static void dwxgmac2_dma_init_rx_chan(struct stmmac_priv *priv, + u32 value; + + value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); +- value &= ~XGMAC_RxPBL; +- value |= (rxpbl << XGMAC_RxPBL_SHIFT) & XGMAC_RxPBL; ++ value = u32_replace_bits(value, rxpbl, XGMAC_RxPBL); + writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + + writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(chan)); +@@ -72,9 +71,7 @@ static void dwxgmac2_dma_init_tx_chan(struct stmmac_priv *priv, + u32 value; + + value = readl(ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); +- value &= ~XGMAC_TxPBL; +- value |= (txpbl << XGMAC_TxPBL_SHIFT) & XGMAC_TxPBL; +- value |= XGMAC_OSP; ++ value = u32_replace_bits(value, txpbl, XGMAC_TxPBL); + writel(value, ioaddr + XGMAC_DMA_CH_TX_CONTROL(chan)); + + writel(upper_32_bits(phy), ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(chan)); +@@ -91,13 +88,8 @@ static void dwxgmac2_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi) + if (axi->axi_xit_frm) + value |= XGMAC_LPI_XIT_PKT; + +- value &= ~XGMAC_WR_OSR_LMT; +- value |= (axi->axi_wr_osr_lmt << XGMAC_WR_OSR_LMT_SHIFT) & +- XGMAC_WR_OSR_LMT; +- +- value &= ~XGMAC_RD_OSR_LMT; +- value |= (axi->axi_rd_osr_lmt << XGMAC_RD_OSR_LMT_SHIFT) & +- XGMAC_RD_OSR_LMT; ++ value = u32_replace_bits(value, axi->axi_wr_osr_lmt, XGMAC_WR_OSR_LMT); ++ value = u32_replace_bits(value, axi->axi_rd_osr_lmt, XGMAC_RD_OSR_LMT); + + if (!axi->axi_fb) + value |= XGMAC_UNDEF; +@@ -148,23 +140,24 @@ static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, + { + u32 value = readl(ioaddr + XGMAC_MTL_RXQ_OPMODE(channel)); + unsigned int rqs = fifosz / 256 - 1; ++ unsigned int rtc; + + if (mode == SF_DMA_MODE) { + value |= XGMAC_RSF; + } else { + value &= ~XGMAC_RSF; +- value &= ~XGMAC_RTC; + + if (mode <= 64) +- value |= 0x0 << XGMAC_RTC_SHIFT; ++ rtc = 0x0; + else if (mode <= 96) +- value |= 0x2 << XGMAC_RTC_SHIFT; ++ rtc = 0x2; + else +- value |= 0x3 << XGMAC_RTC_SHIFT; ++ rtc = 0x3; ++ ++ value = u32_replace_bits(value, rtc, XGMAC_RTC); + } + +- value &= ~XGMAC_RQS; +- value |= (rqs << XGMAC_RQS_SHIFT) & XGMAC_RQS; ++ value = u32_replace_bits(value, rqs, XGMAC_RQS); + + if ((fifosz >= 4096) && (qmode != MTL_QUEUE_AVB)) { + u32 flow = readl(ioaddr + XGMAC_MTL_RXQ_FLOW_CONTROL(channel)); +@@ -193,11 +186,8 @@ static void dwxgmac2_dma_rx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, + break; + } + +- flow &= ~XGMAC_RFD; +- flow |= rfd << XGMAC_RFD_SHIFT; +- +- flow &= ~XGMAC_RFA; +- flow |= rfa << XGMAC_RFA_SHIFT; ++ flow = u32_replace_bits(flow, rfd, XGMAC_RFD); ++ flow = u32_replace_bits(flow, rfa, XGMAC_RFA); + + writel(flow, ioaddr + XGMAC_MTL_RXQ_FLOW_CONTROL(channel)); + } +@@ -210,40 +200,41 @@ static void dwxgmac2_dma_tx_mode(struct stmmac_priv *priv, void __iomem *ioaddr, + { + u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(channel)); + unsigned int tqs = fifosz / 256 - 1; ++ unsigned int ttc, txqen; + + if (mode == SF_DMA_MODE) { + value |= XGMAC_TSF; + } else { + value &= ~XGMAC_TSF; +- value &= ~XGMAC_TTC; + + if (mode <= 64) +- value |= 0x0 << XGMAC_TTC_SHIFT; ++ ttc = 0x0; + else if (mode <= 96) +- value |= 0x2 << XGMAC_TTC_SHIFT; ++ ttc = 0x2; + else if (mode <= 128) +- value |= 0x3 << XGMAC_TTC_SHIFT; ++ ttc = 0x3; + else if (mode <= 192) +- value |= 0x4 << XGMAC_TTC_SHIFT; ++ ttc = 0x4; + else if (mode <= 256) +- value |= 0x5 << XGMAC_TTC_SHIFT; ++ ttc = 0x5; + else if (mode <= 384) +- value |= 0x6 << XGMAC_TTC_SHIFT; ++ ttc = 0x6; + else +- value |= 0x7 << XGMAC_TTC_SHIFT; ++ ttc = 0x7; ++ ++ value = u32_replace_bits(value, ttc, XGMAC_TTC); + } + + /* Use static TC to Queue mapping */ +- value |= (channel << XGMAC_Q2TCMAP_SHIFT) & XGMAC_Q2TCMAP; ++ value |= FIELD_PREP(XGMAC_Q2TCMAP, channel); + +- value &= ~XGMAC_TXQEN; + if (qmode != MTL_QUEUE_AVB) +- value |= 0x2 << XGMAC_TXQEN_SHIFT; ++ txqen = 0x2; + else +- value |= 0x1 << XGMAC_TXQEN_SHIFT; ++ txqen = 0x1; + +- value &= ~XGMAC_TQS; +- value |= (tqs << XGMAC_TQS_SHIFT) & XGMAC_TQS; ++ value = u32_replace_bits(value, txqen, XGMAC_TXQEN); ++ value = u32_replace_bits(value, tqs, XGMAC_TQS); + + writel(value, ioaddr + XGMAC_MTL_TXQ_OPMODE(channel)); + } +@@ -547,16 +538,17 @@ static void dwxgmac2_qmode(struct stmmac_priv *priv, void __iomem *ioaddr, + { + u32 value = readl(ioaddr + XGMAC_MTL_TXQ_OPMODE(channel)); + u32 flow = readl(ioaddr + XGMAC_RX_FLOW_CTRL); ++ unsigned int txqen; + +- value &= ~XGMAC_TXQEN; + if (qmode != MTL_QUEUE_AVB) { +- value |= 0x2 << XGMAC_TXQEN_SHIFT; ++ txqen = 0x2; + writel(0, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(channel)); + } else { +- value |= 0x1 << XGMAC_TXQEN_SHIFT; ++ txqen = 0x1; + writel(flow & (~XGMAC_RFE), ioaddr + XGMAC_RX_FLOW_CTRL); + } + ++ value = u32_replace_bits(value, txqen, XGMAC_TXQEN); + writel(value, ioaddr + XGMAC_MTL_TXQ_OPMODE(channel)); + } + +@@ -566,8 +558,7 @@ static void dwxgmac2_set_bfsize(struct stmmac_priv *priv, void __iomem *ioaddr, + u32 value; + + value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); +- value &= ~XGMAC_RBSZ; +- value |= bfsize << XGMAC_RBSZ_SHIFT; ++ value = u32_replace_bits(value, bfsize, XGMAC_RBSZ); + writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan)); + } + +-- +2.53.0 + diff --git a/queue-6.18/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch b/queue-6.18/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch new file mode 100644 index 0000000000..fd12b9350a --- /dev/null +++ b/queue-6.18/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch @@ -0,0 +1,186 @@ +From 32f96b6c3bfd2101dbe4412f88a395ae6027cee8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 10:49:11 +0300 +Subject: net: stmmac: enable the MAC on link up for all supported speeds + +From: vadik likholetov + +[ Upstream commit 9c99db3a2080b8c2cbbb1100369586a9bea43321 ] + +stmmac_mac_link_down() clears the MAC's transmit and receive enable bits. +stmmac_mac_link_up() is expected to set them again through +stmmac_mac_set(..., true), but it first switches on the negotiated speed +and returns early for a speed the switch does not list. The MAC is then +left gated off. + +The speed selection is split into three switches, keyed on the interface. +The generic branch -- taken for everything that is neither USXGMII nor +XLGMII, so including PHY_INTERFACE_MODE_10GBASER -- lists only SPEED_2500, +SPEED_1000, SPEED_100 and SPEED_10. + +MGBE on Tegra234 runs 10GBASE-R into an Aquantia AQR113C. That PHY does +rate matching, so phylink_link_up() replaces the media speed with the +MAC-side interface speed before calling into the MAC: + + case RATE_MATCH_PAUSE: + speed = phylink_interface_max_speed(link_state.interface); + duplex = DUPLEX_FULL; + +The driver is therefore called as + + stmmac_mac_link_up(interface=10GBASER, speed=10000, duplex=1) + +which falls through to "default: return;". The interface stops passing +traffic after the first link flap. + +The failure is easy to misread. The link still comes up, because the PHY +is polled over MDIO and needs no MAC, so the interface reports carrier 1 +at the media speed. The DMA is untouched, so its start bits stay set and +descriptors are still consumed. Only the MAC itself is gated off: the +receiver counts nothing (mmc_rx_framecount_gb stops advancing, RE is 0) +and nothing reaches the wire (TE is 0). The interface survives boot only +because stmmac_hw_setup(), called from ndo_open, enables the MAC +unconditionally -- so the problem appears only once the cable has been +unplugged and plugged back in, and "ip link set dev down && ip +link set dev up" appears to fix it. + +The interface is not what the speed bits depend on: with the single +exception of 2.5G, which is selected through the XGMII block on USXGMII +and through the regular speed bits otherwise, each speed maps to one +field of struct mac_link. The per-interface switches are speed +validation, and phylink already validates the speed against +priv->hw->link.caps. So collapse the three switches into one keyed on the +speed alone, keeping the interface test only for the 2.5G case. This +covers 10G on 10GBASE-R, and equally 5G, and 1G/100/10 on USXGMII, all of +which hit "default: return;" today. + +A core that does not support a speed leaves the corresponding mac_link +field at 0, and phylink will not offer it that speed in the first place. +For dwxgmac2 at 10G, link.xgmii.speed10000 is XGMAC_CONFIG_SS_10000, +which is 0 and is the correct speed selection for a 10GBASE-R MAC: ctrl +then equals old_ctrl, the register write is skipped, and execution +reaches stmmac_mac_set(..., true). + +Log an error in the default case, since a speed with no entry here leaves +the MAC disabled and the symptom does not point at the cause. + +Fixes: d8ca113724e7 ("net: stmmac: tegra: Add MGBE support") +Suggested-by: Maxime Chevallier +Signed-off-by: vadik likholetov +Reviewed-by: Jacob Keller +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260713074911.30090-1-vadikas@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 92 ++++++++----------- + 1 file changed, 37 insertions(+), 55 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 1ceedd74e42908..3be0b795324964 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -892,63 +892,45 @@ static void stmmac_mac_link_up(struct phylink_config *config, + old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG); + ctrl = old_ctrl & ~priv->hw->link.speed_mask; + +- if (interface == PHY_INTERFACE_MODE_USXGMII) { +- switch (speed) { +- case SPEED_10000: +- ctrl |= priv->hw->link.xgmii.speed10000; +- break; +- case SPEED_5000: +- ctrl |= priv->hw->link.xgmii.speed5000; +- break; +- case SPEED_2500: ++ switch (speed) { ++ case SPEED_100000: ++ ctrl |= priv->hw->link.xlgmii.speed100000; ++ break; ++ case SPEED_50000: ++ ctrl |= priv->hw->link.xlgmii.speed50000; ++ break; ++ case SPEED_40000: ++ ctrl |= priv->hw->link.xlgmii.speed40000; ++ break; ++ case SPEED_25000: ++ ctrl |= priv->hw->link.xlgmii.speed25000; ++ break; ++ case SPEED_10000: ++ ctrl |= priv->hw->link.xgmii.speed10000; ++ break; ++ case SPEED_5000: ++ ctrl |= priv->hw->link.xgmii.speed5000; ++ break; ++ case SPEED_2500: ++ if (interface == PHY_INTERFACE_MODE_USXGMII) + ctrl |= priv->hw->link.xgmii.speed2500; +- break; +- default: +- return; +- } +- } else if (interface == PHY_INTERFACE_MODE_XLGMII) { +- switch (speed) { +- case SPEED_100000: +- ctrl |= priv->hw->link.xlgmii.speed100000; +- break; +- case SPEED_50000: +- ctrl |= priv->hw->link.xlgmii.speed50000; +- break; +- case SPEED_40000: +- ctrl |= priv->hw->link.xlgmii.speed40000; +- break; +- case SPEED_25000: +- ctrl |= priv->hw->link.xlgmii.speed25000; +- break; +- case SPEED_10000: +- ctrl |= priv->hw->link.xgmii.speed10000; +- break; +- case SPEED_2500: +- ctrl |= priv->hw->link.speed2500; +- break; +- case SPEED_1000: +- ctrl |= priv->hw->link.speed1000; +- break; +- default: +- return; +- } +- } else { +- switch (speed) { +- case SPEED_2500: ++ else + ctrl |= priv->hw->link.speed2500; +- break; +- case SPEED_1000: +- ctrl |= priv->hw->link.speed1000; +- break; +- case SPEED_100: +- ctrl |= priv->hw->link.speed100; +- break; +- case SPEED_10: +- ctrl |= priv->hw->link.speed10; +- break; +- default: +- return; +- } ++ break; ++ case SPEED_1000: ++ ctrl |= priv->hw->link.speed1000; ++ break; ++ case SPEED_100: ++ ctrl |= priv->hw->link.speed100; ++ break; ++ case SPEED_10: ++ ctrl |= priv->hw->link.speed10; ++ break; ++ default: ++ netdev_err(priv->dev, ++ "unsupported speed %s on %s, leaving the MAC disabled\n", ++ phy_speed_to_str(speed), phy_modes(interface)); ++ return; + } + + if (priv->plat->fix_mac_speed) +-- +2.53.0 + diff --git a/queue-6.18/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch b/queue-6.18/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch new file mode 100644 index 0000000000..79d00e0af3 --- /dev/null +++ b/queue-6.18/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch @@ -0,0 +1,103 @@ +From 1876652480a989376233a1be26a3a510da0e56b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:15 -0700 +Subject: net: stmmac: fix l3l4 filter rejecting unsupported offload requests + +From: Nazim Amirul + +[ Upstream commit 5536d7c843637e9430279b94935fcf7df98babb3 ] + +The basic flow parser in tc_add_basic_flow() does not validate match +keys before proceeding. Unsupported offload configurations such as +partial protocol masks, non-IPv4 network proto, or non-TCP/UDP transport +proto are silently accepted instead of returning -EOPNOTSUPP. + +Add validation to return -EOPNOTSUPP early for: +- No network or transport proto present in the key +- Partial protocol mask (only full mask supported) +- Network proto is not IPv4 +- Transport proto is not TCP or UDP + +Each rejection includes an extack message so the user knows which part +of the match is unsupported. + +Also propagate -EOPNOTSUPP from tc_add_basic_flow() in tc_add_flow() +by returning it directly rather than using break. The break was silently +discarding the error for FLOW_CLS_REPLACE operations where entry->in_use +is already true, causing tc_add_flow() to return 0 (success) for +unsupported replace requests. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-4-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 34 +++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 3b4d4696afe96a..2050f1fa9f44cb 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -446,6 +446,7 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv, + } + + #define ETHER_TYPE_FULL_MASK cpu_to_be16(~0) ++#define IP_PROTO_FULL_MASK 0xFF + + static int tc_add_basic_flow(struct stmmac_priv *priv, + struct flow_cls_offload *cls, +@@ -461,6 +462,37 @@ static int tc_add_basic_flow(struct stmmac_priv *priv, + + flow_rule_match_basic(rule, &match); + ++ /* Both network proto and transport proto not present in the key */ ++ if (!match.mask || !(match.mask->n_proto || match.mask->ip_proto)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "filter must specify network or transport protocol"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* If the proto is present in the key and is not full mask */ ++ if ((match.mask->n_proto && match.mask->n_proto != ETHER_TYPE_FULL_MASK) || ++ (match.mask->ip_proto && match.mask->ip_proto != IP_PROTO_FULL_MASK)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only full protocol mask is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Network proto is present in the key and is not IPv4 */ ++ if (match.mask->n_proto && match.key->n_proto != cpu_to_be16(ETH_P_IP)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only IPv4 network protocol is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Transport proto is present in the key and is not TCP or UDP */ ++ if (match.mask->ip_proto && ++ match.key->ip_proto != IPPROTO_TCP && ++ match.key->ip_proto != IPPROTO_UDP) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only TCP and UDP transport protocols are supported"); ++ return -EOPNOTSUPP; ++ } ++ + entry->ip_proto = match.key->ip_proto; + return 0; + } +@@ -598,6 +630,8 @@ static int tc_add_flow(struct stmmac_priv *priv, + ret = tc_flow_parsers[i].fn(priv, cls, entry); + if (!ret) + entry->in_use = true; ++ else if (ret == -EOPNOTSUPP) ++ return ret; + } + + if (!entry->in_use) +-- +2.53.0 + diff --git a/queue-6.18/net-stmmac-remove-xstats.pcs_-members.patch b/queue-6.18/net-stmmac-remove-xstats.pcs_-members.patch new file mode 100644 index 0000000000..8a9326b1c4 --- /dev/null +++ b/queue-6.18/net-stmmac-remove-xstats.pcs_-members.patch @@ -0,0 +1,128 @@ +From 8c2eb8f3e7d7c91a8de51fff34ef49794dad1626 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Oct 2025 15:36:51 +0100 +Subject: net: stmmac: remove xstats.pcs_* members + +From: Russell King (Oracle) + +[ Upstream commit 14f74bc6dc699f63b5a6dfa9b22229f0caea89f3 ] + +As a result of the previous commit, the pcs_link, pcs_duplex and +pcs_speed members are not used outside of the interrupt handling code, +and are only used to print their status using the misleading "Link is" +messages that bear no relation to the actual status of the link. + +Remove the printing of these messages, these members, and the code +that decodes them from the hardware. + +Reviewed-by: Andrew Lunn +Signed-off-by: Russell King (Oracle) +Tested-by: Maxime Chevallier +Tested-by: Lad Prabhakar +Link: https://patch.msgid.link/E1v9P63-0000000AolI-23Kf@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +Stable-dep-of: 9fcf274d93af ("net: stmmac: xgmac: fix l4 filter port overwrite on register update") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/common.h | 3 -- + .../ethernet/stmicro/stmmac/dwmac1000_core.c | 28 +------------------ + .../net/ethernet/stmicro/stmmac/dwmac4_core.c | 28 +------------------ + 3 files changed, 2 insertions(+), 57 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h +index acd7719506b612..83929477b058b6 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/common.h ++++ b/drivers/net/ethernet/stmicro/stmmac/common.h +@@ -197,9 +197,6 @@ struct stmmac_extra_stats { + unsigned long irq_pcs_ane_n; + unsigned long irq_pcs_link_n; + unsigned long irq_rgmii_n; +- unsigned long pcs_link; +- unsigned long pcs_duplex; +- unsigned long pcs_speed; + /* debug register */ + unsigned long mtl_tx_status_fifo_full; + unsigned long mtl_tx_fifo_not_empty; +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +index fe776ddf688952..2c5ee59c320864 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +@@ -266,34 +266,8 @@ static void dwmac1000_pmt(struct mac_device_info *hw, unsigned long mode) + /* RGMII or SMII interface */ + static void dwmac1000_rgsmii(void __iomem *ioaddr, struct stmmac_extra_stats *x) + { +- u32 status; +- +- status = readl(ioaddr + GMAC_RGSMIIIS); ++ readl(ioaddr + GMAC_RGSMIIIS); + x->irq_rgmii_n++; +- +- /* Check the link status */ +- if (status & GMAC_RGSMIIIS_LNKSTS) { +- int speed_value; +- +- x->pcs_link = 1; +- +- speed_value = ((status & GMAC_RGSMIIIS_SPEED) >> +- GMAC_RGSMIIIS_SPEED_SHIFT); +- if (speed_value == GMAC_RGSMIIIS_SPEED_125) +- x->pcs_speed = SPEED_1000; +- else if (speed_value == GMAC_RGSMIIIS_SPEED_25) +- x->pcs_speed = SPEED_100; +- else +- x->pcs_speed = SPEED_10; +- +- x->pcs_duplex = (status & GMAC_RGSMIIIS_LNKMOD_MASK); +- +- pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed, +- x->pcs_duplex ? "Full" : "Half"); +- } else { +- x->pcs_link = 0; +- pr_info("Link is Down\n"); +- } + } + + static int dwmac1000_irq_status(struct mac_device_info *hw, +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +index d85bc0bb5c3c05..8a19df7b05775d 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +@@ -592,34 +592,8 @@ static void dwmac4_ctrl_ane(struct stmmac_priv *priv, bool ane, bool srgmi_ral, + /* RGMII or SMII interface */ + static void dwmac4_phystatus(void __iomem *ioaddr, struct stmmac_extra_stats *x) + { +- u32 status; +- +- status = readl(ioaddr + GMAC_PHYIF_CONTROL_STATUS); ++ readl(ioaddr + GMAC_PHYIF_CONTROL_STATUS); + x->irq_rgmii_n++; +- +- /* Check the link status */ +- if (status & GMAC_PHYIF_CTRLSTATUS_LNKSTS) { +- int speed_value; +- +- x->pcs_link = 1; +- +- speed_value = ((status & GMAC_PHYIF_CTRLSTATUS_SPEED) >> +- GMAC_PHYIF_CTRLSTATUS_SPEED_SHIFT); +- if (speed_value == GMAC_PHYIF_CTRLSTATUS_SPEED_125) +- x->pcs_speed = SPEED_1000; +- else if (speed_value == GMAC_PHYIF_CTRLSTATUS_SPEED_25) +- x->pcs_speed = SPEED_100; +- else +- x->pcs_speed = SPEED_10; +- +- x->pcs_duplex = (status & GMAC_PHYIF_CTRLSTATUS_LNKMOD); +- +- pr_info("Link is Up - %d/%s\n", (int)x->pcs_speed, +- x->pcs_duplex ? "Full" : "Half"); +- } else { +- x->pcs_link = 0; +- pr_info("Link is Down\n"); +- } + } + + static int dwmac4_irq_mtl_status(struct stmmac_priv *priv, +-- +2.53.0 + diff --git a/queue-6.18/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch b/queue-6.18/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch new file mode 100644 index 0000000000..c2830f6bf2 --- /dev/null +++ b/queue-6.18/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch @@ -0,0 +1,43 @@ +From a49167737d6067b94bece2fb6ff99721f79c1be6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:16 -0700 +Subject: net: stmmac: reset residual action in L3L4 filters on delete + +From: Nazim Amirul + +[ Upstream commit a448f821289934b961dd9d8d0beb006cc8937ba2 ] + +When deleting an L3/L4 flower filter entry, the action field is not +reset. If a filter was previously configured with a drop action, that +action may persist and affect subsequent filter configurations +unintentionally. + +Clear the action field when the filter entry is deleted. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-5-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 2050f1fa9f44cb..0119b4b89fc0a0 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -661,6 +661,7 @@ static int tc_del_flow(struct stmmac_priv *priv, + entry->in_use = false; + entry->cookie = 0; + entry->is_l4 = false; ++ entry->action = 0; + return ret; + } + +-- +2.53.0 + diff --git a/queue-6.18/net-stmmac-socfpga-add-hardware-supported-cross-time.patch b/queue-6.18/net-stmmac-socfpga-add-hardware-supported-cross-time.patch new file mode 100644 index 0000000000..8fedd74da1 --- /dev/null +++ b/queue-6.18/net-stmmac-socfpga-add-hardware-supported-cross-time.patch @@ -0,0 +1,225 @@ +From fe41323792537a3ad3fb4321bd619af61214579f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Nov 2025 01:27:10 +0800 +Subject: net: stmmac: socfpga: Add hardware supported cross-timestamp + +From: Rohan G Thomas + +[ Upstream commit fd8c4f6454963aa7ea895657472aa57f33779d57 ] + +Cross timestamping is supported on Agilex5 platform with Synchronized +Multidrop Timestamp Gathering(SMTG) IP. The hardware cross-timestamp +result is made available the applications through the ioctl call +PTP_SYS_OFFSET_PRECISE, which inturn calls stmmac_getcrosststamp(). + +Device time is stored in the MAC Auxiliary register. The 64-bit System +time (ARM_ARCH_COUNTER) is stored in SMTG IP. SMTG IP is an MDIO device +with 0xC - 0xF MDIO register space holds 64-bit system time. + +This commit is similar to following commit for Intel platforms: +Commit 341f67e424e5 ("net: stmmac: Add hardware supported cross-timestamp") + +Signed-off-by: Rohan G Thomas +Link: https://patch.msgid.link/20251101-agilex5_ext-v2-4-a6b51b4dca4d@altera.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 9fcf274d93af ("net: stmmac: xgmac: fix l4 filter port overwrite on register update") +Signed-off-by: Sasha Levin +--- + .../ethernet/stmicro/stmmac/dwmac-socfpga.c | 120 ++++++++++++++++++ + .../net/ethernet/stmicro/stmmac/dwxgmac2.h | 5 + + 2 files changed, 125 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +index 4f256f0ae05c15..d8c49083ada21c 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +@@ -5,6 +5,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -15,8 +16,10 @@ + #include + #include + ++#include "dwxgmac2.h" + #include "stmmac.h" + #include "stmmac_platform.h" ++#include "stmmac_ptp.h" + + #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0 + #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1 +@@ -41,6 +44,13 @@ + #define SGMII_ADAPTER_ENABLE 0x0000 + #define SGMII_ADAPTER_DISABLE 0x0001 + ++#define SMTG_MDIO_ADDR 0x15 ++#define SMTG_TSC_WORD0 0xC ++#define SMTG_TSC_WORD1 0xD ++#define SMTG_TSC_WORD2 0xE ++#define SMTG_TSC_WORD3 0xF ++#define SMTG_TSC_SHIFT 16 ++ + struct socfpga_dwmac; + struct socfpga_dwmac_ops { + int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv); +@@ -269,6 +279,112 @@ static int socfpga_set_phy_mode_common(int phymode, u32 *val) + return 0; + } + ++static void get_smtgtime(struct mii_bus *mii, int smtg_addr, u64 *smtg_time) ++{ ++ u64 ns; ++ ++ ns = mdiobus_read(mii, smtg_addr, SMTG_TSC_WORD3); ++ ns <<= SMTG_TSC_SHIFT; ++ ns |= mdiobus_read(mii, smtg_addr, SMTG_TSC_WORD2); ++ ns <<= SMTG_TSC_SHIFT; ++ ns |= mdiobus_read(mii, smtg_addr, SMTG_TSC_WORD1); ++ ns <<= SMTG_TSC_SHIFT; ++ ns |= mdiobus_read(mii, smtg_addr, SMTG_TSC_WORD0); ++ ++ *smtg_time = ns; ++} ++ ++static int smtg_crosststamp(ktime_t *device, struct system_counterval_t *system, ++ void *ctx) ++{ ++ struct stmmac_priv *priv = (struct stmmac_priv *)ctx; ++ u32 num_snapshot, gpio_value, acr_value; ++ void __iomem *ptpaddr = priv->ptpaddr; ++ void __iomem *ioaddr = priv->hw->pcsr; ++ unsigned long flags; ++ u64 smtg_time = 0; ++ u64 ptp_time = 0; ++ int i, ret; ++ u32 v; ++ ++ /* Both internal crosstimestamping and external triggered event ++ * timestamping cannot be run concurrently. ++ */ ++ if (priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN) ++ return -EBUSY; ++ ++ mutex_lock(&priv->aux_ts_lock); ++ /* Enable Internal snapshot trigger */ ++ acr_value = readl(ptpaddr + PTP_ACR); ++ acr_value &= ~PTP_ACR_MASK; ++ switch (priv->plat->int_snapshot_num) { ++ case AUX_SNAPSHOT0: ++ acr_value |= PTP_ACR_ATSEN0; ++ break; ++ case AUX_SNAPSHOT1: ++ acr_value |= PTP_ACR_ATSEN1; ++ break; ++ case AUX_SNAPSHOT2: ++ acr_value |= PTP_ACR_ATSEN2; ++ break; ++ case AUX_SNAPSHOT3: ++ acr_value |= PTP_ACR_ATSEN3; ++ break; ++ default: ++ mutex_unlock(&priv->aux_ts_lock); ++ return -EINVAL; ++ } ++ writel(acr_value, ptpaddr + PTP_ACR); ++ ++ /* Clear FIFO */ ++ acr_value = readl(ptpaddr + PTP_ACR); ++ acr_value |= PTP_ACR_ATSFC; ++ writel(acr_value, ptpaddr + PTP_ACR); ++ /* Release the mutex */ ++ mutex_unlock(&priv->aux_ts_lock); ++ ++ /* Trigger Internal snapshot signal. Create a rising edge by just toggle ++ * the GPO0 to low and back to high. ++ */ ++ gpio_value = readl(ioaddr + XGMAC_GPIO_STATUS); ++ gpio_value &= ~XGMAC_GPIO_GPO0; ++ writel(gpio_value, ioaddr + XGMAC_GPIO_STATUS); ++ gpio_value |= XGMAC_GPIO_GPO0; ++ writel(gpio_value, ioaddr + XGMAC_GPIO_STATUS); ++ ++ /* Poll for time sync operation done */ ++ ret = readl_poll_timeout(priv->ioaddr + XGMAC_INT_STATUS, v, ++ (v & XGMAC_INT_TSIS), 100, 10000); ++ if (ret) { ++ netdev_err(priv->dev, "%s: Wait for time sync operation timeout\n", ++ __func__); ++ return ret; ++ } ++ ++ *system = (struct system_counterval_t) { ++ .cycles = 0, ++ .cs_id = CSID_ARM_ARCH_COUNTER, ++ .use_nsecs = false, ++ }; ++ ++ num_snapshot = (readl(ioaddr + XGMAC_TIMESTAMP_STATUS) & ++ XGMAC_TIMESTAMP_ATSNS_MASK) >> ++ XGMAC_TIMESTAMP_ATSNS_SHIFT; ++ ++ /* Repeat until the timestamps are from the FIFO last segment */ ++ for (i = 0; i < num_snapshot; i++) { ++ read_lock_irqsave(&priv->ptp_lock, flags); ++ stmmac_get_ptptime(priv, ptpaddr, &ptp_time); ++ *device = ns_to_ktime(ptp_time); ++ read_unlock_irqrestore(&priv->ptp_lock, flags); ++ } ++ ++ get_smtgtime(priv->mii, SMTG_MDIO_ADDR, &smtg_time); ++ system->cycles = smtg_time; ++ ++ return 0; ++} ++ + static int socfpga_gen5_set_phy_mode(struct socfpga_dwmac *dwmac) + { + struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr; +@@ -470,6 +586,10 @@ static void socfpga_agilex5_setup_plat_dat(struct socfpga_dwmac *dwmac) + /* Tx Queues 0 - 5 doesn't support TBS on Agilex5 */ + break; + } ++ ++ /* Hw supported cross-timestamp */ ++ plat_dat->int_snapshot_num = AUX_SNAPSHOT0; ++ plat_dat->crosststamp = smtg_crosststamp; + } + + static int socfpga_dwmac_probe(struct platform_device *pdev) +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +index 0d408ee17f3378..e48cfa05000c07 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h +@@ -79,6 +79,7 @@ + #define XGMAC_PSRQ(x) GENMASK((x) * 8 + 7, (x) * 8) + #define XGMAC_PSRQ_SHIFT(x) ((x) * 8) + #define XGMAC_INT_STATUS 0x000000b0 ++#define XGMAC_INT_TSIS BIT(12) + #define XGMAC_LPIIS BIT(5) + #define XGMAC_PMTIS BIT(4) + #define XGMAC_INT_EN 0x000000b4 +@@ -173,6 +174,8 @@ + #define XGMAC_MDIO_ADDR 0x00000200 + #define XGMAC_MDIO_DATA 0x00000204 + #define XGMAC_MDIO_C22P 0x00000220 ++#define XGMAC_GPIO_STATUS 0x0000027c ++#define XGMAC_GPIO_GPO0 BIT(16) + #define XGMAC_ADDRx_HIGH(x) (0x00000300 + (x) * 0x8) + #define XGMAC_ADDR_MAX 32 + #define XGMAC_AE BIT(31) +@@ -220,6 +223,8 @@ + #define XGMAC_OB BIT(0) + #define XGMAC_RSS_DATA 0x00000c8c + #define XGMAC_TIMESTAMP_STATUS 0x00000d20 ++#define XGMAC_TIMESTAMP_ATSNS_MASK GENMASK(29, 25) ++#define XGMAC_TIMESTAMP_ATSNS_SHIFT 25 + #define XGMAC_TXTSC BIT(15) + #define XGMAC_TXTIMESTAMP_NSEC 0x00000d30 + #define XGMAC_TXTSSTSLO GENMASK(30, 0) +-- +2.53.0 + diff --git a/queue-6.18/net-stmmac-socfpga-agilex5-emac-platform-configurati.patch b/queue-6.18/net-stmmac-socfpga-agilex5-emac-platform-configurati.patch new file mode 100644 index 0000000000..d4c2f63e3d --- /dev/null +++ b/queue-6.18/net-stmmac-socfpga-agilex5-emac-platform-configurati.patch @@ -0,0 +1,104 @@ +From f3265ff8d6d393c0f8e45f857caf6f70de5a940a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Nov 2025 01:27:07 +0800 +Subject: net: stmmac: socfpga: Agilex5 EMAC platform configuration + +From: Rohan G Thomas + +[ Upstream commit 93d46ea3e984323fae0e5d2919cf5817e1297d41 ] + +Agilex5 HPS EMAC uses the dwxgmac-3.10a IP, unlike previous socfpga +platforms which use dwmac1000 IP. Due to differences in platform +configuration, Agilex5 requires a distinct setup. + +Introduce a setup_plat_dat() callback in socfpga_dwmac_ops to handle +platform-specific setup. This callback is invoked before +stmmac_dvr_probe() to ensure the platform data is correctly +configured. Also, implemented separate setup_plat_dat() callback for +current socfpga platforms and Agilex5. + +Signed-off-by: Rohan G Thomas +Reviewed-by: Maxime Chevallier +Tested-by: Maxime Chevallier +Link: https://patch.msgid.link/20251101-agilex5_ext-v2-1-a6b51b4dca4d@altera.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 9fcf274d93af ("net: stmmac: xgmac: fix l4 filter port overwrite on register update") +Signed-off-by: Sasha Levin +--- + .../ethernet/stmicro/stmmac/dwmac-socfpga.c | 30 +++++++++++++++++-- + 1 file changed, 27 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +index 2ff5db6d41ca08..5666b017236439 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +@@ -44,6 +44,7 @@ + struct socfpga_dwmac; + struct socfpga_dwmac_ops { + int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv); ++ void (*setup_plat_dat)(struct socfpga_dwmac *dwmac_priv); + }; + + struct socfpga_dwmac { +@@ -441,6 +442,23 @@ static int socfpga_dwmac_init(struct platform_device *pdev, void *bsp_priv) + return dwmac->ops->set_phy_mode(dwmac); + } + ++static void socfpga_gen5_setup_plat_dat(struct socfpga_dwmac *dwmac) ++{ ++ struct plat_stmmacenet_data *plat_dat = dwmac->plat_dat; ++ ++ plat_dat->core_type = DWMAC_CORE_GMAC; ++ ++ /* Rx watchdog timer in dwmac is buggy in this hw */ ++ plat_dat->riwt_off = 1; ++} ++ ++static void socfpga_agilex5_setup_plat_dat(struct socfpga_dwmac *dwmac) ++{ ++ struct plat_stmmacenet_data *plat_dat = dwmac->plat_dat; ++ ++ plat_dat->core_type = DWMAC_CORE_XGMAC; ++} ++ + static int socfpga_dwmac_probe(struct platform_device *pdev) + { + struct plat_stmmacenet_data *plat_dat; +@@ -497,25 +515,31 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) + plat_dat->pcs_init = socfpga_dwmac_pcs_init; + plat_dat->pcs_exit = socfpga_dwmac_pcs_exit; + plat_dat->select_pcs = socfpga_dwmac_select_pcs; +- plat_dat->core_type = DWMAC_CORE_GMAC; + +- plat_dat->riwt_off = 1; ++ ops->setup_plat_dat(dwmac); + + return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); + } + + static const struct socfpga_dwmac_ops socfpga_gen5_ops = { + .set_phy_mode = socfpga_gen5_set_phy_mode, ++ .setup_plat_dat = socfpga_gen5_setup_plat_dat, + }; + + static const struct socfpga_dwmac_ops socfpga_gen10_ops = { + .set_phy_mode = socfpga_gen10_set_phy_mode, ++ .setup_plat_dat = socfpga_gen5_setup_plat_dat, ++}; ++ ++static const struct socfpga_dwmac_ops socfpga_agilex5_ops = { ++ .set_phy_mode = socfpga_gen10_set_phy_mode, ++ .setup_plat_dat = socfpga_agilex5_setup_plat_dat, + }; + + static const struct of_device_id socfpga_dwmac_match[] = { + { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gen5_ops }, + { .compatible = "altr,socfpga-stmmac-a10-s10", .data = &socfpga_gen10_ops }, +- { .compatible = "altr,socfpga-stmmac-agilex5", .data = &socfpga_gen10_ops }, ++ { .compatible = "altr,socfpga-stmmac-agilex5", .data = &socfpga_agilex5_ops }, + { } + }; + MODULE_DEVICE_TABLE(of, socfpga_dwmac_match); +-- +2.53.0 + diff --git a/queue-6.18/net-stmmac-socfpga-enable-tbs-support-for-agilex5.patch b/queue-6.18/net-stmmac-socfpga-enable-tbs-support-for-agilex5.patch new file mode 100644 index 0000000000..43cf8b2d86 --- /dev/null +++ b/queue-6.18/net-stmmac-socfpga-enable-tbs-support-for-agilex5.patch @@ -0,0 +1,48 @@ +From 2e2be7a31cb14b13c641437088619489f881fd7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Nov 2025 01:27:08 +0800 +Subject: net: stmmac: socfpga: Enable TBS support for Agilex5 + +From: Rohan G Thomas + +[ Upstream commit 4c00476d44804db3c16838299b87a11741cd0dbd ] + +Agilex5 supports Time-Based Scheduling(TBS) for Tx queue 6 and Tx +queue 7. This commit enables TBS support for these queues. + +Signed-off-by: Rohan G Thomas +Link: https://patch.msgid.link/20251101-agilex5_ext-v2-2-a6b51b4dca4d@altera.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 9fcf274d93af ("net: stmmac: xgmac: fix l4 filter port overwrite on register update") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +index 5666b017236439..4f256f0ae05c15 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +@@ -457,6 +457,19 @@ static void socfpga_agilex5_setup_plat_dat(struct socfpga_dwmac *dwmac) + struct plat_stmmacenet_data *plat_dat = dwmac->plat_dat; + + plat_dat->core_type = DWMAC_CORE_XGMAC; ++ ++ /* Enable TBS */ ++ switch (plat_dat->tx_queues_to_use) { ++ case 8: ++ plat_dat->tx_queues_cfg[7].tbs_en = true; ++ fallthrough; ++ case 7: ++ plat_dat->tx_queues_cfg[6].tbs_en = true; ++ break; ++ default: ++ /* Tx Queues 0 - 5 doesn't support TBS on Agilex5 */ ++ break; ++ } + } + + static int socfpga_dwmac_probe(struct platform_device *pdev) +-- +2.53.0 + diff --git a/queue-6.18/net-stmmac-xgmac-fix-l4-filter-port-overwrite-on-reg.patch b/queue-6.18/net-stmmac-xgmac-fix-l4-filter-port-overwrite-on-reg.patch new file mode 100644 index 0000000000..ca2cd3a5bf --- /dev/null +++ b/queue-6.18/net-stmmac-xgmac-fix-l4-filter-port-overwrite-on-reg.patch @@ -0,0 +1,88 @@ +From 6e00d22d059882128025582211a8995337dbea62 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:14 -0700 +Subject: net: stmmac: xgmac: fix l4 filter port overwrite on register update + +From: Nazim Amirul + +[ Upstream commit 9fcf274d93af17396f20cccb63f1d4c17492a000 ] + +The XGMAC_L4_ADDR register holds both source and destination port +match values. The current implementation overwrites the entire register +when configuring either port, so setting one silently erases the other. + +Fix this by reading the register first, then masking and updating only +the relevant field before writing back. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-3-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 28 +++++++++++-------- + 1 file changed, 16 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +index 2c10302f53abe4..ee41c77426f1ab 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +@@ -1381,36 +1381,40 @@ static int dwxgmac2_config_l4_filter(struct mac_device_info *hw, u32 filter_no, + value &= ~XGMAC_L4PEN0; + } + +- value &= ~(XGMAC_L4SPM0 | XGMAC_L4SPIM0); +- value &= ~(XGMAC_L4DPM0 | XGMAC_L4DPIM0); + if (sa) { + value |= XGMAC_L4SPM0; + if (inv) + value |= XGMAC_L4SPIM0; ++ else ++ value &= ~XGMAC_L4SPIM0; + } else { + value |= XGMAC_L4DPM0; + if (inv) + value |= XGMAC_L4DPIM0; ++ else ++ value &= ~XGMAC_L4DPIM0; + } + + ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L3L4_CTRL, value); + if (ret) + return ret; + +- if (sa) { +- value = FIELD_PREP(XGMAC_L4SP0, match); ++ ret = dwxgmac2_filter_read(hw, filter_no, XGMAC_L4_ADDR, &value); ++ if (ret) ++ return ret; + +- ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value); +- if (ret) +- return ret; ++ if (sa) { ++ value &= ~XGMAC_L4SP0; ++ value |= FIELD_PREP(XGMAC_L4SP0, match); + } else { +- value = FIELD_PREP(XGMAC_L4DP0, match); +- +- ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value); +- if (ret) +- return ret; ++ value &= ~XGMAC_L4DP0; ++ value |= FIELD_PREP(XGMAC_L4DP0, match); + } + ++ ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value); ++ if (ret) ++ return ret; ++ + if (!en) + return dwxgmac2_filter_write(hw, filter_no, XGMAC_L3L4_CTRL, 0); + +-- +2.53.0 + diff --git a/queue-6.18/net-txgbe-fix-fdir-filter-leak-on-remove.patch b/queue-6.18/net-txgbe-fix-fdir-filter-leak-on-remove.patch new file mode 100644 index 0000000000..cc2146c849 --- /dev/null +++ b/queue-6.18/net-txgbe-fix-fdir-filter-leak-on-remove.patch @@ -0,0 +1,40 @@ +From ddef502efc1060b57d44c5f7cb976746c8fc8a7f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:19:11 +0800 +Subject: net: txgbe: fix FDIR filter leak on remove + +From: Chenguang Zhao + +[ Upstream commit ecaa37826340520664a4e5522f803ff48fc3f564 ] + +Perfect FDIR filters can be added while the interface is down and are +kept on the software list for later restore. unregister_netdev() only +calls ndo_stop when the device is up, so txgbe_fdir_filter_exit() in +txgbe_close() is skipped in that case and the filters are leaked on +driver remove. Free the filter list from txgbe_remove() as well. + +Fixes: 4bdb441105dc ("net: txgbe: support Flow Director perfect filters") +Signed-off-by: Chenguang Zhao +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20260713091911.1614795-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +index 4d20b178af236b..76d2940a49fae6 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +@@ -956,6 +956,7 @@ static void txgbe_remove(struct pci_dev *pdev) + netdev = wx->netdev; + wx_disable_sriov(wx); + unregister_netdev(netdev); ++ txgbe_fdir_filter_exit(wx); + + txgbe_remove_phy(txgbe); + wx_free_isb_resources(wx); +-- +2.53.0 + diff --git a/queue-6.18/netlink-specs-rt-link-convert-bridge-port-flag-attri.patch b/queue-6.18/netlink-specs-rt-link-convert-bridge-port-flag-attri.patch new file mode 100644 index 0000000000..058b28c3c1 --- /dev/null +++ b/queue-6.18/netlink-specs-rt-link-convert-bridge-port-flag-attri.patch @@ -0,0 +1,144 @@ +From 03f3c658415724c11fff0768fa45b5b82d283ef0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:03:04 +0300 +Subject: netlink: specs: rt-link: convert bridge port flag attributes to u8 + +From: Danielle Ratson + +[ Upstream commit f6e3b21608e974c4aaa4cfd73a239dacf1d8a9a3 ] + +A number of IFLA_BRPORT_* attributes are documented in the rt-link spec +as having the "flag" type, i.e. a payload-less NLA_FLAG attribute whose +meaning is presence-only. This does not match the kernel, which emits +these attributes with nla_put_u8() and validates them as NLA_U8 in +br_port_policy[]. The values are not mere presence flags but carry a u8 +payload (0/1). + +Convert these bridge port attributes from "flag" to "u8" so the spec +reflects the actual wire format. + +Fixes: 077b6022d24b ("doc/netlink/specs: Add sub-message type to rt_link family") +Reviewed-by: Petr Machata +Acked-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Signed-off-by: Danielle Ratson +Link: https://patch.msgid.link/a57cdfcfc4a6dcb92106c25b4dde5059fde2bd44.1783236731.git.danieller@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + Documentation/netlink/specs/rt-link.yaml | 40 ++++++++++++------------ + 1 file changed, 20 insertions(+), 20 deletions(-) + +diff --git a/Documentation/netlink/specs/rt-link.yaml b/Documentation/netlink/specs/rt-link.yaml +index ae4db7e032770f..692b3cd47c3108 100644 +--- a/Documentation/netlink/specs/rt-link.yaml ++++ b/Documentation/netlink/specs/rt-link.yaml +@@ -1564,31 +1564,31 @@ attribute-sets: + type: u32 + - + name: mode +- type: flag ++ type: u8 + - + name: guard +- type: flag ++ type: u8 + - + name: protect +- type: flag ++ type: u8 + - + name: fast-leave +- type: flag ++ type: u8 + - + name: learning +- type: flag ++ type: u8 + - + name: unicast-flood +- type: flag ++ type: u8 + - + name: proxyarp +- type: flag ++ type: u8 + - + name: learning-sync +- type: flag ++ type: u8 + - + name: proxyarp-wifi +- type: flag ++ type: u8 + - + name: root-id + type: binary +@@ -1635,34 +1635,34 @@ attribute-sets: + type: pad + - + name: mcast-flood +- type: flag ++ type: u8 + - + name: mcast-to-ucast +- type: flag ++ type: u8 + - + name: vlan-tunnel +- type: flag ++ type: u8 + - + name: bcast-flood +- type: flag ++ type: u8 + - + name: group-fwd-mask + type: u16 + - + name: neigh-suppress +- type: flag ++ type: u8 + - + name: isolated +- type: flag ++ type: u8 + - + name: backup-port + type: u32 + - + name: mrp-ring-open +- type: flag ++ type: u8 + - + name: mrp-in-open +- type: flag ++ type: u8 + - + name: mcast-eht-hosts-limit + type: u32 +@@ -1671,10 +1671,10 @@ attribute-sets: + type: u32 + - + name: locked +- type: flag ++ type: u8 + - + name: mab +- type: flag ++ type: u8 + - + name: mcast-n-groups + type: u32 +@@ -1683,7 +1683,7 @@ attribute-sets: + type: u32 + - + name: neigh-vlan-suppress +- type: flag ++ type: u8 + - + name: backup-nhid + type: u32 +-- +2.53.0 + diff --git a/queue-6.18/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch b/queue-6.18/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch new file mode 100644 index 0000000000..e955c84f97 --- /dev/null +++ b/queue-6.18/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch @@ -0,0 +1,59 @@ +From 24ff816bbaccd6779dcb60741734262a7587c1a0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 22:15:51 +0000 +Subject: nexthop: initialize extack in nh_res_bucket_migrate() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 6347c5314cee49f364aaf2e40ff15415a57a116e ] + +nh_res_bucket_migrate() passes an uninitialized netlink_ext_ack to +call_nexthop_res_bucket_notifiers(). When +nh_notifier_res_bucket_info_init() fails (e.g. the kzalloc returns +-ENOMEM), the error is propagated back before any notifier sets +extack._msg, and the error path formats the stale pointer with +pr_err_ratelimited("%s\n", extack._msg). With CONFIG_INIT_STACK_NONE +this dereferences uninitialized stack memory: + + Oops: general protection fault, probably for non-canonical address ... + KASAN: maybe wild-memory-access in range [...] + RIP: 0010:string (lib/vsprintf.c:730) + vsnprintf (lib/vsprintf.c:2945) + _printk (kernel/printk/printk.c:2504) + nh_res_bucket_migrate (net/ipv4/nexthop.c:1816) + nh_res_table_upkeep (net/ipv4/nexthop.c:1866) + rtm_new_nexthop (net/ipv4/nexthop.c:3323) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7076) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + Kernel panic - not syncing: Fatal exception + +Zero-initialize extack so _msg is NULL on error paths that never set it. + +Fixes: 7c37c7e00411 ("nexthop: Implement notifiers for resilient nexthop groups") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260713221551.3344650-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/nexthop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c +index 5a95b64b61c59e..a8bf1ec548995f 100644 +--- a/net/ipv4/nexthop.c ++++ b/net/ipv4/nexthop.c +@@ -1791,8 +1791,8 @@ static bool nh_res_bucket_migrate(struct nh_res_table *res_table, + bool notify_nl, bool force) + { + struct nh_res_bucket *bucket = &res_table->nh_buckets[bucket_index]; ++ struct netlink_ext_ack extack = {}; + struct nh_grp_entry *new_nhge; +- struct netlink_ext_ack extack; + int err; + + new_nhge = list_first_entry_or_null(&res_table->uw_nh_entries, +-- +2.53.0 + diff --git a/queue-6.18/nfp-check-resource-mutex-allocation.patch b/queue-6.18/nfp-check-resource-mutex-allocation.patch new file mode 100644 index 0000000000..ea12a646ff --- /dev/null +++ b/queue-6.18/nfp-check-resource-mutex-allocation.patch @@ -0,0 +1,52 @@ +From 9d0b3b9eb35e8744b81c1da7445f029b850a67b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:08 +0800 +Subject: nfp: Check resource mutex allocation + +From: Ruoyu Wang + +[ Upstream commit a61b4db34a753bdf5c9e77a7f3d3dddd41dcfacc ] + +nfp_cpp_resource_find() allocates a CPP mutex handle for the matching +resource-table entry and then reports success. nfp_resource_try_acquire() +immediately passes that handle to nfp_cpp_mutex_trylock(). + +However, nfp_cpp_mutex_alloc() returns NULL on failure. If that happens +for a matching table entry, the resource lookup still returns success and +the following trylock dereferences a NULL mutex pointer while opening the +resource. + +nfp_resource_acquire() already treats failure to allocate the table mutex +as -ENOMEM. Do the same for the resource mutex and fail the lookup before +publishing the rest of the resource handle. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: f01a2161577d ("nfp: add support for resources") +Signed-off-by: Ruoyu Wang +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708143408.3168425-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +index 279ea0b5695577..55525f45e447b7 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c ++++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +@@ -96,6 +96,9 @@ static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res) + res->mutex = + nfp_cpp_mutex_alloc(cpp, + NFP_RESOURCE_TBL_TARGET, addr, key); ++ if (!res->mutex) ++ return -ENOMEM; ++ + res->cpp_id = NFP_CPP_ID(entry.region.cpp_target, + entry.region.cpp_action, + entry.region.cpp_token); +-- +2.53.0 + diff --git a/queue-6.18/octeontx2-pf-tc-fix-egress-ratelimiting.patch b/queue-6.18/octeontx2-pf-tc-fix-egress-ratelimiting.patch new file mode 100644 index 0000000000..d54f2df38c --- /dev/null +++ b/queue-6.18/octeontx2-pf-tc-fix-egress-ratelimiting.patch @@ -0,0 +1,89 @@ +From 39109139a0bd4b4f5ffc72aa07eae2aa77adb4a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 14:13:49 +0530 +Subject: octeontx2-pf: tc: fix egress ratelimiting + +From: Hariprasad Kelam + +[ Upstream commit bb0d96ebe5f4d1acccf4dc36ca7f01f9a8fa1ba1 ] + +The egress rate calculation computes an incorrect mantissa and exponent, +causing up to ~50% deviation from the configured rate at lower speeds. + +Rework the computation to follow the hardware rate formula: + + rate = 2 * (1 + mantissa/256) * 2^exp / (1 << div_exp) + +Keep div_exp = 0 and derive exp and mantissa from half of the requested +rate. Rates below 2 Mbps are floored to the smallest encodable step +(exp = 0, mantissa = 0). + +Fixes: e638a83f167e ("octeontx2-pf: TC_MATCHALL egress ratelimiting offload") +Signed-off-by: Hariprasad Kelam +Signed-off-by: Nitin Shetty J +Link: https://patch.msgid.link/20260717084349.2227796-1-nshettyj@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 29 ++++++++++--------- + 1 file changed, 16 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +index 26a08d2cfbb1b6..f4906c67d5eee4 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +@@ -30,6 +30,7 @@ + #define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4) + + #define MCAST_INVALID_GRP (-1U) ++#define RATE_MANTISSA_BITS 8 + + struct otx2_tc_flow_stats { + u64 bytes; +@@ -90,28 +91,30 @@ static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, + static void otx2_get_egress_rate_cfg(u64 maxrate, u32 *exp, + u32 *mantissa, u32 *div_exp) + { +- u64 tmp; +- + /* Rate calculation by hardware + * + * PIR_ADD = ((256 + mantissa) << exp) / 256 + * rate = (2 * PIR_ADD) / ( 1 << div_exp) + * The resultant rate is in Mbps. ++ * ++ * Use div_exp = 0 and compute exp/mantissa for maxrate / 2; the ++ * leading factor of two yields the full rate. Rates below 2 Mbps ++ * are floored to the smallest step (exp = 0, mantissa = 0). + */ + +- /* 2Mbps to 100Gbps can be expressed with div_exp = 0. +- * Setting this to '0' will ease the calculation of +- * exponent and mantissa. +- */ + *div_exp = 0; +- + if (maxrate) { +- *exp = ilog2(maxrate) ? ilog2(maxrate) - 1 : 0; +- tmp = maxrate - rounddown_pow_of_two(maxrate); +- if (maxrate < MAX_RATE_MANTISSA) +- *mantissa = tmp * 2; +- else +- *mantissa = tmp / (1ULL << (*exp - 7)); ++ maxrate = maxrate / 2; ++ if (!maxrate) { ++ /* Rates below 2 Mbps map to the smallest step */ ++ *exp = 0; ++ *mantissa = 0; ++ } else { ++ *exp = ilog2(maxrate); ++ /* Clear MSB and derive fractional bits */ ++ maxrate &= ~BIT(*exp); ++ *mantissa = (maxrate << RATE_MANTISSA_BITS) >> *exp; ++ } + } else { + /* Instead of disabling rate limiting, set all values to max */ + *exp = MAX_RATE_EXPONENT; +-- +2.53.0 + diff --git a/queue-6.18/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch b/queue-6.18/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch new file mode 100644 index 0000000000..5897b84fc1 --- /dev/null +++ b/queue-6.18/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch @@ -0,0 +1,40 @@ +From b7f9a1b313ea12e558ca8915e316ab7c99292cf6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 10:50:07 +0530 +Subject: octeontx2-vf: set TC flower flag on MCAM entry allocation + +From: Suman Ghosh + +[ Upstream commit 0d4d31e3cc5dd6204fa1495c4107f5075acce5ed ] + +When MCAM entries are allocated for a VF netdev via the devlink +mcam_count parameter, only OTX2_FLAG_NTUPLE_SUPPORT was set. That +enabled ethtool ntuple filters but not tc flower offload. Also set +OTX2_FLAG_TC_FLOWER_SUPPORT when entries are successfully allocated. + +Fixes: 2da489432747 ("octeontx2-pf: devlink params support to set mcam entry count") +Signed-off-by: Suman Ghosh +Signed-off-by: Ratheesh Kannoth +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260715052007.2099851-1-rkannoth@marvell.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +index 64c6d9162ef644..17e8f6e51808b5 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +@@ -146,6 +146,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count) + if (allocated) { + pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC; + pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT; ++ pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT; + } + + if (allocated != count) +-- +2.53.0 + diff --git a/queue-6.18/ovl-add-override_creds-cleanup-guard-extension-for-o.patch b/queue-6.18/ovl-add-override_creds-cleanup-guard-extension-for-o.patch new file mode 100644 index 0000000000..7dd54c101d --- /dev/null +++ b/queue-6.18/ovl-add-override_creds-cleanup-guard-extension-for-o.patch @@ -0,0 +1,42 @@ +From ad2fd0ebbfdcf8acfc854e0367f2bc17434aeab4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 10:33:32 +0100 +Subject: ovl: add override_creds cleanup guard extension for overlayfs + +From: Christian Brauner + +[ Upstream commit 6f5c84162a30514a795eab3495a12c19306d6f6c ] + +Overlayfs plucks the relevant creds from the superblock. Extend the +override_creds cleanup class I added to override_creds_ovl which uses +the ovl_override_creds() function as initialization helper. Add +with_ovl_creds() based on this new class. + +Link: https://patch.msgid.link/20251117-work-ovl-cred-guard-v4-1-b31603935724@kernel.org +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner +Stable-dep-of: a1e0eb8f55cf ("ovl: check access to copy_file_range source with src mounter creds") +Signed-off-by: Sasha Levin +--- + fs/overlayfs/overlayfs.h | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h +index d1eb1cbe7a4561..696b13d9e1f102 100644 +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -445,6 +445,11 @@ struct dentry *ovl_workdir(struct dentry *dentry); + const struct cred *ovl_override_creds(struct super_block *sb); + void ovl_revert_creds(const struct cred *old_cred); + ++EXTEND_CLASS(override_creds, _ovl, ovl_override_creds(sb), struct super_block *sb) ++ ++#define with_ovl_creds(sb) \ ++ scoped_class(override_creds_ovl, __UNIQUE_ID(label), sb) ++ + static inline const struct cred *ovl_creds(struct super_block *sb) + { + return OVL_FS(sb)->creator_cred; +-- +2.53.0 + diff --git a/queue-6.18/ovl-check-access-to-copy_file_range-source-with-src-.patch b/queue-6.18/ovl-check-access-to-copy_file_range-source-with-src-.patch new file mode 100644 index 0000000000..e4265b2852 --- /dev/null +++ b/queue-6.18/ovl-check-access-to-copy_file_range-source-with-src-.patch @@ -0,0 +1,82 @@ +From 819745134c674b829b2441c59182cf2fd2f714a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:24:21 +0200 +Subject: ovl: check access to copy_file_range source with src mounter creds + +From: Amir Goldstein + +[ Upstream commit a1e0eb8f55cfe09bb31a202a388babc411292656 ] + +Commit 5dae222a5ff0c ("vfs: allow copy_file_range to copy across devices") +allowed filesystems that implement the copy_file_range() f_op to decide +if they want to access cross-sb copy from/to the same fs type. + +The same commit added checks to verify same sb copy for filesystems that +implement ->copy_file_range() and do not support cross-sb copy at the +time, namely, to ceph, fuse and nfs. + +The two remaining fs which implement ->copy_file_range(), cifs and +overlayfs started to support cross-sb copy from this time. + +While overlayfs does support cross-sb copy when the two underlying files +are on the same base fs, the copy operation on the two real files from +two different overalyfs filesystems is performed with the mounter +creds of the destination overlayfs and the read permission access hook +for the source file was called with the wrong creds. + +This could cause either deny of access to copy which would otherwise be +allowed (e.g. with splice) or allow read access to file which would +otherwise be denied. + +Fix the latter case by explicitly verifying read access to source file +with the source overlayfs mounter creds. + +The former case remains a quirk of cross-sb overlayfs copy, but +userspace could fall back to regular copy so no harm done. + +Fixes: 5dae222a5ff0c ("vfs: allow copy_file_range to copy across devices") +Signed-off-by: Amir Goldstein +Link: https://patch.msgid.link/20260712122421.203113-1-amir73il@gmail.com +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/overlayfs/file.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c +index 4374fbad3fc437..a857ce377b0cfb 100644 +--- a/fs/overlayfs/file.c ++++ b/fs/overlayfs/file.c +@@ -541,6 +541,7 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + loff_t len, unsigned int flags, enum ovl_copyop op) + { ++ struct inode *inode_in = file_inode(file_in); + struct inode *inode_out = file_inode(file_out); + struct file *realfile_in, *realfile_out; + loff_t ret; +@@ -564,7 +565,20 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + if (IS_ERR(realfile_in)) + goto out_unlock; + +- with_ovl_creds(file_inode(file_out)->i_sb) { ++ /* ++ * For cross-sb copy, vfs_copy_file_range() will verify read access with ++ * the mounter creds of the dest fs mounter, so we need to explicitly ++ * verify read access with the source mounter creds. ++ */ ++ if (unlikely(inode_in->i_sb != inode_out->i_sb)) { ++ with_ovl_creds(inode_in->i_sb) { ++ ret = rw_verify_area(READ, realfile_in, &pos_in, len); ++ if (unlikely(ret)) ++ goto out_unlock; ++ } ++ } ++ ++ with_ovl_creds(inode_out->i_sb) { + switch (op) { + case OVL_COPY: + ret = vfs_copy_file_range(realfile_in, pos_in, +-- +2.53.0 + diff --git a/queue-6.18/ovl-fix-trusted-xattr-escape-prefix-matching.patch b/queue-6.18/ovl-fix-trusted-xattr-escape-prefix-matching.patch new file mode 100644 index 0000000000..3fc7d4ce07 --- /dev/null +++ b/queue-6.18/ovl-fix-trusted-xattr-escape-prefix-matching.patch @@ -0,0 +1,49 @@ +From af0e90e7819d86d3d01f356f4a1ad24f233928c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:22:21 +0800 +Subject: ovl: fix trusted xattr escape prefix matching + +From: Yichong Chen + +[ Upstream commit a8e72879cd0d8422c0b47d6d3c1802274fe73b98 ] + +In the trusted.* xattr namespace, ovl_is_escaped_xattr() compares +one byte less than the escaped overlay xattr prefix length. This makes +it match "trusted.overlay.overlay" without requiring the trailing dot. + +As a result, an xattr such as "trusted.overlay.overlayfoo" is +incorrectly treated as an escaped overlay xattr. This can be reproduced +by setting "trusted.overlay.overlayfoo" on a lower file and listing xattrs +through an overlay mount. listxattr() then exposes it as +"trusted.overlay.oo", and a following getxattr() on that listed name fails +with ENODATA. + +Compare the full escaped prefix, including the trailing dot, so +similarly-prefixed private xattrs are not misclassified. + +Fixes: dad02fad84cbc ("ovl: Support escaped overlay.* xattrs") +Signed-off-by: Yichong Chen +Link: https://patch.msgid.link/20260708082221.633602-1-chenyichong@uniontech.com +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/overlayfs/xattrs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/overlayfs/xattrs.c b/fs/overlayfs/xattrs.c +index 88055deca9360f..c86f1a6c8b937a 100644 +--- a/fs/overlayfs/xattrs.c ++++ b/fs/overlayfs/xattrs.c +@@ -13,7 +13,7 @@ static bool ovl_is_escaped_xattr(struct super_block *sb, const char *name) + OVL_XATTR_ESCAPE_USER_PREFIX_LEN) == 0; + else + return strncmp(name, OVL_XATTR_ESCAPE_TRUSTED_PREFIX, +- OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN - 1) == 0; ++ OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN) == 0; + } + + static bool ovl_is_own_xattr(struct super_block *sb, const char *name) +-- +2.53.0 + diff --git a/queue-6.18/ovl-port-ovl_copyfile-to-cred-guard.patch b/queue-6.18/ovl-port-ovl_copyfile-to-cred-guard.patch new file mode 100644 index 0000000000..cedb5c2251 --- /dev/null +++ b/queue-6.18/ovl-port-ovl_copyfile-to-cred-guard.patch @@ -0,0 +1,79 @@ +From b1ffaae5b8cea71cdffae5bd2a7c62fbc7b525ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Nov 2025 10:34:07 +0100 +Subject: ovl: port ovl_copyfile() to cred guard + +From: Christian Brauner + +[ Upstream commit 14d35fda5b1139bacefb47c69f083fe2cfad211b ] + +Use the scoped ovl cred guard. + +Link: https://patch.msgid.link/20251117-work-ovl-cred-guard-v4-36-b31603935724@kernel.org +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner +Stable-dep-of: a1e0eb8f55cf ("ovl: check access to copy_file_range source with src mounter creds") +Signed-off-by: Sasha Levin +--- + fs/overlayfs/file.c | 37 ++++++++++++++++++------------------- + 1 file changed, 18 insertions(+), 19 deletions(-) + +diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c +index 3fedfdddfa7584..4374fbad3fc437 100644 +--- a/fs/overlayfs/file.c ++++ b/fs/overlayfs/file.c +@@ -543,7 +543,6 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + { + struct inode *inode_out = file_inode(file_out); + struct file *realfile_in, *realfile_out; +- const struct cred *old_cred; + loff_t ret; + + inode_lock(inode_out); +@@ -565,25 +564,25 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + if (IS_ERR(realfile_in)) + goto out_unlock; + +- old_cred = ovl_override_creds(file_inode(file_out)->i_sb); +- switch (op) { +- case OVL_COPY: +- ret = vfs_copy_file_range(realfile_in, pos_in, +- realfile_out, pos_out, len, flags); +- break; +- +- case OVL_CLONE: +- ret = vfs_clone_file_range(realfile_in, pos_in, +- realfile_out, pos_out, len, flags); +- break; +- +- case OVL_DEDUPE: +- ret = vfs_dedupe_file_range_one(realfile_in, pos_in, +- realfile_out, pos_out, len, +- flags); +- break; ++ with_ovl_creds(file_inode(file_out)->i_sb) { ++ switch (op) { ++ case OVL_COPY: ++ ret = vfs_copy_file_range(realfile_in, pos_in, ++ realfile_out, pos_out, len, flags); ++ break; ++ ++ case OVL_CLONE: ++ ret = vfs_clone_file_range(realfile_in, pos_in, ++ realfile_out, pos_out, len, flags); ++ break; ++ ++ case OVL_DEDUPE: ++ ret = vfs_dedupe_file_range_one(realfile_in, pos_in, ++ realfile_out, pos_out, len, ++ flags); ++ break; ++ } + } +- ovl_revert_creds(old_cred); + + /* Update size */ + ovl_file_modified(file_out); +-- +2.53.0 + diff --git a/queue-6.18/ovpn-avoid-putting-unrelated-p2p-peer-on-socket-rele.patch b/queue-6.18/ovpn-avoid-putting-unrelated-p2p-peer-on-socket-rele.patch new file mode 100644 index 0000000000..0c03321278 --- /dev/null +++ b/queue-6.18/ovpn-avoid-putting-unrelated-p2p-peer-on-socket-rele.patch @@ -0,0 +1,58 @@ +From 79133faf22c484d2a908ec7ed7a237b346ddc2c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 May 2026 16:15:43 +0800 +Subject: ovpn: avoid putting unrelated P2P peer on socket release + +From: Qing Ming + +[ Upstream commit b52c5103f64ee825996ca1ab8df7283cde8c5f86 ] + +ovpn_peer_release_p2p() is called when an OVPN UDP socket is being +destroyed. It checks the currently published P2P peer and releases it only +if that peer still uses the socket being destroyed. + +A peer replacement can publish a new peer before the old UDP socket is +destroyed. When the old socket destruction path runs afterwards, +ovpn_peer_release_p2p() observes the new peer through ovpn->peer. Since the +new peer uses a different socket, the function takes the socket mismatch +branch. + +That branch still calls ovpn_peer_put(peer). At this point, however, peer +is the currently published replacement peer, not the peer associated with +the socket being destroyed. Dropping its reference can free it while +ovpn->peer still points to it, leading to later use-after-free accesses +from the peer and socket cleanup paths. + +KASAN reports this as a slab-use-after-free on the kmalloc-1k ovpn_peer +object. In the reproducer, the object is allocated from ovpn_peer_new() via +ovpn_nl_peer_new_doit(), and freed through ovpn_peer_release_rcu() from RCU +callback processing. Observed access sites include ovpn_peer_remove(), +ovpn_socket_release(), ovpn_nl_peer_del_notify(), and unlock_ovpn(). + +Fix this by returning from the socket mismatch branch without putting the +peer. + +Fixes: f6226ae7a0cd ("ovpn: introduce the ovpn_socket object") +Signed-off-by: Qing Ming +Reviewed-by: Simon Horman +Signed-off-by: Antonio Quartulli +Signed-off-by: Sasha Levin +--- + drivers/net/ovpn/peer.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c +index 87a83321f1dd5f..795741645e5eb0 100644 +--- a/drivers/net/ovpn/peer.c ++++ b/drivers/net/ovpn/peer.c +@@ -1162,7 +1162,6 @@ static void ovpn_peer_release_p2p(struct ovpn_priv *ovpn, struct sock *sk, + ovpn_sock = rcu_access_pointer(peer->sock); + if (!ovpn_sock || ovpn_sock->sk != sk) { + spin_unlock_bh(&ovpn->lock); +- ovpn_peer_put(peer); + return; + } + } +-- +2.53.0 + diff --git a/queue-6.18/ovpn-fix-use-after-free-in-unlock_ovpn.patch b/queue-6.18/ovpn-fix-use-after-free-in-unlock_ovpn.patch new file mode 100644 index 0000000000..db71db5e00 --- /dev/null +++ b/queue-6.18/ovpn-fix-use-after-free-in-unlock_ovpn.patch @@ -0,0 +1,51 @@ +From 9f672a2c66db0ab3f228af9132a5968506a235dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Jun 2026 16:04:46 +0200 +Subject: ovpn: fix use after free in unlock_ovpn() + +From: Marco Baffo + +[ Upstream commit e1ad6fe5db719874efa45b2caf9934552e09fc43 ] + +unlock_ovpn() iterates over the release_list using llist_for_each_entry() +and drops the peer reference inside the loop body via ovpn_peer_put(). + +If this drops the last reference, the peer is eventually freed. However, +llist_for_each_entry() reads peer->release_entry.next in the loop advance +expression, which runs after the body. By that time the peer may have +already been freed, resulting in a use after free when advancing to the +next list entry. + +Fix this by using llist_for_each_entry_safe(), which caches the next +pointer before executing the loop body. + +Fixes: 80747caef33d ("ovpn: introduce the ovpn_peer object") +Signed-off-by: Marco Baffo +Signed-off-by: Antonio Quartulli +Signed-off-by: Sasha Levin +--- + drivers/net/ovpn/peer.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c +index 795741645e5eb0..7e7ccae1325179 100644 +--- a/drivers/net/ovpn/peer.c ++++ b/drivers/net/ovpn/peer.c +@@ -26,11 +26,12 @@ static void unlock_ovpn(struct ovpn_priv *ovpn, + struct llist_head *release_list) + __releases(&ovpn->lock) + { +- struct ovpn_peer *peer; ++ struct ovpn_peer *peer, *next; + + spin_unlock_bh(&ovpn->lock); + +- llist_for_each_entry(peer, release_list->first, release_entry) { ++ llist_for_each_entry_safe(peer, next, release_list->first, ++ release_entry) { + ovpn_socket_release(peer); + ovpn_peer_put(peer); + } +-- +2.53.0 + diff --git a/queue-6.18/ovpn-use-monotonic-clock-for-peer-keepalive-timeouts.patch b/queue-6.18/ovpn-use-monotonic-clock-for-peer-keepalive-timeouts.patch new file mode 100644 index 0000000000..936e947d20 --- /dev/null +++ b/queue-6.18/ovpn-use-monotonic-clock-for-peer-keepalive-timeouts.patch @@ -0,0 +1,80 @@ +From 36358550de51e7c18b5c31dfa7bfde6e797aba84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Jun 2026 16:06:42 +0200 +Subject: ovpn: use monotonic clock for peer keepalive timeouts + +From: Marco Baffo + +[ Upstream commit f7e6287ccd3abeed9e638b581dc3fdf742106ba3 ] + +Replace ktime_get_real_seconds() with the monotonic +ktime_get_boottime_seconds() to ensure the keepalive mechanism is robust +against system clock modifications. + +Right now, the driver uses ktime_get_real_seconds() to track peer +timeouts, relying on the system wall-clock. + +An administrative time adjustment or an NTP sync that steps the clock +forward can cause `now' to instantly exceed `last_recv + timeout'. + +When this occurs, the driver artificially expires healthy peers. +Depending on the OpenVPN user-space configuration, this triggers a +premature tunnel restart (if --keepalive or --ping-restart is used) or +a complete disconnection of the client (if --ping-exit is used). + +Fixes: 3ecfd9349f40 ("ovpn: implement keepalive mechanism") +Signed-off-by: Marco Baffo +Signed-off-by: Antonio Quartulli +Signed-off-by: Sasha Levin +--- + drivers/net/ovpn/io.c | 4 ++-- + drivers/net/ovpn/peer.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c +index c03e58e28a860d..0008a3d30c198b 100644 +--- a/drivers/net/ovpn/io.c ++++ b/drivers/net/ovpn/io.c +@@ -137,7 +137,7 @@ void ovpn_decrypt_post(void *data, int ret) + } + + /* keep track of last received authenticated packet for keepalive */ +- WRITE_ONCE(peer->last_recv, ktime_get_real_seconds()); ++ WRITE_ONCE(peer->last_recv, ktime_get_boottime_seconds()); + + rcu_read_lock(); + sock = rcu_dereference(peer->sock); +@@ -291,7 +291,7 @@ void ovpn_encrypt_post(void *data, int ret) + + ovpn_peer_stats_increment_tx(&peer->link_stats, orig_len); + /* keep track of last sent packet for keepalive */ +- WRITE_ONCE(peer->last_sent, ktime_get_real_seconds()); ++ WRITE_ONCE(peer->last_sent, ktime_get_boottime_seconds()); + /* skb passed down the stack - don't free it */ + skb = NULL; + err_unlock: +diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c +index 7e7ccae1325179..b7c103fda2ae68 100644 +--- a/drivers/net/ovpn/peer.c ++++ b/drivers/net/ovpn/peer.c +@@ -45,7 +45,7 @@ static void unlock_ovpn(struct ovpn_priv *ovpn, + */ + void ovpn_peer_keepalive_set(struct ovpn_peer *peer, u32 interval, u32 timeout) + { +- time64_t now = ktime_get_real_seconds(); ++ time64_t now = ktime_get_boottime_seconds(); + + netdev_dbg(peer->ovpn->dev, + "scheduling keepalive for peer %u: interval=%u timeout=%u\n", +@@ -1352,7 +1352,7 @@ void ovpn_peer_keepalive_work(struct work_struct *work) + { + struct ovpn_priv *ovpn = container_of(work, struct ovpn_priv, + keepalive_work.work); +- time64_t next_run = 0, now = ktime_get_real_seconds(); ++ time64_t next_run = 0, now = ktime_get_boottime_seconds(); + LLIST_HEAD(release_list); + + spin_lock_bh(&ovpn->lock); +-- +2.53.0 + diff --git a/queue-6.18/pds_core-check-for-workqueue-allocation-failure.patch b/queue-6.18/pds_core-check-for-workqueue-allocation-failure.patch new file mode 100644 index 0000000000..69ad9d7329 --- /dev/null +++ b/queue-6.18/pds_core-check-for-workqueue-allocation-failure.patch @@ -0,0 +1,71 @@ +From 6a8848b37e32c4b870157aea8670c1f056847702 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:27:13 +0000 +Subject: pds_core: check for workqueue allocation failure + +From: Nikhil P. Rao + +[ Upstream commit 3a660ca49e2c3807bffe0519db3cff677a5906e0 ] + +pdsc_init_pf() does not check whether create_singlethread_workqueue() +succeeded. + +Fail probe on failure. The workqueue is set up before the timer and +mutexes, so its failure path must unwind only the earlier setup. + +Fixes: c2dbb0904310 ("pds_core: health timer and workqueue") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Brett Creeley +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714212713.1788438-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/main.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c +index accf3a3fe94457..a4962dba3140b8 100644 +--- a/drivers/net/ethernet/amd/pds_core/main.c ++++ b/drivers/net/ethernet/amd/pds_core/main.c +@@ -239,6 +239,10 @@ static int pdsc_init_pf(struct pdsc *pdsc) + /* General workqueue and timer, but don't start timer yet */ + snprintf(wq_name, sizeof(wq_name), "%s.%d", PDS_CORE_DRV_NAME, pdsc->uid); + pdsc->wq = create_singlethread_workqueue(wq_name); ++ if (!pdsc->wq) { ++ err = -ENOMEM; ++ goto err_out_unmap_bars; ++ } + INIT_WORK(&pdsc->health_work, pdsc_health_thread); + INIT_WORK(&pdsc->pci_reset_work, pdsc_pci_reset_thread); + timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0); +@@ -254,7 +258,7 @@ static int pdsc_init_pf(struct pdsc *pdsc) + err = pdsc_setup(pdsc, PDSC_SETUP_INIT); + if (err) { + mutex_unlock(&pdsc->config_lock); +- goto err_out_unmap_bars; ++ goto err_out_shutdown_timer; + } + + err = pdsc_start(pdsc); +@@ -306,13 +310,14 @@ static int pdsc_init_pf(struct pdsc *pdsc) + pdsc_stop(pdsc); + err_out_teardown: + pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING); +-err_out_unmap_bars: ++err_out_shutdown_timer: + timer_shutdown_sync(&pdsc->wdtimer); + if (pdsc->wq) + destroy_workqueue(pdsc->wq); + mutex_destroy(&pdsc->config_lock); + mutex_destroy(&pdsc->devcmd_lock); + pci_free_irq_vectors(pdsc->pdev); ++err_out_unmap_bars: + pdsc_unmap_bars(pdsc); + err_out_release_regions: + pci_release_regions(pdsc->pdev); +-- +2.53.0 + diff --git a/queue-6.18/pds_core-fix-auxiliary-device-add-del-races.patch b/queue-6.18/pds_core-fix-auxiliary-device-add-del-races.patch new file mode 100644 index 0000000000..fb97f33fc0 --- /dev/null +++ b/queue-6.18/pds_core-fix-auxiliary-device-add-del-races.patch @@ -0,0 +1,80 @@ +From e9db86cfb59204613e7c705d7fddd9f66b2da8c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:07:45 +0000 +Subject: pds_core: fix auxiliary device add/del races + +From: Nikhil P. Rao + +[ Upstream commit bfa33cd513c7ceb93c5a4c30e5662acd73c0a916 ] + +Two paths add or delete the same slot (pf->vfs[vf_id].padev): a VF's +pdsc_reset_done() and the PF's devlink enable_vnet/disable_vnet handler. +They serialize on config_lock, but neither guards the slot under it +correctly. + +add() registers and stores a new auxiliary device without first checking +the slot, so a second add of an already-populated slot leaks the first +device. del() makes that check outside config_lock, so two concurrent +dels can both pass it; the first clears the slot, and the second +dereferences a NULL pointer. + +Check and update the slot under config_lock in both paths. + +Fixes: b699bdc720c0 ("pds_core: specify auxiliary_device to be created") +Reported-by: sashiko-bot@kernel.org # Running on a local machine +Signed-off-by: Nikhil P. Rao +Reviewed-by: Brett Creeley +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714210745.1785625-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/auxbus.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c +index 92f359f2b44920..874812bafc1d39 100644 +--- a/drivers/net/ethernet/amd/pds_core/auxbus.c ++++ b/drivers/net/ethernet/amd/pds_core/auxbus.c +@@ -177,17 +177,21 @@ void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf, + { + struct pds_auxiliary_dev *padev; + +- if (!*pd_ptr) +- return; +- + mutex_lock(&pf->config_lock); + ++ /* A concurrent del may have already torn this device down and ++ * cleared it. ++ */ + padev = *pd_ptr; ++ if (!padev) ++ goto out_unlock; ++ + pds_client_unregister(pf, padev->client_id); + auxiliary_device_delete(&padev->aux_dev); + auxiliary_device_uninit(&padev->aux_dev); + *pd_ptr = NULL; + ++out_unlock: + mutex_unlock(&pf->config_lock); + } + +@@ -210,6 +214,13 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf, + + mutex_lock(&pf->config_lock); + ++ /* Nothing to do if the aux device is already present. This also ++ * guards against a second add overwriting *pd_ptr and leaking the ++ * first, symmetric with the check in pdsc_auxbus_dev_del(). ++ */ ++ if (*pd_ptr) ++ goto out_unlock; ++ + mask = BIT_ULL(PDSC_S_FW_DEAD) | + BIT_ULL(PDSC_S_STOPPING_DRIVER); + if (cf->state & mask) { +-- +2.53.0 + diff --git a/queue-6.18/pds_core-fix-deadlock-between-reset-thread-and-remov.patch b/queue-6.18/pds_core-fix-deadlock-between-reset-thread-and-remov.patch new file mode 100644 index 0000000000..2d379ecacc --- /dev/null +++ b/queue-6.18/pds_core-fix-deadlock-between-reset-thread-and-remov.patch @@ -0,0 +1,59 @@ +From f0bcff721e732755a66457baaf9b01a4b33e4540 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:02:22 +0000 +Subject: pds_core: fix deadlock between reset thread and remove + +From: Nikhil P. Rao + +[ Upstream commit ab0eec0ff0a421737a37f510ceab5c6ea59cd05a ] + +pci_reset_function() acquires device_lock before performing the reset. +pdsc_remove() is called by the PCI core with device_lock already held. +If pdsc_pci_reset_thread() is running when pdsc_remove() is called, +destroy_workqueue() will block waiting for the work to complete, while +the work is blocked waiting for device_lock - deadlock. + +Use pci_try_reset_function() which uses pci_dev_trylock() internally. +This acquires both the device lock and the PCI config access lock +without blocking - if either lock is contended, it returns -EAGAIN +immediately. This avoids the deadlock while also ensuring proper +config space access serialization during the reset. + +The pci_dev_get/put calls are also removed as they were unnecessary - +the driver-owned workqueue is destroyed in pdsc_remove(), guaranteeing +the work completes before remove returns. The PCI core holds its +reference to pci_dev throughout the entire unbind sequence. + +Fixes: 81665adf25d2 ("pds_core: Fix pdsc_check_pci_health function to use work thread") +Reported-by: sashiko-bot +Closes: https://patchwork.kernel.org/comment/27002369/ +Signed-off-by: Nikhil P. Rao +Reviewed-by: Harshitha Ramamurthy +Link: https://patch.msgid.link/20260714180223.1642792-2-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/core.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c +index 076dfe2910c770..1978287cf275fc 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.c ++++ b/drivers/net/ethernet/amd/pds_core/core.c +@@ -603,9 +603,10 @@ void pdsc_pci_reset_thread(struct work_struct *work) + struct pdsc *pdsc = container_of(work, struct pdsc, pci_reset_work); + struct pci_dev *pdev = pdsc->pdev; + +- pci_dev_get(pdev); +- pci_reset_function(pdev); +- pci_dev_put(pdev); ++ /* Use try variant to avoid deadlock with pdsc_remove(). ++ * If lock is contended, the watchdog timer will retry. ++ */ ++ pci_try_reset_function(pdev); + } + + static void pdsc_check_pci_health(struct pdsc *pdsc) +-- +2.53.0 + diff --git a/queue-6.18/pds_core-fix-use-after-free-on-workqueue-during-remo.patch b/queue-6.18/pds_core-fix-use-after-free-on-workqueue-during-remo.patch new file mode 100644 index 0000000000..24f7da7da2 --- /dev/null +++ b/queue-6.18/pds_core-fix-use-after-free-on-workqueue-during-remo.patch @@ -0,0 +1,120 @@ +From 4a829173964064fbcbb44d8b7e7465c09851ab2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:02:23 +0000 +Subject: pds_core: fix use-after-free on workqueue during remove + +From: Nikhil P. Rao + +[ Upstream commit 0ad134881508c36b65c1a8864f8bec53adbd3327 ] + +In pdsc_remove(), the workqueue is destroyed before pdsc_teardown() +is called. This ordering allows two paths to queue work on the +destroyed workqueue: + +1. If pdsc_teardown() -> pdsc_devcmd_reset() times out, the error + path in pdsc_devcmd_locked() queues health_work. + +2. A NotifyQ event can trigger the ISR and queue work before free_irq() + is called in pdsc_teardown(). + +Fix by moving destroy_workqueue() after pdsc_teardown() so the +workqueue outlives every queuer; destroy_workqueue() then flushes any +work still pending. + +Draining the queued work also requires ordering the teardown so the +resources that work touches are freed last: + + - In pdsc_qcq_free(), after freeing the interrupt, cancel_work_sync() + the queue's work and only then clear qcq->intx, so + pdsc_process_adminq()'s read of qcq->intx for interrupt-credit + return cannot race with the clear. + + - Free adminqcq before notifyqcq: the shared adminq ISR is released + when adminqcq is freed, and the adminq work accesses notifyqcq, so + both must be stopped before notifyqcq is freed. + +Fixes: 01ba61b55b20 ("pds_core: Add adminq processing and commands") +Reported-by: sashiko-bot +Closes: https://patchwork.kernel.org/comment/27002369/ +Signed-off-by: Nikhil P. Rao +Link: https://patch.msgid.link/20260714180223.1642792-3-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/core.c | 14 ++++++++++---- + drivers/net/ethernet/amd/pds_core/main.c | 5 +++-- + 2 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c +index 1978287cf275fc..d64e30a204dfcb 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.c ++++ b/drivers/net/ethernet/amd/pds_core/core.c +@@ -110,7 +110,6 @@ static void pdsc_qcq_intr_free(struct pdsc *pdsc, struct pdsc_qcq *qcq) + return; + + pdsc_intr_free(pdsc, qcq->intx); +- qcq->intx = PDS_CORE_INTR_INDEX_NOT_ASSIGNED; + } + + static int pdsc_qcq_intr_alloc(struct pdsc *pdsc, struct pdsc_qcq *qcq) +@@ -145,6 +144,12 @@ void pdsc_qcq_free(struct pdsc *pdsc, struct pdsc_qcq *qcq) + + pdsc_qcq_intr_free(pdsc, qcq); + ++ /* Drain any work queued by ISR before it was freed above */ ++ if (qcq->work.func) ++ cancel_work_sync(&qcq->work); ++ ++ qcq->intx = PDS_CORE_INTR_INDEX_NOT_ASSIGNED; ++ + if (qcq->q_base) + dma_free_coherent(dev, qcq->q_size, + qcq->q_base, qcq->q_base_pa); +@@ -304,8 +309,11 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index, + + static void pdsc_core_uninit(struct pdsc *pdsc) + { +- pdsc_qcq_free(pdsc, &pdsc->notifyqcq); ++ /* Free adminqcq first: its work accesses notifyqcq, so we must ++ * disable its IRQ and drain its work before freeing notifyqcq. ++ */ + pdsc_qcq_free(pdsc, &pdsc->adminqcq); ++ pdsc_qcq_free(pdsc, &pdsc->notifyqcq); + + if (pdsc->kern_dbpage) { + iounmap(pdsc->kern_dbpage); +@@ -478,8 +486,6 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing) + { + if (!pdsc->pdev->is_virtfn) + pdsc_devcmd_reset(pdsc); +- if (pdsc->adminqcq.work.func) +- cancel_work_sync(&pdsc->adminqcq.work); + + pdsc_core_uninit(pdsc); + +diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c +index c7a2eff576325f..accf3a3fe94457 100644 +--- a/drivers/net/ethernet/amd/pds_core/main.c ++++ b/drivers/net/ethernet/amd/pds_core/main.c +@@ -436,8 +436,6 @@ static void pdsc_remove(struct pci_dev *pdev) + pdsc_auxbus_dev_del(pdsc, pdsc, &pdsc->padev); + + timer_shutdown_sync(&pdsc->wdtimer); +- if (pdsc->wq) +- destroy_workqueue(pdsc->wq); + + mutex_lock(&pdsc->config_lock); + set_bit(PDSC_S_STOPPING_DRIVER, &pdsc->state); +@@ -445,6 +443,9 @@ static void pdsc_remove(struct pci_dev *pdev) + pdsc_stop(pdsc); + pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING); + mutex_unlock(&pdsc->config_lock); ++ ++ if (pdsc->wq) ++ destroy_workqueue(pdsc->wq); + mutex_destroy(&pdsc->config_lock); + mutex_destroy(&pdsc->devcmd_lock); + +-- +2.53.0 + diff --git a/queue-6.18/pds_core-order-completion-reads-after-the-ownership-.patch b/queue-6.18/pds_core-order-completion-reads-after-the-ownership-.patch new file mode 100644 index 0000000000..558c01f92e --- /dev/null +++ b/queue-6.18/pds_core-order-completion-reads-after-the-ownership-.patch @@ -0,0 +1,62 @@ +From 8540fe9f256105cd592ab7b91beef6186d572c60 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 20:41:45 +0000 +Subject: pds_core: order completion reads after the ownership check + +From: Nikhil P. Rao + +[ Upstream commit dd6b1cc748cd28147c113f9daa76393916ad9494 ] + +pdsc_process_adminq() and pdsc_process_notifyq() decide a completion is +valid from its ownership field - the color bit for the adminq, the event +id for the notifyq - then read the rest of the descriptor, with no +barrier in between. + +On a weakly ordered architecture the CPU may read the payload first. Add +dma_rmb() between the ownership read and the payload reads. + +Fixes: 7e82a8745b95 ("pds_core: Prevent race issues involving the adminq") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Eric Joyner +Link: https://patch.msgid.link/20260714204145.1782390-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/adminq.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/adminq.c b/drivers/net/ethernet/amd/pds_core/adminq.c +index 097bb092bdb8cd..eadb4b604fbe3c 100644 +--- a/drivers/net/ethernet/amd/pds_core/adminq.c ++++ b/drivers/net/ethernet/amd/pds_core/adminq.c +@@ -18,7 +18,13 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq) + comp = cq_info->comp; + eid = le64_to_cpu(comp->event.eid); + while (eid > pdsc->last_eid) { +- u16 ecode = le16_to_cpu(comp->event.ecode); ++ u16 ecode; ++ ++ /* Order the payload read after the event id, the field the ++ * driver uses to detect a new completion. ++ */ ++ dma_rmb(); ++ ecode = le16_to_cpu(comp->event.ecode); + + switch (ecode) { + case PDS_EVENT_LINK_CHANGE: +@@ -101,6 +107,10 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq) + spin_lock_irqsave(&pdsc->adminq_lock, irqflags); + comp = cq->info[cq->tail_idx].comp; + while (pdsc_color_match(comp->color, cq->done_color)) { ++ /* Order the payload reads after the color bit, the field the ++ * driver uses to detect a new completion. ++ */ ++ dma_rmb(); + q_info = &q->info[q->tail_idx]; + q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1); + +-- +2.53.0 + diff --git a/queue-6.18/pds_core-reject-component-parameter-in-legacy-firmwa.patch b/queue-6.18/pds_core-reject-component-parameter-in-legacy-firmwa.patch new file mode 100644 index 0000000000..7be425de54 --- /dev/null +++ b/queue-6.18/pds_core-reject-component-parameter-in-legacy-firmwa.patch @@ -0,0 +1,44 @@ +From c264dbc0880a170b4446f9acea4a7566567a5fcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:36:49 +0000 +Subject: pds_core: reject component parameter in legacy firmware update + +From: Nikhil P. Rao + +[ Upstream commit 7be2552e601c247a328a5aba6fc06ac844b94a16 ] + +The legacy firmware update path does not support per-component updates. +If a user specifies a component parameter with devlink flash, reject +the request with -EOPNOTSUPP rather than silently ignoring the component +parameter and flashing the entire firmware image. + +Fixes: 49ce92fbee0b ("pds_core: add FW update feature to devlink") +Signed-off-by: Nikhil P. Rao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708163649.128620-1-nikhil.rao@amd.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/devlink.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c +index 621791a3c543be..e35572f099c884 100644 +--- a/drivers/net/ethernet/amd/pds_core/devlink.c ++++ b/drivers/net/ethernet/amd/pds_core/devlink.c +@@ -89,6 +89,12 @@ int pdsc_dl_flash_update(struct devlink *dl, + { + struct pdsc *pdsc = devlink_priv(dl); + ++ if (params->component) { ++ NL_SET_ERR_MSG_MOD(extack, ++ "Component update not supported by this device"); ++ return -EOPNOTSUPP; ++ } ++ + return pdsc_firmware_update(pdsc, params->fw, extack); + } + +-- +2.53.0 + diff --git a/queue-6.18/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch b/queue-6.18/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch new file mode 100644 index 0000000000..20d4ae9a51 --- /dev/null +++ b/queue-6.18/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch @@ -0,0 +1,53 @@ +From 5c8ce39ecb50374e8b29ce7c24a159a170d70dcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 20:14:56 +0000 +Subject: pds_core: yield the CPU while waiting for the adminq to drain + +From: Nikhil P. Rao + +[ Upstream commit a11f0b8a204296fe7db9eaec53441012222cb004 ] + +pdsc_adminq_wait_and_dec_once_unused() busy-waits for adminq_refcnt to +drop to one: + + while (!refcount_dec_if_one(&pdsc->adminq_refcnt)) + cpu_relax(); + +The refcount is held by pdsc_adminq_post() for the duration of an +in-flight command, which can wait up to devcmd_timeout seconds +(PDS_CORE_DEVCMD_TIMEOUT is 5) for the hardware to complete. cpu_relax() +is not a reschedule point, so on a non-preemptible kernel this loop can +spin on the CPU for several seconds, starving other tasks on that core. + +Add cond_resched() to the loop so the waiter yields to other runnable +tasks while it polls, keeping cpu_relax() as the busy-wait hint between +checks. + +Fixes: 7e82a8745b95 ("pds_core: Prevent race issues involving the adminq") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Eric Joyner +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714201456.1776153-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c +index d64e30a204dfcb..d02e096a2c5fb3 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.c ++++ b/drivers/net/ethernet/amd/pds_core/core.c +@@ -536,6 +536,7 @@ static void pdsc_adminq_wait_and_dec_once_unused(struct pdsc *pdsc) + dev_dbg_ratelimited(pdsc->dev, "%s: adminq in use\n", + __func__); + cpu_relax(); ++ cond_resched(); + } + } + +-- +2.53.0 + diff --git a/queue-6.18/ppp-annotate-concurrent-dev-stats-accesses.patch b/queue-6.18/ppp-annotate-concurrent-dev-stats-accesses.patch new file mode 100644 index 0000000000..9451e69828 --- /dev/null +++ b/queue-6.18/ppp-annotate-concurrent-dev-stats-accesses.patch @@ -0,0 +1,142 @@ +From 7845dfb5ab7363e0054c58356bf840e76740023f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 05:55:41 +0000 +Subject: ppp: annotate concurrent dev->stats accesses + +From: Eric Dumazet + +[ Upstream commit ba712ecfd942b68b21a4b0a5daaf72f6616cc66d ] + +dev->stats fields can be updated concurrently from multiple CPUs +without synchronization. + +Use DEV_STATS_INC() for stats increments and DEV_STATS_READ() +when reading dev->stats in ppp_get_stats64() and ppp_get_stats() +to avoid data races. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/20260715055541.1147542-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index e09a916356a1d4..a2fe0fe2f3389f 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1490,7 +1490,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) + + outf: + kfree_skb(skb); +- ++dev->stats.tx_dropped; ++ DEV_STATS_INC(dev, tx_dropped); + return NETDEV_TX_OK; + } + +@@ -1540,11 +1540,11 @@ ppp_net_siocdevprivate(struct net_device *dev, struct ifreq *ifr, + static void + ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) + { +- stats64->rx_errors = dev->stats.rx_errors; +- stats64->tx_errors = dev->stats.tx_errors; +- stats64->rx_dropped = dev->stats.rx_dropped; +- stats64->tx_dropped = dev->stats.tx_dropped; +- stats64->rx_length_errors = dev->stats.rx_length_errors; ++ stats64->rx_errors = DEV_STATS_READ(dev, rx_errors); ++ stats64->tx_errors = DEV_STATS_READ(dev, tx_errors); ++ stats64->rx_dropped = DEV_STATS_READ(dev, rx_dropped); ++ stats64->tx_dropped = DEV_STATS_READ(dev, tx_dropped); ++ stats64->rx_length_errors = DEV_STATS_READ(dev, rx_length_errors); + dev_fetch_sw_netstats(stats64, dev->tstats); + } + +@@ -1901,7 +1901,7 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb) + + drop: + kfree_skb(skb); +- ++ppp->dev->stats.tx_errors; ++ DEV_STATS_INC(ppp->dev, tx_errors); + return 1; + } + +@@ -2191,7 +2191,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + err_linearize: + if (ppp->debug & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); +- ++ppp->dev->stats.tx_errors; ++ DEV_STATS_INC(ppp->dev, tx_errors); + ++ppp->nxseq; + return 1; /* abandon the frame */ + } +@@ -2364,7 +2364,7 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) + if (!ppp_decompress_proto(skb)) { + kfree_skb(skb); + if (ppp) { +- ++ppp->dev->stats.rx_length_errors; ++ DEV_STATS_INC(ppp->dev, rx_length_errors); + ppp_receive_error(ppp); + } + goto done; +@@ -2437,7 +2437,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) + static void + ppp_receive_error(struct ppp *ppp) + { +- ++ppp->dev->stats.rx_errors; ++ DEV_STATS_INC(ppp->dev, rx_errors); + if (ppp->vj) + slhc_toss(ppp->vj); + } +@@ -2704,7 +2704,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) + */ + if (seq_before(seq, ppp->nextseq)) { + kfree_skb(skb); +- ++ppp->dev->stats.rx_dropped; ++ DEV_STATS_INC(ppp->dev, rx_dropped); + ppp_receive_error(ppp); + return; + } +@@ -2740,7 +2740,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) + if (pskb_may_pull(skb, 2)) + ppp_receive_nonmp_frame(ppp, skb); + else { +- ++ppp->dev->stats.rx_length_errors; ++ DEV_STATS_INC(ppp->dev, rx_length_errors); + kfree_skb(skb); + ppp_receive_error(ppp); + } +@@ -2846,7 +2846,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + if (lost == 0 && (PPP_MP_CB(p)->BEbits & E) && + (PPP_MP_CB(head)->BEbits & B)) { + if (len > ppp->mrru + 2) { +- ++ppp->dev->stats.rx_length_errors; ++ DEV_STATS_INC(ppp->dev, rx_length_errors); + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: reconstructed packet" + " is too long (%d)\n", len); +@@ -2901,7 +2901,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + " missed pkts %u..%u\n", + ppp->nextseq, + PPP_MP_CB(head)->sequence-1); +- ++ppp->dev->stats.rx_dropped; ++ DEV_STATS_INC(ppp->dev, rx_dropped); + ppp_receive_error(ppp); + } + +@@ -3370,8 +3370,8 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) + st->p.ppp_opackets += tx_packets; + st->p.ppp_obytes += tx_bytes; + } +- st->p.ppp_ierrors = ppp->dev->stats.rx_errors; +- st->p.ppp_oerrors = ppp->dev->stats.tx_errors; ++ st->p.ppp_ierrors = DEV_STATS_READ(ppp->dev, rx_errors); ++ st->p.ppp_oerrors = DEV_STATS_READ(ppp->dev, tx_errors); + if (!vj) + return; + st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; +-- +2.53.0 + diff --git a/queue-6.18/ppp-annotate-data-races-in-ppp_generic.patch b/queue-6.18/ppp-annotate-data-races-in-ppp_generic.patch new file mode 100644 index 0000000000..7b9dc314e2 --- /dev/null +++ b/queue-6.18/ppp-annotate-data-races-in-ppp_generic.patch @@ -0,0 +1,233 @@ +From db9e1508fdd5d84c3db152097501d3671ca28b04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:16:05 +0000 +Subject: ppp: annotate data races in ppp_generic + +From: Eric Dumazet + +[ Upstream commit 543adf072165aaf2e3b635c0476204f9658ed3bf ] + +Several fields in struct ppp can be read or updated concurrently +from multiple CPUs without synchronization, causing data races: + +1. ppp->mru is read concurrently in ppp_receive_nonmp_frame() while + being updated via PPPIOCSMRU ioctl. Protect ppp->mru updates in + PPPIOCSMRU with ppp_recv_lock(ppp). + +2. PPPIOCGFLAGS reads ppp->flags, ppp->xstate, and ppp->rstate + unlocked. Wrap the read in ppp_lock(ppp) to get a consistent + snapshot. + +3. ppp->debug is updated via PPPIOCSDEBUG and read concurrently on + fast paths. Annotate reads with READ_ONCE() and writes with + WRITE_ONCE(). + +4. ppp->last_xmit and ppp->last_recv are updated on TX/RX data paths + and read via PPPIOCGIDLE32 / PPPIOCGIDLE64 ioctls. Annotate with + WRITE_ONCE() / READ_ONCE() and use max() to handle jiffies + subtraction. + +5. ppp->npmode[] is updated via PPPIOCSNPMODE and read on TX/RX + paths. Annotate with WRITE_ONCE() / READ_ONCE(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/20260722101605.2868548-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 50 ++++++++++++++++++++--------------- + 1 file changed, 28 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index a2fe0fe2f3389f..14fa87a8e08345 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -818,7 +818,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case PPPIOCSMRU: + if (get_user(val, p)) + break; ++ ppp_recv_lock(ppp); + ppp->mru = val; ++ ppp_recv_unlock(ppp); + err = 0; + break; + +@@ -839,7 +841,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + + case PPPIOCGFLAGS: ++ ppp_lock(ppp); + val = ppp->flags | ppp->xstate | ppp->rstate; ++ ppp_unlock(ppp); + if (put_user(val, p)) + break; + err = 0; +@@ -863,7 +867,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case PPPIOCSDEBUG: + if (get_user(val, p)) + break; +- ppp->debug = val; ++ WRITE_ONCE(ppp->debug, val); + err = 0; + break; + +@@ -874,16 +878,16 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + + case PPPIOCGIDLE32: +- idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ; +- idle32.recv_idle = (jiffies - ppp->last_recv) / HZ; +- if (copy_to_user(argp, &idle32, sizeof(idle32))) ++ idle32.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ; ++ idle32.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ; ++ if (copy_to_user(argp, &idle32, sizeof(idle32))) + break; + err = 0; + break; + + case PPPIOCGIDLE64: +- idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ; +- idle64.recv_idle = (jiffies - ppp->last_recv) / HZ; ++ idle64.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ; ++ idle64.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ; + if (copy_to_user(argp, &idle64, sizeof(idle64))) + break; + err = 0; +@@ -924,7 +928,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + if (copy_to_user(argp, &npi, sizeof(npi))) + break; + } else { +- ppp->npmode[i] = npi.mode; ++ WRITE_ONCE(ppp->npmode[i], npi.mode); + /* we may be able to transmit more packets now (??) */ + netif_wake_queue(ppp->dev); + } +@@ -1462,7 +1466,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) + goto outf; + + /* Drop, accept or reject the packet */ +- switch (ppp->npmode[npi]) { ++ switch (READ_ONCE(ppp->npmode[npi])) { + case NPMODE_PASS: + break; + case NPMODE_QUEUE: +@@ -1802,7 +1806,7 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb) + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_OUTBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: outbound frame " + "not passed\n"); +@@ -1812,11 +1816,11 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb) + /* if this packet passes the active filter, record the time */ + if (!(ppp->active_filter && + bpf_prog_run(ppp->active_filter, skb) == 0)) +- ppp->last_xmit = jiffies; ++ WRITE_ONCE(ppp->last_xmit, jiffies); + skb_pull(skb, 2); + #else + /* for data packets, record the time */ +- ppp->last_xmit = jiffies; ++ WRITE_ONCE(ppp->last_xmit, jiffies); + #endif /* CONFIG_PPP_FILTER */ + } + +@@ -2189,7 +2193,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + noskb: + spin_unlock(&pch->downl); + err_linearize: +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); + DEV_STATS_INC(ppp->dev, tx_errors); + ++ppp->nxseq; +@@ -2548,7 +2552,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: inbound frame " + "not passed\n"); +@@ -2557,14 +2561,14 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + } + if (!(ppp->active_filter && + bpf_prog_run(ppp->active_filter, skb) == 0)) +- ppp->last_recv = jiffies; ++ WRITE_ONCE(ppp->last_recv, jiffies); + __skb_pull(skb, 2); + } else + #endif /* CONFIG_PPP_FILTER */ +- ppp->last_recv = jiffies; ++ WRITE_ONCE(ppp->last_recv, jiffies); + + if ((ppp->dev->flags & IFF_UP) == 0 || +- ppp->npmode[npi] != NPMODE_PASS) { ++ READ_ONCE(ppp->npmode[npi]) != NPMODE_PASS) { + kfree_skb(skb); + } else { + /* chop off protocol */ +@@ -2817,7 +2821,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + seq = seq_before(minseq, PPP_MP_CB(p)->sequence)? + minseq + 1: PPP_MP_CB(p)->sequence; + +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "lost frag %u..%u\n", + oldseq, seq-1); +@@ -2866,7 +2870,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + struct sk_buff *tmp2; + + skb_queue_reverse_walk_from_safe(list, p, tmp2) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "discarding frag %u\n", + PPP_MP_CB(p)->sequence); +@@ -2888,7 +2892,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + skb_queue_walk_safe(list, p, tmp) { + if (p == head) + break; +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "discarding frag %u\n", + PPP_MP_CB(p)->sequence); +@@ -2896,7 +2900,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + kfree_skb(p); + } + +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + " missed pkts %u..%u\n", + ppp->nextseq, +@@ -3209,7 +3213,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) + if (!ppp->rc_state) + break; + if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len, +- ppp->file.index, 0, ppp->mru, ppp->debug)) { ++ ppp->file.index, 0, ppp->mru, ++ READ_ONCE(ppp->debug))) { + ppp->rstate |= SC_DECOMP_RUN; + ppp->rstate &= ~(SC_DC_ERROR | SC_DC_FERROR); + } +@@ -3218,7 +3223,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) + if (!ppp->xc_state) + break; + if (ppp->xcomp->comp_init(ppp->xc_state, dp, len, +- ppp->file.index, 0, ppp->debug)) ++ ppp->file.index, 0, ++ READ_ONCE(ppp->debug))) + ppp->xstate |= SC_COMP_RUN; + } + break; +-- +2.53.0 + diff --git a/queue-6.18/ppp-don-t-store-tx-skb-in-the-fastpath.patch b/queue-6.18/ppp-don-t-store-tx-skb-in-the-fastpath.patch new file mode 100644 index 0000000000..f6f27f186e --- /dev/null +++ b/queue-6.18/ppp-don-t-store-tx-skb-in-the-fastpath.patch @@ -0,0 +1,290 @@ +From 65b3f1908fb9770ad7e58942dd14c1010e555dd2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Mar 2026 17:32:19 +0800 +Subject: ppp: don't store tx skb in the fastpath + +From: Qingfang Deng + +[ Upstream commit 70836c8d0fe046400de8cdcf0613b2f1f6bddde3 ] + +Currently, ppp->xmit_pending is used in ppp_send_frame() to pass a skb +to ppp_push(), and holds the skb when a PPP channel cannot immediately +transmit it. This state is redundant because the transmit queue +(ppp->file.xq) can already handle the backlog. Furthermore, during +normal operation, an skb is queued in file.xq only to be immediately +dequeued, causing unnecessary overhead. + +Refactor the transmit path to avoid stashing the skb when possible: +- Remove ppp->xmit_pending. +- Rename ppp_send_frame() to ppp_prepare_tx_skb(), and don't call + ppp_push() in it. It returns 1 if the skb is consumed + (dropped/handled) or 0 if it can be passed to ppp_push(). +- Update ppp_push() to accept the skb. It returns 1 if the skb is + consumed, or 0 if the channel is busy. +- Optimize __ppp_xmit_process(): + - Fastpath: If the queue is empty, attempt to send the skb directly + via ppp_push(). If busy, queue it. + - Slowpath: If the queue is not empty, process the backlog in + file.xq. Split dequeuing loop into a separate function + ppp_xmit_flush() so ppp_channel_push() uses that directly instead of + passing a NULL skb to __ppp_xmit_process(). + +This simplifies the states and reduces locking in the fastpath. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20260303093219.234403-1-dqfext@gmail.com +Signed-off-by: Paolo Abeni +Stable-dep-of: ba712ecfd942 ("ppp: annotate concurrent dev->stats accesses") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 111 ++++++++++++++++++++-------------- + 1 file changed, 65 insertions(+), 46 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 6d001fb1462d30..e09a916356a1d4 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -134,7 +134,6 @@ struct ppp { + int debug; /* debug flags 70 */ + struct slcompress *vj; /* state for VJ header compression */ + enum NPmode npmode[NUM_NP]; /* what to do with each net proto 78 */ +- struct sk_buff *xmit_pending; /* a packet ready to go out 88 */ + struct compressor *xcomp; /* transmit packet compressor 8c */ + void *xc_state; /* its internal state 90 */ + struct compressor *rcomp; /* receive decompressor 94 */ +@@ -265,8 +264,8 @@ struct ppp_net { + static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, + struct file *file, unsigned int cmd, unsigned long arg); + static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb); +-static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); +-static void ppp_push(struct ppp *ppp); ++static int ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb); ++static int ppp_push(struct ppp *ppp, struct sk_buff *skb); + static void ppp_channel_push(struct channel *pch); + static void ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, + struct channel *pch); +@@ -1655,26 +1654,44 @@ static void ppp_setup(struct net_device *dev) + */ + + /* Called to do any work queued up on the transmit side that can now be done */ ++static void ppp_xmit_flush(struct ppp *ppp) ++{ ++ struct sk_buff *skb; ++ ++ while ((skb = skb_dequeue(&ppp->file.xq))) { ++ if (unlikely(!ppp_push(ppp, skb))) { ++ skb_queue_head(&ppp->file.xq, skb); ++ return; ++ } ++ } ++ /* If there's no work left to do, tell the core net code that we can ++ * accept some more. ++ */ ++ netif_wake_queue(ppp->dev); ++} ++ + static void __ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb) + { + ppp_xmit_lock(ppp); +- if (!ppp->closing) { +- ppp_push(ppp); +- +- if (skb) ++ if (unlikely(ppp->closing)) { ++ kfree_skb(skb); ++ goto out; ++ } ++ if (unlikely(ppp_prepare_tx_skb(ppp, &skb))) ++ goto out; ++ /* Fastpath: No backlog, just send the new skb. */ ++ if (likely(skb_queue_empty(&ppp->file.xq))) { ++ if (unlikely(!ppp_push(ppp, skb))) { + skb_queue_tail(&ppp->file.xq, skb); +- while (!ppp->xmit_pending && +- (skb = skb_dequeue(&ppp->file.xq))) +- ppp_send_frame(ppp, skb); +- /* If there's no work left to do, tell the core net +- code that we can accept some more. */ +- if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq)) +- netif_wake_queue(ppp->dev); +- else + netif_stop_queue(ppp->dev); +- } else { +- kfree_skb(skb); ++ } ++ goto out; + } ++ ++ /* Slowpath: Enqueue the new skb and process backlog */ ++ skb_queue_tail(&ppp->file.xq, skb); ++ ppp_xmit_flush(ppp); ++out: + ppp_xmit_unlock(ppp); + } + +@@ -1761,13 +1778,15 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb) + } + + /* +- * Compress and send a frame. +- * The caller should have locked the xmit path, +- * and xmit_pending should be 0. ++ * Compress and prepare to send a frame. ++ * The caller should have locked the xmit path. ++ * Returns 1 if the skb was consumed, 0 if it can be passed to ppp_push(). ++ * @pskb is updated if a compressor is in use. + */ +-static void +-ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) ++static int ++ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb) + { ++ struct sk_buff *skb = *pskb; + int proto = PPP_PROTO(skb); + struct sk_buff *new_skb; + int len; +@@ -1788,7 +1807,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + "PPP: outbound frame " + "not passed\n"); + kfree_skb(skb); +- return; ++ return 1; + } + /* if this packet passes the active filter, record the time */ + if (!(ppp->active_filter && +@@ -1836,6 +1855,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + } + consume_skb(skb); + skb = new_skb; ++ *pskb = skb; + cp = skb_put(skb, len + 2); + cp[0] = 0; + cp[1] = proto; +@@ -1862,6 +1882,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + if (!new_skb) + goto drop; + skb = new_skb; ++ *pskb = skb; + } + + /* +@@ -1873,42 +1894,38 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + goto drop; + skb_queue_tail(&ppp->file.rq, skb); + wake_up_interruptible(&ppp->file.rwait); +- return; ++ return 1; + } + +- ppp->xmit_pending = skb; +- ppp_push(ppp); +- return; ++ return 0; + + drop: + kfree_skb(skb); + ++ppp->dev->stats.tx_errors; ++ return 1; + } + + /* +- * Try to send the frame in xmit_pending. ++ * Try to send the frame. + * The caller should have the xmit path locked. ++ * Returns 1 if the skb was consumed, 0 if not. + */ +-static void +-ppp_push(struct ppp *ppp) ++static int ++ppp_push(struct ppp *ppp, struct sk_buff *skb) + { + struct list_head *list; + struct channel *pch; +- struct sk_buff *skb = ppp->xmit_pending; +- +- if (!skb) +- return; + + list = &ppp->channels; + if (list_empty(list)) { + /* nowhere to send the packet, just drop it */ +- ppp->xmit_pending = NULL; + kfree_skb(skb); +- return; ++ return 1; + } + + if ((ppp->flags & SC_MULTILINK) == 0) { + struct ppp_channel *chan; ++ int ret; + /* not doing multilink: send it down the first channel */ + list = list->next; + pch = list_entry(list, struct channel, clist); +@@ -1920,27 +1937,26 @@ ppp_push(struct ppp *ppp) + * skb but linearization failed + */ + kfree_skb(skb); +- ppp->xmit_pending = NULL; ++ ret = 1; + goto out; + } + +- if (chan->ops->start_xmit(chan, skb)) +- ppp->xmit_pending = NULL; ++ ret = chan->ops->start_xmit(chan, skb); + + out: + spin_unlock(&pch->downl); +- return; ++ return ret; + } + + #ifdef CONFIG_PPP_MULTILINK + /* Multilink: fragment the packet over as many links + as can take the packet at the moment. */ + if (!ppp_mp_explode(ppp, skb)) +- return; ++ return 0; + #endif /* CONFIG_PPP_MULTILINK */ + +- ppp->xmit_pending = NULL; + kfree_skb(skb); ++ return 1; + } + + #ifdef CONFIG_PPP_MULTILINK +@@ -2009,7 +2025,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + * performance if we have a lot of channels. + */ + if (nfree == 0 || nfree < navail / 2) +- return 0; /* can't take now, leave it in xmit_pending */ ++ return 0; /* can't take now, leave it in transmit queue */ + + /* Do protocol field compression */ + if (skb_linearize(skb)) +@@ -2203,8 +2219,12 @@ static void __ppp_channel_push(struct channel *pch, struct ppp *ppp) + spin_unlock(&pch->downl); + /* see if there is anything from the attached unit to be sent */ + if (skb_queue_empty(&pch->file.xq)) { +- if (ppp) +- __ppp_xmit_process(ppp, NULL); ++ if (ppp) { ++ ppp_xmit_lock(ppp); ++ if (!ppp->closing) ++ ppp_xmit_flush(ppp); ++ ppp_xmit_unlock(ppp); ++ } + } + } + +@@ -3464,7 +3484,6 @@ static void ppp_destroy_interface(struct ppp *ppp) + } + #endif /* CONFIG_PPP_FILTER */ + +- kfree_skb(ppp->xmit_pending); + free_percpu(ppp->xmit_recursion); + + free_netdev(ppp->dev); +-- +2.53.0 + diff --git a/queue-6.18/ppp-enable-tx-scatter-gather.patch b/queue-6.18/ppp-enable-tx-scatter-gather.patch new file mode 100644 index 0000000000..4c1ca0ed11 --- /dev/null +++ b/queue-6.18/ppp-enable-tx-scatter-gather.patch @@ -0,0 +1,115 @@ +From e3bc2f17d29785d0e1570e1a46fc5ecb03d3800d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Jan 2026 09:29:02 +0800 +Subject: ppp: enable TX scatter-gather + +From: Qingfang Deng + +[ Upstream commit 42fcb213e58a7da33d5d2d7517b4e521025c68c3 ] + +PPP channels using chan->direct_xmit prepend the PPP header to a skb and +call dev_queue_xmit() directly. In this mode the skb does not need to be +linear, but the PPP netdevice currently does not advertise +scatter-gather features, causing unnecessary linearization and +preventing GSO. + +Enable NETIF_F_SG and NETIF_F_FRAGLIST on PPP devices. In case a linear +buffer is required (PPP compression, multilink, and channels without +direct_xmit), call skb_linearize() explicitly. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20260129012902.941-1-dqfext@gmail.com +Signed-off-by: Paolo Abeni +Stable-dep-of: ba712ecfd942 ("ppp: annotate concurrent dev->stats accesses") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 30 +++++++++++++++++++++++++----- + 1 file changed, 25 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 72e98286fba2fe..6d001fb1462d30 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1645,6 +1645,8 @@ static void ppp_setup(struct net_device *dev) + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->priv_destructor = ppp_dev_priv_destructor; + dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; ++ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST; ++ dev->hw_features = dev->features; + netif_keep_dst(dev); + } + +@@ -1714,6 +1716,10 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb) + ppp->xcomp->comp_extra + ppp->dev->hard_header_len; + int compressor_skb_size = ppp->dev->mtu + + ppp->xcomp->comp_extra + PPP_HDRLEN; ++ ++ if (skb_linearize(skb)) ++ return NULL; ++ + new_skb = alloc_skb(new_skb_size, GFP_ATOMIC); + if (!new_skb) { + if (net_ratelimit()) +@@ -1801,6 +1807,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + case PPP_IP: + if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0) + break; ++ ++ if (skb_linearize(skb)) ++ goto drop; ++ + /* try to do VJ TCP header compression */ + new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2, + GFP_ATOMIC); +@@ -1898,19 +1908,26 @@ ppp_push(struct ppp *ppp) + } + + if ((ppp->flags & SC_MULTILINK) == 0) { ++ struct ppp_channel *chan; + /* not doing multilink: send it down the first channel */ + list = list->next; + pch = list_entry(list, struct channel, clist); + + spin_lock(&pch->downl); +- if (pch->chan) { +- if (pch->chan->ops->start_xmit(pch->chan, skb)) +- ppp->xmit_pending = NULL; +- } else { +- /* channel got unregistered */ ++ chan = pch->chan; ++ if (unlikely(!chan || (!chan->direct_xmit && skb_linearize(skb)))) { ++ /* channel got unregistered, or it requires a linear ++ * skb but linearization failed ++ */ + kfree_skb(skb); + ppp->xmit_pending = NULL; ++ goto out; + } ++ ++ if (chan->ops->start_xmit(chan, skb)) ++ ppp->xmit_pending = NULL; ++ ++out: + spin_unlock(&pch->downl); + return; + } +@@ -1995,6 +2012,8 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + return 0; /* can't take now, leave it in xmit_pending */ + + /* Do protocol field compression */ ++ if (skb_linearize(skb)) ++ goto err_linearize; + p = skb->data; + len = skb->len; + if (*p == 0 && mp_protocol_compress) { +@@ -2153,6 +2172,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + + noskb: + spin_unlock(&pch->downl); ++ err_linearize: + if (ppp->debug & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); + ++ppp->dev->stats.tx_errors; +-- +2.53.0 + diff --git a/queue-6.18/ptp-netc-explicitly-clear-tmr_off-during-initializat.patch b/queue-6.18/ptp-netc-explicitly-clear-tmr_off-during-initializat.patch new file mode 100644 index 0000000000..53d7d96bb1 --- /dev/null +++ b/queue-6.18/ptp-netc-explicitly-clear-tmr_off-during-initializat.patch @@ -0,0 +1,52 @@ +From 76f78d969713a73ea9e8758efb9fef167b1f0fa8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 09:25:08 +0800 +Subject: ptp: netc: explicitly clear TMR_OFF during initialization + +From: Clark Wang + +[ Upstream commit c3f2fc231a39e29fe9f0adc14a3ecc3c1260d3c5 ] + +The NETC timer does not support function level reset, so TMR_OFF_L/H +registers are not cleared by pcie_flr(). If TMR_OFF was set to a +non-zero value in a previous binding, it will persist across driver +rebind and cause inaccurate PTP time. + +There is also a hardware issue: after a warm reset or soft reset, +TMR_OFF_L/H registers appear to be cleared to zero, but the timer clock +domain internally retains the stale value. When the timer is re-enabled, +TMR_CUR_TIME continues to track the old offset until TMR_OFF is written +explicitly. This can cause incorrect PTP timestamps and even PTP clock +synchronization failures. + +Per the recommendation from the IP team, explicitly write 0 to TMR_OFF +in netc_timer_init() to flush the internally cached value and ensure +TMR_CUR_TIME follows the freshly initialized counter. + +Fixes: 87a201d59963 ("ptp: netc: add NETC V4 Timer PTP driver support") +Signed-off-by: Clark Wang +Signed-off-by: Wei Fang +Reviewed-by: Vadim Fedorenko +Reviewed-by: Breno Leitao +Link: https://patch.msgid.link/20260720012508.23227-1-wei.fang@oss.nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/ptp/ptp_netc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/ptp/ptp_netc.c b/drivers/ptp/ptp_netc.c +index 94e952ee69902e..5e381c354d746a 100644 +--- a/drivers/ptp/ptp_netc.c ++++ b/drivers/ptp/ptp_netc.c +@@ -779,6 +779,7 @@ static void netc_timer_init(struct netc_timer *priv) + netc_timer_wr(priv, NETC_TMR_FIPER_CTRL, fiper_ctrl); + netc_timer_wr(priv, NETC_TMR_ECTRL, NETC_TMR_DEFAULT_ETTF_THR); + ++ netc_timer_offset_write(priv, 0); + ktime_get_real_ts64(&now); + ns = timespec64_to_ns(&now); + netc_timer_cnt_write(priv, ns); +-- +2.53.0 + diff --git a/queue-6.18/raw-annotate-lockless-match-fields-in-raw_v4_match.patch b/queue-6.18/raw-annotate-lockless-match-fields-in-raw_v4_match.patch new file mode 100644 index 0000000000..785ba06427 --- /dev/null +++ b/queue-6.18/raw-annotate-lockless-match-fields-in-raw_v4_match.patch @@ -0,0 +1,101 @@ +From cd893a3802058e5b42418ce47eede730935f15bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 22:29:58 +0800 +Subject: raw: annotate lockless match fields in raw_v4_match() + +From: Runyu Xiao + +[ Upstream commit 18f116931f52e3c3303ad4b15ff41eb89b0e4239 ] + +raw_v4_match() is a lockless match helper under sk_for_each_rcu(). It +still reads inet->inet_daddr, inet->inet_rcv_saddr and +sk->sk_bound_dev_if with plain loads while bind, connect and +bind-to-device paths can update the same match fields concurrently. + +Annotate only those mutable match fields in raw_v4_match(), and do so +at the point of use instead of hoisting the bound-device read before +the earlier short-circuit tests. + +Also annotate the raw bind writer and the shared IPv4 datagram connect +writer used by raw sockets, so the address fields updated on bind and +connect match explicit WRITE_ONCE() updates. + +This version intentionally leaves the shared disconnect-side IPv4 +writers to follow-up cleanup and limits the writer changes here to the +raw bind path and the datagram connect path directly exercised by raw +sockets. + +Fixes: 0daf07e52709 ("raw: convert raw sockets to RCU") +Signed-off-by: Runyu Xiao +Link: https://patch.msgid.link/20260716142958.3064224-1-runyu.xiao@seu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/datagram.c | 4 ++-- + net/ipv4/raw.c | 23 ++++++++++++++++------- + 2 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c +index c2b2cda1a7e506..7861615b34fc68 100644 +--- a/net/ipv4/datagram.c ++++ b/net/ipv4/datagram.c +@@ -63,12 +63,12 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len + } + + /* Update addresses before rehashing */ +- inet->inet_daddr = fl4->daddr; ++ WRITE_ONCE(inet->inet_daddr, fl4->daddr); + inet->inet_dport = usin->sin_port; + if (!inet->inet_saddr) + inet->inet_saddr = fl4->saddr; + if (!inet->inet_rcv_saddr) { +- inet->inet_rcv_saddr = fl4->saddr; ++ WRITE_ONCE(inet->inet_rcv_saddr, fl4->saddr); + if (sk->sk_prot->rehash) + sk->sk_prot->rehash(sk); + } +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index 26468a2ec63db1..c10cf41a365dc2 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -120,13 +120,21 @@ bool raw_v4_match(struct net *net, const struct sock *sk, unsigned short num, + __be32 raddr, __be32 laddr, int dif, int sdif) + { + const struct inet_sock *inet = inet_sk(sk); ++ __be32 daddr, rcv_saddr; + +- if (net_eq(sock_net(sk), net) && inet->inet_num == num && +- !(inet->inet_daddr && inet->inet_daddr != raddr) && +- !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && +- raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif)) +- return true; +- return false; ++ if (!net_eq(sock_net(sk), net) || inet->inet_num != num) ++ return false; ++ ++ daddr = READ_ONCE(inet->inet_daddr); ++ if (daddr && daddr != raddr) ++ return false; ++ ++ rcv_saddr = READ_ONCE(inet->inet_rcv_saddr); ++ if (rcv_saddr && rcv_saddr != laddr) ++ return false; ++ ++ return raw_sk_bound_dev_eq(net, READ_ONCE(sk->sk_bound_dev_if), ++ dif, sdif); + } + EXPORT_SYMBOL_GPL(raw_v4_match); + +@@ -721,7 +729,8 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) + chk_addr_ret)) + goto out; + +- inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr; ++ inet->inet_saddr = addr->sin_addr.s_addr; ++ WRITE_ONCE(inet->inet_rcv_saddr, addr->sin_addr.s_addr); + if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) + inet->inet_saddr = 0; /* Use device */ + sk_dst_reset(sk); +-- +2.53.0 + diff --git a/queue-6.18/rds-drop-incoming-messages-that-cross-network-namesp.patch b/queue-6.18/rds-drop-incoming-messages-that-cross-network-namesp.patch new file mode 100644 index 0000000000..d932fe7325 --- /dev/null +++ b/queue-6.18/rds-drop-incoming-messages-that-cross-network-namesp.patch @@ -0,0 +1,78 @@ +From cae2e4071baf3087337560372d4e5669680d0436 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 19:43:14 -0700 +Subject: rds: drop incoming messages that cross network namespace boundaries + +From: Aldo Ariel Panzardo + +[ Upstream commit 5521ae71e32a8069ed4ca6e792179dc57bc43ab2 ] + +rds_find_bound() looks up the destination socket using a global +rhashtable keyed solely on (addr, port, scope_id). Network namespaces +are not part of the key, so a sender in netns A can deliver an incoming +message (inc) to a socket that lives in a different netns B. + +When this happens, inc->i_conn points to an rds_connection whose c_net +is netns A, but the receiving rs lives in netns B. Once the child +process that created netns A exits, cleanup_net() calls +rds_loop_exit_net() -> rds_loop_kill_conns() -> rds_conn_destroy(), +freeing that connection. If the survivor socket in netns B still holds +the inc, any subsequent dereference of inc->i_conn is a use-after-free. + +There are two dangerous sites in rds_clear_recv_queue(): + 1. inc->i_conn->c_lcong (offset 88 of freed rds_connection, size 200) + read via rds_recv_rcvbuf_delta() -- confirmed by KASAN. + 2. inc->i_conn->c_trans->inc_free(inc) (function pointer at offset 80) + called via rds_inc_put() when the inc refcount reaches zero -- same + race window, potential call-through-freed-object primitive. + +The bug is reachable from unprivileged user namespaces +(CLONE_NEWUSER + CLONE_NEWNET), available since Linux 3.8. + +Fix this by rejecting the delivery in rds_recv_incoming() when the +socket returned by rds_find_bound() belongs to a different network +namespace than the connection that carried the message. Use the +existing rds_conn_net() / sock_net() helpers and net_eq() for the +comparison. + +Fixes: c809195f5523 ("rds: clean up loopback rds_connections on netns deletion") +Signed-off-by: Aldo Ariel Panzardo +Reviewed-by: Allison Henderson +Tested-by: Allison Henderson +Signed-off-by: Allison Henderson +Link: https://patch.msgid.link/20260708024314.601139-1-achender@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/rds/recv.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/net/rds/recv.c b/net/rds/recv.c +index 66205d6924bf3d..4b12fa4f1e7869 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -366,6 +366,21 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr, + goto out; + } + ++ /* ++ * rds_find_bound() uses a global (netns-agnostic) hash table. ++ * An RDS connection created in netns A can match a socket bound ++ * in the init netns, delivering inc cross-netns with inc->i_conn ++ * pointing into netns A. When cleanup_net() then frees that conn, ++ * any subsequent dereference of inc->i_conn is a use-after-free. ++ * Drop the inc if the receiving socket lives in a different netns. ++ */ ++ if (!net_eq(sock_net(rds_rs_to_sk(rs)), rds_conn_net(conn))) { ++ rds_stats_inc(s_recv_drop_no_sock); ++ rds_sock_put(rs); ++ rs = NULL; ++ goto out; ++ } ++ + /* Process extension headers */ + rds_recv_incoming_exthdrs(inc, rs); + +-- +2.53.0 + diff --git a/queue-6.18/rds-tcp-unregister-sysctl-before-tearing-down-listen.patch b/queue-6.18/rds-tcp-unregister-sysctl-before-tearing-down-listen.patch new file mode 100644 index 0000000000..3560abedb9 --- /dev/null +++ b/queue-6.18/rds-tcp-unregister-sysctl-before-tearing-down-listen.patch @@ -0,0 +1,64 @@ +From 1e0a5e544a8333d2e94277c5282dfd1f73c1943b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Jul 2026 17:03:57 -0400 +Subject: rds: tcp: unregister sysctl before tearing down listen socket + +From: Cen Zhang (Microsoft) + +[ Upstream commit 167e54c703ccd4fa028feb568b0d1002020cff86 ] + +rds_tcp_exit_net() frees the per-netns RDS TCP listen socket via +rds_tcp_kill_sock() before unregistering the per-netns sysctl table. Since +rds_tcp_skbuf_handler() derives the netns from +rtn->rds_tcp_listen_sock->sk, a concurrent sysctl write can race with +netns teardown and dereference the freed socket/sk. + +KASAN reports the race as: + + BUG: KASAN: slab-use-after-free in rds_tcp_skbuf_handler+0x2aa/0x2e0 + rds_tcp_skbuf_handler net/rds/tcp.c:721 + proc_sys_call_handler fs/proc/proc_sysctl.c + vfs_write fs/read_write.c + __x64_sys_pwrite64 fs/read_write.c + +Fix this by unregistering the RDS TCP sysctl table before calling +rds_tcp_kill_sock(). unregister_net_sysctl_table() prevents new sysctl +handlers from starting and waits for in-flight handlers to finish, so +the listen socket can then be released safely. The fix was tested +against the linked reproducer. + +Fixes: 7f5611cbc487 ("rds: sysctl: rds_tcp_{rcv,snd}buf: avoid using current->nsproxy") +Reported-by: AutonomousCodeSecurity@microsoft.com +Link: https://lore.kernel.org/all/20260719203718.9680-1-blbllhy@gmail.com +Reviewed-by: Allison Henderson +Signed-off-by: Cen Zhang (Microsoft) +Link: https://patch.msgid.link/20260719210357.10179-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/rds/tcp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/rds/tcp.c b/net/rds/tcp.c +index b66dfcc3efaa0f..06a2d8d48bbacf 100644 +--- a/net/rds/tcp.c ++++ b/net/rds/tcp.c +@@ -637,13 +637,13 @@ static void __net_exit rds_tcp_exit_net(struct net *net) + { + struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid); + +- rds_tcp_kill_sock(net); +- + if (rtn->rds_tcp_sysctl) + unregister_net_sysctl_table(rtn->rds_tcp_sysctl); + + if (net != &init_net) + kfree(rtn->ctl_table); ++ ++ rds_tcp_kill_sock(net); + } + + static struct pernet_operations rds_tcp_net_ops = { +-- +2.53.0 + diff --git a/queue-6.18/regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch b/queue-6.18/regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch new file mode 100644 index 0000000000..f188eedacd --- /dev/null +++ b/queue-6.18/regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch @@ -0,0 +1,60 @@ +From f0949b91e6dbe33cb2f3039471cf99cfa9bfb9ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Jul 2026 02:05:59 +0100 +Subject: regulator: mt6358: use regmap helper to read fixed LDO calibration + +From: Daniel Golle + +[ Upstream commit 1d26f125501f3fbe6c259ab75bf6516299a0bf0e ] + +The "fixed" LDOs with output voltage calibration use +mt6358_get_buck_voltage_sel as their get_voltage_sel op, but the +MT6358_REG_FIXED and MT6366_REG_FIXED entries do not populate +da_vsel_reg/da_vsel_mask. The op therefore reads register 0x0 with a +zero mask and shifts the result by ffs(0) - 1 = -1, which is undefined +behaviour and gets flagged by UBSAN on every boot on MT6366 boards: + + UBSAN: shift-out-of-bounds in drivers/regulator/mt6358-regulator.c:384:38 + shift exponent -1 is negative + Call trace: + mt6358_get_buck_voltage_sel+0xc8/0x120 + regulator_get_voltage_rdev+0x70/0x170 + set_machine_constraints+0x504/0xc38 + regulator_register+0x324/0xc68 + +Besides the undefined shift, the returned selector is always 0, so the +actual calibration offset programmed in _ANA_CON0 is never +reported. + +The descriptor already carries the correct vsel_reg/vsel_mask (the +ANA_CON0 calibration field), matching the regulator_set_voltage_sel_regmap +op already in use. Read the selector back through +regulator_get_voltage_sel_regmap instead. + +Fixes: cf08fa74c716 ("regulator: mt6358: Add output voltage fine tuning to fixed regulators") +Signed-off-by: Daniel Golle +Reviewed-by: Chen-Yu Tsai +Tested-by: Chen-Yu Tsai +Link: https://patch.msgid.link/dcd98d81dede338c9bbb9700a9613c848b702e49.1784336005.git.daniel@makrotopia.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/mt6358-regulator.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c +index e4745f616cea3b..44bef0bdfdbe35 100644 +--- a/drivers/regulator/mt6358-regulator.c ++++ b/drivers/regulator/mt6358-regulator.c +@@ -492,7 +492,7 @@ static const struct regulator_ops mt6358_volt_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +- .get_voltage_sel = mt6358_get_buck_voltage_sel, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, +-- +2.53.0 + diff --git a/queue-6.18/rxrpc-fix-io_thread-race-in-rxrpc_wake_up_io_thread.patch b/queue-6.18/rxrpc-fix-io_thread-race-in-rxrpc_wake_up_io_thread.patch new file mode 100644 index 0000000000..3f3353ade2 --- /dev/null +++ b/queue-6.18/rxrpc-fix-io_thread-race-in-rxrpc_wake_up_io_thread.patch @@ -0,0 +1,49 @@ +From e2d669adeba16604cc7bb8c7dedd90d13ee99114 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 17:35:34 +0800 +Subject: rxrpc: fix io_thread race in rxrpc_wake_up_io_thread() + +From: Xuanqiang Luo + +[ Upstream commit 745fb794c3e933c023af9dbb5876a5e16ad2dc71 ] + +rxrpc_wake_up_io_thread() checks local->io_thread before waking it, but +then reloads the pointer for wake_up_process(). + +local->io_thread is cleared with WRITE_ONCE() when the I/O thread exits, so +the second load can see NULL even if the first load did not. + +Take a READ_ONCE() snapshot and use it for both the NULL check and the +wake_up_process() call, as rxrpc_encap_rcv() already does. + +Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for a RESPONSE") +Signed-off-by: Xuanqiang Luo +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708093534.53486-1-xuanqiang.luo@linux.dev +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/rxrpc/ar-internal.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h +index d2b31d15851b96..38b0997ce0cb3a 100644 +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -1266,9 +1266,11 @@ int rxrpc_io_thread(void *data); + void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb); + static inline void rxrpc_wake_up_io_thread(struct rxrpc_local *local) + { +- if (!local->io_thread) ++ struct task_struct *io_thread = READ_ONCE(local->io_thread); ++ ++ if (!io_thread) + return; +- wake_up_process(READ_ONCE(local->io_thread)); ++ wake_up_process(io_thread); + } + + static inline bool rxrpc_protocol_error(struct sk_buff *skb, enum rxrpc_abort_reason why) +-- +2.53.0 + diff --git a/queue-6.18/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch b/queue-6.18/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch new file mode 100644 index 0000000000..73aa11187d --- /dev/null +++ b/queue-6.18/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch @@ -0,0 +1,51 @@ +From ebfea4c10423a4f06ea2a45238dedb580a031641 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 09:55:32 +0800 +Subject: sctp: auth: verify auth requirement when auth_chunk is NULL + +From: Qing Luo + +[ Upstream commit 8e04823c120b376ef7dab14b60ebf6823aa16c14 ] + +sctp_auth_chunk_verify() returns true unconditionally when +chunk->auth_chunk is NULL, silently skipping authentication. +This is incorrect when: + +1. skb_clone() failed in the BH receive path, leaving auth_chunk + NULL. In sctp_endpoint_bh_rcv() asoc is NULL for new + connections, so the early sctp_auth_recv_cid() check cannot + catch this. + +2. No AUTH chunk precedes COOKIE-ECHO, so skb_clone() is never + called and auth_chunk remains NULL. + +Fix by checking sctp_auth_recv_cid() when auth_chunk is NULL: +if authentication is required, return false to drop the chunk; +otherwise continue normally. + +Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk") +Signed-off-by: Qing Luo +Acked-by: Xin Long +Link: https://patch.msgid.link/20260721015532.120157-2-l1138897701@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/sm_statefuns.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index abfd72d1f20c64..4b8d48b6706c85 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -641,7 +641,7 @@ static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, + struct sctp_chunk auth; + + if (!chunk->auth_chunk) +- return true; ++ return !sctp_auth_recv_cid(chunk->chunk_hdr->type, asoc); + + /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo + * is supposed to be authenticated and we have to do delayed +-- +2.53.0 + diff --git a/queue-6.18/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch b/queue-6.18/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch new file mode 100644 index 0000000000..a95ed7b80e --- /dev/null +++ b/queue-6.18/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch @@ -0,0 +1,46 @@ +From d49e205c78164696d32df8f116f9a37bf1fada90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 03:20:21 +0000 +Subject: sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid + +From: HanQuan + +[ Upstream commit ff04b26794a16a8a879eb4fd2c02c2d6b03850e9 ] + +sctp_auth_ep_add_chunkid() uses SCTP_NUM_CHUNK_TYPES (20) as the +capacity limit for ep->auth_chunk_list, allowing it to hold up to +20 chunk entries (param_hdr.length up to 24). However, the copy +destination asoc->c.auth_chunks in struct sctp_cookie is only +SCTP_AUTH_MAX_CHUNKS (16) entries (20 bytes). When more than 16 +chunks are added, sctp_association_init() memcpy overflows the +destination by up to 4 bytes. + +Fix by using SCTP_AUTH_MAX_CHUNKS as the capacity limit, matching +the destination capacity. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Signed-off-by: HanQuan +Acked-by: Xin Long +Link: https://patch.msgid.link/20260713032021.3491702-1-zhoujian.zja@antgroup.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/auth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index 82aad477590e2e..fbbfa0c2795523 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -672,7 +672,7 @@ int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) + /* Check if we can add this chunk to the array */ + param_len = ntohs(p->param_hdr.length); + nchunks = param_len - sizeof(struct sctp_paramhdr); +- if (nchunks == SCTP_NUM_CHUNK_TYPES) ++ if (nchunks == SCTP_AUTH_MAX_CHUNKS) + return -EINVAL; + + p->chunks[nchunks] = chunk_id; +-- +2.53.0 + diff --git a/queue-6.18/sctp-validate-stream-count-in-sctp_process_strreset_.patch b/queue-6.18/sctp-validate-stream-count-in-sctp_process_strreset_.patch new file mode 100644 index 0000000000..264a4c3c1c --- /dev/null +++ b/queue-6.18/sctp-validate-stream-count-in-sctp_process_strreset_.patch @@ -0,0 +1,80 @@ +From 2e1ad89b547288ba0fdea95b1732b7edf0ab2738 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 21:07:18 -0400 +Subject: sctp: validate stream count in sctp_process_strreset_inreq() + +From: Cen Zhang (Microsoft) + +[ Upstream commit 18ae07691d43183d270de8be9dc8e027906015d9 ] + +When processing a RESET_IN_REQUEST from a peer, +sctp_process_strreset_inreq() derives the stream count from the +parameter length but does not check whether the resulting +RESET_OUT_REQUEST would exceed SCTP_MAX_CHUNK_LEN. + +The OUT request header (sctp_strreset_outreq, 16 bytes) is 8 bytes +larger than the IN request header (sctp_strreset_inreq, 8 bytes). +Generally, the IP payload is bounded to 65535 bytes, so the stream +list cannot be large enough to trigger the overflow. However, on +interfaces with MTU > 65535 (e.g., loopback with IPv6 jumbograms), a +stream list that fits within the incoming IN parameter can cause a +__u16 overflow in sctp_make_strreset_req() when computing the OUT +request size, leading to an undersized skb allocation and a kernel +BUG: + + net/core/skbuff.c:207 skb_panic + net/core/skbuff.c:2625 skb_put + net/sctp/sm_make_chunk.c:1535 sctp_addto_chunk + net/sctp/sm_make_chunk.c:3695 sctp_make_strreset_req + net/sctp/stream.c:655 sctp_process_strreset_inreq + +The local setsockopt path validates the generated reset request size. +However, for an incoming-only reset, it accounts for the smaller IN +request even though the peer must generate an OUT request with the same +stream list. Such a request cannot be completed successfully by the +peer. + +Reject peer IN requests whose corresponding OUT request would exceed +SCTP_MAX_CHUNK_LEN. Also tighten the local check so it does not send an +IN request that would require an oversized OUT request from the peer. + +Fixes: 7f9d68ac944e ("sctp: implement sender-side procedures for SSN Reset Request Parameter") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/20260707203215.2752-1-blbllhy@gmail.com/ +Suggested-by: Xin Long +Signed-off-by: Cen Zhang (Microsoft) +Acked-by: Xin Long +Link: https://patch.msgid.link/20260710010718.20318-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/stream.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/stream.c b/net/sctp/stream.c +index 39b8f5e8ce3534..9addcfad467f97 100644 +--- a/net/sctp/stream.c ++++ b/net/sctp/stream.c +@@ -308,7 +308,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc, + goto out; + + param_len += str_nums * sizeof(__u16) + +- sizeof(struct sctp_strreset_inreq); ++ (out ? sizeof(struct sctp_strreset_inreq) ++ : sizeof(struct sctp_strreset_outreq)); + } + + if (param_len > SCTP_MAX_CHUNK_LEN - +@@ -639,6 +640,9 @@ struct sctp_chunk *sctp_process_strreset_inreq( + + nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16); + str_p = inreq->list_of_streams; ++ if (nums * sizeof(__u16) + sizeof(struct sctp_strreset_outreq) > ++ SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_reconf_chunk)) ++ goto out; + for (i = 0; i < nums; i++) { + if (ntohs(str_p[i]) >= stream->outcnt) { + result = SCTP_STRRESET_ERR_WRONG_SSN; +-- +2.53.0 + diff --git a/queue-6.18/selftests-af_unix-add-user_ns-config.patch b/queue-6.18/selftests-af_unix-add-user_ns-config.patch new file mode 100644 index 0000000000..3096e1e64f --- /dev/null +++ b/queue-6.18/selftests-af_unix-add-user_ns-config.patch @@ -0,0 +1,40 @@ +From 8f5ae18d26ece10caa439df2d093c670d397eb38 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:41 +0200 +Subject: selftests: af_unix: add USER_NS config + +From: Matthieu Baerts (NGI0) + +[ Upstream commit f8b1abed736111f914b2c567d9a3db1f71e788e8 ] + +This is required to use unshare(CLONE_NEWUSER). + +This has not been seen on NIPA before, because the 'af_unix' tests are +executed with the 'net' ones, merging their config files. USER_NS is +present in tools/testing/selftests/net/config. + +This issue is visible when only the af_unix config is used on top of the +default one. This is the recommended way to execute selftest targets. + +Fixes: ac011361bd4f ("af_unix: Add test for sock_diag and UDIAG_SHOW_UID.") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-1-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/af_unix/config | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/net/af_unix/config b/tools/testing/selftests/net/af_unix/config +index b5429c15a53c75..41dbb03c747eb7 100644 +--- a/tools/testing/selftests/net/af_unix/config ++++ b/tools/testing/selftests/net/af_unix/config +@@ -1,3 +1,4 @@ + CONFIG_AF_UNIX_OOB=y + CONFIG_UNIX=y + CONFIG_UNIX_DIAG=m ++CONFIG_USER_NS=y +-- +2.53.0 + diff --git a/queue-6.18/selftests-drv-net-increase-timeout.patch b/queue-6.18/selftests-drv-net-increase-timeout.patch new file mode 100644 index 0000000000..355f885768 --- /dev/null +++ b/queue-6.18/selftests-drv-net-increase-timeout.patch @@ -0,0 +1,38 @@ +From 9428cdccf0792b1cdb652c4d43952f89cfc1eacf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:45 +0200 +Subject: selftests: drv-net: increase timeout + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 3529d75d67411497341cd804a045185d6035dff2 ] + +The default timeout is 45 seconds, that's too low for the xdp.py test. + +Indeed, this test can take up to 3 minutes with some debug kernel config +on NIPA. Set a timeout to 6 minutes, just to be on the safe side. + +Note that the Fixes tag here points to the introduction of the xdp.py +test because I don't know when this test started to take more than 45 +seconds. That's OK because a timeout of 6 minutes is not exaggerated. + +Fixes: 1cbcb1b28b26 ("selftests: drv-net: Test XDP_PASS/DROP support") +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-5-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/drivers/net/settings | 1 + + 1 file changed, 1 insertion(+) + create mode 100644 tools/testing/selftests/drivers/net/settings + +diff --git a/tools/testing/selftests/drivers/net/settings b/tools/testing/selftests/drivers/net/settings +new file mode 100644 +index 00000000000000..eef533824a3c19 +--- /dev/null ++++ b/tools/testing/selftests/drivers/net/settings +@@ -0,0 +1 @@ ++timeout=360 +-- +2.53.0 + diff --git a/queue-6.18/selftests-net-ovpn-fix-getaddrinfo-memory-leak-in-ov.patch b/queue-6.18/selftests-net-ovpn-fix-getaddrinfo-memory-leak-in-ov.patch new file mode 100644 index 0000000000..22d8f9b496 --- /dev/null +++ b/queue-6.18/selftests-net-ovpn-fix-getaddrinfo-memory-leak-in-ov.patch @@ -0,0 +1,55 @@ +From d7fd0d2fc9d99e3fd36f65ec443495968ebcc727 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 15:27:41 +0800 +Subject: selftests/net: ovpn: fix getaddrinfo memory leak in + ovpn_parse_remote() + +From: longlong yan + +[ Upstream commit 0bd9cfebc1c91e1066e56d6261b99691b9df6008 ] + +The ovpn_parse_remote() function has two memory management issues: + +1. When both 'host' and 'vpnip' are non-NULL, the first getaddrinfo() + allocation is leaked because 'result' is overwritten by the second + getaddrinfo() call without freeing the first allocation. + +2. When both 'host' and 'vpnip' are NULL, 'result' is an uninitialized + stack variable passed to freeaddrinfo(), which is undefined behavior. + +Fix by initializing 'result' to NULL and calling freeaddrinfo() after +the first getaddrinfo() result is consumed. + +Fixes: 959bc330a439 ("testing/selftests: add test tool and scripts for ovpn module") +Signed-off-by: longlong yan +Signed-off-by: Antonio Quartulli +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/ovpn/ovpn-cli.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/net/ovpn/ovpn-cli.c b/tools/testing/selftests/net/ovpn/ovpn-cli.c +index 0a5226196a2e73..44418118f6ea7a 100644 +--- a/tools/testing/selftests/net/ovpn/ovpn-cli.c ++++ b/tools/testing/selftests/net/ovpn/ovpn-cli.c +@@ -1746,7 +1746,7 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host, + const char *service, const char *vpnip) + { + int ret; +- struct addrinfo *result; ++ struct addrinfo *result = NULL; + struct addrinfo hints = { + .ai_family = ovpn->sa_family, + .ai_socktype = SOCK_DGRAM, +@@ -1770,6 +1770,8 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host, + } + + memcpy(&ovpn->remote, result->ai_addr, result->ai_addrlen); ++ freeaddrinfo(result); ++ result = NULL; + } + + if (vpnip) { +-- +2.53.0 + diff --git a/queue-6.18/selftests-openvswitch-add-config-file.patch b/queue-6.18/selftests-openvswitch-add-config-file.patch new file mode 100644 index 0000000000..0638138049 --- /dev/null +++ b/queue-6.18/selftests-openvswitch-add-config-file.patch @@ -0,0 +1,59 @@ +From 691984dbe820b847b671a2737905e717b28496d9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:42 +0200 +Subject: selftests: openvswitch: add config file + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 441a820ccef9af80a9ac5a4c85b9c396e595967c ] + +The kselftests doc mentions that a config file should be present "if a +test needs specific kernel config options enabled". This selftest +requires some kernel config, but no config file was provided. + +We could say that a sub-target could use the parent's config file, but +the kselftests doc doesn't mention anything about that. Plus the +net/openvswitch target is the only net target without a config file. + +Here is a new config file, which is a trimmed version of the net one, +with hopefully the minimal required kconfig on top of 'make defconfig'. + +The Fixes tag points to the introduction of the net/openvswitch target, +just to help validating this target on stable kernels. + +Fixes: 25f16c873fb1 ("selftests: add openvswitch selftest suite") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Eelco Chaudron +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-2-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/openvswitch/config | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + create mode 100644 tools/testing/selftests/net/openvswitch/config + +diff --git a/tools/testing/selftests/net/openvswitch/config b/tools/testing/selftests/net/openvswitch/config +new file mode 100644 +index 00000000000000..c659749cd086c7 +--- /dev/null ++++ b/tools/testing/selftests/net/openvswitch/config +@@ -0,0 +1,16 @@ ++CONFIG_GENEVE=m ++CONFIG_INET_DIAG=y ++CONFIG_IPV6=y ++CONFIG_NETFILTER=y ++CONFIG_NET_IPGRE=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_OVS=y ++CONFIG_OPENVSWITCH=m ++CONFIG_OPENVSWITCH_GENEVE=m ++CONFIG_OPENVSWITCH_GRE=m ++CONFIG_OPENVSWITCH_VXLAN=m ++CONFIG_PSAMPLE=m ++CONFIG_VETH=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VXLAN=m +-- +2.53.0 + diff --git a/queue-6.18/selftests-ovpn-add-ipv6-and-veth-configs.patch b/queue-6.18/selftests-ovpn-add-ipv6-and-veth-configs.patch new file mode 100644 index 0000000000..f41fc28304 --- /dev/null +++ b/queue-6.18/selftests-ovpn-add-ipv6-and-veth-configs.patch @@ -0,0 +1,49 @@ +From c5f7d2af759f3a157e2169fd739fa598a8b41125 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:43 +0200 +Subject: selftests: ovpn: add IPV6 and VETH configs + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 90c792681a3732caaf7bf5bc435877736baf591a ] + +They are required to run the selftests: + + - Tests are executed in v4 and v6. + + - Virtual Ethernet are used between the different netns. + +This has not been seen on NIPA before, because the 'ovpn' tests are +executed with the 'tcp_ao' ones, merging their config files. These two +kernel config are present in tools/testing/selftests/net/tcp_ao/config. + +This issue is visible when only the ovpn config is used on top of the +default one. This is the recommended way to execute selftest targets. + +Fixes: 959bc330a439 ("testing/selftests: add test tool and scripts for ovpn module") +Signed-off-by: Matthieu Baerts (NGI0) +Acked-by: Antonio Quartulli +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-3-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/ovpn/config | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/testing/selftests/net/ovpn/config b/tools/testing/selftests/net/ovpn/config +index 42699740936dba..c0a21a43018a22 100644 +--- a/tools/testing/selftests/net/ovpn/config ++++ b/tools/testing/selftests/net/ovpn/config +@@ -4,7 +4,9 @@ CONFIG_CRYPTO_CHACHA20POLY1305=y + CONFIG_CRYPTO_GCM=y + CONFIG_DST_CACHE=y + CONFIG_INET=y ++CONFIG_IPV6=y + CONFIG_NET=y + CONFIG_NET_UDP_TUNNEL=y + CONFIG_OVPN=m + CONFIG_STREAM_PARSER=y ++CONFIG_VETH=y +-- +2.53.0 + diff --git a/queue-6.18/selftests-ovpn-increase-timeout.patch b/queue-6.18/selftests-ovpn-increase-timeout.patch new file mode 100644 index 0000000000..89eecef75e --- /dev/null +++ b/queue-6.18/selftests-ovpn-increase-timeout.patch @@ -0,0 +1,40 @@ +From 23852164881268a32ddb5a7c67de0f23674b61eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:44 +0200 +Subject: selftests: ovpn: increase timeout + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 61ac7049aaa86ae044e8a5b94d852218163d5bf8 ] + +The default timeout is 45 seconds, that's too low for a few ovpn tests. + +Indeed, these tests can take up to 50 seconds with some debug kernel +config on NIPA. Set a timeout to 90 seconds, just to be on the safe +side. + +Note that the Fixes tag here points to the introduction of the ovpn +tests because I don't know when they started to take more than 45 +seconds. That's OK because a timeout of 1.5 minutes is not exaggerated. + +Fixes: 959bc330a439 ("testing/selftests: add test tool and scripts for ovpn module") +Signed-off-by: Matthieu Baerts (NGI0) +Acked-by: Antonio Quartulli +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-4-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/ovpn/settings | 1 + + 1 file changed, 1 insertion(+) + create mode 100644 tools/testing/selftests/net/ovpn/settings + +diff --git a/tools/testing/selftests/net/ovpn/settings b/tools/testing/selftests/net/ovpn/settings +new file mode 100644 +index 00000000000000..ba4d85f74cd6b9 +--- /dev/null ++++ b/tools/testing/selftests/net/ovpn/settings +@@ -0,0 +1 @@ ++timeout=90 +-- +2.53.0 + diff --git a/queue-6.18/series b/queue-6.18/series index 1c29ace5f2..c5d7517916 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -165,3 +165,162 @@ revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch selftests-bpf-adjust-verifier_map_ptr-for-the-map-s-.patch selftests-bpf-keep-verifier_map_ptr-exercising-ops-p.patch +ksmbd-validate-compound-request-size-before-reading-.patch-18864 +wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch +wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch +hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch +hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch +hwmon-gigabyte_waterforce-stop-device-io-before-call.patch +hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch +hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch +watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch +watchdog-airoha-prevent-division-by-zero-when-clock-.patch +wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch +wifi-ath11k-flush-the-posted-write-after-writing-to-.patch +wifi-ath12k-flush-the-posted-write-after-writing-to-.patch +firewire-net-fix-fragmented-datagram-reassembly.patch +wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch +wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch +wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch +wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch +wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch +btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch +btrfs-fix-u32-to-s64-type-conversion-in-dirty_metada.patch +btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch +btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch +asoc-tas2781-bound-firmware-description-string-parsi.patch +asoc-sun4i-codec-set-quirks.playback_only-for-h616-c.patch +alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch +asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch +asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch +asoc-cs35l56-fix-potential-probe-deadlock.patch +asoc-cs35l56-use-complete_all-to-signal-init_complet.patch +wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch +wifi-iwlwifi-fix-pointer-arithmetic-in-iwl_add_mcc_t.patch +wifi-iwlwifi-validate-payload-length-in-iwl_pnvm_com.patch +wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch +usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch +drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch +hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch +hwmon-asus-ec-sensors-fix-ec-read-intervals.patch +hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch +smb-client-validate-dfs-referral-pathconsumed.patch +ovpn-avoid-putting-unrelated-p2p-peer-on-socket-rele.patch +selftests-net-ovpn-fix-getaddrinfo-memory-leak-in-ov.patch +ovpn-fix-use-after-free-in-unlock_ovpn.patch +ovpn-use-monotonic-clock-for-peer-keepalive-timeouts.patch +hwmon-occ-validate-poll-response-sensor-blocks.patch +regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch +bluetooth-btusb-validate-realtek-vendor-event-length.patch +net-phy-marvell-fix-return-code.patch +netlink-specs-rt-link-convert-bridge-port-flag-attri.patch +net-packet-avoid-fanout-hook-re-registration-after-u.patch +bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch +rds-drop-incoming-messages-that-cross-network-namesp.patch +gtp-parse-extension-headers-before-reading-inner-pro.patch +rxrpc-fix-io_thread-race-in-rxrpc_wake_up_io_thread.patch +dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch +net-airoha-fix-potential-use-after-free-in-airoha_pp.patch +dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch +net-airoha-fix-dma-direction-for-npu-mailbox-buffer.patch +iommu-amd-wait-for-completion-instead-of-returning-e.patch +wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch +nfp-check-resource-mutex-allocation.patch +wan-wanxl-only-reset-hardware-after-bar-mapping.patch +vhost-net-fix-tx-stall-when-vhost-owns-virtio-net-he.patch +wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch +iommu-amd-bound-the-early-acpi-hid-map.patch +iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch +wifi-mac80211-recalculate-tim-when-a-station-enters-.patch +pds_core-reject-component-parameter-in-legacy-firmwa.patch +arm64-correct-value-returned-by-esr_elx_fsc_addrsz_n.patch +amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch +soreuseport-clear-sk_reuseport_cb-before-failure-in-.patch +net-call-net_enable_timestamp-before-failure-in-sk_c.patch +net-txgbe-fix-fdir-filter-leak-on-remove.patch +sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch +pds_core-fix-deadlock-between-reset-thread-and-remov.patch +pds_core-fix-use-after-free-on-workqueue-during-remo.patch +pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch +pds_core-order-completion-reads-after-the-ownership-.patch +pds_core-fix-auxiliary-device-add-del-races.patch +pds_core-check-for-workqueue-allocation-failure.patch +sctp-validate-stream-count-in-sctp_process_strreset_.patch +net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch +tls-device-push-pending-open-record-on-splice-eof.patch +selftests-af_unix-add-user_ns-config.patch +selftests-openvswitch-add-config-file.patch +selftests-ovpn-add-ipv6-and-veth-configs.patch +selftests-ovpn-increase-timeout.patch +selftests-drv-net-increase-timeout.patch +gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch +nexthop-initialize-extack-in-nh_res_bucket_migrate.patch +tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch +ppp-enable-tx-scatter-gather.patch +ppp-don-t-store-tx-skb-in-the-fastpath.patch +ppp-annotate-concurrent-dev-stats-accesses.patch +wifi-mt76-disable-napi-when-removing-device.patch +wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch +wifi-mt76-mt7915-guard-he-capability-lookups.patch +wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch +wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch +wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch +wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch +wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch +wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch +ovl-fix-trusted-xattr-escape-prefix-matching.patch +drm-panel-s6e3ha8-fix-unmet-dependency-on-drm_displa.patch +cred-add-scoped_with_kernel_creds.patch +ovl-add-override_creds-cleanup-guard-extension-for-o.patch +ovl-port-ovl_copyfile-to-cred-guard.patch +ovl-check-access-to-copy_file_range-source-with-src-.patch +amt-re-read-skb-header-pointers-after-every-pull.patch +amt-make-the-head-writable-before-rewriting-the-l2-h.patch +net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch +net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch +net-dpaa-fix-mode-setting.patch +sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch +vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch +drm-xe-i2c-allow-per-domain-unique-id.patch +drm-xe-vm-fix-svm-leak-on-resv-obj-alloc-failure-in-.patch +iomap-correct-the-range-of-a-partial-dirty-clear.patch +iomap-simplify-iomap_iter_advance.patch +filemap-add-helper-to-look-up-dirty-folios-in-a-rang.patch +iomap-remove-pos-len-bug_on-to-after-folio-lookup.patch +iomap-optional-zero-range-dirty-folio-processing.patch +iomap-fix-incorrect-did_zero-setting-in-iomap_zero_i.patch +tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch +drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch +bpf-tcp-fix-double-sock-release-on-batch-realloc.patch +net-stmmac-remove-xstats.pcs_-members.patch +net-stmmac-socfpga-agilex5-emac-platform-configurati.patch +net-stmmac-socfpga-enable-tbs-support-for-agilex5.patch +net-stmmac-socfpga-add-hardware-supported-cross-time.patch +net-stmmac-cores-remove-many-xxx_shift-definitions.patch +net-stmmac-xgmac-fix-l4-filter-port-overwrite-on-reg.patch +net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch +net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch +net-stmmac-enable-the-mac-on-link-up-for-all-support.patch +net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch +octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch +ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch +ppp-annotate-data-races-in-ppp_generic.patch +hinic-remove-unused-ethtool-rss-user-configuration-b.patch +net-qrtr-restrict-socket-creation-to-the-initial-net.patch +raw-annotate-lockless-match-fields-in-raw_v4_match.patch +net-mlx5-refactor-eeprom-query-error-handling-to-ret.patch +net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch +net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch +net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch +net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch +octeontx2-pf-tc-fix-egress-ratelimiting.patch +net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch +ice-allow-creating-vfs-when-config_ice_switchdev.patch +ice-fix-lag-recipe-to-profile-association.patch +ice-prevent-tstamp-ring-allocation-for-non-pf-vsi-ty.patch +ipv6-change-allocation-flags-to-match-rcu_read_lock-.patch +rds-tcp-unregister-sysctl-before-tearing-down-listen.patch +ptp-netc-explicitly-clear-tmr_off-during-initializat.patch +mctp-check-register_netdevice_notifier-error-in-mctp.patch +net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch +bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch diff --git a/queue-6.18/smb-client-validate-dfs-referral-pathconsumed.patch b/queue-6.18/smb-client-validate-dfs-referral-pathconsumed.patch new file mode 100644 index 0000000000..a53335d5a9 --- /dev/null +++ b/queue-6.18/smb-client-validate-dfs-referral-pathconsumed.patch @@ -0,0 +1,97 @@ +From f74c36de83d5e0212776cf38a95b832e9c9a9419 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 13:25:23 +0800 +Subject: smb: client: validate DFS referral PathConsumed + +From: Yichong Chen + +[ Upstream commit f6f5ee2aa33b350c671721b965251c42cebb962e ] + +parse_dfs_referrals() validates that the response contains the fixed +referral entry array and, on for-next, the per-referral string offsets. +However, the response also contains a PathConsumed value that is later +used for DFS path parsing. + +If a malformed response provides a PathConsumed value larger than the +search name, later DFS parsing can advance beyond the end of the path. + +Validate PathConsumed against the search name length before storing it in +the parsed referral. + +Fixes: 4ecce920e13a ("CIFS: move DFS response parsing out of SMB1 code") +Reviewed-by: Paulo Alcantara (Red Hat) +Signed-off-by: Yichong Chen +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/misc.c | 34 +++++++++++++++++++++++++--------- + 1 file changed, 25 insertions(+), 9 deletions(-) + +diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c +index f378437113129a..d9771d224527d7 100644 +--- a/fs/smb/client/misc.c ++++ b/fs/smb/client/misc.c +@@ -957,6 +957,8 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + int i, rc = 0; + char *data_end; + struct dfs_referral_level_3 *ref; ++ unsigned int path_consumed; ++ size_t search_name_len; + + if (rsp_size < sizeof(*rsp)) { + cifs_dbg(VFS | ONCE, +@@ -1004,6 +1006,7 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + rc = -ENOMEM; + goto parse_DFS_referrals_exit; + } ++ search_name_len = strlen(searchName); + + /* collect necessary data from referrals */ + for (i = 0; i < *num_of_nodes; i++) { +@@ -1012,21 +1015,34 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + struct dfs_info3_param *node = (*target_nodes)+i; + + node->flags = le32_to_cpu(rsp->DFSFlags); ++ path_consumed = le16_to_cpu(rsp->PathConsumed); + if (is_unicode) { +- __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, +- GFP_KERNEL); +- if (tmp == NULL) { ++ size_t search_name_utf16_len = search_name_len * 2 + 2; ++ __le16 *tmp; ++ ++ if (path_consumed > search_name_utf16_len) { ++ rc = -EINVAL; ++ goto parse_DFS_referrals_exit; ++ } ++ ++ tmp = kmalloc(search_name_utf16_len, GFP_KERNEL); ++ if (!tmp) { + rc = -ENOMEM; + goto parse_DFS_referrals_exit; + } +- cifsConvertToUTF16((__le16 *) tmp, searchName, ++ cifsConvertToUTF16((__le16 *)tmp, searchName, + PATH_MAX, nls_codepage, remap); +- node->path_consumed = cifs_utf16_bytes(tmp, +- le16_to_cpu(rsp->PathConsumed), +- nls_codepage); ++ node->path_consumed = cifs_utf16_bytes(tmp, path_consumed, ++ nls_codepage); + kfree(tmp); +- } else +- node->path_consumed = le16_to_cpu(rsp->PathConsumed); ++ } else { ++ if (path_consumed > search_name_len) { ++ rc = -EINVAL; ++ goto parse_DFS_referrals_exit; ++ } ++ ++ node->path_consumed = path_consumed; ++ } + + node->server_type = le16_to_cpu(ref->ServerType); + node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); +-- +2.53.0 + diff --git a/queue-6.18/soreuseport-clear-sk_reuseport_cb-before-failure-in-.patch b/queue-6.18/soreuseport-clear-sk_reuseport_cb-before-failure-in-.patch new file mode 100644 index 0000000000..351eb89163 --- /dev/null +++ b/queue-6.18/soreuseport-clear-sk_reuseport_cb-before-failure-in-.patch @@ -0,0 +1,59 @@ +From f4b217e9a668bb547e0824756beed524e50b5df1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 18:31:39 +0000 +Subject: soreuseport: Clear sk_reuseport_cb before failure in sk_clone(). + +From: Kuniyuki Iwashima + +[ Upstream commit 98da8ce87dd561f08fbe44f75865edc5d9b2ba5f ] + +When sk_clone() fails, sk_destruct() is called for the new socket. + +If the parent socket has sk->sk_reuseport_cb, the child will call +reuseport_detach_sock() for the reuseport group. + +Let's clear sk->sk_reuseport_cb before any failure path in sk_clone(). + +Note that this was not a problem before the cited commit because +reuseport_detach_sock() did nothing if the socket was not found in +the reuseport array. + +Fixes: 5dc4c4b7d4e8 ("bpf: Introduce BPF_MAP_TYPE_REUSEPORT_SOCKARRAY") +Reported-by: Sashiko +Closes: https://lore.kernel.org/all/20260709032007.9E4D61F000E9@smtp.kernel.org/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Willem de Bruijn +Reviewed-by: Jason Xing +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260709183315.965751-2-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/sock.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/core/sock.c b/net/core/sock.c +index c52cec0bf942c0..9803926942c559 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -2525,6 +2525,8 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) + + cgroup_sk_clone(&newsk->sk_cgrp_data); + ++ RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL); ++ + rcu_read_lock(); + filter = rcu_dereference(sk->sk_filter); + if (filter != NULL) +@@ -2547,8 +2549,6 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) + goto free; + } + +- RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL); +- + if (bpf_sk_storage_clone(sk, newsk)) + goto free; + +-- +2.53.0 + diff --git a/queue-6.18/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch b/queue-6.18/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch new file mode 100644 index 0000000000..3d863a29d7 --- /dev/null +++ b/queue-6.18/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch @@ -0,0 +1,47 @@ +From c37a8b91559cac8d4b81423834c96df977589c1a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:49:35 -0300 +Subject: tipc: fix infinite loop in __tipc_nl_compat_dumpit + +From: Helen Koike + +[ Upstream commit 22f8aa35964e8f2ab026578f45befc9605fd1b28 ] + +cmd->dumpit callback can return a negative errno, causing an infinite +loop due to the while(len) condition. As the loop never terminates, +genl_mutex is never released, and other tasks waiting on it starve in D +state. + +Check dumpit's return value, propagate it and jump to err_out on error. + +Reported-by: syzbot+85d0bec020d805014a3a@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=85d0bec020d805014a3a +Fixes: d0796d1ef63d ("tipc: convert legacy nl bearer dump to nl compat") +Signed-off-by: Helen Koike +Reviewed-by: Tung Nguyen +Link: https://patch.msgid.link/20260713204940.647668-1-koike@igalia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/netlink_compat.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c +index 079aebb16ed8ff..30e37c05a3f334 100644 +--- a/net/tipc/netlink_compat.c ++++ b/net/tipc/netlink_compat.c +@@ -222,6 +222,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, + int rem; + + len = (*cmd->dumpit)(buf, &cb); ++ if (len < 0) { ++ err = len; ++ goto err_out; ++ } + + nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) { + err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN, +-- +2.53.0 + diff --git a/queue-6.18/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch b/queue-6.18/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch new file mode 100644 index 0000000000..09432a2018 --- /dev/null +++ b/queue-6.18/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch @@ -0,0 +1,72 @@ +From 1d9996708475fa36484084057fb1f1894ad0c721 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 00:15:41 -0400 +Subject: tipc: fix u16 MTU truncation in media and bearer MTU validation + +From: Cen Zhang (Microsoft) + +[ Upstream commit 9f29cd8a8e7901a2617c8064ce9f50fc67b97cb8 ] + +Both TIPC_NL_MEDIA_SET and TIPC_NL_BEARER_SET accept user-supplied +MTU values but only enforce a minimum bound, not a maximum. When a user +sets the MTU to a value exceeding U16_MAX (65535), it passes validation +but is silently truncated when assigned to u16 fields l->mtu and +l->advertised_mtu in tipc_link_create(). Values like 65536 (0x10000) +truncate to 0, causing a division by zero in tipc_link_set_queue_limits() +which computes TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE). Other overflowing +values (e.g. 65537-131071) produce small incorrect MTU values, resulting +in link malfunction behaviors. + +Crash stack (triggered as unprivileged user via user namespace): + + tipc_link_set_queue_limits net/tipc/link.c:2531 + tipc_link_create net/tipc/link.c:520 + tipc_node_check_dest net/tipc/node.c:1279 + tipc_disc_rcv net/tipc/discover.c:252 + tipc_rcv net/tipc/node.c:2129 + tipc_udp_recv net/tipc/udp_media.c:392 + +Two independent paths lack the upper bound check: +1. tipc_udp_mtu_bad() -- called from __tipc_nl_media_set() (MEDIA_SET) +2. inline check in __tipc_nl_bearer_set() at bearer.c:1160 (BEARER_SET) + +Fix both by rejecting MTU values above U16_MAX. + +Fixes: 901271e0403a ("tipc: implement configuration of UDP media MTU") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/CAB8m9WgETt0AjmFwE=F-CKjGXsK6_WDv0=kbYRcC8-noo+amnA@mail.gmail.com +Reviewed-by: Vadim Fedorenko +Signed-off-by: Cen Zhang (Microsoft) +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260714041541.307702-1-blbllhy@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tipc/netlink.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c +index 8336a9664703fe..1307dd1a961341 100644 +--- a/net/tipc/netlink.c ++++ b/net/tipc/netlink.c +@@ -113,12 +113,16 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { + }; + + /* Properties valid for media, bearer and link */ ++static const struct netlink_range_validation tipc_nl_mtu_range = { ++ .max = U16_MAX, ++}; ++ + const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { + [TIPC_NLA_PROP_UNSPEC] = { .type = NLA_UNSPEC }, + [TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 }, +- [TIPC_NLA_PROP_MTU] = { .type = NLA_U32 }, ++ [TIPC_NLA_PROP_MTU] = NLA_POLICY_FULL_RANGE(NLA_U32, &tipc_nl_mtu_range), + [TIPC_NLA_PROP_BROADCAST] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_BROADCAST_RATIO] = { .type = NLA_U32 } + }; +-- +2.53.0 + diff --git a/queue-6.18/tls-device-push-pending-open-record-on-splice-eof.patch b/queue-6.18/tls-device-push-pending-open-record-on-splice-eof.patch new file mode 100644 index 0000000000..abdf48383b --- /dev/null +++ b/queue-6.18/tls-device-push-pending-open-record-on-splice-eof.patch @@ -0,0 +1,56 @@ +From 76560a4050368c951cc4d28a1095525d22f53e2a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 16:44:36 -0600 +Subject: tls: device: push pending open record on splice EOF + +From: Rishikesh Jethwani + +[ Upstream commit eaa39f9f8ac8c1d032cd26b9cd572804e9d7683f ] + +On kTLS device-offload sockets, sendfile() with count > EOF can reach +->splice_eof() with a fully assembled but still-open TLS record left +pending. tls_device_splice_eof() only flushes partially sent records, +so an abrupt close() can drop the final record and the peer receives +a short file. + +Fix tls_device_splice_eof() to also push pending open records. +This matches the software path, where splice EOF already flushes +pending open records. + +Fixes: d4c1e80b0d1b ("tls/device: Use splice_eof() to flush") +Link: https://lore.kernel.org/netdev/CAMPsyauZ+jzG9AysO0FWv6ZY0kvCUpjX_U7o=oOjCuOQ87BCgg@mail.gmail.com/ +Reported-by: Nils Juenemann +Signed-off-by: Rishikesh Jethwani +Tested-by: Nils Juenemann +Link: https://patch.msgid.link/20260709224436.1608993-2-rjethwani@purestorage.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tls/tls_device.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c +index 71734411ff4c3a..d2e3870590c894 100644 +--- a/net/tls/tls_device.c ++++ b/net/tls/tls_device.c +@@ -594,13 +594,15 @@ void tls_device_splice_eof(struct socket *sock) + struct tls_context *tls_ctx = tls_get_ctx(sk); + struct iov_iter iter = {}; + +- if (!tls_is_partially_sent_record(tls_ctx)) ++ if (!tls_is_partially_sent_record(tls_ctx) && ++ !tls_is_pending_open_record(tls_ctx)) + return; + + mutex_lock(&tls_ctx->tx_lock); + lock_sock(sk); + +- if (tls_is_partially_sent_record(tls_ctx)) { ++ if (tls_is_partially_sent_record(tls_ctx) || ++ tls_is_pending_open_record(tls_ctx)) { + iov_iter_bvec(&iter, ITER_SOURCE, NULL, 0, 0); + tls_push_data(sk, &iter, 0, 0, TLS_RECORD_TYPE_DATA); + } +-- +2.53.0 + diff --git a/queue-6.18/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch b/queue-6.18/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch new file mode 100644 index 0000000000..b57f3a42f8 --- /dev/null +++ b/queue-6.18/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch @@ -0,0 +1,93 @@ +From b1c630db357eb59ccf315a6c7959ae322e3e7e2a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 02:07:04 -0600 +Subject: usb: atm: ueagle-atm: reject descriptors that confuse probe and + disconnect + +From: Diego Fernando Mancera Gomez + +[ Upstream commit 71132cedd1ecbc4032d76e9928c18a10f7e39b80 ] + +uea_probe() distinguishes a pre-firmware device from a post-firmware one +using the USB id (UEA_IS_PREFIRM()), and stores a different object as the +interface data in each case: a 'struct completion' for a pre-firmware +device (to be waited on in .disconnect()), or a 'struct usbatm_data' for a +post-firmware one. + +uea_disconnect() instead tells the two apart by the number of interfaces +of the active configuration (a pre-firmware device exposes a single +interface, ADI930 has 2 and eagle has 3), and casts the interface data +accordingly. + +Because the two handlers use different criteria, a crafted device that +advertises a pre-firmware id together with a multi-interface descriptor +(or a post-firmware id with a single interface) makes them disagree: the +small 'struct completion' stored by uea_probe() is then passed to +usbatm_usb_disconnect(), which casts it to 'struct usbatm_data' and takes +instance->serialize, reading past the end of the allocation: + + BUG: KASAN: slab-out-of-bounds in __mutex_lock+0x152a/0x1b80 + Read of size 8 at addr ffff8880470e2c60 by task kworker/1:2/982 + ... + __mutex_lock+0x152a/0x1b80 + usbatm_usb_disconnect+0x70/0x820 + uea_disconnect+0x133/0x2c0 + usb_unbind_interface+0x1dd/0x9e0 + ... + which belongs to the cache kmalloc-96 of size 96 + The buggy address is located 0 bytes to the right of + allocated 96-byte region [ffff8880470e2c00, ffff8880470e2c60) + +Reject such inconsistent descriptors in uea_probe() so that both handlers +always make the same pre/post-firmware decision. + +Reported-by: syzbot+e62a973f8322b3bbe3ac@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e62a973f8322b3bbe3ac +Fixes: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()") +Signed-off-by: Diego Fernando Mancera Gomez +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260717080704.1264-1-diegomancera.dev@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/atm/ueagle-atm.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c +index a943a5257a59fb..f1f1fc16a4711f 100644 +--- a/drivers/usb/atm/ueagle-atm.c ++++ b/drivers/usb/atm/ueagle-atm.c +@@ -2550,6 +2550,7 @@ static struct usbatm_driver uea_usbatm_driver = { + static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + { + struct usb_device *usb = interface_to_usbdev(intf); ++ bool single_iface = usb->config->desc.bNumInterfaces == 1; + int ret; + + uea_dbg(usb, "ADSL device found with vid (%#X) pid (%#X) Rev (%#X): %s\n", +@@ -2558,6 +2559,22 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + le16_to_cpu(usb->descriptor.bcdDevice), + chip_name[UEA_CHIP_VERSION(id)]); + ++ /* ++ * uea_probe() decides between the pre-firmware and post-firmware case ++ * from the USB id and stores a different object as interface data in ++ * each case: a struct completion for a pre-firmware device, a struct ++ * usbatm_data for a post-firmware one. uea_disconnect() instead tells ++ * the two apart by the number of interfaces (a pre-firmware device ++ * exposes a single interface, ADI930 has 2 and eagle has 3). A crafted ++ * device advertising a pre-firmware id together with a multi-interface ++ * descriptor (or the other way around) makes the two disagree, so that ++ * usbatm_usb_disconnect() treats the small completion object as a ++ * struct usbatm_data and reads out of bounds. Reject such inconsistent ++ * descriptors so both paths make the same decision. ++ */ ++ if (UEA_IS_PREFIRM(id) != single_iface) ++ return -ENODEV; ++ + usb_reset_device(usb); + + if (UEA_IS_PREFIRM(id)) { +-- +2.53.0 + diff --git a/queue-6.18/vhost-net-fix-tx-stall-when-vhost-owns-virtio-net-he.patch b/queue-6.18/vhost-net-fix-tx-stall-when-vhost-owns-virtio-net-he.patch new file mode 100644 index 0000000000..0ec870fae7 --- /dev/null +++ b/queue-6.18/vhost-net-fix-tx-stall-when-vhost-owns-virtio-net-he.patch @@ -0,0 +1,58 @@ +From 2f8f4d1e9bc09e5dbd87196ffad1057d608cf40f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:22:42 +0100 +Subject: vhost-net: fix TX stall when vhost owns virtio-net header + +From: Enrico Zanda + +[ Upstream commit 3c0d10f233f19153f81fef685b5c6716776a5af3 ] + +When vhost owns the virtio-net header, i.e. when +VHOST_NET_F_VIRTIO_NET_HDR is negotiated, sock_hlen is 0, +meaning that no header will be forwarded to the TAP device. + +In the current vhost_net_build_xdp() implementation, +when sock_hlen == 0, the gso pointer can point at the start of the +Ethernet frame instead of a virtio-net header. +This results in a wrong interpretation of the destination MAC address +bytes as struct virtio_net_hdr fields. + +This can, for some MAC addresses, trigger -EINVAL and return early +before the TX descriptor is completed, which can stall vhost-net TX. + +Before 97b2409f28e0, the gso pointer was set to the zeroed padding area, +using it as a synthetic virtio-net header. Restore that behavior. + +Fixes: 97b2409f28e0 ("vhost-net: reduce one userspace copy when building XDP buff") +Signed-off-by: Enrico Zanda +Acked-by: Michael S. Tsirkin +Link: https://patch.msgid.link/20260708152242.2268848-1-enrico.zanda@arm.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/vhost/net.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c +index b2b90732b1d595..89d5438ba7af97 100644 +--- a/drivers/vhost/net.c ++++ b/drivers/vhost/net.c +@@ -724,10 +724,12 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, + goto err; + } + +- gso = buf + pad - sock_hlen; +- +- if (!sock_hlen) ++ if (!sock_hlen) { + memset(buf, 0, pad); ++ gso = buf; ++ } else { ++ gso = buf + pad - sock_hlen; ++ } + + if ((gso->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && + vhost16_to_cpu(vq, gso->csum_start) + +-- +2.53.0 + diff --git a/queue-6.18/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch b/queue-6.18/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch new file mode 100644 index 0000000000..0da360ea80 --- /dev/null +++ b/queue-6.18/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch @@ -0,0 +1,84 @@ +From c4e045074da687898a81145a46e7857dfe8a6fe7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 07:09:15 -0700 +Subject: vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets + +From: Harshaka Narayana + +[ Upstream commit 34a71f5361fc3adb5b7138da78750b0d535a8252 ] + +vmxnet3_get_hdr_len() assumes gdesc->rcd.v4/v6/tcp always describe the +outer header, but for a Geneve-encapsulated packet the device can set +them based on the inner header instead, signalled by the +VMXNET3_RCD_HDR_INNER_SHIFT bit in the completion descriptor. Since the +function never skips the outer encapsulation, this mismatch triggers: + +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP), because the outer + protocol is UDP (Geneve), not TCP. +- BUG_ON(hdr.eth->h_proto != ...), when the tunnel's outer and inner + IP versions differ (e.g. outer IPv6/inner IPv4 or vice versa). + +Check VMXNET3_RCD_HDR_INNER_SHIFT up front and bail out, since the +function cannot locate the inner header it would need to parse. Also +convert the remaining BUG_ON()s in this function to return 0 +defensively. + +Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)") +Signed-off-by: Harshaka Narayana +Reviewed-by: Ronak Doshi +Reviewed-by: Sankararaman Jayaraman +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260713140915.3381715-1-harshaka.narayana@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c +index 0572f6a9bdb628..679208d587f853 100644 +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -1530,7 +1530,11 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + struct ipv6hdr *ipv6; + struct tcphdr *tcp; + } hdr; +- BUG_ON(gdesc->rcd.tcp == 0); ++ ++ /* v4/v6/tcp then describe the inner header, which we can't locate. */ ++ if ((le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT)) || ++ gdesc->rcd.tcp == 0) ++ return 0; + + maplen = skb_headlen(skb); + if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen)) +@@ -1544,15 +1548,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + + hdr.eth = eth_hdr(skb); + if (gdesc->rcd.v4) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)); ++ if (hdr.eth->h_proto != htons(ETH_P_IP) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)) ++ return 0; ++ + hdr.ptr += hlen; +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP); ++ if (hdr.ipv4->protocol != IPPROTO_TCP) ++ return 0; ++ + hlen = hdr.ipv4->ihl << 2; + hdr.ptr += hdr.ipv4->ihl << 2; + } else if (gdesc->rcd.v6) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)); ++ if (hdr.eth->h_proto != htons(ETH_P_IPV6) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)) ++ return 0; ++ + hdr.ptr += hlen; + /* Use an estimated value, since we also need to handle + * TSO case. +-- +2.53.0 + diff --git a/queue-6.18/wan-wanxl-only-reset-hardware-after-bar-mapping.patch b/queue-6.18/wan-wanxl-only-reset-hardware-after-bar-mapping.patch new file mode 100644 index 0000000000..b7f4b209f4 --- /dev/null +++ b/queue-6.18/wan-wanxl-only-reset-hardware-after-bar-mapping.patch @@ -0,0 +1,51 @@ +From 236946eb8130df476c71bb3f417c518a84312f22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:15 +0800 +Subject: wan: wanxl: Only reset hardware after BAR mapping + +From: Ruoyu Wang + +[ Upstream commit 91957b89da995607cb654b1f9a3c126ddbaee10f ] + +wanxl_pci_init_one() stores the freshly allocated card in driver data +before the PLX BAR is mapped. Several early probe failures then unwind +through wanxl_pci_remove_one(), including failure to allocate the coherent +status area or to restore the DMA mask. + +wanxl_pci_remove_one() unconditionally calls wanxl_reset(), and +wanxl_reset() dereferences card->plx. On those early failures card->plx +is still NULL, so the error path can dereference a NULL MMIO pointer. + +Only issue the hardware reset once the BAR mapping exists. The remaining +cleanup in wanxl_pci_remove_one() already checks whether later resources +were allocated. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ruoyu Wang +Link: https://patch.msgid.link/20260708143415.3169358-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/wan/wanxl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c +index 5a9e262188efe1..c38dd741401e13 100644 +--- a/drivers/net/wan/wanxl.c ++++ b/drivers/net/wan/wanxl.c +@@ -514,7 +514,8 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) + if (card->irq) + free_irq(card->irq, card); + +- wanxl_reset(card); ++ if (card->plx) ++ wanxl_reset(card); + + for (i = 0; i < RX_QUEUE_LENGTH; i++) + if (card->rx_skbs[i]) { +-- +2.53.0 + diff --git a/queue-6.18/watchdog-airoha-prevent-division-by-zero-when-clock-.patch b/queue-6.18/watchdog-airoha-prevent-division-by-zero-when-clock-.patch new file mode 100644 index 0000000000..395ef74d26 --- /dev/null +++ b/queue-6.18/watchdog-airoha-prevent-division-by-zero-when-clock-.patch @@ -0,0 +1,46 @@ +From cc64c26a5bcf1c88ad6d639570c8a42abec3b5c7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 10:41:54 +0800 +Subject: watchdog: airoha: Prevent division by zero when clock frequency is + zero + +From: Wayen Yan + +[ Upstream commit bcfcd7619f277842430d197556463b401b839ee9 ] + +clk_get_rate() can return 0 when the clock provider is not properly +configured or the clock is unmanaged. The driver uses wdt_freq as a +divisor directly in airoha_wdt_probe() to compute max_timeout and in +airoha_wdt_get_timeleft() to compute the remaining time, which results +in a division by zero. + +Add a check for wdt_freq == 0 in probe and return -EINVAL with +dev_err_probe() to prevent the division by zero and provide a +diagnostic message. + +Fixes: 3cf67f3769b8 ("watchdog: Add support for Airoha EN7851 watchdog") +Signed-off-by: Wayen Yan +Link: https://lore.kernel.org/r/178347932594.81327.4834644880399144119@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/airoha_wdt.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/watchdog/airoha_wdt.c b/drivers/watchdog/airoha_wdt.c +index dc8ca11c14d81a..4bd333189b87ec 100644 +--- a/drivers/watchdog/airoha_wdt.c ++++ b/drivers/watchdog/airoha_wdt.c +@@ -147,6 +147,9 @@ static int airoha_wdt_probe(struct platform_device *pdev) + + /* Watchdog ticks at half the bus rate */ + airoha_wdt->wdt_freq = clk_get_rate(bus_clk) / 2; ++ if (!airoha_wdt->wdt_freq) ++ return dev_err_probe(dev, -EINVAL, ++ "invalid clock frequency\n"); + + /* Initialize struct watchdog device */ + wdog_dev = &airoha_wdt->wdog_dev; +-- +2.53.0 + diff --git a/queue-6.18/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch b/queue-6.18/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch new file mode 100644 index 0000000000..09a9b13557 --- /dev/null +++ b/queue-6.18/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch @@ -0,0 +1,48 @@ +From b0259f5605201ee718729d65fe420a7105ff70c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:18:03 +0000 +Subject: watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() + +From: Tzung-Bi Shih + +[ Upstream commit 7362ba0f9c96ac3ad6a2ca3995bd9fc9a28a8661 ] + +When a watchdog governor is unregistered, it updates existing watchdog +devices that were using this governor by falling back to `default_gov`. + +If the governor being unregistered is currently set as `default_gov`, +the `default_gov` is never cleared. This leads to 2 use-after-free +issues: +1. New watchdog devices registered after this point will inherit the + dangling `default_gov`. +2. Existing watchdog devices using the unregistered governor will have + their `wdd->gov` reassigned to the dangling `default_gov`. + +Fix the UAF by clearing `default_gov` if it matches the governor being +unregistered. + +Fixes: da0d12ff2b82 ("watchdog: pretimeout: add panic pretimeout governor") +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20260707101803.3598173-1-tzungbi@kernel.org +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/watchdog_pretimeout.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c +index 2526436dc74dd8..ea05f84f07e184 100644 +--- a/drivers/watchdog/watchdog_pretimeout.c ++++ b/drivers/watchdog/watchdog_pretimeout.c +@@ -167,6 +167,8 @@ void watchdog_unregister_governor(struct watchdog_governor *gov) + } + + spin_lock_irq(&pretimeout_lock); ++ if (default_gov == gov) ++ default_gov = NULL; + list_for_each_entry(p, &pretimeout_list, entry) + if (p->wdd->gov == gov) + p->wdd->gov = default_gov; +-- +2.53.0 + diff --git a/queue-6.18/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch b/queue-6.18/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch new file mode 100644 index 0000000000..da5b3e3dcc --- /dev/null +++ b/queue-6.18/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch @@ -0,0 +1,68 @@ +From 18e29867d328a788492331fa1df23dbe710d2316 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jun 2026 17:06:09 +0800 +Subject: wifi: ath11k: fix NULL pointer dereference in + ath11k_hal_srng_access_begin + +From: Gaole Zhang + +[ Upstream commit e8d85672dd7e2523f774caafba8f858384e18df7 ] + +In ATH11K_QMI_EVENT_FW_READY, ATH11K_FLAG_REGISTERED is set +unconditionally even when ath11k_core_qmi_firmware_ready() fails. +This leaves the driver in an inconsistent state where +initialization is considered complete although the firmware ready +handling did not finish successfully. During the subsequent SSR, +the driver enters the restart path based on this incorrect state +and dereferences uninitialized srng members, resulting in a NULL +pointer dereference. + +Call trace: + ath11k_hal_srng_access_begin+0xc/0x60 [ath11k] (P) + ath11k_ce_cleanup_pipes+0x17c/0x180 [ath11k] + ath11k_core_restart+0x40/0x168 [ath11k] + +Fix this by: +- skipping firmware_ready if ATH11K_FLAG_REGISTERED is already set +- setting ATH11K_FLAG_REGISTERED only when firmware_ready succeeds +- setting ATH11K_FLAG_QMI_FAIL and aborting the FW_READY handling +on error + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.2.0.c2-00204-QCAMSLSWPLZ-1 + +Fixes: 6fe62a8cec51c ("wifi: ath11k: Add cold boot calibration support on WCN6750") +Signed-off-by: Gaole Zhang +Reviewed-by: Baochen Qiang +Reviewed-by: Rameshkumar Sundaram +Link: https://patch.msgid.link/20260609090609.4041009-1-gaole.zhang@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/qmi.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index aea56c38bf8f38..f23d75c8ad6794 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -3295,9 +3295,14 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) + clear_bit(ATH11K_FLAG_CRASH_FLUSH, + &ab->dev_flags); + clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); +- ath11k_core_qmi_firmware_ready(ab); +- set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); +- ++ if (!test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { ++ ret = ath11k_core_qmi_firmware_ready(ab); ++ if (ret) { ++ set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); ++ break; ++ } ++ set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); ++ } + break; + case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE: + break; +-- +2.53.0 + diff --git a/queue-6.18/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch b/queue-6.18/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch new file mode 100644 index 0000000000..4483be0bbf --- /dev/null +++ b/queue-6.18/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch @@ -0,0 +1,48 @@ +From 7cb70c61d7f51a50cb8fad75198f8d47b940d3e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 May 2026 11:42:52 +0000 +Subject: wifi: ath11k: fix potential buffer underflow in + ath11k_hal_rx_msdu_list_get() + +From: Dmitry Morgun + +[ Upstream commit 7f11e70629650ff6ea140984e5ce188b775b2683 ] + +When the first entry in msdu_details has a zero buffer address, +the code accesses msdu_details[i - 1] with i == 0, causing a +buffer underflow. + +Fix similarly to ath12k_wifi7_hal_rx_msdu_list_get() by adding +a separate check for i == 0 before the main condition to prevent +the out-of-bounds access. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Dmitry Morgun +Reviewed-by: Rameshkumar Sundaram +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20260530114252.42615-1-d.morgun@ispras.ru +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 5666f66474455a..330446f279cd6d 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -4609,6 +4609,9 @@ static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar, + msdu_details = &msdu_link->msdu_link[0]; + + for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) { ++ if (!i && FIELD_GET(BUFFER_ADDR_INFO0_ADDR, ++ msdu_details[i].buf_addr_info.info0) == 0) ++ break; + if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR, + msdu_details[i].buf_addr_info.info0) == 0) { + msdu_desc_info = &msdu_details[i - 1].rx_msdu_info; +-- +2.53.0 + diff --git a/queue-6.18/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch b/queue-6.18/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch new file mode 100644 index 0000000000..eb7e0fc35a --- /dev/null +++ b/queue-6.18/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch @@ -0,0 +1,60 @@ +From c1ed9381ef95434b00419e9f91caf2b492d761f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 16:16:48 +0200 +Subject: wifi: ath11k: Flush the posted write after writing to + PCIE_SOC_GLOBAL_RESET + +From: Manivannan Sadhasivam + +[ Upstream commit 0fe8010fc5b147607fc19ba010ba469afc95f35f ] + +ath11k_pci_soc_global_reset() tries to reset the device by writing to the +PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure +that the write gets flushed to the device before the delay. + +This may lead to the delay on the host to be insufficient, if the posted +write doesn't reach the device before the delay. + +So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and +before the delay. + +Compile tested only. + +Fixes: f3c603d412b3 ("ath11k: reset MHI during power down and power up") +Reported-by: Alex Williamson +Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Reviewed-by: Raj Kumar Bhagat +Link: https://patch.msgid.link/20260623141649.41087-1-manivannan.sadhasivam@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c +index 7114eca8810dbf..c7048219f3e08a 100644 +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -199,6 +199,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) + val |= PCIE_SOC_GLOBAL_RESET_V; + + ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); + + /* TODO: exact time to sleep is uncertain */ + delay = 10; +@@ -208,6 +210,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) + val &= ~PCIE_SOC_GLOBAL_RESET_V; + + ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); + + mdelay(delay); + +-- +2.53.0 + diff --git a/queue-6.18/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch b/queue-6.18/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch new file mode 100644 index 0000000000..0e4989ec6e --- /dev/null +++ b/queue-6.18/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch @@ -0,0 +1,62 @@ +From 1d4870a3c6a19c2b21a774029a029e7d7b801616 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 16:16:49 +0200 +Subject: wifi: ath12k: Flush the posted write after writing to + PCIE_SOC_GLOBAL_RESET + +From: Manivannan Sadhasivam + +[ Upstream commit 55f3aa06951cac78b0206bde961c8cf11929a27a ] + +ath12k_pci_soc_global_reset() tries to reset the device by writing to the +PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure +that the write gets flushed to the device before the delay. + +This may lead to the delay on the host to be insufficient, if the posted +write doesn't reach the device before the delay. + +So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and +before the delay. + +Compile tested only. +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1 + +Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") +Reported-by: Alex Williamson +Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Reviewed-by: Raj Kumar Bhagat +Tested-by: Raj Kumar Bhagat +Link: https://patch.msgid.link/20260623141649.41087-2-manivannan.sadhasivam@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c +index 60b8f7361b7f63..37f41635d3b00e 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -240,6 +240,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab) + val |= PCIE_SOC_GLOBAL_RESET_V; + + ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET); + + /* TODO: exact time to sleep is uncertain */ + delay = 10; +@@ -249,6 +251,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab) + val &= ~PCIE_SOC_GLOBAL_RESET_V; + + ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET); + + mdelay(delay); + +-- +2.53.0 + diff --git a/queue-6.18/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch b/queue-6.18/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch new file mode 100644 index 0000000000..e3bcd71d3e --- /dev/null +++ b/queue-6.18/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch @@ -0,0 +1,49 @@ +From 7bce3eb67e58673943f8628d00998e9db1648b3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:50:08 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware IE lengths in connect event + +From: Tristan Madani + +[ Upstream commit 6b47b29730de3232b919d8362749f6814c5f2a33 ] + +The firmware-controlled beacon_ie_len, assoc_req_len, and assoc_resp_len +fields in ath6kl_wmi_connect_event_rx() are not validated against the +buffer length. Their sum (up to 765) can exceed the actual WMI event +data, causing out-of-bounds reads during IE parsing and state corruption +of wmi->is_wmm_enabled. + +Add a check that the total IE length fits within the buffer. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20260421135009.348084-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index aab1ad80a8b6c2..0cdcbc3c77966a 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -874,6 +874,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, + + ev = (struct wmi_connect_event *) datap; + ++ if (len < sizeof(*ev) + ev->beacon_ie_len + ++ ev->assoc_req_len + ev->assoc_resp_len) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, ++ "connect event: IE lengths %u+%u+%u exceed buffer %d\n", ++ ev->beacon_ie_len, ev->assoc_req_len, ++ ev->assoc_resp_len, len); ++ return -EINVAL; ++ } + if (vif->nw_type == AP_NETWORK) { + /* AP mode start/STA connected event */ + struct net_device *dev = vif->ndev; +-- +2.53.0 + diff --git a/queue-6.18/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch b/queue-6.18/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch new file mode 100644 index 0000000000..d5f1a1c167 --- /dev/null +++ b/queue-6.18/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch @@ -0,0 +1,53 @@ +From bffbd8357c7c2eabe8e39e6e8f15ba3b6e513cb5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jun 2026 23:29:07 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware num_msg in TX complete + handler + +From: Tristan Madani + +[ Upstream commit 3a21c89215cc18f1a97c5e5bfd1da6d4f3d44495 ] + +The firmware-controlled num_msg field (u8, 0-255) drives the loop in +ath6kl_wmi_tx_complete_event_rx() without validation against the buffer +length. This allows out-of-bounds reads of up to 1020 bytes past the +WMI event buffer when the firmware sends an inflated num_msg. + +Add a check that the buffer is large enough to hold the fixed struct +and the num_msg variable-length entries. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Link: https://patch.msgid.link/20260625232907.3620746-1-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index 08a154bce1396e..aab1ad80a8b6c2 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -484,6 +484,18 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) + + evt = (struct wmi_tx_complete_event *) datap; + ++ if (len < sizeof(*evt)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d\n", ++ len); ++ return -EINVAL; ++ } ++ ++ if (len < sizeof(*evt) + evt->num_msg * sizeof(struct tx_complete_msg_v1)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d for %u msgs\n", ++ len, evt->num_msg); ++ return -EINVAL; ++ } ++ + ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", + evt->num_msg, evt->msg_len, evt->msg_type); + +-- +2.53.0 + diff --git a/queue-6.18/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch b/queue-6.18/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch new file mode 100644 index 0000000000..42a857bdbd --- /dev/null +++ b/queue-6.18/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch @@ -0,0 +1,90 @@ +From ee68d240cea883eaacf1e4a273cd678462513bcd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 08:32:10 -0700 +Subject: wifi: ath9k: hif_usb: don't dereference hif_dev after re-arming + firmware request +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Cheng Yongkang + +[ Upstream commit dad9f96945d77ecd4708f730c06ef54dcd8cc057 ] + +ath9k_hif_request_firmware() re-arms an asynchronous firmware load via +request_firmware_nowait(), passing hif_dev as the completion context, and +then still dereferences hif_dev: + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", + hif_dev->fw_name); + +The re-armed callback ath9k_hif_usb_firmware_cb() runs on the "events" +workqueue and, when the firmware is missing, walks the retry chain into +ath9k_hif_usb_firmware_fail() -> complete_all(&hif_dev->fw_done). That +releases the wait_for_completion(&hif_dev->fw_done) in a concurrent +ath9k_hif_usb_disconnect(), which then kfree()s hif_dev. The trailing +dev_info() in the frame that re-armed the request can therefore read freed +memory (hif_dev->udev, the first field of struct hif_device_usb): + + BUG: KASAN: slab-use-after-free in ath9k_hif_request_firmware + Read of size 8 ... by task kworker/... + ath9k_hif_request_firmware + ath9k_hif_usb_firmware_cb drivers/net/wireless/ath/ath9k/hif_usb.c:1247 + request_firmware_work_func + Allocated by ...: + ath9k_hif_usb_probe drivers/net/wireless/ath/ath9k/hif_usb.c + Freed by ...: + ath9k_hif_usb_disconnect -> kfree drivers/net/wireless/ath/ath9k/hif_usb.c + +The fw_done barrier only makes disconnect wait for the firmware chain to +*terminate*; it does not protect the outer ath9k_hif_request_firmware() +frame that re-armed the request and keeps touching hif_dev afterwards. + +Drop the post-request dev_info(): it is the only use of hif_dev after the +async request is armed, and it is purely informational (the dev_err() on the +failure path runs only when request_firmware_nowait() did not arm a callback, +so hif_dev is still alive there). + +This was first reported by syzbot as a single, non-reproduced crash that was +later auto-obsoleted, and was independently rediscovered by the reFuzz fuzzer, +which produced a C reproducer (USB-gadget connect/disconnect of an ath9k_htc +device whose firmware download fails). The vulnerable code is unchanged and +still present in v7.1-rc6, where the slab-use-after-free reproduces under KASAN +once the (sub-microsecond) race window is widened. + +Fixes: e904cf6fe230 ("ath9k_htc: introduce support for different fw versions") +Reported-by: syzbot+50122cbc2874b1eb25b0@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=50122cbc2874b1eb25b0 +Signed-off-by: Cheng Yongkang +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260605153210.20471-1-1020691186@qq.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index fe9abe8cd268fa..0a3d2190b9beec 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -1225,15 +1225,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, + ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, + &hif_dev->udev->dev, GFP_KERNEL, + hif_dev, ath9k_hif_usb_firmware_cb); +- if (ret) { ++ if (ret) + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Async request for firmware %s failed\n", + hif_dev->fw_name); +- return ret; +- } +- +- dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", +- hif_dev->fw_name); + + return ret; + } +-- +2.53.0 + diff --git a/queue-6.18/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch b/queue-6.18/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch new file mode 100644 index 0000000000..045f95ec18 --- /dev/null +++ b/queue-6.18/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch @@ -0,0 +1,69 @@ +From 89ee1f74b75a64922a877a562b90f39636931d4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 May 2026 16:38:59 +0800 +Subject: wifi: brcmfmac: fix 802.1X-SHA256 call trace warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Shelley Yang + +[ Upstream commit 7cb34f6c4fe8a68af621d870abe63bfca2275dd6 ] + +Based on wpa_auth as 1x_256 mode, need to set up +"use_fwsup" with BRCMF_PROFILE_FWSUP_1X. +Or it will happen trace warning when call brcmf_cfg80211_set_pmk(). + +[ 4481.831101] ------------[ cut here ]------------ +[ 4481.831102] WARNING: CPU: 1 PID: 2997 at +drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:7242 brcmf_cfg80211_set_pmk+0x77/0xd0 [brcmfmac] +[...] +[ 4481.831202] Call Trace: +[ 4481.831204]   +[ 4481.831205]  nl80211_set_pmk+0x183/0x250 [cfg80211] +[ 4481.831233]  genl_family_rcv_msg_doit+0xea/0x150 +[ 4481.831237]  genl_rcv_msg+0x104/0x240 +[ 4481.831239]  ? cfg80211_probe_status+0x2c0/0x2c0 [cfg80211] +[ 4481.831257]  ? genl_family_rcv_msg_doit+0x150/0x150 +[ 4481.831259]  netlink_rcv_skb+0x4e/0x100 +[ 4481.831261]  genl_rcv+0x24/0x40 +[ 4481.831262]  netlink_unicast+0x236/0x380 +[ 4481.831264]  netlink_sendmsg+0x250/0x4b0 +[ 4481.831266]  sock_sendmsg+0x5c/0x70 +[ 4481.831269]  ____sys_sendmsg+0x236/0x2b0 +[ 4481.831271]  ? copy_msghdr_from_user+0x6d/0xa0 +[ 4481.831272]  ___sys_sendmsg+0x86/0xd0 +[ 4481.831274]  ? avc_has_perm+0x8c/0x1a0 +[ 4481.831276]  ? preempt_count_add+0x6a/0xa0 +[ 4481.831279]  ? sock_has_perm+0x82/0xa0 +[ 4481.831280]  __sys_sendmsg+0x57/0xa0 +[ 4481.831282]  do_syscall_64+0x38/0x90 +[ 4481.831284]  entry_SYSCALL_64_after_hwframe+0x63/0xcd +[ 4481.831286] RIP: 0033:0x7fd270d369b4 + +Fixes: 2526ff21aa77 ("brcmfmac: support 4-way handshake offloading for 802.1X") +Signed-off-by: Shelley Yang +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260525083859.581246-1-shelley.yang@infineon.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index bb96b87b2a6e56..1fc9ecd86d5d9d 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2146,7 +2146,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) + sme->crypto.akm_suites[0]); + return -EINVAL; + } +- } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { ++ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_1X_SHA256)) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + val = WPA2_AUTH_UNSPECIFIED; +-- +2.53.0 + diff --git a/queue-6.18/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch b/queue-6.18/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch new file mode 100644 index 0000000000..8b4dcaeba2 --- /dev/null +++ b/queue-6.18/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch @@ -0,0 +1,48 @@ +From 863557922a19f62f8157c686683f06c5cbcecc9e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:26 +0000 +Subject: wifi: carl9170: bound memcpy length in cmd callback to prevent OOB + read + +From: Tristan Madani + +[ Upstream commit 4cde55b2feff9504d1f993ab80e84e7ccb62791c ] + +When the firmware sends a command response with a length mismatch, +carl9170_cmd_callback() logs the mismatch and calls carl9170_restart() +but then falls through to memcpy(ar->readbuf, buffer + 4, len - 4). +Since len comes from the firmware and can exceed ar->readlen, this +copies more data than the readbuf was allocated for. + +Bound the memcpy to min(len - 4, ar->readlen) so that the response +is still completed -- avoiding repeated restarts from queued garbage -- +while preventing an overread past the response buffer. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-2-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 6833430130f4ca..f6855efc05c0f1 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -150,7 +150,8 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) + spin_lock(&ar->cmd_lock); + if (ar->readbuf) { + if (len >= 4) +- memcpy(ar->readbuf, buffer + 4, len - 4); ++ memcpy(ar->readbuf, buffer + 4, ++ min_t(u32, len - 4, ar->readlen)); + + ar->readbuf = NULL; + } +-- +2.53.0 + diff --git a/queue-6.18/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch b/queue-6.18/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch new file mode 100644 index 0000000000..dc40741ff0 --- /dev/null +++ b/queue-6.18/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch @@ -0,0 +1,46 @@ +From 6158900f031b25227ee18c4f176582961f3bf9fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:28 +0000 +Subject: wifi: carl9170: fix buffer overflow in rx_stream failover path + +From: Tristan Madani + +[ Upstream commit a1a21995c2e1cc2ca6b2226cfe4f5f018370182a ] + +The failover continuation in carl9170_rx_stream() copies the full tlen +from the second USB transfer instead of capping at rx_failover_missing +bytes. When both transfers are near maximum size, the total exceeds the +65535-byte failover SKB, triggering skb_over_panic. + +Limit the copy size to the missing byte count. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-4-tristmd@gmail.com +[Fix checkpatch CHECK:PARENTHESIS_ALIGNMENT] +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index f6855efc05c0f1..0383d5c9698bfa 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -918,7 +918,9 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) + } + } + +- skb_put_data(ar->rx_failover, tbuf, tlen); ++ skb_put_data(ar->rx_failover, tbuf, ++ min_t(unsigned int, tlen, ++ ar->rx_failover_missing)); + ar->rx_failover_missing -= tlen; + + if (ar->rx_failover_missing <= 0) { +-- +2.53.0 + diff --git a/queue-6.18/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch b/queue-6.18/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch new file mode 100644 index 0000000000..32aa15d189 --- /dev/null +++ b/queue-6.18/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch @@ -0,0 +1,42 @@ +From 625a390b68d08298c03940467e30caea988c98b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:27 +0000 +Subject: wifi: carl9170: fix OOB read from off-by-two in TX status handler + +From: Tristan Madani + +[ Upstream commit a3f42f1049ad80c65560d2b078ad426c3134f78d ] + +The bounds check in carl9170_tx_process_status() uses +`i > ((cmd->hdr.len / 2) + 1)` which is off by two, allowing +2 extra iterations past valid _tx_status entries when the firmware- +controlled hdr.ext exceeds hdr.len/2. Fix by using the correct +comparison `i >= (cmd->hdr.len / 2)`. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c +index b7717f9e1e9b92..b0eee8f892af70 100644 +--- a/drivers/net/wireless/ath/carl9170/tx.c ++++ b/drivers/net/wireless/ath/carl9170/tx.c +@@ -692,7 +692,7 @@ void carl9170_tx_process_status(struct ar9170 *ar, + unsigned int i; + + for (i = 0; i < cmd->hdr.ext; i++) { +- if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) { ++ if (WARN_ON(i >= (cmd->hdr.len / 2))) { + print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE, + (void *) cmd, cmd->hdr.len + 4); + break; +-- +2.53.0 + diff --git a/queue-6.18/wifi-iwlwifi-fix-pointer-arithmetic-in-iwl_add_mcc_t.patch b/queue-6.18/wifi-iwlwifi-fix-pointer-arithmetic-in-iwl_add_mcc_t.patch new file mode 100644 index 0000000000..a78d2a79ee --- /dev/null +++ b/queue-6.18/wifi-iwlwifi-fix-pointer-arithmetic-in-iwl_add_mcc_t.patch @@ -0,0 +1,46 @@ +From 0bd1d931df9d2f23b980bdc0b213b0a468638441 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:06 +0300 +Subject: wifi: iwlwifi: fix pointer arithmetic in + iwl_add_mcc_to_tas_block_list + +From: Emmanuel Grumbach + +[ Upstream commit bc796f84ec9a95b356959ec7caf1d4fce33f3a76 ] + +The expression list[*size++] increments the pointer 'size' +rather than the u8 value it points to (operator precedence: ++ +binds to the pointer before the dereference). As a result the +block-list entry is written at the correct index but *size is +never incremented, so the caller's count stays at zero and +subsequent calls overwrite slot 0 every time. + +Change to list[(*size)++] so that the value pointed to by size +is incremented after use as the array index. + +Fixes: 5f4656610edb ("wifi: iwlwifi: extend TAS_CONFIG cmd support for v5") +Assisted-by: GitHubCopilot:gpt-5.3-codex +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.d2cd92242582.Ife4140a4e27be2a1cd9f886c5a9b376ce182a019@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/fw/regulatory.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +index e1f28b0532530a..818eb1c4b158f1 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +@@ -483,7 +483,7 @@ bool iwl_add_mcc_to_tas_block_list(u16 *list, u8 *size, u16 mcc) + if (*size >= IWL_WTAS_BLACK_LIST_MAX) + return false; + +- list[*size++] = mcc; ++ list[(*size)++] = mcc; + return true; + } + IWL_EXPORT_SYMBOL(iwl_add_mcc_to_tas_block_list); +-- +2.53.0 + diff --git a/queue-6.18/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch b/queue-6.18/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch new file mode 100644 index 0000000000..c81d668e3f --- /dev/null +++ b/queue-6.18/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch @@ -0,0 +1,50 @@ +From a915cfb34255aebe607aff7acc372d0e89ac0f25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:08 +0300 +Subject: wifi: iwlwifi: mvm: fix read in wake packet notification handler + +From: Shahar Tzarfati + +[ Upstream commit 9d7657aae8c1579584c67b0b66114a6a98db8b2f ] + +In iwl_mvm_wowlan_store_wake_pkt(), packet_len was initialized from +notif->wake_packet_length before the explicit check that len >= +sizeof(*notif). + +Move the assignment of packet_len to after the size check so that +notif->wake_packet_length is only accessed once the payload length +has been validated. + +Fixes: 219ed58feda9 ("wifi: iwlwifi: mvm: Add support for wowlan wake packet notification") +Signed-off-by: Shahar Tzarfati +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.99d5cf85a528.Ic4aa736011d4fe88e0cd19723d1d48bb24642198@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +index 11afe373961f3d..46e95e25dcd44e 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +@@ -2783,7 +2783,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, + struct iwl_wowlan_status_data *status, + u32 len) + { +- u32 data_size, packet_len = le32_to_cpu(notif->wake_packet_length); ++ u32 data_size, packet_len; + + if (len < sizeof(*notif)) { + IWL_ERR(mvm, "Invalid WoWLAN wake packet notification!\n"); +@@ -2802,6 +2802,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, + return -EIO; + } + ++ packet_len = le32_to_cpu(notif->wake_packet_length); + data_size = len - offsetof(struct iwl_wowlan_wake_pkt_notif, wake_packet); + + /* data_size got the padding from the notification, remove it. */ +-- +2.53.0 + diff --git a/queue-6.18/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch b/queue-6.18/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch new file mode 100644 index 0000000000..3559cdf8fc --- /dev/null +++ b/queue-6.18/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch @@ -0,0 +1,56 @@ +From 12e7851d862d71a38bafcf853b131c78fa8bc026 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:04 +0300 +Subject: wifi: iwlwifi: mvm: validate SAR GEO response payload size + +From: Pagadala Yesu Anjaneyulu + +[ Upstream commit 408d7da38272ce48e2db79b8a9895999f94d7655 ] + +The SAR GEO command response is cast to +iwl_geo_tx_power_profiles_resp without verifying the payload length. +A malformed or unexpected firmware response can lead to reading an +invalid structure layout. + +Add an explicit size check before accessing the response data and +return -EIO when the payload size is wrong. + +Fixes: f604324eefec ("iwlwifi: remove iwl_validate_sar_geo_profile() export") +Signed-off-by: Pagadala Yesu Anjaneyulu +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.7e749b7d374a.I4ef54548bff6c6e7c7a57bee771ac12508aad677@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +index aa517978fc7a35..cfca5a3ee78ec8 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +@@ -955,12 +955,22 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) + return ret; + } + ++ if (IWL_FW_CHECK(mvm, ++ iwl_rx_packet_payload_len(cmd.resp_pkt) != ++ sizeof(*resp), ++ "Wrong size for iwl_geo_tx_power_profiles_resp: %d\n", ++ iwl_rx_packet_payload_len(cmd.resp_pkt))) { ++ ret = -EIO; ++ goto out; ++ } ++ + resp = (void *)cmd.resp_pkt->data; + ret = le32_to_cpu(resp->profile_idx); + + if (WARN_ON(ret > BIOS_GEO_MAX_PROFILE_NUM)) + ret = -EIO; + ++out: + iwl_free_resp(&cmd); + return ret; + } +-- +2.53.0 + diff --git a/queue-6.18/wifi-iwlwifi-validate-payload-length-in-iwl_pnvm_com.patch b/queue-6.18/wifi-iwlwifi-validate-payload-length-in-iwl_pnvm_com.patch new file mode 100644 index 0000000000..640b8e8669 --- /dev/null +++ b/queue-6.18/wifi-iwlwifi-validate-payload-length-in-iwl_pnvm_com.patch @@ -0,0 +1,64 @@ +From a63520a0d9a8b216bf6cb146c600776fb00b1af0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:07 +0300 +Subject: wifi: iwlwifi: validate payload length in iwl_pnvm_complete_fn + +From: Emmanuel Grumbach + +[ Upstream commit daec24a5ed5da77a108e246ad77aa8b889911f93 ] + +iwl_pnvm_complete_fn() casts pkt->data directly to +struct iwl_pnvm_init_complete_ntfy and reads the status field +without first verifying that the firmware notification payload +is large enough to contain that structure. + +Add a WARN_ON_ONCE check against sizeof(*pnvm_ntf) and return +early without reading uninitialised memory if the payload is too +short. + +Fixes: b3e4c0f34c17 ("iwlwifi: move PNVM implementation to common code") +Assisted-by: GitHubCopilot:gpt-5.3-codex +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.7f2a669e5c75.I00465dcfcbccb250ae9af2d9bb305e24de1ba394@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +index f297e82d63d234..5de3a9c0b3ef09 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright(c) 2020-2025 Intel Corporation ++ * Copyright(c) 2020-2026 Intel Corporation + */ + + #include "iwl-drv.h" +@@ -12,6 +12,7 @@ + #include "fw/api/alive.h" + #include "fw/uefi.h" + #include "fw/img.h" ++#include "fw/dbg.h" + + #define IWL_PNVM_REDUCED_CAP_BIT BIT(25) + +@@ -26,6 +27,12 @@ static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait, + struct iwl_trans *trans = (struct iwl_trans *)data; + struct iwl_pnvm_init_complete_ntfy *pnvm_ntf = (void *)pkt->data; + ++ if (IWL_FW_CHECK(trans, ++ iwl_rx_packet_payload_len(pkt) < sizeof(*pnvm_ntf), ++ "Bad notif len: %d\n", ++ iwl_rx_packet_payload_len(pkt))) ++ return true; ++ + IWL_DEBUG_FW(trans, + "PNVM complete notification received with status 0x%0x\n", + le32_to_cpu(pnvm_ntf->status)); +-- +2.53.0 + diff --git a/queue-6.18/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch b/queue-6.18/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch new file mode 100644 index 0000000000..81ed0d42d0 --- /dev/null +++ b/queue-6.18/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch @@ -0,0 +1,56 @@ +From aed4c5c47c708f4cceba9e9ff075073197897d69 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:17:51 +1000 +Subject: wifi: mac80211: recalculate TIM when a station enters power save + +From: Andrew Pope + +[ Upstream commit a007a384c9eb17610f53a53e2f59944c31f1565a ] + +When an AP buffers frames for a station on its per-station TXQs and the +station subsequently enters power save, sta_ps_start() records the +buffered TIDs in txq_buffered_tids but does not update the TIM. The +station's TIM bit is only ever set when a further frame is buffered +while the station is already asleep +(ieee80211_tx_h_unicast_ps_buf() -> sta_info_recalc_tim()). + +If no further downlink frame arrives for that station the beacon +TIM never advertises the buffered traffic. A station relying on the +TIM then remains in doze indefinitely on top of a non-empty queue. Its +TXQs were removed from the scheduler's active list at PS entry, nothing +pages it, and the flow deadlocks until an unrelated event wakes the +station. + +Recalculate the TIM at the end of sta_ps_start(), so traffic +already buffered at PS entry is advertised immediately. +sta_info_recalc_tim() already consults txq_buffered_tids, which is +updated above, and is safe in this context (it is already called +from equivalent paths such as the tx handlers and +ieee80211_handle_filtered_frame()). + +Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation") +Signed-off-by: Andrew Pope +Link: https://patch.msgid.link/20260717011751.79524-1-andrew.pope@morsemicro.com +[add wifi: subject prefix] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 0a986607e65922..13b7432d732f87 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1612,6 +1612,8 @@ static void sta_ps_start(struct sta_info *sta) + else + clear_bit(tid, &sta->txq_buffered_tids); + } ++ ++ sta_info_recalc_tim(sta); + } + + static void sta_ps_end(struct sta_info *sta) +-- +2.53.0 + diff --git a/queue-6.18/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch b/queue-6.18/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch new file mode 100644 index 0000000000..4cbc3f0007 --- /dev/null +++ b/queue-6.18/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch @@ -0,0 +1,75 @@ +From edaa218008b9f48055df70f3e6d8e3ec1c73c2a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 14:03:02 -0700 +Subject: wifi: mac80211: tear down new links on vif update error path + +From: Xiang Mei + +[ Upstream commit 952c02b33f56207a160421bcd61e7ac53c9c59ae ] + +When ieee80211_vif_update_links() adds new links it allocates a link +container for each and calls ieee80211_link_init() (which registers the +per-link debugfs files with file->private_data pointing into the container) +and ieee80211_link_setup(). If the subsequent drv_change_vif_links() fails, +the error path restores the old pointers and jumps to 'free', which frees +the new containers but never removes their debugfs entries or stops the +links. The debugfs files survive with file->private_data dangling at the +freed container, so a later open()+read() (e.g. link-1/txpower) +dereferences freed memory in ieee80211_if_read_link(), a use-after-free. + +The removal path already dismantles links correctly via +ieee80211_tear_down_links(), which removes each link's keys and debugfs +entries and calls ieee80211_link_stop(); the add path on the error branch +does not. Commit be1ba9ed221f ("wifi: mac80211: avoid weird state in error +path") hardened this same error path for the link-removal case +(new_links == 0) but left the newly-added links' teardown unaddressed. + +drv_change_vif_links() can fail at runtime on MLO drivers (internal +allocation / queue / firmware command failures). + +Remove the new links' debugfs entries and stop them before freeing. + + BUG: KASAN: slab-use-after-free in ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + Read of size 8 at addr ffff888011290000 by task exploit/145 + Call Trace: + ... + ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + short_proxy_read (fs/debugfs/file.c:373) + vfs_read (fs/read_write.c:572) + ksys_read (fs/read_write.c:716) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + ... + Oops: general protection fault, probably for non-canonical address 0xdffffc000000000a + RIP: 0010:ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + Kernel panic - not syncing: Fatal exception + +Fixes: 170cd6a66d9a ("wifi: mac80211: add netdev per-link debugfs data and driver hook") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/20260711210302.2098404-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/link.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/mac80211/link.c b/net/mac80211/link.c +index 05b0472bda40ed..235e370c2b59eb 100644 +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -382,6 +382,10 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata, + memcpy(sdata->link, old_data, sizeof(old_data)); + memcpy(sdata->vif.link_conf, old, sizeof(old)); + ieee80211_set_vif_links_bitmaps(sdata, old_links, dormant_links); ++ for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { ++ ieee80211_link_debugfs_remove(&links[link_id]->data); ++ ieee80211_link_stop(&links[link_id]->data); ++ } + /* and free (only) the newly allocated links */ + memset(to_free, 0, sizeof(links)); + goto free; +-- +2.53.0 + diff --git a/queue-6.18/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch b/queue-6.18/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..e68c134c16 --- /dev/null +++ b/queue-6.18/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,38 @@ +From 3dce87cc94897b79bdee0e2fdbc0aebb613e3907 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:24:59 +0200 +Subject: wifi: mt76: connac: fix possible NULL-pointer deref in + mt76_connac_mcu_uni_bss_he_tlv() + +From: Lorenzo Bianconi + +[ Upstream commit 2c1fb2335f5e3afb34f91bc07ecb63517c328090 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: d0e274af2f2e4 ("mt76: mt76_connac: create mcu library") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-1-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index fc3e6728fcfbfb..2aa7b711c774e0 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -1441,6 +1441,8 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct bss_info_uni_he *he; + + cap = mt76_connac_get_he_phy_cap(phy, vif); ++ if (!cap) ++ return; + + he = (struct bss_info_uni_he *)tlv; + he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; +-- +2.53.0 + diff --git a/queue-6.18/wifi-mt76-disable-napi-when-removing-device.patch b/queue-6.18/wifi-mt76-disable-napi-when-removing-device.patch new file mode 100644 index 0000000000..225d4c1902 --- /dev/null +++ b/queue-6.18/wifi-mt76-disable-napi-when-removing-device.patch @@ -0,0 +1,49 @@ +From ec85c41196070fef11374b2a774ece87083c8a84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:43:47 +0200 +Subject: wifi: mt76: Disable napi when removing device + +From: Nicolas Cavallari + +[ Upstream commit 13b7e6a96a005c656d38f3da51581deaf9866375 ] + +Unloading the mt7915e module with a MT7916 triggers multiples WARN in +__netif_napi_del_locked() and in page_pool_disable_direct_recycling() +because the driver does not disable the napi before destroying it. + +This is troublesome since on MT7916 it is required to unload the module +and reinsert it with a different enable_6ghz parameter to change the +frequency. The system generally becomes unstable after reinserting the +module. + +Fix it by disabling napi before deleting it. Also, do not delete napi +on WED queues since napi is neither used nor initialized on them. + +Fixes: 17f1de56df05 ("mt76: add common code shared between multiple chipsets") +Signed-off-by: Nicolas Cavallari +Link: https://patch.msgid.link/20260708144615.24092-1-nicolas.cavallari@green-communications.fr +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/dma.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c +index 9ef073c27f3096..f5b2c8996affd1 100644 +--- a/drivers/net/wireless/mediatek/mt76/dma.c ++++ b/drivers/net/wireless/mediatek/mt76/dma.c +@@ -1174,7 +1174,10 @@ void mt76_dma_cleanup(struct mt76_dev *dev) + mt76_for_each_q_rx(dev, i) { + struct mt76_queue *q = &dev->q_rx[i]; + +- netif_napi_del(&dev->napi[i]); ++ if (!mt76_queue_is_wed_rro(q)) { ++ napi_disable(&dev->napi[i]); ++ netif_napi_del(&dev->napi[i]); ++ } + mt76_dma_rx_cleanup(dev, q); + + page_pool_destroy(q->page_pool); +-- +2.53.0 + diff --git a/queue-6.18/wifi-mt76-mt7915-guard-he-capability-lookups.patch b/queue-6.18/wifi-mt76-mt7915-guard-he-capability-lookups.patch new file mode 100644 index 0000000000..8e94727022 --- /dev/null +++ b/queue-6.18/wifi-mt76-mt7915-guard-he-capability-lookups.patch @@ -0,0 +1,90 @@ +From ff5615a57a35ff5d952b33c4fc513b94bff0d3b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 23:53:32 +0800 +Subject: wifi: mt76: mt7915: guard HE capability lookups + +From: Ruoyu Wang + +[ Upstream commit 8e9db062654a388d0fa587acbeeae68dd33eba41 ] + +mt7915_mcu_bss_he_tlv() and mt7915_mcu_sta_bfer_tlv() both run after +checking HE support, then dereference the HE PHY capability returned by +mt76_connac_get_he_phy_cap(). That helper can return NULL when no +capability entry matches the vif type. + +Fetch the capability before appending the TLV and skip the HE-specific +setup when no matching capability is available. + +Fixes: e6d557a78b60 ("mt76: mt7915: rely on mt76_connac_get_phy utilities") +Signed-off-by: Ruoyu Wang +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260620155332.81120-1-ruoyuw560@gmail.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +index 79e021ac0bdbcc..f60e2eaea2af4a 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +@@ -595,6 +595,8 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!cap) ++ return; + + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he)); + +@@ -1177,13 +1179,12 @@ mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy, + } + + static void +-mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, +- struct mt7915_phy *phy, struct sta_rec_bf *bf) ++mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, ++ const struct ieee80211_sta_he_cap *vc, ++ struct sta_rec_bf *bf) + { + struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap; + struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; +- const struct ieee80211_sta_he_cap *vc = +- mt76_connac_get_he_phy_cap(phy->mt76, vif); + const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; + u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); + u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map); +@@ -1242,6 +1243,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_phy *phy = mvif->phy; ++ const struct ieee80211_sta_he_cap *vc = NULL; + int tx_ant = hweight8(phy->mt76->chainmask) - 1; + struct sta_rec_bf *bf; + struct tlv *tlv; +@@ -1260,6 +1262,12 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + if (!ebf && !dev->ibf) + return; + ++ if (sta->deflink.he_cap.has_he && ebf) { ++ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!vc) ++ return; ++ } ++ + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); + bf = (struct sta_rec_bf *)tlv; + +@@ -1268,7 +1276,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + * ht: iBF only, since mac80211 lacks of eBF support + */ + if (sta->deflink.he_cap.has_he && ebf) +- mt7915_mcu_sta_bfer_he(sta, vif, phy, bf); ++ mt7915_mcu_sta_bfer_he(sta, vc, bf); + else if (sta->deflink.vht_cap.vht_supported) + mt7915_mcu_sta_bfer_vht(sta, phy, bf, ebf); + else if (sta->deflink.ht_cap.ht_supported) +-- +2.53.0 + diff --git a/queue-6.18/wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch b/queue-6.18/wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch new file mode 100644 index 0000000000..9b7ed3f02d --- /dev/null +++ b/queue-6.18/wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch @@ -0,0 +1,55 @@ +From a864488269ee462122814a23c819a223d0709475 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jun 2026 11:10:16 -0500 +Subject: wifi: mt76: mt7925: fix crash in reset link replay + +From: Sean Wang + +[ Upstream commit bd8b2ec838184236c3fcbf738a926328836adf12 ] + +During reset recovery, mt7925_vif_connect_iter() replays firmware state +for links tracked in mvif->valid_links. After MLO link changes or MCU +timeout recovery, the driver bitmap can temporarily contain a link whose +mac80211 bss_conf has already gone away. + +This can pass a NULL bss_conf to mt76_connac_mcu_uni_add_dev(), matching +the crash where x1, the second argument, is NULL: + +pc : mt76_connac_mcu_uni_add_dev+0x8c/0x1f8 [mt76_connac_lib] +lr : mt7925_vif_connect_iter+0x9c/0x168 [mt7925_common] +x2 : ffffff80a77f6018 x1 : 0000000000000000 x0 : ffffff8099402080 +Call trace: +mt76_connac_mcu_uni_add_dev+0x8c/0x1f8 [mt76_connac_lib] +mt7925_vif_connect_iter+0x9c/0x168 [mt7925_common] +mt7925_mac_reset_work+0x264/0x2f8 [mt7925_common] + +Skip missing bss_conf entries before replaying the link. Non-MLO AP/STA +reset replay is unchanged because the helper still returns &vif->bss_conf +for the legacy link. + +Fixes: 14061994184d ("wifi: mt76: mt7925: add link handling in mt7925_vif_connect_iter") +Signed-off-by: Sean Wang +Link: https://patch.msgid.link/20260616161016.19346-1-sean.wang@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +index d951a46e9d48ce..2ff74d0bef9d0e 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +@@ -1274,6 +1274,9 @@ mt7925_vif_connect_iter(void *priv, u8 *mac, + + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + bss_conf = mt792x_vif_to_bss_conf(vif, i); ++ if (!bss_conf) ++ continue; ++ + mconf = mt792x_vif_to_link(mvif, i); + + mt76_connac_mcu_uni_add_dev(&dev->mphy, bss_conf, &mconf->mt76, +-- +2.53.0 + diff --git a/queue-6.18/wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch b/queue-6.18/wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..8fdfcf7834 --- /dev/null +++ b/queue-6.18/wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,38 @@ +From 6196a7932b513c9a6077af0e166d580dcd2d98c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:00 +0200 +Subject: wifi: mt76: mt7925: fix possible NULL-pointer deref in + mt7925_mcu_bss_he_tlv() + +From: Lorenzo Bianconi + +[ Upstream commit 8d1b6738c1ab48c086b17e7994034aca94258931 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: c948b5da6bbec ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-2-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +index d887aa9a3dff72..647efa963db48d 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +@@ -2706,6 +2706,8 @@ mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, link_conf->vif); ++ if (!cap) ++ return; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he)); + +-- +2.53.0 + diff --git a/queue-6.18/wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch b/queue-6.18/wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch new file mode 100644 index 0000000000..571f2ae329 --- /dev/null +++ b/queue-6.18/wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch @@ -0,0 +1,46 @@ +From 3229d7aebdd1e82c679dc932c795e7f30d555d13 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 15:55:39 +0800 +Subject: wifi: mt76: mt7925: guard link STA in decap offload + +From: Guangshuo Li + +[ Upstream commit 96ea44f2269f30364cffa054ee3a87e595bef0d4 ] + +mt7925_sta_set_decap_offload() iterates over the vif valid_links mask +when updating decap offload state for an MLO station. The station may not +have a link STA for every valid link of the vif, so mt792x_sta_to_link() +can return NULL for a link that belongs to the vif but not to the station. + +The function currently dereferences mlink before checking whether the +link WCID is ready. If mlink is NULL, setting or clearing +MT_WCID_FLAG_HDR_TRANS dereferences a NULL pointer. + +Skip links without a station link before touching mlink->wcid. + +Fixes: b859ad65309a ("wifi: mt76: mt7925: add link handling in mt7925_sta_set_decap_offload") +Signed-off-by: Guangshuo Li +Link: https://patch.msgid.link/20260708075539.726200-1-lgs201920130244@gmail.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c +index 6c0dc72efc3928..910713e62e14a5 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c +@@ -1573,6 +1573,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, + + mlink = mt792x_sta_to_link(msta, i); + ++ if (!mlink) ++ continue; ++ + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags); + else +-- +2.53.0 + diff --git a/queue-6.18/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch b/queue-6.18/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch new file mode 100644 index 0000000000..8b91ae05ef --- /dev/null +++ b/queue-6.18/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch @@ -0,0 +1,60 @@ +From 65dcc0ce3f773b769fe827c421a02fb551b02314 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:01 +0200 +Subject: wifi: mt76: mt7996: check pointer returned by + mt76_connac_get_he_phy_cap() + +From: Lorenzo Bianconi + +[ Upstream commit e858cf6bf99880343348ff1e8c942aaff1d9d592 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: 98686cd21624c ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-3-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +index a3f813be107df7..87ec7e90dfeebe 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +@@ -860,6 +860,8 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!cap) ++ return; + + tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he)); + +@@ -1659,17 +1661,18 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_link_sta *link_sta, + { + struct ieee80211_sta_he_cap *pc = &link_sta->he_cap; + struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; +- const struct ieee80211_sta_he_cap *vc = +- mt76_connac_get_he_phy_cap(phy->mt76, vif); +- const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; + u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); + u8 nss_mcs = mt7996_mcu_get_sta_nss(mcs_map); ++ const struct ieee80211_he_cap_elem *ve; ++ const struct ieee80211_sta_he_cap *vc; + u8 snd_dim, sts; + ++ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif); + if (!vc) + return; + + bf->tx_mode = MT_PHY_TYPE_HE_SU; ++ ve = &vc->he_cap_elem; + + mt7996_mcu_sta_sounding_rate(bf, phy); + +-- +2.53.0 + diff --git a/queue-6.18/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch b/queue-6.18/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..98def55d84 --- /dev/null +++ b/queue-6.18/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,51 @@ +From a24f3e768ab96b8fe4d21aa0df96eb9362a92865 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:02 +0200 +Subject: wifi: mt76: mt7996: fix possible NULL-pointer deref in + mt7996_mcu_sta_bfer_eht() + +From: Lorenzo Bianconi + +[ Upstream commit 2fffc472bec490c8357defcee9c075ca74467352 ] + +mt76_connac_get_eht_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: ba01944adee9f ("wifi: mt76: mt7996: add EHT beamforming support") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-4-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +index 87ec7e90dfeebe..72851399575f9d 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +@@ -1728,14 +1728,18 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_link_sta *link_sta, + struct ieee80211_sta_eht_cap *pc = &link_sta->eht_cap; + struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; + struct ieee80211_eht_mcs_nss_supp *eht_nss = &pc->eht_mcs_nss_supp; +- const struct ieee80211_sta_eht_cap *vc = +- mt76_connac_get_eht_phy_cap(phy->mt76, vif); +- const struct ieee80211_eht_cap_elem_fixed *ve = &vc->eht_cap_elem; + u8 nss_mcs = u8_get_bits(eht_nss->bw._80.rx_tx_mcs9_max_nss, + IEEE80211_EHT_MCS_NSS_RX) - 1; ++ const struct ieee80211_eht_cap_elem_fixed *ve; ++ const struct ieee80211_sta_eht_cap *vc; + u8 snd_dim, sts; + ++ vc = mt76_connac_get_eht_phy_cap(phy->mt76, vif); ++ if (!vc) ++ return; ++ + bf->tx_mode = MT_PHY_TYPE_EHT_MU; ++ ve = &vc->eht_cap_elem; + + mt7996_mcu_sta_sounding_rate(bf, phy); + +-- +2.53.0 + diff --git a/queue-6.18/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch b/queue-6.18/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch new file mode 100644 index 0000000000..10ba8d596d --- /dev/null +++ b/queue-6.18/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch @@ -0,0 +1,104 @@ +From 05eb747468f044f8379e281108016d32ae320ef1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 22:57:11 +0900 +Subject: wifi: mwifiex: bound uAP association event IEs to the event buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit f0858bfc7d3cab411a447b88e3ef970e575032c9 ] + +mwifiex_process_uap_event() handles EVENT_UAP_STA_ASSOC by exposing the +(re)association request IEs that the firmware copies into the event: + + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - (u8 *)&event->frame_control; + sinfo->assoc_req_ies_len = le16_to_cpu(event->len) - (u16)len; + +event->len is supplied by the device firmware and is never validated, +and the subtraction is unchecked. assoc_req_ies points into +adapter->event_body[MAX_EVENT_SIZE], a fixed-size array embedded in the +kmalloc()'d struct mwifiex_adapter. + +On the ap_11n_enabled path mwifiex_set_sta_ht_cap() walks these IEs with +cfg80211_find_ie(), whose for_each_element() loop dereferences each +element header. A firmware-reported event->len larger than the bytes +actually received makes assoc_req_ies_len describe IEs that extend past +event_body, so the walk reads out of the adapter slab object, a +slab-out-of-bounds read (KASAN: slab-out-of-bounds in cfg80211_find_ie). +An event->len smaller than the header instead makes the int subtraction +negative, which wraps to a huge size_t when stored in assoc_req_ies_len. +The same length is handed to cfg80211_new_sta(), so a more modest +over-claim can also copy stale event_body bytes into the +NL80211_CMD_NEW_STATION notification. + +A malicious or malfunctioning mwifiex device (USB/SDIO/PCIe) can deliver +such an event while the interface is in AP/uAP mode. + +Validate event->len before use: reject a length that underflows the +header or that would place the IEs outside the event_body[] buffer the +event was copied into. event->len here is struct mwifiex_assoc_event.len, +a payload field internal to this event, not the transport frame length, +so it is validated in this handler rather than at the generic +MWIFIEX_TYPE_EVENT receive path, which only sees the event cause and the +transport frame length. The bound is against event_body[MAX_EVENT_SIZE] +rather than the actually-received length because the transports store the +event differently (USB and SDIO leave the 4-byte event header in +event_skb, PCIe strips it via skb_pull), whereas event_body is the single +fixed buffer all of them copy the event into. This is the event-path +analogue of the receive-path bounds checks added in commit 119585281617 +("wifi: mwifiex: Fix OOB and integer underflow when rx packets"). + +Fixes: e568634ae7ac ("mwifiex: add AP event handling framework") +Signed-off-by: HE WEI (ギカク) +Reviewed-by: Francesco Dolcini +Link: https://patch.msgid.link/20260715135711.34688-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + .../net/wireless/marvell/mwifiex/uap_event.c | 24 +++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c +index 245cb99a3daad2..fc9da9006a782c 100644 +--- a/drivers/net/wireless/marvell/mwifiex/uap_event.c ++++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c +@@ -123,11 +123,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) + len = ETH_ALEN; + + if (len != -1) { ++ u16 evt_len = le16_to_cpu(event->len); ++ + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - + (u8 *)&event->frame_control; +- sinfo->assoc_req_ies_len = +- le16_to_cpu(event->len) - (u16)len; ++ ++ /* ++ * event->len is reported by the device firmware ++ * and is not otherwise validated. Reject a ++ * length that underflows the header, or that ++ * would place the association request IEs ++ * outside the fixed-size event_body[] buffer the ++ * event was copied into; otherwise the IE walk ++ * in mwifiex_set_sta_ht_cap() reads past ++ * event_body and out of the adapter slab object. ++ */ ++ if (evt_len < len || ++ (u8 *)&event->frame_control + evt_len > ++ adapter->event_body + MAX_EVENT_SIZE) { ++ mwifiex_dbg(adapter, ERROR, ++ "invalid STA assoc event length\n"); ++ kfree(sinfo); ++ return -1; ++ } ++ sinfo->assoc_req_ies_len = evt_len - (u16)len; + } + } + cfg80211_new_sta(priv->netdev, event->sta_addr, sinfo, +-- +2.53.0 + diff --git a/queue-6.6/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch b/queue-6.6/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch new file mode 100644 index 0000000000..9e628b81f0 --- /dev/null +++ b/queue-6.6/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch @@ -0,0 +1,58 @@ +From 5448fb98c01d575f6c1d14fb06623109898acaa7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 15:20:06 +0530 +Subject: amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN + +From: Prashanth Kumar KR + +[ Upstream commit 4bf22afe53a1de4b44b04cf677fd5199089cbdff ] + +MAC_AUTO_SW (VR_MII_DIG_CTRL1 bit 9) enables automatic XPCS speed +mode switching after CL37 auto-negotiation and is only meaningful in +SGMII MAC mode. The original code unconditionally set this bit on +every call to xgbe_an37_set(), including when called from +xgbe_an37_disable() with enable=false. This left MAC_AUTO_SW=1 after +AN was disabled, causing the XPCS to autonomously switch speed from +stale AN state during subsequent mode changes, breaking SGMII speed +negotiation on 1G copper SFP modules. + +Patrick: This was breaking negotiation for all 1G SFP modules, +not just copper modules. + +Fixes: 42fd432fe6d3 ("amd-xgbe: align CL37 AN sequence as per databook") +Reported-by: Patrick Oppenlander +Link: https://lore.kernel.org/netdev/CAEg67GmFS0Q4oSZkz8zWdOzckSth9_vBPiOy6a7-d697C2w2Xg@mail.gmail.com +Signed-off-by: Prashanth Kumar KR +Tested-by: Patrick Oppenlander +Link: https://patch.msgid.link/20260709095006.3683940-1-prashanthkumar.k.r@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index 63012119f2c8eb..4e4e0735cb2ada 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -376,9 +376,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, + + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); + +- reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); +- reg |= XGBE_VEND2_MAC_AUTO_SW; +- XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ if (pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) { ++ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); ++ if (enable) ++ reg |= XGBE_VEND2_MAC_AUTO_SW; ++ else ++ reg &= ~XGBE_VEND2_MAC_AUTO_SW; ++ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ } + } + + static void xgbe_an37_restart(struct xgbe_prv_data *pdata) +-- +2.53.0 + diff --git a/queue-6.6/amt-make-the-head-writable-before-rewriting-the-l2-h.patch b/queue-6.6/amt-make-the-head-writable-before-rewriting-the-l2-h.patch new file mode 100644 index 0000000000..a92c34dbd0 --- /dev/null +++ b/queue-6.6/amt-make-the-head-writable-before-rewriting-the-l2-h.patch @@ -0,0 +1,67 @@ +From a17b413d8fea66e55db3a88850da8f9708038c56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:19:34 -0400 +Subject: amt: make the head writable before rewriting the L2 header + +From: Michael Bommarito + +[ Upstream commit 53969d704fa5b7c1751e277fac96bfc22b435eac ] + +amt_multicast_data_handler(), amt_membership_query_handler() and +amt_update_handler() rewrite the ethernet header of the decapsulated skb +in place (eth->h_proto, eth->h_dest and, for the query, also +eth->h_source) before handing it up the stack. The skb head may be +shared, for example when a packet tap has cloned it on the underlay +interface, so writing through it corrupts the other reader's copy. + +Call skb_cow_head() before the rewrite so the head is private. It is +placed before the pointers into the head are (re-)derived, so a +reallocation caused by the copy is picked up by those derivations. + +Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") +Signed-off-by: Michael Bommarito +Reviewed-by: Simon Horman +Reviewed-by: Taehee Yoo +Link: https://patch.msgid.link/20260711151934.2955226-3-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/amt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/amt.c b/drivers/net/amt.c +index 64aff304c51c66..4799f8fd03c45c 100644 +--- a/drivers/net/amt.c ++++ b/drivers/net/amt.c +@@ -2315,6 +2315,9 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + skb_reset_mac_header(skb); + skb_pull(skb, sizeof(*eth)); + ++ if (skb_cow_head(skb, 0)) ++ return true; ++ + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + iph = ip_hdr(skb); +@@ -2391,6 +2394,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_network_header(skb); + eth = eth_hdr(skb); + ether_addr_copy(h_source, oeth->h_source); ++ if (skb_cow_head(skb, 0)) ++ return true; + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + +@@ -2516,6 +2521,9 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + ++ if (skb_cow_head(skb, 0)) ++ return true; ++ + iph = ip_hdr(skb); + if (iph->version == 4) { + if (ip_mc_check_igmp(skb)) { +-- +2.53.0 + diff --git a/queue-6.6/amt-re-read-skb-header-pointers-after-every-pull.patch b/queue-6.6/amt-re-read-skb-header-pointers-after-every-pull.patch new file mode 100644 index 0000000000..edf25760a5 --- /dev/null +++ b/queue-6.6/amt-re-read-skb-header-pointers-after-every-pull.patch @@ -0,0 +1,367 @@ +From 0aceedcce0be374abe60301aa48ad19e5276d24a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:19:33 -0400 +Subject: amt: re-read skb header pointers after every pull + +From: Michael Bommarito + +[ Upstream commit 3656a79f94c471827a08f2cacce5f94ad5e52c24 ] + +Several AMT receive and transmit paths cache a pointer into the skb head +(ip_hdr(), ipv6_hdr(), eth_hdr() or the AMT message header) and then call +a helper that can reallocate that head before the cached pointer is used +again. pskb_may_pull(), ip_mc_may_pull(), ipv6_mc_may_pull(), +iptunnel_pull_header(), ip_mc_check_igmp() and ipv6_mc_check_mld() can all +free the old head and move the data, so a pointer taken before the call +dangles afterwards and the later access is a use-after-free of the freed +head. + +The affected sites are: + + amt_rcv() caches ip_hdr() before amt_parse_type() pulls, then reads + iph->saddr. + + amt_dev_xmit() caches ip_hdr()/ipv6_hdr() before ip_mc_check_igmp()/ + ipv6_mc_check_mld() and pskb_may_pull(), then reads the group address. + + amt_multicast_data_handler() caches eth_hdr() before pskb_may_pull(), + then writes the L2 header. + + amt_membership_query_handler() caches the AMT header, the outer and + inner eth_hdr() and ip_hdr() before iptunnel_pull_header() and several + pulls, then reads and writes them. + + amt_igmpv3_report_handler() and amt_mldv2_report_handler() cache + ip_hdr()/ipv6_hdr() and the current group record and read the record + count from the report header inside the record loop, across the + *_mc_may_pull() calls. + + amt_update_handler() caches ip_hdr() and the AMT membership-update + header before pskb_may_pull(), iptunnel_pull_header(), + ip_mc_check_igmp() and the report handler, then reads iph->daddr and + amtmu->nonce / amtmu->response_mac. + +Fix each site by either snapshotting the scalar that is used after the +pull before the first pull runs, or re-deriving the header pointer from +the skb after the last pull that can move the head. Values that are +stable across the pull (source and group address, the response MAC and +nonce, the record count, the outer source MAC) are snapshotted; pointers +that are written through or read repeatedly are re-derived. + +Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") +Signed-off-by: Michael Bommarito +Reviewed-by: Simon Horman +Reviewed-by: Taehee Yoo +Link: https://patch.msgid.link/20260711151934.2955226-2-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/amt.c | 79 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 55 insertions(+), 24 deletions(-) + +diff --git a/drivers/net/amt.c b/drivers/net/amt.c +index f2da0c49171f5d..64aff304c51c66 100644 +--- a/drivers/net/amt.c ++++ b/drivers/net/amt.c +@@ -1206,7 +1206,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + data = true; + } + v6 = false; +- group.ip4 = iph->daddr; ++ group.ip4 = ip_hdr(skb)->daddr; + #if IS_ENABLED(CONFIG_IPV6) + } else if (iph->version == 6) { + ip6h = ipv6_hdr(skb); +@@ -1230,7 +1230,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + data = true; + } + v6 = true; +- group.ip6 = ip6h->daddr; ++ group.ip6 = ipv6_hdr(skb)->daddr; + #endif + } else { + dev->stats.tx_errors++; +@@ -1273,12 +1273,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash], + node) { + if (!v6) { +- if (gnode->group_addr.ip4 == iph->daddr) ++ if (gnode->group_addr.ip4 == group.ip4) + goto found; + #if IS_ENABLED(CONFIG_IPV6) + } else { + if (ipv6_addr_equal(&gnode->group_addr.ip6, +- &ip6h->daddr)) ++ &group.ip6)) + goto found; + #endif + } +@@ -1995,14 +1995,18 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb, + struct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb); + int len = skb_transport_offset(skb) + sizeof(*ihrv3); + void *zero_grec = (void *)&igmpv3_zero_grec; +- struct iphdr *iph = ip_hdr(skb); + struct amt_group_node *gnode; + union amt_addr group, host; + struct igmpv3_grec *grec; ++ __be32 saddr; + u16 nsrcs; ++ u16 ngrec; + int i; + +- for (i = 0; i < ntohs(ihrv3->ngrec); i++) { ++ saddr = ip_hdr(skb)->saddr; ++ ngrec = ntohs(ihrv3->ngrec); ++ ++ for (i = 0; i < ngrec; i++) { + len += sizeof(*grec); + if (!ip_mc_may_pull(skb, len)) + break; +@@ -2014,10 +2018,13 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb, + if (!ip_mc_may_pull(skb, len)) + break; + ++ grec = (void *)(skb->data + len - sizeof(*grec) - ++ nsrcs * sizeof(__be32)); ++ + memset(&group, 0, sizeof(union amt_addr)); + group.ip4 = grec->grec_mca; + memset(&host, 0, sizeof(union amt_addr)); +- host.ip4 = iph->saddr; ++ host.ip4 = saddr; + gnode = amt_lookup_group(tunnel, &group, &host, false); + if (!gnode) { + gnode = amt_add_group(amt, tunnel, &group, &host, +@@ -2157,14 +2164,18 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb, + struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb); + int len = skb_transport_offset(skb) + sizeof(*mld2r); + void *zero_grec = (void *)&mldv2_zero_grec; +- struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct amt_group_node *gnode; + union amt_addr group, host; + struct mld2_grec *grec; ++ struct in6_addr saddr; + u16 nsrcs; ++ u16 ngrec; + int i; + +- for (i = 0; i < ntohs(mld2r->mld2r_ngrec); i++) { ++ saddr = ipv6_hdr(skb)->saddr; ++ ngrec = ntohs(mld2r->mld2r_ngrec); ++ ++ for (i = 0; i < ngrec; i++) { + len += sizeof(*grec); + if (!ipv6_mc_may_pull(skb, len)) + break; +@@ -2176,10 +2187,13 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb, + if (!ipv6_mc_may_pull(skb, len)) + break; + ++ grec = (void *)(skb->data + len - sizeof(*grec) - ++ nsrcs * sizeof(struct in6_addr)); ++ + memset(&group, 0, sizeof(union amt_addr)); + group.ip6 = grec->grec_mca; + memset(&host, 0, sizeof(union amt_addr)); +- host.ip6 = ip6h->saddr; ++ host.ip6 = saddr; + gnode = amt_lookup_group(tunnel, &group, &host, true); + if (!gnode) { + gnode = amt_add_group(amt, tunnel, &group, &host, +@@ -2300,7 +2314,6 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + skb_push(skb, sizeof(*eth)); + skb_reset_mac_header(skb); + skb_pull(skb, sizeof(*eth)); +- eth = eth_hdr(skb); + + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; +@@ -2310,6 +2323,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!ipv4_is_multicast(iph->daddr)) + return true; + skb->protocol = htons(ETH_P_IP); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IP); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) +@@ -2323,6 +2337,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!ipv6_addr_is_multicast(&ip6h->daddr)) + return true; + skb->protocol = htons(ETH_P_IPV6); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IPV6); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif +@@ -2346,10 +2361,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + struct sk_buff *skb) + { + struct amt_header_membership_query *amtmq; +- struct igmpv3_query *ihv3; + struct ethhdr *eth, *oeth; ++ struct igmpv3_query *ihv3; ++ u8 h_source[ETH_ALEN]; + struct iphdr *iph; + int hdr_size, len; ++ u64 response_mac; + + hdr_size = sizeof(*amtmq) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) +@@ -2362,6 +2379,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + if (amtmq->nonce != amt->nonce) + return true; + ++ response_mac = amtmq->response_mac; ++ + hdr_size -= sizeof(*eth); + if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false)) + return true; +@@ -2371,6 +2390,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_pull(skb, sizeof(*eth)); + skb_reset_network_header(skb); + eth = eth_hdr(skb); ++ ether_addr_copy(h_source, oeth->h_source); + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + +@@ -2383,6 +2403,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + sizeof(*ihv3))) + return true; + ++ iph = ip_hdr(skb); + if (!ipv4_is_multicast(iph->daddr)) + return true; + +@@ -2390,10 +2411,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS); + WRITE_ONCE(amt->ready4, true); +- amt->mac = amtmq->response_mac; ++ amt->mac = response_mac; + amt->req_cnt = 0; + amt->qi = ihv3->qqic; + skb->protocol = htons(ETH_P_IP); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IP); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) +@@ -2416,10 +2438,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS); + WRITE_ONCE(amt->ready6, true); +- amt->mac = amtmq->response_mac; ++ amt->mac = response_mac; + amt->req_cnt = 0; + amt->qi = mld2q->mld2q_qqic; + skb->protocol = htons(ETH_P_IPV6); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IPV6); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif +@@ -2427,7 +2450,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + return true; + } + +- ether_addr_copy(eth->h_source, oeth->h_source); ++ ether_addr_copy(eth->h_source, h_source); + skb->pkt_type = PACKET_MULTICAST; + skb->ip_summed = CHECKSUM_NONE; + len = skb->len; +@@ -2450,8 +2473,11 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + struct ethhdr *eth; + struct iphdr *iph; + int len, hdr_size; ++ u64 response_mac; ++ __be32 saddr; ++ __be32 nonce; + +- iph = ip_hdr(skb); ++ saddr = ip_hdr(skb)->saddr; + + hdr_size = sizeof(*amtmu) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) +@@ -2461,15 +2487,18 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + if (amtmu->reserved || amtmu->version) + return true; + ++ nonce = amtmu->nonce; ++ response_mac = amtmu->response_mac; ++ + if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false)) + return true; + + skb_reset_network_header(skb); + + list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) { +- if (tunnel->ip4 == iph->saddr) { +- if ((amtmu->nonce == tunnel->nonce && +- amtmu->response_mac == tunnel->mac)) { ++ if (tunnel->ip4 == saddr) { ++ if ((nonce == tunnel->nonce && ++ response_mac == tunnel->mac)) { + mod_delayed_work(amt_wq, &tunnel->gc_wq, + msecs_to_jiffies(amt_gmi(amt)) + * 3); +@@ -2503,6 +2532,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + eth = eth_hdr(skb); + skb->protocol = htons(ETH_P_IP); + eth->h_proto = htons(ETH_P_IP); ++ iph = ip_hdr(skb); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) + } else if (iph->version == 6) { +@@ -2522,6 +2552,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + eth = eth_hdr(skb); + skb->protocol = htons(ETH_P_IPV6); + eth->h_proto = htons(ETH_P_IPV6); ++ ip6h = ipv6_hdr(skb); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif + } else { +@@ -2767,7 +2798,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb) + static int amt_rcv(struct sock *sk, struct sk_buff *skb) + { + struct amt_dev *amt; +- struct iphdr *iph; ++ __be32 saddr; + int type; + bool err; + +@@ -2780,7 +2811,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + } + + skb->dev = amt->dev; +- iph = ip_hdr(skb); ++ saddr = ip_hdr(skb)->saddr; + type = amt_parse_type(skb); + if (type == -1) { + err = true; +@@ -2790,7 +2821,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + if (amt->mode == AMT_MODE_GATEWAY) { + switch (type) { + case AMT_MSG_ADVERTISEMENT: +- if (iph->saddr != amt->discovery_ip) { ++ if (saddr != amt->discovery_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +@@ -2802,7 +2833,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + } + goto out; + case AMT_MSG_MULTICAST_DATA: +- if (iph->saddr != amt->remote_ip) { ++ if (saddr != amt->remote_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +@@ -2813,7 +2844,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + else + goto out; + case AMT_MSG_MEMBERSHIP_QUERY: +- if (iph->saddr != amt->remote_ip) { ++ if (saddr != amt->remote_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +-- +2.53.0 + diff --git a/queue-6.6/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch b/queue-6.6/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch new file mode 100644 index 0000000000..a118c8584a --- /dev/null +++ b/queue-6.6/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch @@ -0,0 +1,72 @@ +From 0902fa73eeeda5cd879156daf8bc7c038ee94a3c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 18:06:20 +0800 +Subject: ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI + +From: Shengjiu Wang + +[ Upstream commit 0b604e886ece11b71c4daaeccc512c784b89b014 ] + +The bt-sco-pcm-wb DAI uses the same stream_name strings as bt-sco-pcm +("Playback" and "Capture"). This causes duplicate DAPM AIF widget +names within the same component, leading to debugfs warnings: + + debugfs: 'Playback' already exists in 'dapm' + debugfs: 'Capture' already exists in 'dapm' + +Give the wideband DAI distinct stream names ("WB Playback" and +"WB Capture") and add corresponding DAPM AIF widgets and routes for +them. + +Fixes: 5947e1b4992e ("ASoC: bt-sco: extend rate and add a general compatible string") +Assisted-by: VeroCoder:claude-sonnet-4-5 +Signed-off-by: Shengjiu Wang +Link: https://patch.msgid.link/20260715100620.1387159-1-shengjiu.wang@oss.nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/bt-sco.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c +index 3afcef2dfa3529..c0bf45b76cb8c5 100644 +--- a/sound/soc/codecs/bt-sco.c ++++ b/sound/soc/codecs/bt-sco.c +@@ -17,11 +17,17 @@ static const struct snd_soc_dapm_widget bt_sco_widgets[] = { + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0, + SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_IN("BT_SCO_RX_WB", "WB Playback", 0, ++ SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("BT_SCO_TX_WB", "WB Capture", 0, ++ SND_SOC_NOPM, 0, 0), + }; + + static const struct snd_soc_dapm_route bt_sco_routes[] = { + { "BT_SCO_TX", NULL, "RX" }, + { "TX", NULL, "BT_SCO_RX" }, ++ { "BT_SCO_TX_WB", NULL, "RX" }, ++ { "TX", NULL, "BT_SCO_RX_WB" }, + }; + + static struct snd_soc_dai_driver bt_sco_dai[] = { +@@ -45,14 +51,14 @@ static struct snd_soc_dai_driver bt_sco_dai[] = { + { + .name = "bt-sco-pcm-wb", + .playback = { +- .stream_name = "Playback", ++ .stream_name = "WB Playback", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { +- .stream_name = "Capture", ++ .stream_name = "WB Capture", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, +-- +2.53.0 + diff --git a/queue-6.6/asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch b/queue-6.6/asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch new file mode 100644 index 0000000000..b28419a5ff --- /dev/null +++ b/queue-6.6/asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch @@ -0,0 +1,61 @@ +From 6199d358dfdacb5ab0b4512058dcb516f615f318 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 May 2026 17:11:23 +0100 +Subject: ASoC: cs35l56: Don't use devres to unregister component + +From: Richard Fitzgerald + +[ Upstream commit bee87cf0f1248c0f20710d7a79df41fe892d9f88 ] + +Manually call snd_soc_unregister_component() from cs35l56_remove() +instead of using devres cleanup. This ensures that the component is +destroyed before cs35l56_remove() starts cleanup of anything the +component code could be using. + +Devres cleanup happens after the driver remove() callback, so if +snd_soc_register_component() is used, it will not be destroyed until +after cs35l56_remove() has returned. But there is some cleanup that +must be done in cs35l56_remove(), or wrapped in a custom devres +cleanup handler to ensure correct ordering. The simplest option is +to call snd_soc_unregister_component() at the start of cs35l56_remove(). + +Fixes: e49611252900 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Closes: https://sashiko.dev/#/patchset/20260501103002.2843735-1-rf%40opensource.cirrus.com +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260505161124.3621000-2-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Stable-dep-of: 93c2a8ea2454 ("ASoC: cs35l56: Fix potential probe() deadlock") +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index 832ff2cd3d24e9..b581e8f1576634 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -1318,9 +1318,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + goto err; + } + +- ret = devm_snd_soc_register_component(cs35l56->base.dev, +- &soc_component_dev_cs35l56, +- cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); ++ ret = snd_soc_register_component(cs35l56->base.dev, ++ &soc_component_dev_cs35l56, ++ cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); + if (ret < 0) { + dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n"); + goto err_remove_wm_adsp; +@@ -1416,6 +1416,8 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_SOC_CS35L56_CORE); + + void cs35l56_remove(struct cs35l56_private *cs35l56) + { ++ snd_soc_unregister_component(cs35l56->base.dev); ++ + cs35l56->base.init_done = false; + + /* +-- +2.53.0 + diff --git a/queue-6.6/asoc-cs35l56-fix-potential-probe-deadlock.patch b/queue-6.6/asoc-cs35l56-fix-potential-probe-deadlock.patch new file mode 100644 index 0000000000..25d37d9a10 --- /dev/null +++ b/queue-6.6/asoc-cs35l56-fix-potential-probe-deadlock.patch @@ -0,0 +1,111 @@ +From a7a3fcf44be4a1fa757a65e2a1b3eecb1724e12e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 14:20:44 +0100 +Subject: ASoC: cs35l56: Fix potential probe() deadlock + +From: Richard Fitzgerald + +[ Upstream commit 93c2a8ea2454b7b14eb378a58cad8a83c0ffc903 ] + +On I2C/SPI call cs35l56_init() before calling +snd_soc_register_component() to prevent the potential for a deadlock +on init_completion. + +For most buses all the hardware would be ready when probe() returns, +but on SoundWire, probe() must return before the SoundWire bus driver +will enumerate the device. All access to the registers must be deferred +until the driver receives an ATTACHED notification. But anything that +could return -EPROBE_DEFER must be called during probe, and that includes +snd_soc_register_component(). Because of that, on SoundWire the ASoC +component can be created before the registers are accssible, so +cs35l56_component_probe() waits for init_completion to signal that the +registers are accessible. + +On I2C/SPI this 2-stage startup isn't required so their probe() +functions simply called cs35l56_common_probe() and then cs35l56_init(). +The problem with this was that snd_soc_register_component() was still +called early. If this triggered ASoC to create the card, ASoC would call +cs35l56_component_probe() which waits on init_completion - but this would +be running inside the cs35l56 driver probe() so blocking it from reaching +the code that signals init_completion, causing a deadlock. + +Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Reported-by: Salman S. Tahir +Closes: https://lore.kernel.org/linux-sound/95c21574-97d5-4311-9263-9e174d22d22c@opensource.cirrus.com/T/#u +Tested-by: Salman S. Tahir +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260716132045.1469156-2-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56-i2c.c | 4 +--- + sound/soc/codecs/cs35l56-spi.c | 4 +--- + sound/soc/codecs/cs35l56.c | 15 +++++++++++++++ + 3 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c +index d10e0e2380e852..61dde15d5a5f55 100644 +--- a/sound/soc/codecs/cs35l56-i2c.c ++++ b/sound/soc/codecs/cs35l56-i2c.c +@@ -39,9 +39,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client) + if (ret != 0) + return ret; + +- ret = cs35l56_init(cs35l56); +- if (ret == 0) +- ret = cs35l56_irq_request(&cs35l56->base, client->irq); ++ ret = cs35l56_irq_request(&cs35l56->base, client->irq); + if (ret < 0) + cs35l56_remove(cs35l56); + +diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c +index 9962703915e1f1..df23d19308d4a2 100644 +--- a/sound/soc/codecs/cs35l56-spi.c ++++ b/sound/soc/codecs/cs35l56-spi.c +@@ -37,9 +37,7 @@ static int cs35l56_spi_probe(struct spi_device *spi) + if (ret != 0) + return ret; + +- ret = cs35l56_init(cs35l56); +- if (ret == 0) +- ret = cs35l56_irq_request(&cs35l56->base, spi->irq); ++ ret = cs35l56_irq_request(&cs35l56->base, spi->irq); + if (ret < 0) + cs35l56_remove(cs35l56); + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index b581e8f1576634..dda40e97cf5e66 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -1318,6 +1318,16 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + goto err; + } + ++ /* ++ * On SoundWire the cs35l56_init() cannot be run until after the ++ * device has been enumerated by the SoundWire core. ++ */ ++ if (!cs35l56->sdw_peripheral) { ++ ret = cs35l56_init(cs35l56); ++ if (ret) ++ goto err_remove_wm_adsp; ++ } ++ + ret = snd_soc_register_component(cs35l56->base.dev, + &soc_component_dev_cs35l56, + cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); +@@ -1332,6 +1342,11 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + wm_adsp2_remove(&cs35l56->dsp); + + err: ++ if (pm_runtime_enabled(cs35l56->base.dev)) { ++ pm_runtime_dont_use_autosuspend(cs35l56->base.dev); ++ pm_runtime_disable(cs35l56->base.dev); ++ } ++ + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); + regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + +-- +2.53.0 + diff --git a/queue-6.6/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch b/queue-6.6/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch new file mode 100644 index 0000000000..a6f11a8ae8 --- /dev/null +++ b/queue-6.6/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch @@ -0,0 +1,57 @@ +From 41f815b71a9fbcc056742a340d5113c26187b22e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 14:20:45 +0100 +Subject: ASoC: cs35l56: Use complete_all() to signal init_completion + +From: Richard Fitzgerald + +[ Upstream commit e0bffb63a2eda0af82ed7e6357ac67c2db990c21 ] + +In cs35l56_init() use complete_all() to signal init_completion instead +of complete(). + +cs35l56_init() was signaling init_completion using the complete() function. +This only releases ONE waiter. + +If cs35l56_component_probe() was called multiple times the first time +would consume that one signal, then future calls would timeout waiting for +the completion. This could happen if: + + - The component is probed, removed, then probed again without the cs35l56 + module being removed. + + - A call to component_probe() returns an error and ASoC calls it again + later. + +It should use complete_all() so that after it has been signaled it will +allow any code that waits on it to continue immediately. + +The one case where the driver must wait for initialization to run again is +when waiting for a reboot after firmware download, and here the code +correctly calls reinit_completion() first. + +Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260716132045.1469156-3-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index dda40e97cf5e66..987bd7a3cf1d48 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -1423,7 +1423,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56) + return dev_err_probe(cs35l56->base.dev, ret, "Failed to write ASP1_CONTROL3\n"); + + cs35l56->base.init_done = true; +- complete(&cs35l56->init_completion); ++ complete_all(&cs35l56->init_completion); + + return 0; + } +-- +2.53.0 + diff --git a/queue-6.6/asoc-tas2781-bound-firmware-description-string-parsi.patch b/queue-6.6/asoc-tas2781-bound-firmware-description-string-parsi.patch new file mode 100644 index 0000000000..06521ddd56 --- /dev/null +++ b/queue-6.6/asoc-tas2781-bound-firmware-description-string-parsi.patch @@ -0,0 +1,153 @@ +From 0411dc124f7348bf622eff37caea4f88fe15b1af Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:45:39 +0800 +Subject: ASoC: tas2781: bound firmware description string parsing + +From: Pengpeng Hou + +[ Upstream commit bc889dfcea9294a1eae7f8e2f3573a90764ae4d0 ] + +The TAS2781 firmware parser reads several variable-length description +strings with strlen() before checking that the string terminator is +present inside the firmware blob. A malformed firmware image without a +NUL terminator can therefore make the parser walk past the end of the +firmware buffer before the later size checks run. + +Add a small bounded string-length helper and use it for all description +fields that are parsed from the firmware buffer. Keep the existing size +checks for the fixed bytes that follow each string. + +Fixes: 915f5eadebd2 ("ASoC: tas2781: firmware lib") +Signed-off-by: Pengpeng Hou +Link: https://patch.msgid.link/20260706144540.93929-1-pengpeng@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2781-fmwlib.c | 63 ++++++++++++++++++++++++++++--- + 1 file changed, 57 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c +index 1cc64ed8de6da8..4b6bed6bf11567 100644 +--- a/sound/soc/codecs/tas2781-fmwlib.c ++++ b/sound/soc/codecs/tas2781-fmwlib.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -921,13 +922,42 @@ static int tasdevice_load_block_kernel( + return 0; + } + ++static int tasdevice_fw_strnlen(const struct firmware *fmw, int offset) ++{ ++ const u8 *start; ++ const u8 *nul; ++ size_t remaining; ++ size_t len; ++ ++ if (offset < 0 || offset >= fmw->size) ++ return -EINVAL; ++ ++ start = fmw->data + offset; ++ remaining = fmw->size - offset; ++ nul = memchr(start, '\0', remaining); ++ if (!nul) ++ return -EINVAL; ++ ++ len = nul - start; ++ if (len > INT_MAX) ++ return -EOVERFLOW; ++ ++ return len; ++} ++ + static int fw_parse_variable_hdr(struct tasdevice_priv + *tas_priv, struct tasdevice_dspfw_hdr *fw_hdr, + const struct firmware *fmw, int offset) + { + const unsigned char *buf = fmw->data; +- int len = strlen((char *)&buf[offset]); ++ int len; + ++ len = tasdevice_fw_strnlen(fmw, offset); ++ if (len < 0) { ++ dev_err(tas_priv->dev, "%s: Description error\n", __func__); ++ offset = len; ++ goto out; ++ } + len++; + + if (offset + len + 8 > fmw->size) { +@@ -1059,7 +1089,12 @@ static int fw_parse_data(struct tasdevice_fw *tas_fmw, + memcpy(img_data->name, &data[offset], 64); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_fmw->dev, "%s: Description error\n", __func__); ++ offset = n; ++ goto out; ++ } + n++; + if (offset + n + 2 > fmw->size) { + dev_err(tas_fmw->dev, "%s: Description error\n", __func__); +@@ -1132,7 +1167,12 @@ static int fw_parse_program_data(struct tasdevice_priv *tas_priv, + } + offset += 64; + +- n = strlen((char *)&buf[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + /* skip '\0' and 5 unused bytes */ + n += 6; + if (offset + n > fmw->size) { +@@ -1195,7 +1235,12 @@ static int fw_parse_configuration_data( + memcpy(config->name, &data[offset], 64); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + n += 15; + if (offset + n > fmw->size) { + dev_err(tas_priv->dev, "Description err\n"); +@@ -1849,7 +1894,8 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, + { + struct tasdevice_calibration *calibration; + unsigned char *data = (unsigned char *)fmw->data; +- unsigned int i, n; ++ unsigned int i; ++ int n; + + if (offset + 2 > fmw->size) { + dev_err(tas_priv->dev, "%s: Calibrations error\n", __func__); +@@ -1881,7 +1927,12 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, + calibration = &(tas_fmw->calibrations[i]); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + /* skip '\0' and 2 unused bytes */ + n += 3; + if (offset + n > fmw->size) { +-- +2.53.0 + diff --git a/queue-6.6/bluetooth-btusb-validate-realtek-vendor-event-length.patch b/queue-6.6/bluetooth-btusb-validate-realtek-vendor-event-length.patch new file mode 100644 index 0000000000..41d2b8e68d --- /dev/null +++ b/queue-6.6/bluetooth-btusb-validate-realtek-vendor-event-length.patch @@ -0,0 +1,48 @@ +From 13c02d6f180be471b5634c8d382ccb7d3b464994 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:47:17 +0800 +Subject: Bluetooth: btusb: validate Realtek vendor event length + +From: Pengpeng Hou + +[ Upstream commit df541cd485ff80a5ddc579d99687bc7506df9851 ] + +btusb_recv_event_realtek() reads the event code at data[0] and the Realtek +subevent code at data[2] before deciding whether to consume a vendor event +as a coredump. + +For example, the two-byte event ff 00 contains a complete vendor-event +header declaring zero parameters. The old classifier still reads a +nonexistent third byte and can misclassify the event as a coredump if the +adjacent byte is 0x34. + +Require the HCI event header and first parameter to be present before +inspecting the Realtek subevent code. Short events continue through the +normal HCI receive path, which owns their protocol validation. + +Fixes: 044014ce85a1 ("Bluetooth: btrtl: Add Realtek devcoredump support") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index c3eb668c39943d..08b01d93b86c7f 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2671,7 +2671,9 @@ static int btusb_setup_realtek(struct hci_dev *hdev) + + static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb) + { +- if (skb->data[0] == HCI_VENDOR_PKT && skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) { ++ if (skb->len >= HCI_EVENT_HDR_SIZE + 1 && ++ skb->data[0] == HCI_VENDOR_PKT && ++ skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) { + struct rtk_dev_coredump_hdr hdr = { + .code = RTK_DEVCOREDUMP_CODE_MEMDUMP, + }; +-- +2.53.0 + diff --git a/queue-6.6/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch b/queue-6.6/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch new file mode 100644 index 0000000000..9da700b396 --- /dev/null +++ b/queue-6.6/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch @@ -0,0 +1,75 @@ +From 92ed1434e240156f11da76e6d151ef5f0921404f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 09:06:22 +0800 +Subject: bonding: fix devconf_all NULL dereference when IPv6 is disabled + +From: Zhaolong Zhang + +[ Upstream commit 1c975de3343cdef506f2eecc833cc1f14b0401c4 ] + +When booting with the 'ipv6.disable=1' parameter, the devconf_all is +never initialized because inet6_init() exits before addrconf_init() is +called which initializes it. bond_send_validate(), however, will still +call bond_ns_send_all() even ipv6 is indeed disabled. It will lead to +NULL derefence of net->ipv6.devconf_all in ip6_pol_route(). + + BUG: kernel NULL pointer dereference, address: 000000000000000c + [...] + Workqueue: bond0 bond_arp_monitor [bonding] + RIP: 0010:ip6_pol_route+0x69/0x480 + [...] + Call Trace: + + ? srso_return_thunk+0x5/0x5f + ? __pfx_ip6_pol_route_output+0x10/0x10 + fib6_rule_lookup+0xfe/0x260 + ? wakeup_preempt+0x8a/0x90 + ? srso_return_thunk+0x5/0x5f + ? srso_return_thunk+0x5/0x5f + ? sched_balance_rq+0x369/0x810 + ip6_route_output_flags+0xd7/0x170 + bond_ns_send_all+0xde/0x280 [bonding] + bond_ab_arp_probe+0x296/0x320 [bonding] + ? srso_return_thunk+0x5/0x5f + bond_activebackup_arp_mon+0xb4/0x2c0 [bonding] + process_one_work+0x196/0x370 + worker_thread+0x1af/0x320 + ? srso_return_thunk+0x5/0x5f + ? __pfx_worker_thread+0x10/0x10 + kthread+0xe3/0x120 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x199/0x260 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Fix this by adding ipv6_mod_enabled() condition check in the caller. + +Fixes: 4e24be018eb9 ("bonding: add new parameter ns_targets") +Signed-off-by: Qianheng Peng +Signed-off-by: Zhaolong Zhang +Reviewed-by: Hangbin Liu +Link: https://patch.msgid.link/20260707010622.487333-1-zhangzl2013@126.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 6b558aa98c6d2f..09e2ae6739073f 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -3431,7 +3431,8 @@ static void bond_send_validate(struct bonding *bond, struct slave *slave) + { + bond_arp_send_all(bond, slave); + #if IS_ENABLED(CONFIG_IPV6) +- bond_ns_send_all(bond, slave); ++ if (likely(ipv6_mod_enabled())) ++ bond_ns_send_all(bond, slave); + #endif + } + +-- +2.53.0 + diff --git a/queue-6.6/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch b/queue-6.6/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch new file mode 100644 index 0000000000..a6ea8d1123 --- /dev/null +++ b/queue-6.6/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch @@ -0,0 +1,79 @@ +From fb01ea6fb1e889e28c4f9be9b0951a3fe266d056 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jul 2026 18:38:56 +0800 +Subject: bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() + +From: Chengfeng Ye + +[ Upstream commit 2d66a033864e27ab8d5e44cb36f31d9d2413bee4 ] + +tcp_bpf_sendmsg() keeps msg_tx across sk_stream_wait_memory(), which +drops and reacquires the socket lock. Its error path tries to decide +whether msg_tx names the local temporary message by comparing it with +the current value of psock->cork. + +This comparison is unsafe when two threads send on the same socket: + + Thread A Thread B + msg_tx = psock->cork + sk_msg_alloc() fails + sk_stream_wait_memory() + releases the socket lock acquires the socket lock + completes the cork + psock->cork = NULL + frees the cork + reacquires the socket lock + msg_tx != psock->cork + sk_msg_free(msg_tx) + +The stale cork is therefore mistaken for the local temporary message +and freed again. KASAN reported: + + BUG: KASAN: slab-use-after-free in sk_msg_free+0x49/0x50 + Read of size 4 at addr ffff88810c908800 by task poc/90 + Call Trace: + sk_msg_free+0x49/0x50 + tcp_bpf_sendmsg+0x14f5/0x1cc0 + __sys_sendto+0x32c/0x3a0 + __x64_sys_sendto+0xdb/0x1b0 + Allocated by task 89: + __kasan_kmalloc+0x8f/0xa0 + tcp_bpf_sendmsg+0x16b3/0x1cc0 + Freed by task 91: + __kasan_slab_free+0x43/0x70 + kfree+0x131/0x3c0 + tcp_bpf_sendmsg+0xec3/0x1cc0 + +msg_tx can only name the stack-local tmp or the shared cork. Check for +tmp directly so a changed psock->cork cannot turn a shared message into +an apparent local one. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Chengfeng Ye +Reviewed-by: Emil Tsalapatis +Reviewed-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/87fr18lmzo.fsf%40cloudflare.com/ +Link: https://lore.kernel.org/netdev/20260719161630.2901208-1-nicoyip.dev%40gmail.com/ [v1] +Link: https://patch.msgid.link/20260724103856.3399001-1-nicoyip.dev@gmail.com +Signed-off-by: Eduard Zingerman +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index da5e14ec8ed6da..337f6edd4757e3 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -590,7 +590,7 @@ static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + wait_for_memory: + err = sk_stream_wait_memory(sk, &timeo); + if (err) { +- if (msg_tx && msg_tx != psock->cork) ++ if (msg_tx == &tmp) + sk_msg_free(sk, msg_tx); + goto out_err; + } +-- +2.53.0 + diff --git a/queue-6.6/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch b/queue-6.6/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch new file mode 100644 index 0000000000..a603b8a29a --- /dev/null +++ b/queue-6.6/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch @@ -0,0 +1,55 @@ +From fa68fe846aec78e014e88b83386d6e6e711790db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jun 2026 18:39:07 +0800 +Subject: btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8 + +From: You-Kai Zheng + +[ Upstream commit b95181f3929ff98949fa9460ca93eccebbf2d7fc ] + +The variable-sized buffer buf in struct btrfs_ioctl_search_args_v2 is +declared as __u64[], but it holds a packed byte stream of search results, +where all offsets into the buffer are in bytes. + +Declaring buf as __u64[] makes it easy for user space to write incorrect +pointer arithmetic: adding a byte offset directly to a __u64 pointer +scales the offset by 8, landing at byte position offset*8 instead of +offset. + +This recently caused an infinite loop in btrfs-progs: the accessor read +all-zero data from misaddressed items, which fed zeroed search keys back +into the ioctl loop and spun forever. The issue was worked around at the +time by disabling TREE_SEARCH_V2 entirely in btrfs-progs (d73e69824854: +"btrfs-progs: temporarily disable usage of v2 of search tree ioctl"). + +The kernel side already treats buf as a byte buffer, so change the +declaration to __u8[] to match the actual semantics and prevent similar +misuse in user space. The change is ABI compatible: both the structure size +and alignment are unchanged. + +Fixes: cc68a8a5a433 ("btrfs: new ioctl TREE_SEARCH_V2") +Reviewed-by: Qu Wenruo +Signed-off-by: You-Kai Zheng +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + include/uapi/linux/btrfs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h +index 7b499b90bb779e..9c921ae7c9187b 100644 +--- a/include/uapi/linux/btrfs.h ++++ b/include/uapi/linux/btrfs.h +@@ -595,7 +595,7 @@ struct btrfs_ioctl_search_args_v2 { + __u64 buf_size; /* in - size of buffer + * out - on EOVERFLOW: needed size + * to store item */ +- __u64 buf[]; /* out - found items */ ++ __u8 buf[]; /* out - found items */ + }; + + /* With a @src_length of zero, the range from @src_offset->EOF is cloned! */ +-- +2.53.0 + diff --git a/queue-6.6/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch b/queue-6.6/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch new file mode 100644 index 0000000000..30f5cb3681 --- /dev/null +++ b/queue-6.6/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch @@ -0,0 +1,47 @@ +From bbbaf20aeef82e2829ffff2a68b8dad8b631b20e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 03:17:28 +0000 +Subject: btrfs: free mapping node on duplicate reloc root insert + +From: Guanghui Yang <3497809730@qq.com> + +[ Upstream commit 6a8269b6459ed870a8156c106a0f597383907872 ] + +__add_reloc_root() allocates a mapping_node before inserting it into +rc->reloc_root_tree. If rb_simple_insert() finds an existing entry, it +returns the existing rb_node and leaves the newly allocated node unlinked. + +The error path then returns -EEXIST without freeing the new node. Since +the node was never inserted into reloc_root_tree, the later cleanup in +put_reloc_control() cannot find it either. + +Free the newly allocated node before returning -EEXIST. + +The callers currently assert that -EEXIST should not happen, so this is a +defensive cleanup for an unexpected duplicate insert path. If the path is +ever reached, the local allocation should still be released. + +Fixes: 57a304cfd43b ("btrfs: do not panic in __add_reloc_root") +Reviewed-by: Qu Wenruo +Signed-off-by: Guanghui Yang <3497809730@qq.com> +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 90aacda2523eb5..0b7a4b90053692 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -586,6 +586,7 @@ static int __must_check __add_reloc_root(struct btrfs_root *root) + btrfs_err(fs_info, + "Duplicate root found for start=%llu while inserting into relocation tree", + node->bytenr); ++ kfree(node); + return -EEXIST; + } + +-- +2.53.0 + diff --git a/queue-6.6/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch b/queue-6.6/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..6c2a356773 --- /dev/null +++ b/queue-6.6/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,48 @@ +From b3dbbe76b10771ea8be688bc0699fdd73a47cd54 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:17:37 +0800 +Subject: dpaa2-eth: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit b4b201cc93ff70150853aba03e14d314d1980ca0 ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The Ethernet connect path stores that +device in mac->mc_dev and keeps it for the lifetime of the connected MAC +object. + +However, the disconnect path only disconnects and closes the MAC before +freeing the dpaa2_mac object. It does not drop the endpoint device +reference stored in mac->mc_dev, so every successful connect leaks that +device reference when the MAC is later disconnected. + +Drop the endpoint device reference after closing the MAC and before +freeing the dpaa2_mac object. + +Fixes: 719479230893 ("dpaa2-eth: add MAC/PHY support through phylink") +Signed-off-by: Guangshuo Li +Reviewed-by: Ioana Ciornei +Reviewed-by: Ioana Ciornei +Link: https://patch.msgid.link/20260708111738.750391-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index 61bd2389ef4b54..d77c22d1030a92 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -4720,6 +4720,7 @@ static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-6.6/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch b/queue-6.6/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..f79debd1c7 --- /dev/null +++ b/queue-6.6/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,46 @@ +From 607732058bfe48964c5527868d1279b2773cac66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:10:25 +0800 +Subject: dpaa2-switch: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit 4c1eabbef7a1707635652e956e39db1269c3af2b ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The switch port connect path stores +that device in mac->mc_dev and keeps it for the lifetime of the connected +MAC object. + +However, the disconnect path only closes the MAC and frees the dpaa2_mac +object. It does not drop the endpoint device reference stored in +mac->mc_dev, so every successful connect leaks that device reference when +the MAC is later disconnected. + +Drop the endpoint device reference before freeing the dpaa2_mac object. + +Fixes: 84cba72956fd ("dpaa2-switch: integrate the MAC endpoint support") +Signed-off-by: Guangshuo Li +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708111025.749311-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +index 0f8b46dccc0971..501e86e9fd487c 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +@@ -1510,6 +1510,7 @@ static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-6.6/firewire-net-fix-fragmented-datagram-reassembly.patch b/queue-6.6/firewire-net-fix-fragmented-datagram-reassembly.patch new file mode 100644 index 0000000000..087dcb3313 --- /dev/null +++ b/queue-6.6/firewire-net-fix-fragmented-datagram-reassembly.patch @@ -0,0 +1,99 @@ +From 66df6fa7e9c25bcb3981ee2ae4ccae96fbd45ff4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 23:04:54 +0800 +Subject: firewire: net: Fix fragmented datagram reassembly + +From: Ruoyu Wang + +[ Upstream commit d52a13adbb8ccbab99cd3bad36804e87d8b5c052 ] + +fwnet_frag_new() keeps a sorted list of received fragments for a partial +datagram. When a new fragment is adjacent to an existing fragment, the +code checks whether the new fragment also closes the gap to the next or +previous list entry. + +Those neighbor lookups currently assume that the current fragment always +has a real next or previous fragment. At a list edge, the next or +previous entry is the list head, not a struct fwnet_fragment_info. + +The gap checks also compare against the old edge of the current fragment +instead of the edge after adding the new fragment. As a result, a +fragment that bridges two existing ranges may leave two adjacent ranges +unmerged, so fwnet_pd_is_complete() can miss a complete datagram. + +Check for the list head before looking up the neighboring fragment, and +compare the neighbor against the new fragment's far edge when deciding +whether to merge all three ranges. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: c76acec6d551 ("firewire: add IPv4 support") +Signed-off-by: Ruoyu Wang +Link: https://lore.kernel.org/r/20260707150454.2265951-1-ruoyuw560@gmail.com +Signed-off-by: Takashi Sakamoto +Signed-off-by: Sasha Levin +--- + drivers/firewire/net.c | 39 +++++++++++++++++++++------------------ + 1 file changed, 21 insertions(+), 18 deletions(-) + +diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c +index 21f3a9dae072a9..2a2dd75120b6e3 100644 +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -298,31 +298,34 @@ static struct fwnet_fragment_info *fwnet_frag_new( + if (fi->offset + fi->len == offset) { + /* The new fragment can be tacked on to the end */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.next, +- struct fwnet_fragment_info, fi_link); +- if (fi->offset + fi->len == fi2->offset) { +- /* glue fragments together */ +- fi->len += len + fi2->len; +- list_del(&fi2->fi_link); +- kfree(fi2); +- } else { +- fi->len += len; ++ if (!list_is_last(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_next_entry(fi, fi_link); ++ if (offset + len == fi2->offset) { ++ /* glue fragments together */ ++ fi->len += len + fi2->len; ++ list_del(&fi2->fi_link); ++ kfree(fi2); ++ ++ return fi; ++ } + } ++ fi->len += len; + + return fi; + } + if (offset + len == fi->offset) { + /* The new fragment can be tacked on to the beginning */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.prev, +- struct fwnet_fragment_info, fi_link); +- if (fi2->offset + fi2->len == fi->offset) { +- /* glue fragments together */ +- fi2->len += fi->len + len; +- list_del(&fi->fi_link); +- kfree(fi); +- +- return fi2; ++ if (!list_is_first(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_prev_entry(fi, fi_link); ++ if (fi2->offset + fi2->len == offset) { ++ /* glue fragments together */ ++ fi2->len += fi->len + len; ++ list_del(&fi->fi_link); ++ kfree(fi); ++ ++ return fi2; ++ } + } + fi->offset = offset; + fi->len += len; +-- +2.53.0 + diff --git a/queue-6.6/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch b/queue-6.6/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch new file mode 100644 index 0000000000..d6d0c537f8 --- /dev/null +++ b/queue-6.6/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch @@ -0,0 +1,58 @@ +From c2a833bc6800cc08a4f0f7f243707ba62b885b6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 23:07:24 +0000 +Subject: gtp: check skb_pull_data() return in gtp1u_send_echo_resp() + +From: Xiang Mei (Microsoft) + +[ Upstream commit cd170f051dba9ac146fabcd1b91726487c0cb9fa ] + +gtp1u_send_echo_resp() ignores skb_pull_data()'s return value. Its +caller gtp1u_udp_encap_recv() only guarantees 16 bytes (udphdr + +gtp1_header), but the pull requests 20 (gtp1_header_long + udphdr). For +a 16-19 byte echo request the pull fails and returns NULL without +advancing skb->data; execution continues, and the following skb_push() +plus the IP header pushed by iptunnel_xmit() move skb->data below +skb->head, tripping skb_under_panic(). + +Fix it by dropping the packet when skb_pull_data() fails. + + skbuff: skb_under_panic: ... + kernel BUG at net/core/skbuff.c:214! + Call Trace: + skb_push (net/core/skbuff.c:2648) + iptunnel_xmit (net/ipv4/ip_tunnel_core.c:82) + gtp_encap_recv (drivers/net/gtp.c:701 drivers/net/gtp.c:808 drivers/net/gtp.c:920) + udp_queue_rcv_one_skb (net/ipv4/udp.c:2388) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 9af41cc33471 ("gtp: Implement GTP echo response") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Link: https://patch.msgid.link/20260710230724.942574-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/gtp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index 55160a5fc90fc6..7bb3da8f253635 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -490,8 +490,9 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb) + return -1; + + /* pull GTP and UDP headers */ +- skb_pull_data(skb, +- sizeof(struct gtp1_header_long) + sizeof(struct udphdr)); ++ if (!skb_pull_data(skb, sizeof(struct gtp1_header_long) + ++ sizeof(struct udphdr))) ++ return -1; + + gtp_pkt = skb_push(skb, sizeof(struct gtp1u_packet)); + memset(gtp_pkt, 0, sizeof(struct gtp1u_packet)); +-- +2.53.0 + diff --git a/queue-6.6/hinic-remove-unused-ethtool-rss-user-configuration-b.patch b/queue-6.6/hinic-remove-unused-ethtool-rss-user-configuration-b.patch new file mode 100644 index 0000000000..9be406ef3c --- /dev/null +++ b/queue-6.6/hinic-remove-unused-ethtool-rss-user-configuration-b.patch @@ -0,0 +1,83 @@ +From 26ff7d331020864ea88577c70ca1b39306ec3dd8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:53:53 +0800 +Subject: hinic: remove unused ethtool RSS user configuration buffers + +From: Chenguang Zhao + +[ Upstream commit fe0c002928c6749b7f4a726f6f600f6dd70280ea ] + +rss_indir_user and rss_hkey_user are allocated and filled in +__set_rss_rxfh() when the user configures RSS via ethtool, but +nothing ever reads them. hinic_get_rxfh() fetches the state from +the device, and the hardware is programmed from the original +indir/key arguments. These buffers only leaked on driver unload. + +Drop the unused allocations, memcpys, and struct fields. + +Fixes: 4fdc51bb4e92 ("hinic: add support for rss parameters with ethtool") +Signed-off-by: Chenguang Zhao +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260722025353.328179-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/huawei/hinic/hinic_dev.h | 2 -- + .../net/ethernet/huawei/hinic/hinic_ethtool.c | 21 ------------------- + 2 files changed, 23 deletions(-) + +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +index 52ea97c818b8ec..d9ab94910a2a79 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h ++++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +@@ -104,8 +104,6 @@ struct hinic_dev { + u16 num_rss; + u16 rss_limit; + struct hinic_rss_type rss_type; +- u8 *rss_hkey_user; +- s32 *rss_indir_user; + struct hinic_intr_coal_info *rx_intr_coalesce; + struct hinic_intr_coal_info *tx_intr_coalesce; + struct hinic_sriov_info sriov_info; +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +index f4b68028691194..660ab3edf73939 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c ++++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +@@ -1061,17 +1061,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + int err; + + if (indir) { +- if (!nic_dev->rss_indir_user) { +- nic_dev->rss_indir_user = +- kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE, +- GFP_KERNEL); +- if (!nic_dev->rss_indir_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_indir_user, indir, +- sizeof(u32) * HINIC_RSS_INDIR_SIZE); +- + err = hinic_rss_set_indir_tbl(nic_dev, + nic_dev->rss_tmpl_idx, indir); + if (err) +@@ -1079,16 +1068,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + } + + if (key) { +- if (!nic_dev->rss_hkey_user) { +- nic_dev->rss_hkey_user = +- kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL); +- +- if (!nic_dev->rss_hkey_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE); +- + err = hinic_rss_set_template_tbl(nic_dev, + nic_dev->rss_tmpl_idx, key); + if (err) +-- +2.53.0 + diff --git a/queue-6.6/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch b/queue-6.6/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch new file mode 100644 index 0000000000..df4d9f31dd --- /dev/null +++ b/queue-6.6/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch @@ -0,0 +1,42 @@ +From 20aef93a0dcd2aa2868822ea5341dd0fe1efff6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 15:05:05 +0200 +Subject: hwmon: (asus-ec-sensors) add missed handle for ENOMEM + +From: Eugene Shalygin + +[ Upstream commit 9813c1f49efeadbcb17e4a41972350ac783f9cac ] + +Add missing return value check in the setup function. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260712130602.1256700-2-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index 3ada7db8008970..95bf1670156ed6 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -1042,9 +1042,11 @@ static int asus_ec_probe(struct platform_device *pdev) + if (!nr_count[type]) + continue; + +- asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, +- nr_count[type], type, +- hwmon_attributes[type]); ++ status = asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, ++ nr_count[type], type, ++ hwmon_attributes[type]); ++ if (status) ++ return status; + *ptr_asus_ec_ci++ = asus_ec_hwmon_chan++; + } + +-- +2.53.0 + diff --git a/queue-6.6/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch b/queue-6.6/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch new file mode 100644 index 0000000000..55590a01c4 --- /dev/null +++ b/queue-6.6/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch @@ -0,0 +1,60 @@ +From c058f7abc80d9b5ebfb45662c8c86eb3802e792c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 13:05:03 +0200 +Subject: hwmon: (asus-ec-sensors) fix EC read intervals + +From: Eugene Shalygin + +[ Upstream commit 60710b2af13b81da71b429d3f8b19dd70310729d ] + +Take INITIAL_JIFFIES into account when setting up next update time. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260712110650.1240071-2-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index a6949358979e2f..3ada7db8008970 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -574,7 +574,7 @@ struct ec_sensors_data { + /* sorted list of unique register banks */ + u8 banks[ASUS_EC_MAX_BANK + 1]; + /* in jiffies */ +- unsigned long last_updated; ++ u64 next_update; + struct lock_data lock_data; + /* number of board EC sensors */ + u8 nr_sensors; +@@ -843,13 +843,12 @@ static int get_cached_value_or_update(const struct device *dev, + int sensor_index, + struct ec_sensors_data *state, s32 *value) + { +- if (time_after(jiffies, state->last_updated + HZ)) { ++ if (time_after64(get_jiffies_64(), state->next_update)) { + if (update_ec_sensors(dev, state)) { + dev_err(dev, "update_ec_sensors() failure\n"); + return -EIO; + } +- +- state->last_updated = jiffies; ++ state->next_update = get_jiffies_64() + HZ; + } + + *value = state->sensors[sensor_index].cached_value; +@@ -967,6 +966,7 @@ static int asus_ec_probe(struct platform_device *pdev) + if (!ec_data) + return -ENOMEM; + ++ ec_data->next_update = INITIAL_JIFFIES; + dev_set_drvdata(dev, ec_data); + ec_data->board_info = pboard_info; + +-- +2.53.0 + diff --git a/queue-6.6/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch b/queue-6.6/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch new file mode 100644 index 0000000000..dd83261f88 --- /dev/null +++ b/queue-6.6/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch @@ -0,0 +1,37 @@ +From e1cfc791126018d9d5815821a8a4e0deed2c0024 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 09:42:07 +0200 +Subject: hwmon: (asus-ec-sensors) fix looping over banks while reading from EC + +From: Eugene Shalygin + +[ Upstream commit e741d13cc2abfc6fccebe2008057aa52e285223e ] + +Do not assume there are only bank 0 and bank 1 available, just use '!=' +for bank comparison. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260711074217.554656-1-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index bc2197f1dfb7f5..a6949358979e2f 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -754,7 +754,7 @@ static int asus_ec_block_read(const struct device *dev, + } + for (ireg = 0; ireg < ec->nr_registers; ireg++) { + reg_bank = register_bank(ec->registers[ireg]); +- if (reg_bank < bank) { ++ if (reg_bank != bank) { + continue; + } + ec_read(register_index(ec->registers[ireg]), +-- +2.53.0 + diff --git a/queue-6.6/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch b/queue-6.6/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch new file mode 100644 index 0000000000..f6276dd29b --- /dev/null +++ b/queue-6.6/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch @@ -0,0 +1,41 @@ +From 8d6944a5cc92de0d68bac7a13217715c04800e33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 17:52:54 -0700 +Subject: hwmon: (corsair-cpro) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 94c87871b051d7ad758828a805215a2ec194512a ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 40c3a44542257 ("hwmon: add Corsair Commander Pro driver") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-cpro.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c +index b37f36f55f88a5..096e187082b80a 100644 +--- a/drivers/hwmon/corsair-cpro.c ++++ b/drivers/hwmon/corsair-cpro.c +@@ -558,6 +558,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) + + out_hw_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.6/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch b/queue-6.6/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..fcfa8dc025 --- /dev/null +++ b/queue-6.6/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,89 @@ +From 9dcd6189f1095db19539f9b077d0a210065ef95d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Apr 2026 12:12:26 +0800 +Subject: hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop + +From: Edward Adam Davis + +[ Upstream commit 9ab8656548cd737b98d0b19c4253aff8d68e97f4 ] + +hid_hw_stop() does not stop the device IO. + +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +corsairpsu_probe(). If the probe operation fails after "io start" has +been initiated, this race condition will result in a uaf vulnerability +[1]. + +CPU0 CPU1 +==== ==== +corsairpsu_probe() + hid_device_io_start() + ... unlock driver_input_lock + hid_hw_stop() + kfree(hidraw) __hid_input_report() + ... acquire driver_input_lock + hid_report_raw_event() + hidraw_report_event() + ... access hidraw's list_lock // trigger uaf + +Consequently, when corsairpsu_probe() fails and hid_hw_stop() needs to +be executed, the io_started flag is first cleared while holding the +driver_input_lock to prevent potential race conditions involving input +reports. + +[1] +BUG: KASAN: slab-use-after-free in rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56 +Call Trace: + hidraw_report_event+0x5d/0x3a0 drivers/hid/hidraw.c:577 + hid_report_raw_event+0x311/0x1730 drivers/hid/hid-core.c:2076 + __hid_input_report drivers/hid/hid-core.c:2152 [inline] + hid_input_report+0x44e/0x580 drivers/hid/hid-core.c:2174 + hid_irq_in+0x47e/0x6d0 drivers/hid/usbhid/hid-core.c:286 + __usb_hcd_giveback_urb+0x3b3/0x5e0 drivers/usb/core/hcd.c:1657 + dummy_timer+0x8a9/0x47d0 drivers/usb/gadget/udc/dummy_hcd.c:2005 + +Allocated by task 10: + hidraw_connect+0x57/0x430 drivers/hid/hidraw.c:606 + hid_connect+0x5bf/0x19d0 drivers/hid/hid-core.c:2277 + hid_hw_start+0xa8/0x120 drivers/hid/hid-core.c:2387 + corsairpsu_probe+0xd9/0x3c0 drivers/hwmon/corsair-psu.c:782 + +Freed by task 10: + hidraw_disconnect+0x4f/0x60 drivers/hid/hidraw.c:662 + hid_disconnect drivers/hid/hid-core.c:2362 [inline] + hid_hw_stop+0x101/0x1e0 drivers/hid/hid-core.c:2407 + corsairpsu_probe+0x327/0x3c0 drivers/hwmon/corsair-psu.c:826 + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Fixes: d115b51e0e56 ("hwmon: add Corsair PSU HID controller driver") +Reported-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9eebf5f6544c5e873858 +Tested-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Link: https://lore.kernel.org/r/tencent_BB7C33EB9EA41B7B4B5F1B8B25C0BA13BB08@qq.com +[groeck: Updated subject and description; + call hid_device_io_stop() only if IO has been started] +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-psu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c +index 93937e1bce196b..4ab73bcef1d125 100644 +--- a/drivers/hwmon/corsair-psu.c ++++ b/drivers/hwmon/corsair-psu.c +@@ -831,6 +831,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id + + fail_and_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + fail_and_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.6/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch b/queue-6.6/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..21e214030a --- /dev/null +++ b/queue-6.6/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,42 @@ +From e162bd244362a3762ab472046d653f6ffbcc0286 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:00:32 -0700 +Subject: hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 59d104b54b0b42e30fd2a68d24ee5c49dcc54d1e ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 53e68c20aeb1e ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/nzxt-smart2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c +index 7aa586eb74be15..0ce956954378dd 100644 +--- a/drivers/hwmon/nzxt-smart2.c ++++ b/drivers/hwmon/nzxt-smart2.c +@@ -774,7 +774,7 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev, + + out_hw_close: + hid_hw_close(hdev); +- ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-6.6/hwmon-occ-validate-poll-response-sensor-blocks.patch b/queue-6.6/hwmon-occ-validate-poll-response-sensor-blocks.patch new file mode 100644 index 0000000000..cb03549492 --- /dev/null +++ b/queue-6.6/hwmon-occ-validate-poll-response-sensor-blocks.patch @@ -0,0 +1,118 @@ +From 313f9a18c977847faa71b2094145b2a92a87800d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:58:26 +0800 +Subject: hwmon: occ: validate poll response sensor blocks + +From: Pengpeng Hou + +[ Upstream commit 70e76e700fc6c46afb4e17aec099a1ea089b4a22 ] + +The OCC poll response parser walks a counted list of sensor data blocks. +It used the static backing-array capacity as the parse boundary, but a +transport response makes only data_length bytes current and valid. A +truncated response can therefore make the parser consume a block header or +block extent outside the current response. + +Use data_length as the parent boundary, prove the fixed poll header and +each current block header before reading them, and prove the complete block +before advancing. Keep parsed sensor metadata local until the complete +response has passed validation, then publish it. Propagate +malformed-response errors before publishing the OCC as active. + +Fixes: aa195fe49b03 ("hwmon (occ): Parse OCC poll response") +Signed-off-by: Pengpeng Hou +Link: https://lore.kernel.org/r/20260720115826.14813-1-pengpeng@iscas.ac.cn +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/common.c | 38 ++++++++++++++++++++++++++++++-------- + 1 file changed, 30 insertions(+), 8 deletions(-) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index c92d08e9827ac5..d0c8a043445a25 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -1052,32 +1052,49 @@ static int occ_setup_sensor_attrs(struct occ *occ) + } + + /* only need to do this once at startup, as OCC won't change sensors on us */ +-static void occ_parse_poll_response(struct occ *occ) ++static int occ_parse_poll_response(struct occ *occ) + { + unsigned int i, old_offset, offset = 0, size = 0; ++ u16 data_length; + struct occ_sensor *sensor; +- struct occ_sensors *sensors = &occ->sensors; ++ struct occ_sensors parsed = {}; ++ struct occ_sensors *sensors = &parsed; + struct occ_response *resp = &occ->resp; + struct occ_poll_response *poll = + (struct occ_poll_response *)&resp->data[0]; + struct occ_poll_response_header *header = &poll->header; + struct occ_sensor_data_block *block = &poll->block; + ++ data_length = get_unaligned_be16(&resp->data_length); ++ if (data_length < sizeof(*header) || data_length > OCC_RESP_DATA_BYTES) { ++ dev_err(occ->bus_dev, "invalid OCC poll response length %u\n", ++ data_length); ++ return -EMSGSIZE; ++ } ++ + dev_info(occ->bus_dev, "OCC found, code level: %.16s\n", + header->occ_code_level); + + for (i = 0; i < header->num_sensor_data_blocks; ++i) { + block = (struct occ_sensor_data_block *)((u8 *)block + offset); ++ if (size + sizeof(*header) + sizeof(block->header) > ++ data_length) { ++ dev_err(occ->bus_dev, ++ "truncated OCC sensor block header\n"); ++ return -EMSGSIZE; ++ } ++ + old_offset = offset; + offset = (block->header.num_sensors * + block->header.sensor_length) + sizeof(block->header); +- size += offset; + + /* validate all the length/size fields */ +- if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) { +- dev_warn(occ->bus_dev, "exceeded response buffer\n"); +- return; ++ if (size + sizeof(*header) + offset > data_length) { ++ dev_err(occ->bus_dev, ++ "exceeded OCC poll response length\n"); ++ return -EMSGSIZE; + } ++ size += offset; + + dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n", + old_offset, offset - 1, block->header.eye_catcher, +@@ -1107,6 +1124,9 @@ static void occ_parse_poll_response(struct occ *occ) + + dev_dbg(occ->bus_dev, "Max resp size: %u+%zd=%zd\n", size, + sizeof(*header), size + sizeof(*header)); ++ occ->sensors = parsed; ++ ++ return 0; + } + + int occ_active(struct occ *occ, bool active) +@@ -1138,10 +1158,12 @@ int occ_active(struct occ *occ, bool active) + goto unlock; + } + +- occ->active = true; + occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; +- occ_parse_poll_response(occ); ++ rc = occ_parse_poll_response(occ); ++ if (rc) ++ goto unlock; + ++ occ->active = true; + rc = occ_setup_sensor_attrs(occ); + if (rc) { + dev_err(occ->bus_dev, +-- +2.53.0 + diff --git a/queue-6.6/ice-fix-lag-recipe-to-profile-association.patch b/queue-6.6/ice-fix-lag-recipe-to-profile-association.patch new file mode 100644 index 0000000000..af02707424 --- /dev/null +++ b/queue-6.6/ice-fix-lag-recipe-to-profile-association.patch @@ -0,0 +1,49 @@ +From c8d0cefa65fba804d13bbc28a6d2f8a44d2352d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:53:28 -0700 +Subject: ice: fix LAG recipe to profile association + +From: Marcin Szycik + +[ Upstream commit d6da9b7d48599db078aea6144997a381f8d90d45 ] + +ice_init_lag() associates recipes to profiles, assuming that Link +Aggregation-related profiles will always have profile ID lower than 70 +(ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER). This value seems arbitrary and +might not always be valid for some versions of DDP package, i.e. LAG +profiles may have profile ID greater than 70. This would lead to +misconfigured switch and LAG not working properly. + +Fix it by checking up to maximum profile ID. + +Fixes: 1e0f9881ef79 ("ice: Flesh out implementation of support for SRIOV on bonded interface") +Signed-off-by: Marcin Szycik +Reviewed-by: Michal Swiatkowski +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Dave Ertman +Reviewed-by: Simon Horman +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260717185340.3595286-7-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_lag.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c +index 8ed9918ea4e894..dcd4148dff4b0b 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lag.c ++++ b/drivers/net/ethernet/intel/ice/ice_lag.c +@@ -2004,7 +2004,7 @@ int ice_init_lag(struct ice_pf *pf) + goto lag_error; + + /* associate recipes to profiles */ +- for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) { ++ for (n = 0; n < ICE_MAX_NUM_PROFILES; n++) { + err = ice_aq_get_recipe_to_profile(&pf->hw, n, + &recipe_bits, NULL); + if (err) +-- +2.53.0 + diff --git a/queue-6.6/iomap-correct-the-range-of-a-partial-dirty-clear.patch b/queue-6.6/iomap-correct-the-range-of-a-partial-dirty-clear.patch new file mode 100644 index 0000000000..82723eafa1 --- /dev/null +++ b/queue-6.6/iomap-correct-the-range-of-a-partial-dirty-clear.patch @@ -0,0 +1,60 @@ +From d74fa60888041fac4b351dd3fda9e52497ad6442 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:23:21 +0800 +Subject: iomap: correct the range of a partial dirty clear + +From: Zhang Yi + +[ Upstream commit 88c26515313169806a412a362b32a1eca53d21bd ] + +The block range calculation in ifs_clear_range_dirty() is incorrect when +partially clearing a range in a folio. We cannot clear the dirty bit of +the first block or the last block if the start or end offset is not +blocksize-aligned. This has not yet caused any issues since we always +clear a whole folio in iomap_writeback_folio(). + +Fix this by rounding up the first block to blocksize alignment, and +calculate the last block by rounding down (using truncation). Correct +the nr_blks calculation accordingly. + +Fixes: 4ce02c679722 ("iomap: Add per-block dirty state tracking to improve performance") +Signed-off-by: Zhang Yi +Link: https://patch.msgid.link/20260714082325.325163-2-yi.zhang@huaweicloud.com +Reviewed-by: Joanne Koong +Reviewed-by: "Darrick J. Wong" +Reviewed-by: Christoph Hellwig +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/iomap/buffered-io.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index 4bc57934aa52df..bc7d176c4cf139 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -98,13 +98,17 @@ static void ifs_clear_range_dirty(struct folio *folio, + { + struct inode *inode = folio->mapping->host; + unsigned int blks_per_folio = i_blocks_per_folio(inode, folio); +- unsigned int first_blk = (off >> inode->i_blkbits); +- unsigned int last_blk = (off + len - 1) >> inode->i_blkbits; +- unsigned int nr_blks = last_blk - first_blk + 1; ++ unsigned int first_blk = round_up(off, i_blocksize(inode)) >> ++ inode->i_blkbits; ++ unsigned int last_blk = (off + len) >> inode->i_blkbits; + unsigned long flags; + ++ if (first_blk >= last_blk) ++ return; ++ + spin_lock_irqsave(&ifs->state_lock, flags); +- bitmap_clear(ifs->state, first_blk + blks_per_folio, nr_blks); ++ bitmap_clear(ifs->state, first_blk + blks_per_folio, ++ last_blk - first_blk); + spin_unlock_irqrestore(&ifs->state_lock, flags); + } + +-- +2.53.0 + diff --git a/queue-6.6/iommu-amd-bound-the-early-acpi-hid-map.patch b/queue-6.6/iommu-amd-bound-the-early-acpi-hid-map.patch new file mode 100644 index 0000000000..bbab4db42b --- /dev/null +++ b/queue-6.6/iommu-amd-bound-the-early-acpi-hid-map.patch @@ -0,0 +1,45 @@ +From 2091bb58a3ed11ef256897dbf5fbb6a0dbff7827 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:46:13 +0800 +Subject: iommu/amd: Bound the early ACPI HID map + +From: Pengpeng Hou + +[ Upstream commit fb80117fddb5b477218dc99bb53911b72c3847f8 ] + +The ivrs_acpihid command-line parser appends entries to a fixed +four-element early_acpihid_map array. Unlike the sibling IOAPIC and HPET +parsers, it does not reject a fifth entry before incrementing the map size. + +Check the capacity at the common found label before parsing the HID and +UID or writing the entry. + +Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter") +Signed-off-by: Pengpeng Hou +Reviewed-by: Ankit Soni +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/init.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index e5fee1aae587be..d3dc03fa93c652 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -3675,6 +3675,12 @@ static int __init parse_ivrs_acpihid(char *str) + return 1; + + found: ++ if (early_acpihid_map_size == EARLY_MAP_SIZE) { ++ pr_err("Early ACPI HID map overflow - ignoring ivrs_acpihid%s\n", ++ str); ++ return 1; ++ } ++ + p = acpiid; + hid = strsep(&p, ":"); + uid = p; +-- +2.53.0 + diff --git a/queue-6.6/iommu-amd-wait-for-completion-instead-of-returning-e.patch b/queue-6.6/iommu-amd-wait-for-completion-instead-of-returning-e.patch new file mode 100644 index 0000000000..b8bd27d1fc --- /dev/null +++ b/queue-6.6/iommu-amd-wait-for-completion-instead-of-returning-e.patch @@ -0,0 +1,95 @@ +From 2a20c5b5b61eb6353d5c39c02a287e6b670ffeeb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 22:16:22 +0800 +Subject: iommu/amd: Wait for completion instead of returning early in + iommu_completion_wait() + +From: Guanghui Feng + +[ Upstream commit 1e75a8255f11c81fb07e81e5029cfd75804350a0 ] + +need_sync is a per-IOMMU flag shared by all domains and devices behind +that IOMMU. It is set whenever a command is queued with sync == true and +cleared when a completion-wait (CWAIT) command is queued. However, a +cleared need_sync only means that a covering CWAIT has been queued, not +that all previously queued commands have actually completed in hardware. + +iommu_completion_wait() read need_sync locklessly and returned early +when it was false. This breaks the "block until all previously queued +commands have completed" contract in a multi-CPU scenario: + + CPU2: queue inv-B => need_sync = true + CPU1: queue CWAIT(N); need_sync = false; then wait_on_sem(N) + CPU2: read need_sync == false => return 0 (no wait!) + +CPU2 returns without waiting for any sequence number even though its +inv-B may not have completed yet (CWAIT(N), queued after inv-B, has not +been signaled). CPU2 then proceeds to, for example, free page-table +pages while the IOMMU can still walk stale translations, opening a +use-after-free window. This is a logical race in the meaning of the +flag, not a memory-visibility issue, so barriers alone do not help. + +Fix it without losing the optimization of avoiding redundant CWAIT +commands: take iommu->lock before testing need_sync, and when it is +false do not return early but wait for the last allocated sequence +number (cmd_sem_val). Since need_sync == false implies no sync command +was queued after the last CWAIT, that CWAIT is FIFO-ordered after every +not-yet-completed command, so waiting for its sequence number guarantees +all prior commands (possibly queued by another CPU) have completed. The +common path with pending work is unchanged and no extra hardware command +is issued. + +Signed-off-by: Guanghui Feng +Fixes: 815b33fdc279 ("x86/amd-iommu: Cleanup completion-wait handling") +Reviewed-by: Vasant Hegde +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/iommu.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c +index 48cf9e9e15976c..29ae44513cf688 100644 +--- a/drivers/iommu/amd/iommu.c ++++ b/drivers/iommu/amd/iommu.c +@@ -1212,11 +1212,23 @@ static int iommu_completion_wait(struct amd_iommu *iommu) + int ret; + u64 data; + +- if (!iommu->need_sync) +- return 0; +- + raw_spin_lock_irqsave(&iommu->lock, flags); + ++ if (!iommu->need_sync) { ++ /* ++ * No command has been queued since the last completion-wait. ++ * A concurrent CPU may have already queued that CWAIT and ++ * cleared need_sync; need_sync == false only means a covering ++ * CWAIT is queued, not that all prior commands have completed. ++ * Wait for the last allocated sequence number so that any ++ * command queued before this call (possibly on another CPU) ++ * is guaranteed to have completed before returning. ++ */ ++ data = iommu->cmd_sem_val; ++ raw_spin_unlock_irqrestore(&iommu->lock, flags); ++ return wait_on_sem(iommu, data); ++ } ++ + data = get_cmdsem_val(iommu); + build_completion_wait(&cmd, iommu, data); + +@@ -1226,9 +1238,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu) + if (ret) + return ret; + +- ret = wait_on_sem(iommu, data); +- +- return ret; ++ return wait_on_sem(iommu, data); + } + + static int iommu_flush_dte(struct amd_iommu *iommu, u16 devid) +-- +2.53.0 + diff --git a/queue-6.6/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch b/queue-6.6/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch new file mode 100644 index 0000000000..4fb9a6e13c --- /dev/null +++ b/queue-6.6/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch @@ -0,0 +1,43 @@ +From 93d155540ee538fd994bd54b9eb2abb42f6e225c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:34:10 +0800 +Subject: iommu/intel: Fix out-of-bounds memset in dmar_latency_disable() + +From: Li RongQing + +[ Upstream commit 754f8efe45f87e3a9c6871b645b2f9d46d1b407b ] + +dmar_latency_disable() intends to zero out only the single +latency_statistic entry for the given type, but the memset size was +computed as sizeof(*lstat) * DMAR_LATENCY_NUM, which clears the entire +array starting from &lstat[type]. + +When type > 0, this writes beyond the end of the allocated array, +corrupting adjacent memory. + +Fix by using sizeof(*lstat) to clear only the target entry. + +Fixes: 55ee5e67a59a ("iommu/vt-d: Add common code for dmar latency performance monitors") +Signed-off-by: Li RongQing +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/perf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/intel/perf.c b/drivers/iommu/intel/perf.c +index ae64e1123f2571..08ffebdbd09cec 100644 +--- a/drivers/iommu/intel/perf.c ++++ b/drivers/iommu/intel/perf.c +@@ -63,7 +63,7 @@ void dmar_latency_disable(struct intel_iommu *iommu, enum latency_type type) + return; + + spin_lock_irqsave(&latency_lock, flags); +- memset(&lstat[type], 0, sizeof(*lstat) * DMAR_LATENCY_NUM); ++ memset(&lstat[type], 0, sizeof(*lstat)); + spin_unlock_irqrestore(&latency_lock, flags); + } + +-- +2.53.0 + diff --git a/queue-6.6/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch b/queue-6.6/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch new file mode 100644 index 0000000000..d51ad09227 --- /dev/null +++ b/queue-6.6/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch @@ -0,0 +1,88 @@ +From 8b9bb1f98d580fd8001eba67e9e7c5f6ceedb7b5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:42:36 +0000 +Subject: ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup + +From: Eric Dumazet + +[ Upstream commit 853e164c2b321f0711361bc23505aaeb7dc432c3 ] + +When Linux forwards a packet and needs to generate an ICMP error, +icmp_route_lookup() performs a reverse-path relookup. For non-local +destinations, it performs a decoy lookup to find the expected egress +interface (rt2->dst.dev) before validating the path with ip_route_input(). + +Currently, the decoy flow structure (fl4_2) only sets .daddr = fl4_dec.saddr, +leaving .saddr, .flowi4_dscp, .flowi4_proto, .flowi4_mark, .flowi4_oif, +.fl4_sport, .fl4_dport, and .flowi4_uid zeroed out. + +When policy routing rules (such as ip rule add from $SRC lookup 100, or +dscp/fwmark/ipproto/port rules, or VRF bindings) are configured: +1. The decoy lookup fails to match the policy rule because saddr and other + key flow selectors are missing in fl4_2. +2. It resolves a route using the default table instead, returning an incorrect + egress netdev. +3. Passing the wrong netdev to ip_route_input() causes strict reverse-path + filtering (rp_filter=1) to fail, logging false-positive "martian source" + warnings and causing the relookup to fail. + +Fix this by initializing fl4_2 from fl4_dec and: +- Swapping source/destination IP addresses. +- Swapping L4 ports for transport protocols with ports (TCP, UDP, SCTP, DCCP) + so port-based policy routing matches correctly. Non-port protocols (such as + ICMP or GRE) leave the flowi_uli union fields intact to prevent corruption. +- Setting .flowi4_oif = l3mdev_master_ifindex(route_lookup_dev) to ensure + VRF routing tables are respected. +- Setting .flowi4_flags |= FLOWI_FLAG_ANYSRC to allow output route lookups + for non-local source IP addresses. +- Using __ip_route_output_key() instead of ip_route_output_key() for fl4_2 + so that raw FIB routing is used without triggering spurious XFRM policy + lookups on the decoy flow (the actual XFRM lookup is performed later using + fl4_dec). + +Fixes: 415b3334a21a ("icmp: Fix regression in nexthop resolution during replies.") +Reported-by: Muhammad Ziad +Closes: https://lore.kernel.org/netdev/CAOAwikA60AYKdFr_UDLyja3oU4hqyAE7uFZWqum5uRdaQsgRYg@mail.gmail.com/ +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260722104236.2938082-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index 3fcf11f83d87bd..7c4c7b7fe38468 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -536,11 +536,23 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4, + if (IS_ERR(rt2)) + err = PTR_ERR(rt2); + } else { +- struct flowi4 fl4_2 = {}; ++ struct flowi4 fl4_2 = fl4_dec; + unsigned long orefdst; + +- fl4_2.daddr = fl4_dec.saddr; +- rt2 = ip_route_output_key(net, &fl4_2); ++ swap(fl4_2.daddr, fl4_2.saddr); ++ switch (fl4_2.flowi4_proto) { ++ case IPPROTO_TCP: ++ case IPPROTO_UDP: ++ case IPPROTO_SCTP: ++ case IPPROTO_DCCP: ++ swap(fl4_2.fl4_sport, fl4_2.fl4_dport); ++ break; ++ } ++ ++ fl4_2.flowi4_oif = l3mdev_master_ifindex(route_lookup_dev); ++ fl4_2.flowi4_flags |= FLOWI_FLAG_ANYSRC; ++ ++ rt2 = __ip_route_output_key(net, &fl4_2); + if (IS_ERR(rt2)) { + err = PTR_ERR(rt2); + goto relookup_failed; +-- +2.53.0 + diff --git a/queue-6.6/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch b/queue-6.6/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch new file mode 100644 index 0000000000..64e7a48149 --- /dev/null +++ b/queue-6.6/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch @@ -0,0 +1,149 @@ +From af20dd6235215163c196412ef81a8c4fd255eb46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:09:21 +0300 +Subject: net: bridge: vlan: fix vlan range dumps starting with pvid + +From: Nikolay Aleksandrov + +[ Upstream commit 43171c97e4714bf601b468401b37732244639c21 ] + +There is a bug in all range dumps that rely on br_vlan_can_enter_range() +when the PVID is a range starting VLAN, all following VLANs that match +its flags can enter the range, but when the range is filled in only the +PVID VLAN is dumped and the rest of the range is discarded because +br_vlan_fill_vids() checks for the PVID flag. Since the PVID VLAN can +be only one, we need to break ranges around it, the best way to do that +consistently for all is to alter br_vlan_can_enter_range() to take into +account the PVID and return false to break the range when it's matched. + +Before the fix: +$ ip l add br0 type bridge vlan_filtering 1 +$ ip l add dumdum type dummy +$ ip l set dumdum master br0 +$ ip l set br0 up +$ ip l set dumdum up +$ bridge vlan add dev dumdum vid 1 pvid untagged master +$ bridge vlan add dev dumdum vid 2 untagged master +$ bridge vlan show dev dumdum # use legacy dump to show all vlans +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged + +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + +VLAN 2 is missing, and if there are more matching VLANs afterwards +they'd be missing too. + +After the fix: +[ same setup steps ] +$ bridge vlan show dev dumdum +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + 2 Egress Untagged + state forwarding mcast_router 1 + +Fixes: 0ab558795184 ("net: bridge: vlan: add rtm range support") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260721140922.682265-2-razor@blackwall.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_netlink_tunnel.c | 3 ++- + net/bridge/br_private.h | 6 ++++-- + net/bridge/br_vlan.c | 10 ++++++---- + net/bridge/br_vlan_options.c | 3 +-- + 4 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/net/bridge/br_netlink_tunnel.c b/net/bridge/br_netlink_tunnel.c +index 17abf092f7cac1..b006d1127c5495 100644 +--- a/net/bridge/br_netlink_tunnel.c ++++ b/net/bridge/br_netlink_tunnel.c +@@ -271,7 +271,8 @@ static void __vlan_tunnel_handle_range(const struct net_bridge_port *p, + if (!*v_start) + goto out_init; + +- if (v && curr_change && br_vlan_can_enter_range(v, *v_end)) { ++ if (v && curr_change && ++ br_vlan_can_enter_range(v, *v_end, br_get_pvid(vg))) { + *v_end = v; + return; + } +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index f0d8edc378a0eb..4867464bde32b6 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1563,7 +1563,8 @@ void br_vlan_notify(const struct net_bridge *br, + u16 vid, u16 vid_range, + int cmd); + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end); ++ const struct net_bridge_vlan *range_end, ++ u16 pvid); + + void br_vlan_fill_forward_path_pvid(struct net_bridge *br, + struct net_device_path_ctx *ctx, +@@ -1804,7 +1805,8 @@ static inline void br_vlan_notify(const struct net_bridge *br, + } + + static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { + return true; + } +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index cc54b8267bcc7b..171d1dddb26a81 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1943,9 +1943,11 @@ void br_vlan_notify(const struct net_bridge *br, + + /* check if v_curr can enter a range ending in range_end */ + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { +- return v_curr->vid - range_end->vid == 1 && ++ return v_curr->vid != pvid && range_end->vid != pvid && ++ v_curr->vid - range_end->vid == 1 && + range_end->flags == v_curr->flags && + br_vlan_opts_eq_range(v_curr, range_end); + } +@@ -2027,8 +2029,8 @@ static int br_vlan_dump_dev(const struct net_device *dev, + idx += range_end->vid - range_start->vid + 1; + + range_start = v; +- } else if (dump_stats || v->vid == pvid || +- !br_vlan_can_enter_range(v, range_end)) { ++ } else if (dump_stats || ++ !br_vlan_can_enter_range(v, range_end, pvid)) { + u16 vlan_flags = br_vlan_flags(range_start, pvid); + + if (!br_vlan_fill_vids(skb, range_start->vid, +diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c +index 8fa89b04ee942d..4a736e005bad7e 100644 +--- a/net/bridge/br_vlan_options.c ++++ b/net/bridge/br_vlan_options.c +@@ -310,8 +310,7 @@ int br_vlan_process_options(const struct net_bridge *br, + continue; + } + +- if (v->vid == pvid || +- !br_vlan_can_enter_range(v, curr_end)) { ++ if (!br_vlan_can_enter_range(v, curr_end, pvid)) { + br_vlan_notify(br, p, curr_start->vid, + curr_end->vid, RTM_NEWVLAN); + curr_start = v; +-- +2.53.0 + diff --git a/queue-6.6/net-dpaa-fix-mode-setting.patch b/queue-6.6/net-dpaa-fix-mode-setting.patch new file mode 100644 index 0000000000..8fdb32c42d --- /dev/null +++ b/queue-6.6/net-dpaa-fix-mode-setting.patch @@ -0,0 +1,81 @@ +From 31b36e66d0e1db59cb4fea4c564291dd1617462e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 15:20:29 +0200 +Subject: net: dpaa: fix mode setting + +From: Michael Walle + +[ Upstream commit da2c6bcc5e30b1496ac587785dcacf6e849eb6ef ] + +Before converting to the phylink interface, the init function would have +set a non-reserved I/F mode in the maccfg2 register. After converting to +phylink, 0 is written as mode, which is a reserved value (although it's +the hardware default). Without a valid mode, a SGMII link is never +established between the MAC and the PHY and thus .link_up() is never +called which could set the correct mode according to the actual speed. + +Fix it by setting the maximum speed of the phy_interface_t in use in +.mac_config() - just like the driver did before the phylink conversion. + +Fixes: 5d93cfcf7360 ("net: dpaa: Convert to phylink") +Suggested-by: Sean Anderson +Signed-off-by: Michael Walle +Reviewed-by: Sean Anderson +Reviewed-by: Sean Anderson +Link: https://patch.msgid.link/20260717132401.2653252-1-mwalle@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/freescale/fman/fman_dtsec.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +index 3088da7adf0f84..074ca626a51508 100644 +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +@@ -900,22 +900,28 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, + { + struct mac_device *mac_dev = fman_config_to_mac(config); + struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs; +- u32 tmp; ++ u32 ecntrl, maccfg2; ++ ++ maccfg2 = ioread32be(®s->maccfg2); ++ maccfg2 &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); + + switch (state->interface) { + case PHY_INTERFACE_MODE_RMII: +- tmp = DTSEC_ECNTRL_RMM; ++ ecntrl = DTSEC_ECNTRL_RMM; ++ maccfg2 |= MACCFG2_NIBBLE_MODE; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: +- tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; ++ ecntrl = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; ++ maccfg2 |= MACCFG2_BYTE_MODE; + break; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: +- tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; ++ ecntrl = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; ++ maccfg2 |= MACCFG2_BYTE_MODE; + break; + default: + dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n", +@@ -923,7 +929,8 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, + return; + } + +- iowrite32be(tmp, ®s->ecntrl); ++ iowrite32be(ecntrl, ®s->ecntrl); ++ iowrite32be(maccfg2, ®s->maccfg2); + } + + static void dtsec_link_up(struct phylink_config *config, struct phy_device *phy, +-- +2.53.0 + diff --git a/queue-6.6/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch b/queue-6.6/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch new file mode 100644 index 0000000000..a3a802a78c --- /dev/null +++ b/queue-6.6/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch @@ -0,0 +1,56 @@ +From aec1b6e77a75589486b7fceb505acb677345d786 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 10:12:40 +0000 +Subject: net: hsr: fix memory leak on slave unregistration by removing synced + VLANs + +From: Eric Dumazet + +[ Upstream commit dcf15eaf5641812f1cfc5e96537380132a7da89d ] + +When an HSR master device is brought UP, it auto-adds VLAN 0 via +vlan_vid0_add(), which propagates VID 0 to its slave devices (slave A and B). + +If a slave device is later unregistered while HSR is active (e.g., during +netns cleanup or interface destruction), hsr_del_port() is called to +detach the slave port from the HSR master. However, hsr_del_port() currently +does not delete the VLAN IDs that were synced to the slave device by HSR. + +As a result, the slave device retains a refcount on VID 0 (and any other +synced VLANs). When the slave device is destroyed, its vlan_info / +vlan_vid_info structure remains allocated, leading to a memory leak. + +Fix this by calling vlan_vids_del_by_dev(port->dev, master->dev) in +hsr_del_port() before unlinking slave A or slave B ports, matching the +propagation logic in hsr_ndo_vlan_rx_add_vid() / hsr_ndo_vlan_rx_kill_vid() +and the cleanup behavior in bonding and team drivers. + +Fixes: 1a8a63a5305e ("net: hsr: Add VLAN CTAG filter support") +Reported-by: syzbot+456957213f32970c0762@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/6a4cb6ca.57639fcc.86d58.000b.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Fernando Fernandez Mancera +Reviewed-by: Felix Maurer +Link: https://patch.msgid.link/20260721101240.995597-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_slave.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c +index b8230faa567f77..58e757dc555461 100644 +--- a/net/hsr/hsr_slave.c ++++ b/net/hsr/hsr_slave.c +@@ -228,6 +228,8 @@ void hsr_del_port(struct hsr_port *port) + netdev_rx_handler_unregister(port->dev); + if (!port->hsr->fwd_offloaded) + dev_set_promiscuity(port->dev, -1); ++ if (port->type == HSR_PT_SLAVE_A || port->type == HSR_PT_SLAVE_B) ++ vlan_vids_del_by_dev(port->dev, master->dev); + netdev_upper_dev_unlink(port->dev, master->dev); + } + +-- +2.53.0 + diff --git a/queue-6.6/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch b/queue-6.6/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch new file mode 100644 index 0000000000..43290d0956 --- /dev/null +++ b/queue-6.6/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch @@ -0,0 +1,48 @@ +From 3f1cd27c171207e730986db99cf52c2779bbbaf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 22:32:30 +0800 +Subject: net: ipv6: fix dif and sdif mismatch in raw6_icmp_error + +From: Li RongQing + +[ Upstream commit 440e274da4d1b93c7df2cb0ce893c3009dd4db55 ] + +In raw6_icmp_error(), raw_v6_match() is called with inet6_iif(skb) passed +to both the 'dif' and 'sdif' arguments. This is a copy-paste or typo error, +as the last argument should represent the secondary interface index (sdif). + +This mismatch breaks ICMPv6 error handling for IPv6 raw sockets in VRF +(Virtual Routing and Forwarding) environments. When a raw socket is bound +to a VRF master device, raw_v6_match() fails to find a match because it is +not given the correct sdif value, causing the socket to miss relevant +ICMPv6 error notifications. + +Fix this by properly passing inet6_sdif(skb) as the last argument to +raw_v6_match(). + +Fixes: 5108ab4bf446fa ("net: ipv6: add second dif to raw socket lookups") +Signed-off-by: Li RongQing +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260717143230.1836-1-lirongqing@baidu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/raw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 7d72633ea01982..95d7dd7a4d0483 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -341,7 +341,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data; + + if (!raw_v6_match(net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr, +- inet6_iif(skb), inet6_iif(skb))) ++ inet6_iif(skb), inet6_sdif(skb))) + continue; + rawv6_err(sk, skb, NULL, type, code, inner_offset, info); + } +-- +2.53.0 + diff --git a/queue-6.6/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch b/queue-6.6/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch new file mode 100644 index 0000000000..364314038c --- /dev/null +++ b/queue-6.6/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch @@ -0,0 +1,51 @@ +From 4edc45a8767943d32f29190e02ea5df7d0f8ebc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:33:06 +0300 +Subject: net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule + +From: Yael Chemla + +[ Upstream commit d12956d083eb70f2c6d72711aebaf8c2ce21e170 ] + +esw_egress_acl_vlan_create() hardcodes num_dest=0 in its +mlx5_add_flow_rules() call. When invoked from the non-bond path +fwd_dest is NULL and num_dest=0 is correct. When invoked from +esw_acl_egress_ofld_rules_create() during a bond event, fwd_dest is +non-NULL and flow_act.action carries MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, +but _mlx5_add_flow_rules() rejects a non-NULL dest pointer paired with +dest_num<=0 and returns -EINVAL. The error propagates as +"configure slave vport egress fwd, err(-22)". The passive vport's egress +ACL table ends up with its flow groups allocated but no FTEs, so +prio-tagged packets are not popped and bond failover is broken on +prio_tag_required devices. + +Fix by passing fwd_dest ? 1 : 0 as num_dest to match the actual number +of destinations supplied. + +Fixes: bf773dc0e6d5 ("net/mlx5: E-Switch, Introduce APIs to enable egress acl forward-to-vport rule") +Signed-off-by: Yael Chemla +Reviewed-by: Cosmin Ratiu +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20260717073306.1242399-1-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +index d599e50af346be..fc545bfb54de76 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +@@ -71,7 +71,7 @@ int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw, + flow_act.action = flow_action; + vport->egress.allowed_vlan = + mlx5_add_flow_rules(vport->egress.acl, spec, +- &flow_act, fwd_dest, 0); ++ &flow_act, fwd_dest, fwd_dest ? 1 : 0); + if (IS_ERR(vport->egress.allowed_vlan)) { + err = PTR_ERR(vport->egress.allowed_vlan); + esw_warn(esw->dev, +-- +2.53.0 + diff --git a/queue-6.6/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch b/queue-6.6/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch new file mode 100644 index 0000000000..93b1e2d3e8 --- /dev/null +++ b/queue-6.6/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch @@ -0,0 +1,46 @@ +From 6450aaefb85320b5592805c6fe94b8746a5c5897 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:25 +0300 +Subject: net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation + +From: Alexei Lazar + +[ Upstream commit 9173e1d3c7c7d49a71eee813091f9e834ec7cee5 ] + +Credit Based (CB) TSA is not supported by the mlx5 driver, so reject +any configurations that specify it. + +Fixes: 08fb1dacdd76 ("net/mlx5e: Support DCBNL IEEE ETS") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-3-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 0bc3ae071e8324..1a73fa436a1368 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -309,6 +309,14 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev, + } + } + ++ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { ++ if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_CB_SHAPER) { ++ netdev_err(netdev, ++ "Failed to validate ETS: CB Shaper is not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ + /* Validate Bandwidth Sum */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { +-- +2.53.0 + diff --git a/queue-6.6/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch b/queue-6.6/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch new file mode 100644 index 0000000000..94cb854e59 --- /dev/null +++ b/queue-6.6/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch @@ -0,0 +1,53 @@ +From c0ecb76edaed188cad6611336887234af2ef1ae7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:24 +0300 +Subject: net/mlx5e: Report zero bandwidth for non-ETS traffic classes + +From: Alexei Lazar + +[ Upstream commit ffb1873b2df11945b8c395e859169248675c91c5 ] + +The IEEE 802.1Qaz standard defines that bandwidth allocation percentages +only apply to Enhanced Transmission Selection (ETS) traffic classes. +For STRICT and VENDOR transmission selection algorithms, bandwidth +percentage values are not applicable. + +Currently for non-ETS 100 bandwidth is being reported for all traffic +classes in the get operation due to hardware limitation, regardless of +their TSA type. + +Fix this by reporting 0 for non-ETS traffic classes. + +Fixes: 820c2c5e773d ("net/mlx5e: Read ETS settings directly from firmware") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-2-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index e29a8ed7e7ac13..0bc3ae071e8324 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -158,6 +158,13 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, + } + memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa)); + ++ /* Report 0 for non ETS TSA */ ++ for (i = 0; i < ets->ets_cap; i++) { ++ if (ets->tc_tx_bw[i] == MLX5E_MAX_BW_ALLOC && ++ priv->dcbx.tc_tsa[i] != IEEE_8021QAZ_TSA_ETS) ++ ets->tc_tx_bw[i] = 0; ++ } ++ + return err; + } + +-- +2.53.0 + diff --git a/queue-6.6/net-packet-avoid-fanout-hook-re-registration-after-u.patch b/queue-6.6/net-packet-avoid-fanout-hook-re-registration-after-u.patch new file mode 100644 index 0000000000..8596e3b2e3 --- /dev/null +++ b/queue-6.6/net-packet-avoid-fanout-hook-re-registration-after-u.patch @@ -0,0 +1,61 @@ +From b8bd3187b46c208c933256baa8ec4383aedb0b8d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:44:37 +0000 +Subject: net/packet: avoid fanout hook re-registration after unregister + +From: David Lee + +[ Upstream commit 50aff80475abd3533eef4320477037e6fcc6b56e ] + +packet_set_ring() temporarily detaches a socket from packet delivery while +reconfiguring its ring. It records the previous running state, clears +po->num, unregisters the protocol hook when needed, drops po->bind_lock, +and later restores po->num and re-registers the hook from the saved +was_running value. + +That unlocked window can race with NETDEV_UNREGISTER. The notifier can +observe the socket as not running, skip __unregister_prot_hook(), and +invalidate the per-socket binding by setting po->ifindex to -1 and clearing +po->prot_hook.dev. A one-member fanout group can still retain its shared +fanout hook device pointer. When packet_set_ring() resumes, re-registering +solely from the stale was_running state can re-add the fanout hook after +the device has been unregistered. + +Treat po->ifindex == -1 as an invalidated binding after reacquiring +po->bind_lock. This is distinct from ifindex 0, the normal +unbound/wildcard state: ifindex -1 marks an existing device binding that +was invalidated when the device was unregistered. Restore po->num as +before, but do not re-register the hook if device unregister already +detached the socket. + +Fixes: dc99f600698d ("packet: Add fanout support.") +Link: https://lore.kernel.org/netdev/20260701113947.23180-1-david.lee@trailofbits.com/ +Signed-off-by: David Lee +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260707104440.833129-1-david.lee@trailofbits.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 1de0ef429f9310..d435a48bc0e3b7 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -4608,7 +4608,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + + spin_lock(&po->bind_lock); + WRITE_ONCE(po->num, num); +- if (was_running) ++ /* ++ * NETDEV_UNREGISTER may have invalidated the binding while bind_lock ++ * was dropped above. Do not re-add a fanout hook to a dead device. ++ */ ++ if (was_running && READ_ONCE(po->ifindex) != -1) + register_prot_hook(sk); + + spin_unlock(&po->bind_lock); +-- +2.53.0 + diff --git a/queue-6.6/net-qrtr-restrict-socket-creation-to-the-initial-net.patch b/queue-6.6/net-qrtr-restrict-socket-creation-to-the-initial-net.patch new file mode 100644 index 0000000000..2d9cd4619f --- /dev/null +++ b/queue-6.6/net-qrtr-restrict-socket-creation-to-the-initial-net.patch @@ -0,0 +1,63 @@ +From 5c28693e0c0cf24355e7a2f3ae7d948b13625bd3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 12:43:19 -0300 +Subject: net: qrtr: restrict socket creation to the initial network namespace + +From: Aldo Ariel Panzardo + +[ Upstream commit 3b536db8fb32da9e9c62f2bb45e2e319331f0426 ] + +QRTR keeps its entire port and node state in module-global variables +that are not partitioned per network namespace: qrtr_local_nid is a +single global node id (always 1) and qrtr_ports is a single global +xarray. qrtr_port_lookup() and qrtr_local_enqueue() operate on that +global state with no network-namespace check, and qrtr_create() places +no restriction on the namespace a socket is created in. + +As a result an unprivileged process that creates an AF_QIPCRTR socket +in a separate network namespace, e.g. via +unshare(CLONE_NEWUSER | CLONE_NEWNET), can send QRTR datagrams - +including control-plane messages such as QRTR_TYPE_NEW_SERVER - to QRTR +sockets owned by another namespace, and vice versa. The receiving +socket sees such a message as coming from node id 1, indistinguishable +from a legitimate local client, breaking the isolation that network +namespaces are expected to provide. + +QRTR is a transport to global hardware endpoints (the modem and other +remote processors) and has no per-namespace semantics; its in-kernel +name service already creates its socket in init_net only. Confine the +socket family to the initial network namespace, as other +non-namespace-aware socket families do (see llc_ui_create() and the +ieee802154 socket code). + +Fixes: bdabad3e363d ("net: Add Qualcomm IPC router") +Signed-off-by: Aldo Ariel Panzardo +Link: https://patch.msgid.link/20260716154319.3297699-1-qwe.aldo@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/qrtr/af_qrtr.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c +index 305523cebe3baa..fcd24a7df3f00d 100644 +--- a/net/qrtr/af_qrtr.c ++++ b/net/qrtr/af_qrtr.c +@@ -1261,6 +1261,14 @@ static int qrtr_create(struct net *net, struct socket *sock, + if (sock->type != SOCK_DGRAM) + return -EPROTOTYPE; + ++ /* QRTR keeps its port and node state in module-global variables that ++ * are not partitioned per network namespace, and the in-kernel name ++ * service only operates in init_net. Confine the family to init_net so ++ * a socket in another namespace cannot reach the global control plane. ++ */ ++ if (!net_eq(net, &init_net)) ++ return -EAFNOSUPPORT; ++ + sk = sk_alloc(net, AF_QIPCRTR, GFP_KERNEL, &qrtr_proto, kern); + if (!sk) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-6.6/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch b/queue-6.6/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch new file mode 100644 index 0000000000..e2fa6f7082 --- /dev/null +++ b/queue-6.6/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch @@ -0,0 +1,186 @@ +From 4f6f94a8fea949e2b17809251745124cfa0c529e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 10:49:11 +0300 +Subject: net: stmmac: enable the MAC on link up for all supported speeds + +From: vadik likholetov + +[ Upstream commit 9c99db3a2080b8c2cbbb1100369586a9bea43321 ] + +stmmac_mac_link_down() clears the MAC's transmit and receive enable bits. +stmmac_mac_link_up() is expected to set them again through +stmmac_mac_set(..., true), but it first switches on the negotiated speed +and returns early for a speed the switch does not list. The MAC is then +left gated off. + +The speed selection is split into three switches, keyed on the interface. +The generic branch -- taken for everything that is neither USXGMII nor +XLGMII, so including PHY_INTERFACE_MODE_10GBASER -- lists only SPEED_2500, +SPEED_1000, SPEED_100 and SPEED_10. + +MGBE on Tegra234 runs 10GBASE-R into an Aquantia AQR113C. That PHY does +rate matching, so phylink_link_up() replaces the media speed with the +MAC-side interface speed before calling into the MAC: + + case RATE_MATCH_PAUSE: + speed = phylink_interface_max_speed(link_state.interface); + duplex = DUPLEX_FULL; + +The driver is therefore called as + + stmmac_mac_link_up(interface=10GBASER, speed=10000, duplex=1) + +which falls through to "default: return;". The interface stops passing +traffic after the first link flap. + +The failure is easy to misread. The link still comes up, because the PHY +is polled over MDIO and needs no MAC, so the interface reports carrier 1 +at the media speed. The DMA is untouched, so its start bits stay set and +descriptors are still consumed. Only the MAC itself is gated off: the +receiver counts nothing (mmc_rx_framecount_gb stops advancing, RE is 0) +and nothing reaches the wire (TE is 0). The interface survives boot only +because stmmac_hw_setup(), called from ndo_open, enables the MAC +unconditionally -- so the problem appears only once the cable has been +unplugged and plugged back in, and "ip link set dev down && ip +link set dev up" appears to fix it. + +The interface is not what the speed bits depend on: with the single +exception of 2.5G, which is selected through the XGMII block on USXGMII +and through the regular speed bits otherwise, each speed maps to one +field of struct mac_link. The per-interface switches are speed +validation, and phylink already validates the speed against +priv->hw->link.caps. So collapse the three switches into one keyed on the +speed alone, keeping the interface test only for the 2.5G case. This +covers 10G on 10GBASE-R, and equally 5G, and 1G/100/10 on USXGMII, all of +which hit "default: return;" today. + +A core that does not support a speed leaves the corresponding mac_link +field at 0, and phylink will not offer it that speed in the first place. +For dwxgmac2 at 10G, link.xgmii.speed10000 is XGMAC_CONFIG_SS_10000, +which is 0 and is the correct speed selection for a 10GBASE-R MAC: ctrl +then equals old_ctrl, the register write is skipped, and execution +reaches stmmac_mac_set(..., true). + +Log an error in the default case, since a speed with no entry here leaves +the MAC disabled and the symptom does not point at the cause. + +Fixes: d8ca113724e7 ("net: stmmac: tegra: Add MGBE support") +Suggested-by: Maxime Chevallier +Signed-off-by: vadik likholetov +Reviewed-by: Jacob Keller +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260713074911.30090-1-vadikas@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 92 ++++++++----------- + 1 file changed, 37 insertions(+), 55 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index dea3d66619ce3c..2fc0a87534c72a 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1009,63 +1009,45 @@ static void stmmac_mac_link_up(struct phylink_config *config, + old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG); + ctrl = old_ctrl & ~priv->hw->link.speed_mask; + +- if (interface == PHY_INTERFACE_MODE_USXGMII) { +- switch (speed) { +- case SPEED_10000: +- ctrl |= priv->hw->link.xgmii.speed10000; +- break; +- case SPEED_5000: +- ctrl |= priv->hw->link.xgmii.speed5000; +- break; +- case SPEED_2500: ++ switch (speed) { ++ case SPEED_100000: ++ ctrl |= priv->hw->link.xlgmii.speed100000; ++ break; ++ case SPEED_50000: ++ ctrl |= priv->hw->link.xlgmii.speed50000; ++ break; ++ case SPEED_40000: ++ ctrl |= priv->hw->link.xlgmii.speed40000; ++ break; ++ case SPEED_25000: ++ ctrl |= priv->hw->link.xlgmii.speed25000; ++ break; ++ case SPEED_10000: ++ ctrl |= priv->hw->link.xgmii.speed10000; ++ break; ++ case SPEED_5000: ++ ctrl |= priv->hw->link.xgmii.speed5000; ++ break; ++ case SPEED_2500: ++ if (interface == PHY_INTERFACE_MODE_USXGMII) + ctrl |= priv->hw->link.xgmii.speed2500; +- break; +- default: +- return; +- } +- } else if (interface == PHY_INTERFACE_MODE_XLGMII) { +- switch (speed) { +- case SPEED_100000: +- ctrl |= priv->hw->link.xlgmii.speed100000; +- break; +- case SPEED_50000: +- ctrl |= priv->hw->link.xlgmii.speed50000; +- break; +- case SPEED_40000: +- ctrl |= priv->hw->link.xlgmii.speed40000; +- break; +- case SPEED_25000: +- ctrl |= priv->hw->link.xlgmii.speed25000; +- break; +- case SPEED_10000: +- ctrl |= priv->hw->link.xgmii.speed10000; +- break; +- case SPEED_2500: +- ctrl |= priv->hw->link.speed2500; +- break; +- case SPEED_1000: +- ctrl |= priv->hw->link.speed1000; +- break; +- default: +- return; +- } +- } else { +- switch (speed) { +- case SPEED_2500: ++ else + ctrl |= priv->hw->link.speed2500; +- break; +- case SPEED_1000: +- ctrl |= priv->hw->link.speed1000; +- break; +- case SPEED_100: +- ctrl |= priv->hw->link.speed100; +- break; +- case SPEED_10: +- ctrl |= priv->hw->link.speed10; +- break; +- default: +- return; +- } ++ break; ++ case SPEED_1000: ++ ctrl |= priv->hw->link.speed1000; ++ break; ++ case SPEED_100: ++ ctrl |= priv->hw->link.speed100; ++ break; ++ case SPEED_10: ++ ctrl |= priv->hw->link.speed10; ++ break; ++ default: ++ netdev_err(priv->dev, ++ "unsupported speed %s on %s, leaving the MAC disabled\n", ++ phy_speed_to_str(speed), phy_modes(interface)); ++ return; + } + + priv->speed = speed; +-- +2.53.0 + diff --git a/queue-6.6/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch b/queue-6.6/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch new file mode 100644 index 0000000000..0719627f4d --- /dev/null +++ b/queue-6.6/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch @@ -0,0 +1,103 @@ +From 21cc89f1a0831a817c005e513b228155d377b303 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:15 -0700 +Subject: net: stmmac: fix l3l4 filter rejecting unsupported offload requests + +From: Nazim Amirul + +[ Upstream commit 5536d7c843637e9430279b94935fcf7df98babb3 ] + +The basic flow parser in tc_add_basic_flow() does not validate match +keys before proceeding. Unsupported offload configurations such as +partial protocol masks, non-IPv4 network proto, or non-TCP/UDP transport +proto are silently accepted instead of returning -EOPNOTSUPP. + +Add validation to return -EOPNOTSUPP early for: +- No network or transport proto present in the key +- Partial protocol mask (only full mask supported) +- Network proto is not IPv4 +- Transport proto is not TCP or UDP + +Each rejection includes an extack message so the user knows which part +of the match is unsupported. + +Also propagate -EOPNOTSUPP from tc_add_basic_flow() in tc_add_flow() +by returning it directly rather than using break. The break was silently +discarding the error for FLOW_CLS_REPLACE operations where entry->in_use +is already true, causing tc_add_flow() to return 0 (success) for +unsupported replace requests. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-4-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 34 +++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 97ff2dd8f2aecd..8eef993c47e968 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -456,6 +456,7 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv, + } + + #define ETHER_TYPE_FULL_MASK cpu_to_be16(~0) ++#define IP_PROTO_FULL_MASK 0xFF + + static int tc_add_basic_flow(struct stmmac_priv *priv, + struct flow_cls_offload *cls, +@@ -471,6 +472,37 @@ static int tc_add_basic_flow(struct stmmac_priv *priv, + + flow_rule_match_basic(rule, &match); + ++ /* Both network proto and transport proto not present in the key */ ++ if (!match.mask || !(match.mask->n_proto || match.mask->ip_proto)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "filter must specify network or transport protocol"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* If the proto is present in the key and is not full mask */ ++ if ((match.mask->n_proto && match.mask->n_proto != ETHER_TYPE_FULL_MASK) || ++ (match.mask->ip_proto && match.mask->ip_proto != IP_PROTO_FULL_MASK)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only full protocol mask is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Network proto is present in the key and is not IPv4 */ ++ if (match.mask->n_proto && match.key->n_proto != cpu_to_be16(ETH_P_IP)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only IPv4 network protocol is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Transport proto is present in the key and is not TCP or UDP */ ++ if (match.mask->ip_proto && ++ match.key->ip_proto != IPPROTO_TCP && ++ match.key->ip_proto != IPPROTO_UDP) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only TCP and UDP transport protocols are supported"); ++ return -EOPNOTSUPP; ++ } ++ + entry->ip_proto = match.key->ip_proto; + return 0; + } +@@ -608,6 +640,8 @@ static int tc_add_flow(struct stmmac_priv *priv, + ret = tc_flow_parsers[i].fn(priv, cls, entry); + if (!ret) + entry->in_use = true; ++ else if (ret == -EOPNOTSUPP) ++ return ret; + } + + if (!entry->in_use) +-- +2.53.0 + diff --git a/queue-6.6/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch b/queue-6.6/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch new file mode 100644 index 0000000000..7e324298aa --- /dev/null +++ b/queue-6.6/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch @@ -0,0 +1,43 @@ +From 23e1d4d74e0f61cad935378c25eeea2ab00ad4ad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:16 -0700 +Subject: net: stmmac: reset residual action in L3L4 filters on delete + +From: Nazim Amirul + +[ Upstream commit a448f821289934b961dd9d8d0beb006cc8937ba2 ] + +When deleting an L3/L4 flower filter entry, the action field is not +reset. If a filter was previously configured with a drop action, that +action may persist and affect subsequent filter configurations +unintentionally. + +Clear the action field when the filter entry is deleted. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-5-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 8eef993c47e968..9b58a91cce7e4d 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -671,6 +671,7 @@ static int tc_del_flow(struct stmmac_priv *priv, + entry->in_use = false; + entry->cookie = 0; + entry->is_l4 = false; ++ entry->action = 0; + return ret; + } + +-- +2.53.0 + diff --git a/queue-6.6/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch b/queue-6.6/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch new file mode 100644 index 0000000000..7801868ecb --- /dev/null +++ b/queue-6.6/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch @@ -0,0 +1,59 @@ +From 3583569b3980a424bbb4ec3414dca1f494aa128c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 22:15:51 +0000 +Subject: nexthop: initialize extack in nh_res_bucket_migrate() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 6347c5314cee49f364aaf2e40ff15415a57a116e ] + +nh_res_bucket_migrate() passes an uninitialized netlink_ext_ack to +call_nexthop_res_bucket_notifiers(). When +nh_notifier_res_bucket_info_init() fails (e.g. the kzalloc returns +-ENOMEM), the error is propagated back before any notifier sets +extack._msg, and the error path formats the stale pointer with +pr_err_ratelimited("%s\n", extack._msg). With CONFIG_INIT_STACK_NONE +this dereferences uninitialized stack memory: + + Oops: general protection fault, probably for non-canonical address ... + KASAN: maybe wild-memory-access in range [...] + RIP: 0010:string (lib/vsprintf.c:730) + vsnprintf (lib/vsprintf.c:2945) + _printk (kernel/printk/printk.c:2504) + nh_res_bucket_migrate (net/ipv4/nexthop.c:1816) + nh_res_table_upkeep (net/ipv4/nexthop.c:1866) + rtm_new_nexthop (net/ipv4/nexthop.c:3323) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7076) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + Kernel panic - not syncing: Fatal exception + +Zero-initialize extack so _msg is NULL on error paths that never set it. + +Fixes: 7c37c7e00411 ("nexthop: Implement notifiers for resilient nexthop groups") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260713221551.3344650-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/nexthop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c +index 4f30ddd2016b68..e751464f4fad9e 100644 +--- a/net/ipv4/nexthop.c ++++ b/net/ipv4/nexthop.c +@@ -1527,8 +1527,8 @@ static bool nh_res_bucket_migrate(struct nh_res_table *res_table, + bool notify_nl, bool force) + { + struct nh_res_bucket *bucket = &res_table->nh_buckets[bucket_index]; ++ struct netlink_ext_ack extack = {}; + struct nh_grp_entry *new_nhge; +- struct netlink_ext_ack extack; + int err; + + new_nhge = list_first_entry_or_null(&res_table->uw_nh_entries, +-- +2.53.0 + diff --git a/queue-6.6/nfp-check-resource-mutex-allocation.patch b/queue-6.6/nfp-check-resource-mutex-allocation.patch new file mode 100644 index 0000000000..37a4c78a2d --- /dev/null +++ b/queue-6.6/nfp-check-resource-mutex-allocation.patch @@ -0,0 +1,52 @@ +From ed63ab85180ccae75b7a2bd1ab515b2b77775787 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:08 +0800 +Subject: nfp: Check resource mutex allocation + +From: Ruoyu Wang + +[ Upstream commit a61b4db34a753bdf5c9e77a7f3d3dddd41dcfacc ] + +nfp_cpp_resource_find() allocates a CPP mutex handle for the matching +resource-table entry and then reports success. nfp_resource_try_acquire() +immediately passes that handle to nfp_cpp_mutex_trylock(). + +However, nfp_cpp_mutex_alloc() returns NULL on failure. If that happens +for a matching table entry, the resource lookup still returns success and +the following trylock dereferences a NULL mutex pointer while opening the +resource. + +nfp_resource_acquire() already treats failure to allocate the table mutex +as -ENOMEM. Do the same for the resource mutex and fail the lookup before +publishing the rest of the resource handle. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: f01a2161577d ("nfp: add support for resources") +Signed-off-by: Ruoyu Wang +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708143408.3168425-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +index ce7492a6a98fad..908d99f398b819 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c ++++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +@@ -96,6 +96,9 @@ static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res) + res->mutex = + nfp_cpp_mutex_alloc(cpp, + NFP_RESOURCE_TBL_TARGET, addr, key); ++ if (!res->mutex) ++ return -ENOMEM; ++ + res->cpp_id = NFP_CPP_ID(entry.region.cpp_target, + entry.region.cpp_action, + entry.region.cpp_token); +-- +2.53.0 + diff --git a/queue-6.6/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch b/queue-6.6/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch new file mode 100644 index 0000000000..25f8d144ba --- /dev/null +++ b/queue-6.6/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch @@ -0,0 +1,40 @@ +From df7b1b2d4f0e43bc616256d8087422d975431bb3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 10:50:07 +0530 +Subject: octeontx2-vf: set TC flower flag on MCAM entry allocation + +From: Suman Ghosh + +[ Upstream commit 0d4d31e3cc5dd6204fa1495c4107f5075acce5ed ] + +When MCAM entries are allocated for a VF netdev via the devlink +mcam_count parameter, only OTX2_FLAG_NTUPLE_SUPPORT was set. That +enabled ethtool ntuple filters but not tc flower offload. Also set +OTX2_FLAG_TC_FLOWER_SUPPORT when entries are successfully allocated. + +Fixes: 2da489432747 ("octeontx2-pf: devlink params support to set mcam entry count") +Signed-off-by: Suman Ghosh +Signed-off-by: Ratheesh Kannoth +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260715052007.2099851-1-rkannoth@marvell.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +index e6082f90f57a50..99e2391ef947a2 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +@@ -153,6 +153,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count) + if (allocated) { + pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC; + pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT; ++ pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT; + } + + if (allocated != count) +-- +2.53.0 + diff --git a/queue-6.6/pds_core-check-for-workqueue-allocation-failure.patch b/queue-6.6/pds_core-check-for-workqueue-allocation-failure.patch new file mode 100644 index 0000000000..18d74f3ec7 --- /dev/null +++ b/queue-6.6/pds_core-check-for-workqueue-allocation-failure.patch @@ -0,0 +1,71 @@ +From 7e897b13ca2dde415dcfe095dd0d07a05e168beb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:27:13 +0000 +Subject: pds_core: check for workqueue allocation failure + +From: Nikhil P. Rao + +[ Upstream commit 3a660ca49e2c3807bffe0519db3cff677a5906e0 ] + +pdsc_init_pf() does not check whether create_singlethread_workqueue() +succeeded. + +Fail probe on failure. The workqueue is set up before the timer and +mutexes, so its failure path must unwind only the earlier setup. + +Fixes: c2dbb0904310 ("pds_core: health timer and workqueue") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Brett Creeley +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714212713.1788438-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/main.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c +index 76652e0e5b6d9c..93fa7dfd74cbc9 100644 +--- a/drivers/net/ethernet/amd/pds_core/main.c ++++ b/drivers/net/ethernet/amd/pds_core/main.c +@@ -238,6 +238,10 @@ static int pdsc_init_pf(struct pdsc *pdsc) + /* General workqueue and timer, but don't start timer yet */ + snprintf(wq_name, sizeof(wq_name), "%s.%d", PDS_CORE_DRV_NAME, pdsc->uid); + pdsc->wq = create_singlethread_workqueue(wq_name); ++ if (!pdsc->wq) { ++ err = -ENOMEM; ++ goto err_out_unmap_bars; ++ } + INIT_WORK(&pdsc->health_work, pdsc_health_thread); + timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0); + pdsc->wdtimer_period = PDSC_WATCHDOG_SECS * HZ; +@@ -252,7 +256,7 @@ static int pdsc_init_pf(struct pdsc *pdsc) + err = pdsc_setup(pdsc, PDSC_SETUP_INIT); + if (err) { + mutex_unlock(&pdsc->config_lock); +- goto err_out_unmap_bars; ++ goto err_out_shutdown_timer; + } + + err = pdsc_start(pdsc); +@@ -298,13 +302,14 @@ static int pdsc_init_pf(struct pdsc *pdsc) + pdsc_stop(pdsc); + err_out_teardown: + pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING); +-err_out_unmap_bars: ++err_out_shutdown_timer: + timer_shutdown_sync(&pdsc->wdtimer); + if (pdsc->wq) + destroy_workqueue(pdsc->wq); + mutex_destroy(&pdsc->config_lock); + mutex_destroy(&pdsc->devcmd_lock); + pci_free_irq_vectors(pdsc->pdev); ++err_out_unmap_bars: + pdsc_unmap_bars(pdsc); + err_out_release_regions: + pci_release_regions(pdsc->pdev); +-- +2.53.0 + diff --git a/queue-6.6/pds_core-fix-auxiliary-device-add-del-races.patch b/queue-6.6/pds_core-fix-auxiliary-device-add-del-races.patch new file mode 100644 index 0000000000..5ba33a177a --- /dev/null +++ b/queue-6.6/pds_core-fix-auxiliary-device-add-del-races.patch @@ -0,0 +1,80 @@ +From fb6cbbd8746368174c35dcb86b8afdf38beffbcf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:07:45 +0000 +Subject: pds_core: fix auxiliary device add/del races + +From: Nikhil P. Rao + +[ Upstream commit bfa33cd513c7ceb93c5a4c30e5662acd73c0a916 ] + +Two paths add or delete the same slot (pf->vfs[vf_id].padev): a VF's +pdsc_reset_done() and the PF's devlink enable_vnet/disable_vnet handler. +They serialize on config_lock, but neither guards the slot under it +correctly. + +add() registers and stores a new auxiliary device without first checking +the slot, so a second add of an already-populated slot leaks the first +device. del() makes that check outside config_lock, so two concurrent +dels can both pass it; the first clears the slot, and the second +dereferences a NULL pointer. + +Check and update the slot under config_lock in both paths. + +Fixes: b699bdc720c0 ("pds_core: specify auxiliary_device to be created") +Reported-by: sashiko-bot@kernel.org # Running on a local machine +Signed-off-by: Nikhil P. Rao +Reviewed-by: Brett Creeley +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714210745.1785625-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/auxbus.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c +index 889a18962270aa..7d7c87fe9e8f27 100644 +--- a/drivers/net/ethernet/amd/pds_core/auxbus.c ++++ b/drivers/net/ethernet/amd/pds_core/auxbus.c +@@ -177,17 +177,21 @@ void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf, + { + struct pds_auxiliary_dev *padev; + +- if (!*pd_ptr) +- return; +- + mutex_lock(&pf->config_lock); + ++ /* A concurrent del may have already torn this device down and ++ * cleared it. ++ */ + padev = *pd_ptr; ++ if (!padev) ++ goto out_unlock; ++ + pds_client_unregister(pf, padev->client_id); + auxiliary_device_delete(&padev->aux_dev); + auxiliary_device_uninit(&padev->aux_dev); + *pd_ptr = NULL; + ++out_unlock: + mutex_unlock(&pf->config_lock); + } + +@@ -210,6 +214,13 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf, + + mutex_lock(&pf->config_lock); + ++ /* Nothing to do if the aux device is already present. This also ++ * guards against a second add overwriting *pd_ptr and leaking the ++ * first, symmetric with the check in pdsc_auxbus_dev_del(). ++ */ ++ if (*pd_ptr) ++ goto out_unlock; ++ + mask = BIT_ULL(PDSC_S_FW_DEAD) | + BIT_ULL(PDSC_S_STOPPING_DRIVER); + if (cf->state & mask) { +-- +2.53.0 + diff --git a/queue-6.6/pds_core-order-completion-reads-after-the-ownership-.patch b/queue-6.6/pds_core-order-completion-reads-after-the-ownership-.patch new file mode 100644 index 0000000000..d22b77637f --- /dev/null +++ b/queue-6.6/pds_core-order-completion-reads-after-the-ownership-.patch @@ -0,0 +1,62 @@ +From d435025f4652d7ba32d1c0dc769e7f96d484ceff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 20:41:45 +0000 +Subject: pds_core: order completion reads after the ownership check + +From: Nikhil P. Rao + +[ Upstream commit dd6b1cc748cd28147c113f9daa76393916ad9494 ] + +pdsc_process_adminq() and pdsc_process_notifyq() decide a completion is +valid from its ownership field - the color bit for the adminq, the event +id for the notifyq - then read the rest of the descriptor, with no +barrier in between. + +On a weakly ordered architecture the CPU may read the payload first. Add +dma_rmb() between the ownership read and the payload reads. + +Fixes: 7e82a8745b95 ("pds_core: Prevent race issues involving the adminq") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Eric Joyner +Link: https://patch.msgid.link/20260714204145.1782390-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/adminq.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/adminq.c b/drivers/net/ethernet/amd/pds_core/adminq.c +index 733f133d69e75f..b363d006e044ea 100644 +--- a/drivers/net/ethernet/amd/pds_core/adminq.c ++++ b/drivers/net/ethernet/amd/pds_core/adminq.c +@@ -18,7 +18,13 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq) + comp = cq_info->comp; + eid = le64_to_cpu(comp->event.eid); + while (eid > pdsc->last_eid) { +- u16 ecode = le16_to_cpu(comp->event.ecode); ++ u16 ecode; ++ ++ /* Order the payload read after the event id, the field the ++ * driver uses to detect a new completion. ++ */ ++ dma_rmb(); ++ ecode = le16_to_cpu(comp->event.ecode); + + switch (ecode) { + case PDS_EVENT_LINK_CHANGE: +@@ -102,6 +108,10 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq) + spin_lock_irqsave(&pdsc->adminq_lock, irqflags); + comp = cq->info[cq->tail_idx].comp; + while (pdsc_color_match(comp->color, cq->done_color)) { ++ /* Order the payload reads after the color bit, the field the ++ * driver uses to detect a new completion. ++ */ ++ dma_rmb(); + q_info = &q->info[q->tail_idx]; + q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1); + +-- +2.53.0 + diff --git a/queue-6.6/pds_core-reject-component-parameter-in-legacy-firmwa.patch b/queue-6.6/pds_core-reject-component-parameter-in-legacy-firmwa.patch new file mode 100644 index 0000000000..1100357ca9 --- /dev/null +++ b/queue-6.6/pds_core-reject-component-parameter-in-legacy-firmwa.patch @@ -0,0 +1,44 @@ +From 730bb5b20b85dd05e0f9ca06455288beec290a3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:36:49 +0000 +Subject: pds_core: reject component parameter in legacy firmware update + +From: Nikhil P. Rao + +[ Upstream commit 7be2552e601c247a328a5aba6fc06ac844b94a16 ] + +The legacy firmware update path does not support per-component updates. +If a user specifies a component parameter with devlink flash, reject +the request with -EOPNOTSUPP rather than silently ignoring the component +parameter and flashing the entire firmware image. + +Fixes: 49ce92fbee0b ("pds_core: add FW update feature to devlink") +Signed-off-by: Nikhil P. Rao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708163649.128620-1-nikhil.rao@amd.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/devlink.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c +index 3144bad75a4df5..9939296145b522 100644 +--- a/drivers/net/ethernet/amd/pds_core/devlink.c ++++ b/drivers/net/ethernet/amd/pds_core/devlink.c +@@ -88,6 +88,12 @@ int pdsc_dl_flash_update(struct devlink *dl, + { + struct pdsc *pdsc = devlink_priv(dl); + ++ if (params->component) { ++ NL_SET_ERR_MSG_MOD(extack, ++ "Component update not supported by this device"); ++ return -EOPNOTSUPP; ++ } ++ + return pdsc_firmware_update(pdsc, params->fw, extack); + } + +-- +2.53.0 + diff --git a/queue-6.6/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch b/queue-6.6/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch new file mode 100644 index 0000000000..92e94604d2 --- /dev/null +++ b/queue-6.6/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch @@ -0,0 +1,53 @@ +From 074f0e98fb60e4f58b0c8dd9c4b904d783edc7ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 20:14:56 +0000 +Subject: pds_core: yield the CPU while waiting for the adminq to drain + +From: Nikhil P. Rao + +[ Upstream commit a11f0b8a204296fe7db9eaec53441012222cb004 ] + +pdsc_adminq_wait_and_dec_once_unused() busy-waits for adminq_refcnt to +drop to one: + + while (!refcount_dec_if_one(&pdsc->adminq_refcnt)) + cpu_relax(); + +The refcount is held by pdsc_adminq_post() for the duration of an +in-flight command, which can wait up to devcmd_timeout seconds +(PDS_CORE_DEVCMD_TIMEOUT is 5) for the hardware to complete. cpu_relax() +is not a reschedule point, so on a non-preemptible kernel this loop can +spin on the CPU for several seconds, starving other tasks on that core. + +Add cond_resched() to the loop so the waiter yields to other runnable +tasks while it polls, keeping cpu_relax() as the busy-wait hint between +checks. + +Fixes: 7e82a8745b95 ("pds_core: Prevent race issues involving the adminq") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Eric Joyner +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714201456.1776153-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c +index c2ef55cff6b3ec..cd0c698983debe 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.c ++++ b/drivers/net/ethernet/amd/pds_core/core.c +@@ -526,6 +526,7 @@ static void pdsc_adminq_wait_and_dec_once_unused(struct pdsc *pdsc) + dev_dbg_ratelimited(pdsc->dev, "%s: adminq in use\n", + __func__); + cpu_relax(); ++ cond_resched(); + } + } + +-- +2.53.0 + diff --git a/queue-6.6/ppp-annotate-data-races-in-ppp_generic.patch b/queue-6.6/ppp-annotate-data-races-in-ppp_generic.patch new file mode 100644 index 0000000000..c0cfc71537 --- /dev/null +++ b/queue-6.6/ppp-annotate-data-races-in-ppp_generic.patch @@ -0,0 +1,233 @@ +From d237ee460a5bed4b2d878af127208bd3cfe6e6b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:16:05 +0000 +Subject: ppp: annotate data races in ppp_generic + +From: Eric Dumazet + +[ Upstream commit 543adf072165aaf2e3b635c0476204f9658ed3bf ] + +Several fields in struct ppp can be read or updated concurrently +from multiple CPUs without synchronization, causing data races: + +1. ppp->mru is read concurrently in ppp_receive_nonmp_frame() while + being updated via PPPIOCSMRU ioctl. Protect ppp->mru updates in + PPPIOCSMRU with ppp_recv_lock(ppp). + +2. PPPIOCGFLAGS reads ppp->flags, ppp->xstate, and ppp->rstate + unlocked. Wrap the read in ppp_lock(ppp) to get a consistent + snapshot. + +3. ppp->debug is updated via PPPIOCSDEBUG and read concurrently on + fast paths. Annotate reads with READ_ONCE() and writes with + WRITE_ONCE(). + +4. ppp->last_xmit and ppp->last_recv are updated on TX/RX data paths + and read via PPPIOCGIDLE32 / PPPIOCGIDLE64 ioctls. Annotate with + WRITE_ONCE() / READ_ONCE() and use max() to handle jiffies + subtraction. + +5. ppp->npmode[] is updated via PPPIOCSNPMODE and read on TX/RX + paths. Annotate with WRITE_ONCE() / READ_ONCE(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/20260722101605.2868548-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 50 ++++++++++++++++++++--------------- + 1 file changed, 28 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index fe4a8bca0c2e8d..3c42f131e89f26 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -811,7 +811,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case PPPIOCSMRU: + if (get_user(val, p)) + break; ++ ppp_recv_lock(ppp); + ppp->mru = val; ++ ppp_recv_unlock(ppp); + err = 0; + break; + +@@ -832,7 +834,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + + case PPPIOCGFLAGS: ++ ppp_lock(ppp); + val = ppp->flags | ppp->xstate | ppp->rstate; ++ ppp_unlock(ppp); + if (put_user(val, p)) + break; + err = 0; +@@ -856,7 +860,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case PPPIOCSDEBUG: + if (get_user(val, p)) + break; +- ppp->debug = val; ++ WRITE_ONCE(ppp->debug, val); + err = 0; + break; + +@@ -867,16 +871,16 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + + case PPPIOCGIDLE32: +- idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ; +- idle32.recv_idle = (jiffies - ppp->last_recv) / HZ; +- if (copy_to_user(argp, &idle32, sizeof(idle32))) ++ idle32.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ; ++ idle32.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ; ++ if (copy_to_user(argp, &idle32, sizeof(idle32))) + break; + err = 0; + break; + + case PPPIOCGIDLE64: +- idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ; +- idle64.recv_idle = (jiffies - ppp->last_recv) / HZ; ++ idle64.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ; ++ idle64.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ; + if (copy_to_user(argp, &idle64, sizeof(idle64))) + break; + err = 0; +@@ -917,7 +921,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + if (copy_to_user(argp, &npi, sizeof(npi))) + break; + } else { +- ppp->npmode[i] = npi.mode; ++ WRITE_ONCE(ppp->npmode[i], npi.mode); + /* we may be able to transmit more packets now (??) */ + netif_wake_queue(ppp->dev); + } +@@ -1454,7 +1458,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) + goto outf; + + /* Drop, accept or reject the packet */ +- switch (ppp->npmode[npi]) { ++ switch (READ_ONCE(ppp->npmode[npi])) { + case NPMODE_PASS: + break; + case NPMODE_QUEUE: +@@ -1769,7 +1773,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_OUTBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: outbound frame " + "not passed\n"); +@@ -1779,11 +1783,11 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + /* if this packet passes the active filter, record the time */ + if (!(ppp->active_filter && + bpf_prog_run(ppp->active_filter, skb) == 0)) +- ppp->last_xmit = jiffies; ++ WRITE_ONCE(ppp->last_xmit, jiffies); + skb_pull(skb, 2); + #else + /* for data packets, record the time */ +- ppp->last_xmit = jiffies; ++ WRITE_ONCE(ppp->last_xmit, jiffies); + #endif /* CONFIG_PPP_FILTER */ + } + +@@ -2159,7 +2163,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + noskb: + spin_unlock(&pch->downl); + err_linearize: +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); + ++ppp->dev->stats.tx_errors; + ++ppp->nxseq; +@@ -2505,7 +2509,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: inbound frame " + "not passed\n"); +@@ -2514,14 +2518,14 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + } + if (!(ppp->active_filter && + bpf_prog_run(ppp->active_filter, skb) == 0)) +- ppp->last_recv = jiffies; ++ WRITE_ONCE(ppp->last_recv, jiffies); + __skb_pull(skb, 2); + } else + #endif /* CONFIG_PPP_FILTER */ +- ppp->last_recv = jiffies; ++ WRITE_ONCE(ppp->last_recv, jiffies); + + if ((ppp->dev->flags & IFF_UP) == 0 || +- ppp->npmode[npi] != NPMODE_PASS) { ++ READ_ONCE(ppp->npmode[npi]) != NPMODE_PASS) { + kfree_skb(skb); + } else { + /* chop off protocol */ +@@ -2774,7 +2778,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + seq = seq_before(minseq, PPP_MP_CB(p)->sequence)? + minseq + 1: PPP_MP_CB(p)->sequence; + +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "lost frag %u..%u\n", + oldseq, seq-1); +@@ -2823,7 +2827,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + struct sk_buff *tmp2; + + skb_queue_reverse_walk_from_safe(list, p, tmp2) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "discarding frag %u\n", + PPP_MP_CB(p)->sequence); +@@ -2845,7 +2849,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + skb_queue_walk_safe(list, p, tmp) { + if (p == head) + break; +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "discarding frag %u\n", + PPP_MP_CB(p)->sequence); +@@ -2853,7 +2857,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + kfree_skb(p); + } + +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + " missed pkts %u..%u\n", + ppp->nextseq, +@@ -3163,7 +3167,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) + if (!ppp->rc_state) + break; + if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len, +- ppp->file.index, 0, ppp->mru, ppp->debug)) { ++ ppp->file.index, 0, ppp->mru, ++ READ_ONCE(ppp->debug))) { + ppp->rstate |= SC_DECOMP_RUN; + ppp->rstate &= ~(SC_DC_ERROR | SC_DC_FERROR); + } +@@ -3172,7 +3177,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) + if (!ppp->xc_state) + break; + if (ppp->xcomp->comp_init(ppp->xc_state, dp, len, +- ppp->file.index, 0, ppp->debug)) ++ ppp->file.index, 0, ++ READ_ONCE(ppp->debug))) + ppp->xstate |= SC_COMP_RUN; + } + break; +-- +2.53.0 + diff --git a/queue-6.6/ppp-convert-to-percpu-netstats.patch b/queue-6.6/ppp-convert-to-percpu-netstats.patch new file mode 100644 index 0000000000..7f445d5b66 --- /dev/null +++ b/queue-6.6/ppp-convert-to-percpu-netstats.patch @@ -0,0 +1,137 @@ +From 820f85928f4f97563bfa5dbce6432cb069762277 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 10 Jun 2025 16:32:10 +0800 +Subject: ppp: convert to percpu netstats + +From: Qingfang Deng + +[ Upstream commit 1a3e9b7a6b09e8ab3d2af019e4a392622685855e ] + +Convert to percpu netstats to avoid lock contention when reading them. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20250610083211.909015-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 52 +++++++++++++---------------------- + 1 file changed, 19 insertions(+), 33 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 62169a38b984a2..065a99c9d6b3e2 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -107,18 +107,6 @@ struct ppp_file { + #define PF_TO_PPP(pf) PF_TO_X(pf, struct ppp) + #define PF_TO_CHANNEL(pf) PF_TO_X(pf, struct channel) + +-/* +- * Data structure to hold primary network stats for which +- * we want to use 64 bit storage. Other network stats +- * are stored in dev->stats of the ppp strucute. +- */ +-struct ppp_link_stats { +- u64 rx_packets; +- u64 tx_packets; +- u64 rx_bytes; +- u64 tx_bytes; +-}; +- + /* + * Data structure describing one ppp unit. + * A ppp unit corresponds to a ppp network interface device +@@ -162,7 +150,6 @@ struct ppp { + struct bpf_prog *active_filter; /* filter for pkts to reset idle */ + #endif /* CONFIG_PPP_FILTER */ + struct net *ppp_net; /* the net we belong to */ +- struct ppp_link_stats stats64; /* 64 bit network stats */ + }; + + /* +@@ -1545,23 +1532,12 @@ ppp_net_siocdevprivate(struct net_device *dev, struct ifreq *ifr, + static void + ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) + { +- struct ppp *ppp = netdev_priv(dev); +- +- ppp_recv_lock(ppp); +- stats64->rx_packets = ppp->stats64.rx_packets; +- stats64->rx_bytes = ppp->stats64.rx_bytes; +- ppp_recv_unlock(ppp); +- +- ppp_xmit_lock(ppp); +- stats64->tx_packets = ppp->stats64.tx_packets; +- stats64->tx_bytes = ppp->stats64.tx_bytes; +- ppp_xmit_unlock(ppp); +- + stats64->rx_errors = dev->stats.rx_errors; + stats64->tx_errors = dev->stats.tx_errors; + stats64->rx_dropped = dev->stats.rx_dropped; + stats64->tx_dropped = dev->stats.tx_dropped; + stats64->rx_length_errors = dev->stats.rx_length_errors; ++ dev_fetch_sw_netstats(stats64, dev->tstats); + } + + static int ppp_dev_init(struct net_device *dev) +@@ -1659,6 +1635,7 @@ static void ppp_setup(struct net_device *dev) + dev->type = ARPHRD_PPP; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->priv_destructor = ppp_dev_priv_destructor; ++ dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; + netif_keep_dst(dev); + } + +@@ -1804,8 +1781,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + #endif /* CONFIG_PPP_FILTER */ + } + +- ++ppp->stats64.tx_packets; +- ppp->stats64.tx_bytes += skb->len - PPP_PROTO_LEN; ++ dev_sw_netstats_tx_add(ppp->dev, 1, skb->len - PPP_PROTO_LEN); + + switch (proto) { + case PPP_IP: +@@ -2483,8 +2459,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + break; + } + +- ++ppp->stats64.rx_packets; +- ppp->stats64.rx_bytes += skb->len - 2; ++ dev_sw_netstats_rx_add(ppp->dev, skb->len - PPP_PROTO_LEN); + + npi = proto_to_npindex(proto); + if (npi < 0) { +@@ -3312,14 +3287,25 @@ static void + ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) + { + struct slcompress *vj = ppp->vj; ++ int cpu; + + memset(st, 0, sizeof(*st)); +- st->p.ppp_ipackets = ppp->stats64.rx_packets; ++ for_each_possible_cpu(cpu) { ++ struct pcpu_sw_netstats *p = per_cpu_ptr(ppp->dev->tstats, cpu); ++ u64 rx_packets, rx_bytes, tx_packets, tx_bytes; ++ ++ rx_packets = u64_stats_read(&p->rx_packets); ++ rx_bytes = u64_stats_read(&p->rx_bytes); ++ tx_packets = u64_stats_read(&p->tx_packets); ++ tx_bytes = u64_stats_read(&p->tx_bytes); ++ ++ st->p.ppp_ipackets += rx_packets; ++ st->p.ppp_ibytes += rx_bytes; ++ st->p.ppp_opackets += tx_packets; ++ st->p.ppp_obytes += tx_bytes; ++ } + st->p.ppp_ierrors = ppp->dev->stats.rx_errors; +- st->p.ppp_ibytes = ppp->stats64.rx_bytes; +- st->p.ppp_opackets = ppp->stats64.tx_packets; + st->p.ppp_oerrors = ppp->dev->stats.tx_errors; +- st->p.ppp_obytes = ppp->stats64.tx_bytes; + if (!vj) + return; + st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; +-- +2.53.0 + diff --git a/queue-6.6/ppp-enable-tx-scatter-gather.patch b/queue-6.6/ppp-enable-tx-scatter-gather.patch new file mode 100644 index 0000000000..4de12ac2f9 --- /dev/null +++ b/queue-6.6/ppp-enable-tx-scatter-gather.patch @@ -0,0 +1,115 @@ +From fb6d1ee74f1475e14883d1ffaf5e284ed4d88719 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 29 Jan 2026 09:29:02 +0800 +Subject: ppp: enable TX scatter-gather + +From: Qingfang Deng + +[ Upstream commit 42fcb213e58a7da33d5d2d7517b4e521025c68c3 ] + +PPP channels using chan->direct_xmit prepend the PPP header to a skb and +call dev_queue_xmit() directly. In this mode the skb does not need to be +linear, but the PPP netdevice currently does not advertise +scatter-gather features, causing unnecessary linearization and +preventing GSO. + +Enable NETIF_F_SG and NETIF_F_FRAGLIST on PPP devices. In case a linear +buffer is required (PPP compression, multilink, and channels without +direct_xmit), call skb_linearize() explicitly. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20260129012902.941-1-dqfext@gmail.com +Signed-off-by: Paolo Abeni +Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 30 +++++++++++++++++++++++++----- + 1 file changed, 25 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 065a99c9d6b3e2..fe4a8bca0c2e8d 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1636,6 +1636,8 @@ static void ppp_setup(struct net_device *dev) + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->priv_destructor = ppp_dev_priv_destructor; + dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; ++ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST; ++ dev->hw_features = dev->features; + netif_keep_dst(dev); + } + +@@ -1700,6 +1702,10 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb) + ppp->xcomp->comp_extra + ppp->dev->hard_header_len; + int compressor_skb_size = ppp->dev->mtu + + ppp->xcomp->comp_extra + PPP_HDRLEN; ++ ++ if (skb_linearize(skb)) ++ return NULL; ++ + new_skb = alloc_skb(new_skb_size, GFP_ATOMIC); + if (!new_skb) { + if (net_ratelimit()) +@@ -1787,6 +1793,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) + case PPP_IP: + if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0) + break; ++ ++ if (skb_linearize(skb)) ++ goto drop; ++ + /* try to do VJ TCP header compression */ + new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2, + GFP_ATOMIC); +@@ -1884,19 +1894,26 @@ ppp_push(struct ppp *ppp) + } + + if ((ppp->flags & SC_MULTILINK) == 0) { ++ struct ppp_channel *chan; + /* not doing multilink: send it down the first channel */ + list = list->next; + pch = list_entry(list, struct channel, clist); + + spin_lock(&pch->downl); +- if (pch->chan) { +- if (pch->chan->ops->start_xmit(pch->chan, skb)) +- ppp->xmit_pending = NULL; +- } else { +- /* channel got unregistered */ ++ chan = pch->chan; ++ if (unlikely(!chan || (!chan->direct_xmit && skb_linearize(skb)))) { ++ /* channel got unregistered, or it requires a linear ++ * skb but linearization failed ++ */ + kfree_skb(skb); + ppp->xmit_pending = NULL; ++ goto out; + } ++ ++ if (chan->ops->start_xmit(chan, skb)) ++ ppp->xmit_pending = NULL; ++ ++out: + spin_unlock(&pch->downl); + return; + } +@@ -1981,6 +1998,8 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + return 0; /* can't take now, leave it in xmit_pending */ + + /* Do protocol field compression */ ++ if (skb_linearize(skb)) ++ goto err_linearize; + p = skb->data; + len = skb->len; + if (*p == 0 && mp_protocol_compress) { +@@ -2139,6 +2158,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + + noskb: + spin_unlock(&pch->downl); ++ err_linearize: + if (ppp->debug & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); + ++ppp->dev->stats.tx_errors; +-- +2.53.0 + diff --git a/queue-6.6/ppp-use-iff_no_queue-in-virtual-interfaces.patch b/queue-6.6/ppp-use-iff_no_queue-in-virtual-interfaces.patch new file mode 100644 index 0000000000..c3fa42f456 --- /dev/null +++ b/queue-6.6/ppp-use-iff_no_queue-in-virtual-interfaces.patch @@ -0,0 +1,105 @@ +From fd4d7da5f7808ce8d226caf3e5ffeeaace89986e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 1 Mar 2025 21:55:16 +0800 +Subject: ppp: use IFF_NO_QUEUE in virtual interfaces +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Qingfang Deng + +[ Upstream commit 95d0d094ba26432ec467e2260f4bf553053f1f8f ] + +For PPPoE, PPTP, and PPPoL2TP, the start_xmit() function directly +forwards packets to the underlying network stack and never returns +anything other than 1. So these interfaces do not require a qdisc, +and the IFF_NO_QUEUE flag should be set. + +Introduces a direct_xmit flag in struct ppp_channel to indicate when +IFF_NO_QUEUE should be applied. The flag is set in ppp_connect_channel() +for relevant protocols. + +While at it, remove the usused latency member from struct ppp_channel. + +Signed-off-by: Qingfang Deng +Reviewed-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20250301135517.695809-1-dqfext@gmail.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic") +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 4 ++++ + drivers/net/ppp/pppoe.c | 1 + + drivers/net/ppp/pptp.c | 1 + + include/linux/ppp_channel.h | 3 +-- + net/l2tp/l2tp_ppp.c | 1 + + 5 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 53e96a8740397c..62169a38b984a2 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -3508,6 +3508,10 @@ ppp_connect_channel(struct channel *pch, int unit) + ret = -ENOTCONN; + goto outl; + } ++ if (pch->chan->direct_xmit) ++ ppp->dev->priv_flags |= IFF_NO_QUEUE; ++ else ++ ppp->dev->priv_flags &= ~IFF_NO_QUEUE; + spin_unlock_bh(&pch->downl); + if (pch->file.hdrlen > ppp->file.hdrlen) + ppp->file.hdrlen = pch->file.hdrlen; +diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c +index bc726b54ca745d..4aab447f0d65c9 100644 +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -699,6 +699,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, + po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr) - 2; + po->chan.private = sk; + po->chan.ops = &pppoe_chan_ops; ++ po->chan.direct_xmit = true; + + error = ppp_register_net_channel(dev_net(dev), &po->chan); + if (error) { +diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c +index 3a10303eb756a8..386e0be78a6a96 100644 +--- a/drivers/net/ppp/pptp.c ++++ b/drivers/net/ppp/pptp.c +@@ -469,6 +469,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, + po->chan.mtu -= PPTP_HEADER_OVERHEAD; + + po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header); ++ po->chan.direct_xmit = true; + error = ppp_register_channel(&po->chan); + if (error) { + pr_err("PPTP: failed to register PPP channel (%d)\n", error); +diff --git a/include/linux/ppp_channel.h b/include/linux/ppp_channel.h +index 45e6e427ceb8a0..f73fbea0dbc239 100644 +--- a/include/linux/ppp_channel.h ++++ b/include/linux/ppp_channel.h +@@ -42,8 +42,7 @@ struct ppp_channel { + int hdrlen; /* amount of headroom channel needs */ + void *ppp; /* opaque to channel */ + int speed; /* transfer rate (bytes/second) */ +- /* the following is not used at present */ +- int latency; /* overhead time in milliseconds */ ++ bool direct_xmit; /* no qdisc, xmit directly */ + }; + + #ifdef __KERNEL__ +diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c +index 34d8582c0c072e..2e856a83a7506b 100644 +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -810,6 +810,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, + po->chan.private = sk; + po->chan.ops = &pppol2tp_chan_ops; + po->chan.mtu = pppol2tp_tunnel_mtu(tunnel); ++ po->chan.direct_xmit = true; + + error = ppp_register_net_channel(sock_net(sk), &po->chan); + if (error) { +-- +2.53.0 + diff --git a/queue-6.6/rds-drop-incoming-messages-that-cross-network-namesp.patch b/queue-6.6/rds-drop-incoming-messages-that-cross-network-namesp.patch new file mode 100644 index 0000000000..64af806bd1 --- /dev/null +++ b/queue-6.6/rds-drop-incoming-messages-that-cross-network-namesp.patch @@ -0,0 +1,78 @@ +From fb9b6b118c870eaafe2143e9c9e009033ac2cfef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 19:43:14 -0700 +Subject: rds: drop incoming messages that cross network namespace boundaries + +From: Aldo Ariel Panzardo + +[ Upstream commit 5521ae71e32a8069ed4ca6e792179dc57bc43ab2 ] + +rds_find_bound() looks up the destination socket using a global +rhashtable keyed solely on (addr, port, scope_id). Network namespaces +are not part of the key, so a sender in netns A can deliver an incoming +message (inc) to a socket that lives in a different netns B. + +When this happens, inc->i_conn points to an rds_connection whose c_net +is netns A, but the receiving rs lives in netns B. Once the child +process that created netns A exits, cleanup_net() calls +rds_loop_exit_net() -> rds_loop_kill_conns() -> rds_conn_destroy(), +freeing that connection. If the survivor socket in netns B still holds +the inc, any subsequent dereference of inc->i_conn is a use-after-free. + +There are two dangerous sites in rds_clear_recv_queue(): + 1. inc->i_conn->c_lcong (offset 88 of freed rds_connection, size 200) + read via rds_recv_rcvbuf_delta() -- confirmed by KASAN. + 2. inc->i_conn->c_trans->inc_free(inc) (function pointer at offset 80) + called via rds_inc_put() when the inc refcount reaches zero -- same + race window, potential call-through-freed-object primitive. + +The bug is reachable from unprivileged user namespaces +(CLONE_NEWUSER + CLONE_NEWNET), available since Linux 3.8. + +Fix this by rejecting the delivery in rds_recv_incoming() when the +socket returned by rds_find_bound() belongs to a different network +namespace than the connection that carried the message. Use the +existing rds_conn_net() / sock_net() helpers and net_eq() for the +comparison. + +Fixes: c809195f5523 ("rds: clean up loopback rds_connections on netns deletion") +Signed-off-by: Aldo Ariel Panzardo +Reviewed-by: Allison Henderson +Tested-by: Allison Henderson +Signed-off-by: Allison Henderson +Link: https://patch.msgid.link/20260708024314.601139-1-achender@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/rds/recv.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/net/rds/recv.c b/net/rds/recv.c +index 5627f80013f8b1..bd9d00326e94fd 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -366,6 +366,21 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr, + goto out; + } + ++ /* ++ * rds_find_bound() uses a global (netns-agnostic) hash table. ++ * An RDS connection created in netns A can match a socket bound ++ * in the init netns, delivering inc cross-netns with inc->i_conn ++ * pointing into netns A. When cleanup_net() then frees that conn, ++ * any subsequent dereference of inc->i_conn is a use-after-free. ++ * Drop the inc if the receiving socket lives in a different netns. ++ */ ++ if (!net_eq(sock_net(rds_rs_to_sk(rs)), rds_conn_net(conn))) { ++ rds_stats_inc(s_recv_drop_no_sock); ++ rds_sock_put(rs); ++ rs = NULL; ++ goto out; ++ } ++ + /* Process extension headers */ + rds_recv_incoming_exthdrs(inc, rs); + +-- +2.53.0 + diff --git a/queue-6.6/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch b/queue-6.6/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch new file mode 100644 index 0000000000..4615a6d4ed --- /dev/null +++ b/queue-6.6/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch @@ -0,0 +1,51 @@ +From db7f257a9c2b21683b3ecc3bb8e5a4c134e031ec Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 09:55:32 +0800 +Subject: sctp: auth: verify auth requirement when auth_chunk is NULL + +From: Qing Luo + +[ Upstream commit 8e04823c120b376ef7dab14b60ebf6823aa16c14 ] + +sctp_auth_chunk_verify() returns true unconditionally when +chunk->auth_chunk is NULL, silently skipping authentication. +This is incorrect when: + +1. skb_clone() failed in the BH receive path, leaving auth_chunk + NULL. In sctp_endpoint_bh_rcv() asoc is NULL for new + connections, so the early sctp_auth_recv_cid() check cannot + catch this. + +2. No AUTH chunk precedes COOKIE-ECHO, so skb_clone() is never + called and auth_chunk remains NULL. + +Fix by checking sctp_auth_recv_cid() when auth_chunk is NULL: +if authentication is required, return false to drop the chunk; +otherwise continue normally. + +Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk") +Signed-off-by: Qing Luo +Acked-by: Xin Long +Link: https://patch.msgid.link/20260721015532.120157-2-l1138897701@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/sm_statefuns.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index fc04bea029dc1d..ce0b5d6b4c5239 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -640,7 +640,7 @@ static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, + struct sctp_chunk auth; + + if (!chunk->auth_chunk) +- return true; ++ return !sctp_auth_recv_cid(chunk->chunk_hdr->type, asoc); + + /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo + * is supposed to be authenticated and we have to do delayed +-- +2.53.0 + diff --git a/queue-6.6/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch b/queue-6.6/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch new file mode 100644 index 0000000000..3154f5af87 --- /dev/null +++ b/queue-6.6/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch @@ -0,0 +1,46 @@ +From d307d74fdf49bbb11374950a5079e50ffb21f840 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 03:20:21 +0000 +Subject: sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid + +From: HanQuan + +[ Upstream commit ff04b26794a16a8a879eb4fd2c02c2d6b03850e9 ] + +sctp_auth_ep_add_chunkid() uses SCTP_NUM_CHUNK_TYPES (20) as the +capacity limit for ep->auth_chunk_list, allowing it to hold up to +20 chunk entries (param_hdr.length up to 24). However, the copy +destination asoc->c.auth_chunks in struct sctp_cookie is only +SCTP_AUTH_MAX_CHUNKS (16) entries (20 bytes). When more than 16 +chunks are added, sctp_association_init() memcpy overflows the +destination by up to 4 bytes. + +Fix by using SCTP_AUTH_MAX_CHUNKS as the capacity limit, matching +the destination capacity. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Signed-off-by: HanQuan +Acked-by: Xin Long +Link: https://patch.msgid.link/20260713032021.3491702-1-zhoujian.zja@antgroup.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/auth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index c58fffc86a0c2d..8320764b16b928 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -766,7 +766,7 @@ int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) + /* Check if we can add this chunk to the array */ + param_len = ntohs(p->param_hdr.length); + nchunks = param_len - sizeof(struct sctp_paramhdr); +- if (nchunks == SCTP_NUM_CHUNK_TYPES) ++ if (nchunks == SCTP_AUTH_MAX_CHUNKS) + return -EINVAL; + + p->chunks[nchunks] = chunk_id; +-- +2.53.0 + diff --git a/queue-6.6/sctp-validate-stream-count-in-sctp_process_strreset_.patch b/queue-6.6/sctp-validate-stream-count-in-sctp_process_strreset_.patch new file mode 100644 index 0000000000..401fff2bb5 --- /dev/null +++ b/queue-6.6/sctp-validate-stream-count-in-sctp_process_strreset_.patch @@ -0,0 +1,80 @@ +From 4dabc4b53ee9d6bdf3335df4fef00450fd529569 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 21:07:18 -0400 +Subject: sctp: validate stream count in sctp_process_strreset_inreq() + +From: Cen Zhang (Microsoft) + +[ Upstream commit 18ae07691d43183d270de8be9dc8e027906015d9 ] + +When processing a RESET_IN_REQUEST from a peer, +sctp_process_strreset_inreq() derives the stream count from the +parameter length but does not check whether the resulting +RESET_OUT_REQUEST would exceed SCTP_MAX_CHUNK_LEN. + +The OUT request header (sctp_strreset_outreq, 16 bytes) is 8 bytes +larger than the IN request header (sctp_strreset_inreq, 8 bytes). +Generally, the IP payload is bounded to 65535 bytes, so the stream +list cannot be large enough to trigger the overflow. However, on +interfaces with MTU > 65535 (e.g., loopback with IPv6 jumbograms), a +stream list that fits within the incoming IN parameter can cause a +__u16 overflow in sctp_make_strreset_req() when computing the OUT +request size, leading to an undersized skb allocation and a kernel +BUG: + + net/core/skbuff.c:207 skb_panic + net/core/skbuff.c:2625 skb_put + net/sctp/sm_make_chunk.c:1535 sctp_addto_chunk + net/sctp/sm_make_chunk.c:3695 sctp_make_strreset_req + net/sctp/stream.c:655 sctp_process_strreset_inreq + +The local setsockopt path validates the generated reset request size. +However, for an incoming-only reset, it accounts for the smaller IN +request even though the peer must generate an OUT request with the same +stream list. Such a request cannot be completed successfully by the +peer. + +Reject peer IN requests whose corresponding OUT request would exceed +SCTP_MAX_CHUNK_LEN. Also tighten the local check so it does not send an +IN request that would require an oversized OUT request from the peer. + +Fixes: 7f9d68ac944e ("sctp: implement sender-side procedures for SSN Reset Request Parameter") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/20260707203215.2752-1-blbllhy@gmail.com/ +Suggested-by: Xin Long +Signed-off-by: Cen Zhang (Microsoft) +Acked-by: Xin Long +Link: https://patch.msgid.link/20260710010718.20318-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/stream.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/stream.c b/net/sctp/stream.c +index e8922f350bafe6..0f81820c730bae 100644 +--- a/net/sctp/stream.c ++++ b/net/sctp/stream.c +@@ -308,7 +308,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc, + goto out; + + param_len += str_nums * sizeof(__u16) + +- sizeof(struct sctp_strreset_inreq); ++ (out ? sizeof(struct sctp_strreset_inreq) ++ : sizeof(struct sctp_strreset_outreq)); + } + + if (param_len > SCTP_MAX_CHUNK_LEN - +@@ -639,6 +640,9 @@ struct sctp_chunk *sctp_process_strreset_inreq( + + nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16); + str_p = inreq->list_of_streams; ++ if (nums * sizeof(__u16) + sizeof(struct sctp_strreset_outreq) > ++ SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_reconf_chunk)) ++ goto out; + for (i = 0; i < nums; i++) { + if (ntohs(str_p[i]) >= stream->outcnt) { + result = SCTP_STRRESET_ERR_WRONG_SSN; +-- +2.53.0 + diff --git a/queue-6.6/selftest-af_unix-add-kconfig-file.patch b/queue-6.6/selftest-af_unix-add-kconfig-file.patch new file mode 100644 index 0000000000..3a7732a56c --- /dev/null +++ b/queue-6.6/selftest-af_unix-add-kconfig-file.patch @@ -0,0 +1,49 @@ +From 2295e747da74e3a97ce0e4a8b600435576dd105b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Jun 2024 19:10:51 -0700 +Subject: selftest: af_unix: Add Kconfig file. + +From: Kuniyuki Iwashima + +[ Upstream commit 11b006d6896c0471ad29c6f1fb1af606e7ba278f ] + +diag_uid selftest failed on NIPA where the received nlmsg_type is +NLMSG_ERROR [0] because CONFIG_UNIX_DIAG is not set [1] by default +and sock_diag_lock_handler() failed to load the module. + + # # Starting 2 tests from 2 test cases. + # # RUN diag_uid.uid.1 ... + # # diag_uid.c:159:1:Expected nlh->nlmsg_type (2) == SOCK_DIAG_BY_FAMILY (20) + # # 1: Test terminated by assertion + # # FAIL diag_uid.uid.1 + # not ok 1 diag_uid.uid.1 + +Let's add all AF_UNIX Kconfig to the config file under af_unix dir +so that NIPA consumes it. + +Fixes: ac011361bd4f ("af_unix: Add test for sock_diag and UDIAG_SHOW_UID.") +Link: https://netdev-3.bots.linux.dev/vmksft-net/results/644841/104-diag-uid/stdout [0] +Link: https://netdev-3.bots.linux.dev/vmksft-net/results/644841/config [1] +Reported-by: Jakub Kicinski +Closes: https://lore.kernel.org/netdev/20240617073033.0cbb829d@kernel.org/ +Signed-off-by: Kuniyuki Iwashima +Signed-off-by: David S. Miller +Stable-dep-of: f8b1abed7361 ("selftests: af_unix: add USER_NS config") +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/af_unix/config | 3 +++ + 1 file changed, 3 insertions(+) + create mode 100644 tools/testing/selftests/net/af_unix/config + +diff --git a/tools/testing/selftests/net/af_unix/config b/tools/testing/selftests/net/af_unix/config +new file mode 100644 +index 00000000000000..37368567768cc0 +--- /dev/null ++++ b/tools/testing/selftests/net/af_unix/config +@@ -0,0 +1,3 @@ ++CONFIG_UNIX=y ++CONFIG_AF_UNIX_OOB=y ++CONFIG_UNIX_DIAG=m +-- +2.53.0 + diff --git a/queue-6.6/selftests-af_unix-add-user_ns-config.patch b/queue-6.6/selftests-af_unix-add-user_ns-config.patch new file mode 100644 index 0000000000..96643e67d1 --- /dev/null +++ b/queue-6.6/selftests-af_unix-add-user_ns-config.patch @@ -0,0 +1,40 @@ +From d4d7b99f80060d5635db3f037879e51c5451cb82 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:41 +0200 +Subject: selftests: af_unix: add USER_NS config + +From: Matthieu Baerts (NGI0) + +[ Upstream commit f8b1abed736111f914b2c567d9a3db1f71e788e8 ] + +This is required to use unshare(CLONE_NEWUSER). + +This has not been seen on NIPA before, because the 'af_unix' tests are +executed with the 'net' ones, merging their config files. USER_NS is +present in tools/testing/selftests/net/config. + +This issue is visible when only the af_unix config is used on top of the +default one. This is the recommended way to execute selftest targets. + +Fixes: ac011361bd4f ("af_unix: Add test for sock_diag and UDIAG_SHOW_UID.") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-1-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/af_unix/config | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/net/af_unix/config b/tools/testing/selftests/net/af_unix/config +index 37368567768cc0..9c4fb9c31c9506 100644 +--- a/tools/testing/selftests/net/af_unix/config ++++ b/tools/testing/selftests/net/af_unix/config +@@ -1,3 +1,4 @@ + CONFIG_UNIX=y + CONFIG_AF_UNIX_OOB=y + CONFIG_UNIX_DIAG=m ++CONFIG_USER_NS=y +-- +2.53.0 + diff --git a/queue-6.6/selftests-openvswitch-add-config-file.patch b/queue-6.6/selftests-openvswitch-add-config-file.patch new file mode 100644 index 0000000000..c2b52cbeb9 --- /dev/null +++ b/queue-6.6/selftests-openvswitch-add-config-file.patch @@ -0,0 +1,59 @@ +From 0bb78948ca26bc7599045972b021b0ad73959774 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:42 +0200 +Subject: selftests: openvswitch: add config file + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 441a820ccef9af80a9ac5a4c85b9c396e595967c ] + +The kselftests doc mentions that a config file should be present "if a +test needs specific kernel config options enabled". This selftest +requires some kernel config, but no config file was provided. + +We could say that a sub-target could use the parent's config file, but +the kselftests doc doesn't mention anything about that. Plus the +net/openvswitch target is the only net target without a config file. + +Here is a new config file, which is a trimmed version of the net one, +with hopefully the minimal required kconfig on top of 'make defconfig'. + +The Fixes tag points to the introduction of the net/openvswitch target, +just to help validating this target on stable kernels. + +Fixes: 25f16c873fb1 ("selftests: add openvswitch selftest suite") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Eelco Chaudron +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-2-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/openvswitch/config | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + create mode 100644 tools/testing/selftests/net/openvswitch/config + +diff --git a/tools/testing/selftests/net/openvswitch/config b/tools/testing/selftests/net/openvswitch/config +new file mode 100644 +index 00000000000000..c659749cd086c7 +--- /dev/null ++++ b/tools/testing/selftests/net/openvswitch/config +@@ -0,0 +1,16 @@ ++CONFIG_GENEVE=m ++CONFIG_INET_DIAG=y ++CONFIG_IPV6=y ++CONFIG_NETFILTER=y ++CONFIG_NET_IPGRE=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_OVS=y ++CONFIG_OPENVSWITCH=m ++CONFIG_OPENVSWITCH_GENEVE=m ++CONFIG_OPENVSWITCH_GRE=m ++CONFIG_OPENVSWITCH_VXLAN=m ++CONFIG_PSAMPLE=m ++CONFIG_VETH=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VXLAN=m +-- +2.53.0 + diff --git a/queue-6.6/series b/queue-6.6/series index e9d9d6b586..cce986689b 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -114,3 +114,93 @@ crypto-rsa-pkcs1pad-don-t-warn-on-an-empty-digest.patch revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch risc-v-kvm-serialize-virtual-interrupt-pending-state.patch usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch +wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch +wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch +hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch +hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch +hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch +watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch +wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch +wifi-ath11k-flush-the-posted-write-after-writing-to-.patch +wifi-ath12k-flush-the-posted-write-after-writing-to-.patch +firewire-net-fix-fragmented-datagram-reassembly.patch +wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch +wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch +wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch +wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch +wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch +btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch +btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch +asoc-tas2781-bound-firmware-description-string-parsi.patch +asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch +asoc-cs35l56-don-t-use-devres-to-unregister-componen.patch +asoc-cs35l56-fix-potential-probe-deadlock.patch +asoc-cs35l56-use-complete_all-to-signal-init_complet.patch +wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch +wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch +usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch +hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch +hwmon-asus-ec-sensors-fix-ec-read-intervals.patch +hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch +smb-client-validate-dfs-referral-pathconsumed.patch +hwmon-occ-validate-poll-response-sensor-blocks.patch +bluetooth-btusb-validate-realtek-vendor-event-length.patch +net-packet-avoid-fanout-hook-re-registration-after-u.patch +bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch +rds-drop-incoming-messages-that-cross-network-namesp.patch +dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch +dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch +iommu-amd-wait-for-completion-instead-of-returning-e.patch +wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch +nfp-check-resource-mutex-allocation.patch +wan-wanxl-only-reset-hardware-after-bar-mapping.patch +wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch +iommu-amd-bound-the-early-acpi-hid-map.patch +iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch +wifi-mac80211-recalculate-tim-when-a-station-enters-.patch +pds_core-reject-component-parameter-in-legacy-firmwa.patch +amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch +sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch +pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch +pds_core-order-completion-reads-after-the-ownership-.patch +pds_core-fix-auxiliary-device-add-del-races.patch +pds_core-check-for-workqueue-allocation-failure.patch +sctp-validate-stream-count-in-sctp_process_strreset_.patch +tls-device-push-pending-open-record-on-splice-eof.patch +selftest-af_unix-add-kconfig-file.patch +selftests-af_unix-add-user_ns-config.patch +selftests-openvswitch-add-config-file.patch +gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch +nexthop-initialize-extack-in-nh_res_bucket_migrate.patch +tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch +wifi-mt76-mt7915-guard-he-capability-lookups.patch +wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch +wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch +wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch +wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch +amt-re-read-skb-header-pointers-after-every-pull.patch +amt-make-the-head-writable-before-rewriting-the-l2-h.patch +net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch +net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch +net-dpaa-fix-mode-setting.patch +sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch +vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch +iomap-correct-the-range-of-a-partial-dirty-clear.patch +tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch +net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch +net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch +net-stmmac-enable-the-mac-on-link-up-for-all-support.patch +octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch +ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch +ppp-use-iff_no_queue-in-virtual-interfaces.patch +ppp-convert-to-percpu-netstats.patch +ppp-enable-tx-scatter-gather.patch +ppp-annotate-data-races-in-ppp_generic.patch +hinic-remove-unused-ethtool-rss-user-configuration-b.patch +net-qrtr-restrict-socket-creation-to-the-initial-net.patch +net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch +net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch +net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch +net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch +ice-fix-lag-recipe-to-profile-association.patch +bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch diff --git a/queue-6.6/smb-client-validate-dfs-referral-pathconsumed.patch b/queue-6.6/smb-client-validate-dfs-referral-pathconsumed.patch new file mode 100644 index 0000000000..0bd6927e89 --- /dev/null +++ b/queue-6.6/smb-client-validate-dfs-referral-pathconsumed.patch @@ -0,0 +1,97 @@ +From 0841237f9cd4f129d14ebbc105084f3877daa22a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 13:25:23 +0800 +Subject: smb: client: validate DFS referral PathConsumed + +From: Yichong Chen + +[ Upstream commit f6f5ee2aa33b350c671721b965251c42cebb962e ] + +parse_dfs_referrals() validates that the response contains the fixed +referral entry array and, on for-next, the per-referral string offsets. +However, the response also contains a PathConsumed value that is later +used for DFS path parsing. + +If a malformed response provides a PathConsumed value larger than the +search name, later DFS parsing can advance beyond the end of the path. + +Validate PathConsumed against the search name length before storing it in +the parsed referral. + +Fixes: 4ecce920e13a ("CIFS: move DFS response parsing out of SMB1 code") +Reviewed-by: Paulo Alcantara (Red Hat) +Signed-off-by: Yichong Chen +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/misc.c | 34 +++++++++++++++++++++++++--------- + 1 file changed, 25 insertions(+), 9 deletions(-) + +diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c +index 46ca8f326c9813..29a390a497aefe 100644 +--- a/fs/smb/client/misc.c ++++ b/fs/smb/client/misc.c +@@ -964,6 +964,8 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + int i, rc = 0; + char *data_end; + struct dfs_referral_level_3 *ref; ++ unsigned int path_consumed; ++ size_t search_name_len; + + if (rsp_size < sizeof(*rsp)) { + cifs_dbg(VFS | ONCE, +@@ -1011,6 +1013,7 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + rc = -ENOMEM; + goto parse_DFS_referrals_exit; + } ++ search_name_len = strlen(searchName); + + /* collect necessary data from referrals */ + for (i = 0; i < *num_of_nodes; i++) { +@@ -1019,21 +1022,34 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + struct dfs_info3_param *node = (*target_nodes)+i; + + node->flags = le32_to_cpu(rsp->DFSFlags); ++ path_consumed = le16_to_cpu(rsp->PathConsumed); + if (is_unicode) { +- __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, +- GFP_KERNEL); +- if (tmp == NULL) { ++ size_t search_name_utf16_len = search_name_len * 2 + 2; ++ __le16 *tmp; ++ ++ if (path_consumed > search_name_utf16_len) { ++ rc = -EINVAL; ++ goto parse_DFS_referrals_exit; ++ } ++ ++ tmp = kmalloc(search_name_utf16_len, GFP_KERNEL); ++ if (!tmp) { + rc = -ENOMEM; + goto parse_DFS_referrals_exit; + } +- cifsConvertToUTF16((__le16 *) tmp, searchName, ++ cifsConvertToUTF16((__le16 *)tmp, searchName, + PATH_MAX, nls_codepage, remap); +- node->path_consumed = cifs_utf16_bytes(tmp, +- le16_to_cpu(rsp->PathConsumed), +- nls_codepage); ++ node->path_consumed = cifs_utf16_bytes(tmp, path_consumed, ++ nls_codepage); + kfree(tmp); +- } else +- node->path_consumed = le16_to_cpu(rsp->PathConsumed); ++ } else { ++ if (path_consumed > search_name_len) { ++ rc = -EINVAL; ++ goto parse_DFS_referrals_exit; ++ } ++ ++ node->path_consumed = path_consumed; ++ } + + node->server_type = le16_to_cpu(ref->ServerType); + node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); +-- +2.53.0 + diff --git a/queue-6.6/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch b/queue-6.6/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch new file mode 100644 index 0000000000..0ef5a0a3bc --- /dev/null +++ b/queue-6.6/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch @@ -0,0 +1,47 @@ +From 74f8f6051024a13f3ed6222a689f0fc17c5cd388 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:49:35 -0300 +Subject: tipc: fix infinite loop in __tipc_nl_compat_dumpit + +From: Helen Koike + +[ Upstream commit 22f8aa35964e8f2ab026578f45befc9605fd1b28 ] + +cmd->dumpit callback can return a negative errno, causing an infinite +loop due to the while(len) condition. As the loop never terminates, +genl_mutex is never released, and other tasks waiting on it starve in D +state. + +Check dumpit's return value, propagate it and jump to err_out on error. + +Reported-by: syzbot+85d0bec020d805014a3a@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=85d0bec020d805014a3a +Fixes: d0796d1ef63d ("tipc: convert legacy nl bearer dump to nl compat") +Signed-off-by: Helen Koike +Reviewed-by: Tung Nguyen +Link: https://patch.msgid.link/20260713204940.647668-1-koike@igalia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/netlink_compat.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c +index c763008a8adbaa..c760ba270547e1 100644 +--- a/net/tipc/netlink_compat.c ++++ b/net/tipc/netlink_compat.c +@@ -222,6 +222,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, + int rem; + + len = (*cmd->dumpit)(buf, &cb); ++ if (len < 0) { ++ err = len; ++ goto err_out; ++ } + + nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) { + err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN, +-- +2.53.0 + diff --git a/queue-6.6/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch b/queue-6.6/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch new file mode 100644 index 0000000000..42a29c4312 --- /dev/null +++ b/queue-6.6/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch @@ -0,0 +1,72 @@ +From 08b7ea4c4100912567aed9f8e8fc2c11cc6079ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 00:15:41 -0400 +Subject: tipc: fix u16 MTU truncation in media and bearer MTU validation + +From: Cen Zhang (Microsoft) + +[ Upstream commit 9f29cd8a8e7901a2617c8064ce9f50fc67b97cb8 ] + +Both TIPC_NL_MEDIA_SET and TIPC_NL_BEARER_SET accept user-supplied +MTU values but only enforce a minimum bound, not a maximum. When a user +sets the MTU to a value exceeding U16_MAX (65535), it passes validation +but is silently truncated when assigned to u16 fields l->mtu and +l->advertised_mtu in tipc_link_create(). Values like 65536 (0x10000) +truncate to 0, causing a division by zero in tipc_link_set_queue_limits() +which computes TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE). Other overflowing +values (e.g. 65537-131071) produce small incorrect MTU values, resulting +in link malfunction behaviors. + +Crash stack (triggered as unprivileged user via user namespace): + + tipc_link_set_queue_limits net/tipc/link.c:2531 + tipc_link_create net/tipc/link.c:520 + tipc_node_check_dest net/tipc/node.c:1279 + tipc_disc_rcv net/tipc/discover.c:252 + tipc_rcv net/tipc/node.c:2129 + tipc_udp_recv net/tipc/udp_media.c:392 + +Two independent paths lack the upper bound check: +1. tipc_udp_mtu_bad() -- called from __tipc_nl_media_set() (MEDIA_SET) +2. inline check in __tipc_nl_bearer_set() at bearer.c:1160 (BEARER_SET) + +Fix both by rejecting MTU values above U16_MAX. + +Fixes: 901271e0403a ("tipc: implement configuration of UDP media MTU") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/CAB8m9WgETt0AjmFwE=F-CKjGXsK6_WDv0=kbYRcC8-noo+amnA@mail.gmail.com +Reviewed-by: Vadim Fedorenko +Signed-off-by: Cen Zhang (Microsoft) +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260714041541.307702-1-blbllhy@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tipc/netlink.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c +index 8336a9664703fe..1307dd1a961341 100644 +--- a/net/tipc/netlink.c ++++ b/net/tipc/netlink.c +@@ -113,12 +113,16 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { + }; + + /* Properties valid for media, bearer and link */ ++static const struct netlink_range_validation tipc_nl_mtu_range = { ++ .max = U16_MAX, ++}; ++ + const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { + [TIPC_NLA_PROP_UNSPEC] = { .type = NLA_UNSPEC }, + [TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 }, +- [TIPC_NLA_PROP_MTU] = { .type = NLA_U32 }, ++ [TIPC_NLA_PROP_MTU] = NLA_POLICY_FULL_RANGE(NLA_U32, &tipc_nl_mtu_range), + [TIPC_NLA_PROP_BROADCAST] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_BROADCAST_RATIO] = { .type = NLA_U32 } + }; +-- +2.53.0 + diff --git a/queue-6.6/tls-device-push-pending-open-record-on-splice-eof.patch b/queue-6.6/tls-device-push-pending-open-record-on-splice-eof.patch new file mode 100644 index 0000000000..0bc0e19fc4 --- /dev/null +++ b/queue-6.6/tls-device-push-pending-open-record-on-splice-eof.patch @@ -0,0 +1,56 @@ +From 0aac8f09ff3c80335db5dcbba797b7d9908ea698 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 16:44:36 -0600 +Subject: tls: device: push pending open record on splice EOF + +From: Rishikesh Jethwani + +[ Upstream commit eaa39f9f8ac8c1d032cd26b9cd572804e9d7683f ] + +On kTLS device-offload sockets, sendfile() with count > EOF can reach +->splice_eof() with a fully assembled but still-open TLS record left +pending. tls_device_splice_eof() only flushes partially sent records, +so an abrupt close() can drop the final record and the peer receives +a short file. + +Fix tls_device_splice_eof() to also push pending open records. +This matches the software path, where splice EOF already flushes +pending open records. + +Fixes: d4c1e80b0d1b ("tls/device: Use splice_eof() to flush") +Link: https://lore.kernel.org/netdev/CAMPsyauZ+jzG9AysO0FWv6ZY0kvCUpjX_U7o=oOjCuOQ87BCgg@mail.gmail.com/ +Reported-by: Nils Juenemann +Signed-off-by: Rishikesh Jethwani +Tested-by: Nils Juenemann +Link: https://patch.msgid.link/20260709224436.1608993-2-rjethwani@purestorage.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tls/tls_device.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c +index 1fc1e8e2a9cb2c..7fce47197d0a45 100644 +--- a/net/tls/tls_device.c ++++ b/net/tls/tls_device.c +@@ -600,13 +600,15 @@ void tls_device_splice_eof(struct socket *sock) + struct tls_context *tls_ctx = tls_get_ctx(sk); + struct iov_iter iter = {}; + +- if (!tls_is_partially_sent_record(tls_ctx)) ++ if (!tls_is_partially_sent_record(tls_ctx) && ++ !tls_is_pending_open_record(tls_ctx)) + return; + + mutex_lock(&tls_ctx->tx_lock); + lock_sock(sk); + +- if (tls_is_partially_sent_record(tls_ctx)) { ++ if (tls_is_partially_sent_record(tls_ctx) || ++ tls_is_pending_open_record(tls_ctx)) { + iov_iter_bvec(&iter, ITER_SOURCE, NULL, 0, 0); + tls_push_data(sk, &iter, 0, 0, TLS_RECORD_TYPE_DATA); + } +-- +2.53.0 + diff --git a/queue-6.6/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch b/queue-6.6/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch new file mode 100644 index 0000000000..751cb3ce16 --- /dev/null +++ b/queue-6.6/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch @@ -0,0 +1,93 @@ +From c98c9a3dd63c4fba998a724eb8a97c879a9bb464 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 02:07:04 -0600 +Subject: usb: atm: ueagle-atm: reject descriptors that confuse probe and + disconnect + +From: Diego Fernando Mancera Gomez + +[ Upstream commit 71132cedd1ecbc4032d76e9928c18a10f7e39b80 ] + +uea_probe() distinguishes a pre-firmware device from a post-firmware one +using the USB id (UEA_IS_PREFIRM()), and stores a different object as the +interface data in each case: a 'struct completion' for a pre-firmware +device (to be waited on in .disconnect()), or a 'struct usbatm_data' for a +post-firmware one. + +uea_disconnect() instead tells the two apart by the number of interfaces +of the active configuration (a pre-firmware device exposes a single +interface, ADI930 has 2 and eagle has 3), and casts the interface data +accordingly. + +Because the two handlers use different criteria, a crafted device that +advertises a pre-firmware id together with a multi-interface descriptor +(or a post-firmware id with a single interface) makes them disagree: the +small 'struct completion' stored by uea_probe() is then passed to +usbatm_usb_disconnect(), which casts it to 'struct usbatm_data' and takes +instance->serialize, reading past the end of the allocation: + + BUG: KASAN: slab-out-of-bounds in __mutex_lock+0x152a/0x1b80 + Read of size 8 at addr ffff8880470e2c60 by task kworker/1:2/982 + ... + __mutex_lock+0x152a/0x1b80 + usbatm_usb_disconnect+0x70/0x820 + uea_disconnect+0x133/0x2c0 + usb_unbind_interface+0x1dd/0x9e0 + ... + which belongs to the cache kmalloc-96 of size 96 + The buggy address is located 0 bytes to the right of + allocated 96-byte region [ffff8880470e2c00, ffff8880470e2c60) + +Reject such inconsistent descriptors in uea_probe() so that both handlers +always make the same pre/post-firmware decision. + +Reported-by: syzbot+e62a973f8322b3bbe3ac@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e62a973f8322b3bbe3ac +Fixes: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()") +Signed-off-by: Diego Fernando Mancera Gomez +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260717080704.1264-1-diegomancera.dev@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/atm/ueagle-atm.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c +index b41f352769f072..5dfe82a4c130da 100644 +--- a/drivers/usb/atm/ueagle-atm.c ++++ b/drivers/usb/atm/ueagle-atm.c +@@ -2591,6 +2591,7 @@ static struct usbatm_driver uea_usbatm_driver = { + static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + { + struct usb_device *usb = interface_to_usbdev(intf); ++ bool single_iface = usb->config->desc.bNumInterfaces == 1; + int ret; + + uea_enters(usb); +@@ -2600,6 +2601,22 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + le16_to_cpu(usb->descriptor.bcdDevice), + chip_name[UEA_CHIP_VERSION(id)]); + ++ /* ++ * uea_probe() decides between the pre-firmware and post-firmware case ++ * from the USB id and stores a different object as interface data in ++ * each case: a struct completion for a pre-firmware device, a struct ++ * usbatm_data for a post-firmware one. uea_disconnect() instead tells ++ * the two apart by the number of interfaces (a pre-firmware device ++ * exposes a single interface, ADI930 has 2 and eagle has 3). A crafted ++ * device advertising a pre-firmware id together with a multi-interface ++ * descriptor (or the other way around) makes the two disagree, so that ++ * usbatm_usb_disconnect() treats the small completion object as a ++ * struct usbatm_data and reads out of bounds. Reject such inconsistent ++ * descriptors so both paths make the same decision. ++ */ ++ if (UEA_IS_PREFIRM(id) != single_iface) ++ return -ENODEV; ++ + usb_reset_device(usb); + + if (UEA_IS_PREFIRM(id)) { +-- +2.53.0 + diff --git a/queue-6.6/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch b/queue-6.6/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch new file mode 100644 index 0000000000..e15b4632e7 --- /dev/null +++ b/queue-6.6/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch @@ -0,0 +1,84 @@ +From 740fc33295e4f7a6116740a4c84958d101e6990f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 07:09:15 -0700 +Subject: vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets + +From: Harshaka Narayana + +[ Upstream commit 34a71f5361fc3adb5b7138da78750b0d535a8252 ] + +vmxnet3_get_hdr_len() assumes gdesc->rcd.v4/v6/tcp always describe the +outer header, but for a Geneve-encapsulated packet the device can set +them based on the inner header instead, signalled by the +VMXNET3_RCD_HDR_INNER_SHIFT bit in the completion descriptor. Since the +function never skips the outer encapsulation, this mismatch triggers: + +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP), because the outer + protocol is UDP (Geneve), not TCP. +- BUG_ON(hdr.eth->h_proto != ...), when the tunnel's outer and inner + IP versions differ (e.g. outer IPv6/inner IPv4 or vice versa). + +Check VMXNET3_RCD_HDR_INNER_SHIFT up front and bail out, since the +function cannot locate the inner header it would need to parse. Also +convert the remaining BUG_ON()s in this function to return 0 +defensively. + +Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)") +Signed-off-by: Harshaka Narayana +Reviewed-by: Ronak Doshi +Reviewed-by: Sankararaman Jayaraman +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260713140915.3381715-1-harshaka.narayana@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c +index 68b8e458a88f6a..16af7c4f8eda59 100644 +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -1457,7 +1457,11 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + struct ipv6hdr *ipv6; + struct tcphdr *tcp; + } hdr; +- BUG_ON(gdesc->rcd.tcp == 0); ++ ++ /* v4/v6/tcp then describe the inner header, which we can't locate. */ ++ if ((le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT)) || ++ gdesc->rcd.tcp == 0) ++ return 0; + + maplen = skb_headlen(skb); + if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen)) +@@ -1471,15 +1475,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + + hdr.eth = eth_hdr(skb); + if (gdesc->rcd.v4) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)); ++ if (hdr.eth->h_proto != htons(ETH_P_IP) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)) ++ return 0; ++ + hdr.ptr += hlen; +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP); ++ if (hdr.ipv4->protocol != IPPROTO_TCP) ++ return 0; ++ + hlen = hdr.ipv4->ihl << 2; + hdr.ptr += hdr.ipv4->ihl << 2; + } else if (gdesc->rcd.v6) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)); ++ if (hdr.eth->h_proto != htons(ETH_P_IPV6) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)) ++ return 0; ++ + hdr.ptr += hlen; + /* Use an estimated value, since we also need to handle + * TSO case. +-- +2.53.0 + diff --git a/queue-6.6/wan-wanxl-only-reset-hardware-after-bar-mapping.patch b/queue-6.6/wan-wanxl-only-reset-hardware-after-bar-mapping.patch new file mode 100644 index 0000000000..77558d7286 --- /dev/null +++ b/queue-6.6/wan-wanxl-only-reset-hardware-after-bar-mapping.patch @@ -0,0 +1,51 @@ +From fdd27feb07ebfbc01c31fbc3e9fa1e389b3ca377 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:15 +0800 +Subject: wan: wanxl: Only reset hardware after BAR mapping + +From: Ruoyu Wang + +[ Upstream commit 91957b89da995607cb654b1f9a3c126ddbaee10f ] + +wanxl_pci_init_one() stores the freshly allocated card in driver data +before the PLX BAR is mapped. Several early probe failures then unwind +through wanxl_pci_remove_one(), including failure to allocate the coherent +status area or to restore the DMA mask. + +wanxl_pci_remove_one() unconditionally calls wanxl_reset(), and +wanxl_reset() dereferences card->plx. On those early failures card->plx +is still NULL, so the error path can dereference a NULL MMIO pointer. + +Only issue the hardware reset once the BAR mapping exists. The remaining +cleanup in wanxl_pci_remove_one() already checks whether later resources +were allocated. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ruoyu Wang +Link: https://patch.msgid.link/20260708143415.3169358-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/wan/wanxl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c +index 5a9e262188efe1..c38dd741401e13 100644 +--- a/drivers/net/wan/wanxl.c ++++ b/drivers/net/wan/wanxl.c +@@ -514,7 +514,8 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) + if (card->irq) + free_irq(card->irq, card); + +- wanxl_reset(card); ++ if (card->plx) ++ wanxl_reset(card); + + for (i = 0; i < RX_QUEUE_LENGTH; i++) + if (card->rx_skbs[i]) { +-- +2.53.0 + diff --git a/queue-6.6/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch b/queue-6.6/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch new file mode 100644 index 0000000000..5a15b36a97 --- /dev/null +++ b/queue-6.6/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch @@ -0,0 +1,48 @@ +From 1f4e5b337bf5abbaf8c2128f799e308a6ad81f14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:18:03 +0000 +Subject: watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() + +From: Tzung-Bi Shih + +[ Upstream commit 7362ba0f9c96ac3ad6a2ca3995bd9fc9a28a8661 ] + +When a watchdog governor is unregistered, it updates existing watchdog +devices that were using this governor by falling back to `default_gov`. + +If the governor being unregistered is currently set as `default_gov`, +the `default_gov` is never cleared. This leads to 2 use-after-free +issues: +1. New watchdog devices registered after this point will inherit the + dangling `default_gov`. +2. Existing watchdog devices using the unregistered governor will have + their `wdd->gov` reassigned to the dangling `default_gov`. + +Fix the UAF by clearing `default_gov` if it matches the governor being +unregistered. + +Fixes: da0d12ff2b82 ("watchdog: pretimeout: add panic pretimeout governor") +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20260707101803.3598173-1-tzungbi@kernel.org +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/watchdog_pretimeout.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c +index e5295c990fa1b8..787b6227b8ccc3 100644 +--- a/drivers/watchdog/watchdog_pretimeout.c ++++ b/drivers/watchdog/watchdog_pretimeout.c +@@ -165,6 +165,8 @@ void watchdog_unregister_governor(struct watchdog_governor *gov) + } + + spin_lock_irq(&pretimeout_lock); ++ if (default_gov == gov) ++ default_gov = NULL; + list_for_each_entry(p, &pretimeout_list, entry) + if (p->wdd->gov == gov) + p->wdd->gov = default_gov; +-- +2.53.0 + diff --git a/queue-6.6/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch b/queue-6.6/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch new file mode 100644 index 0000000000..59dfb90b4b --- /dev/null +++ b/queue-6.6/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch @@ -0,0 +1,68 @@ +From d0c235f77d27a772458d3d9f3a909929d899e44a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jun 2026 17:06:09 +0800 +Subject: wifi: ath11k: fix NULL pointer dereference in + ath11k_hal_srng_access_begin + +From: Gaole Zhang + +[ Upstream commit e8d85672dd7e2523f774caafba8f858384e18df7 ] + +In ATH11K_QMI_EVENT_FW_READY, ATH11K_FLAG_REGISTERED is set +unconditionally even when ath11k_core_qmi_firmware_ready() fails. +This leaves the driver in an inconsistent state where +initialization is considered complete although the firmware ready +handling did not finish successfully. During the subsequent SSR, +the driver enters the restart path based on this incorrect state +and dereferences uninitialized srng members, resulting in a NULL +pointer dereference. + +Call trace: + ath11k_hal_srng_access_begin+0xc/0x60 [ath11k] (P) + ath11k_ce_cleanup_pipes+0x17c/0x180 [ath11k] + ath11k_core_restart+0x40/0x168 [ath11k] + +Fix this by: +- skipping firmware_ready if ATH11K_FLAG_REGISTERED is already set +- setting ATH11K_FLAG_REGISTERED only when firmware_ready succeeds +- setting ATH11K_FLAG_QMI_FAIL and aborting the FW_READY handling +on error + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.2.0.c2-00204-QCAMSLSWPLZ-1 + +Fixes: 6fe62a8cec51c ("wifi: ath11k: Add cold boot calibration support on WCN6750") +Signed-off-by: Gaole Zhang +Reviewed-by: Baochen Qiang +Reviewed-by: Rameshkumar Sundaram +Link: https://patch.msgid.link/20260609090609.4041009-1-gaole.zhang@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/qmi.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index 91e31f30d2c80f..84d214c38f0f47 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -3276,9 +3276,14 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) + clear_bit(ATH11K_FLAG_CRASH_FLUSH, + &ab->dev_flags); + clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); +- ath11k_core_qmi_firmware_ready(ab); +- set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); +- ++ if (!test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { ++ ret = ath11k_core_qmi_firmware_ready(ab); ++ if (ret) { ++ set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); ++ break; ++ } ++ set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); ++ } + break; + case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE: + break; +-- +2.53.0 + diff --git a/queue-6.6/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch b/queue-6.6/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch new file mode 100644 index 0000000000..00294808ce --- /dev/null +++ b/queue-6.6/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch @@ -0,0 +1,48 @@ +From 4be806666552b447a85c5df18b9964d81bad17b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 May 2026 11:42:52 +0000 +Subject: wifi: ath11k: fix potential buffer underflow in + ath11k_hal_rx_msdu_list_get() + +From: Dmitry Morgun + +[ Upstream commit 7f11e70629650ff6ea140984e5ce188b775b2683 ] + +When the first entry in msdu_details has a zero buffer address, +the code accesses msdu_details[i - 1] with i == 0, causing a +buffer underflow. + +Fix similarly to ath12k_wifi7_hal_rx_msdu_list_get() by adding +a separate check for i == 0 before the main condition to prevent +the out-of-bounds access. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Dmitry Morgun +Reviewed-by: Rameshkumar Sundaram +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20260530114252.42615-1-d.morgun@ispras.ru +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 31fd92bd9efe8f..23771abb3acec5 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -4619,6 +4619,9 @@ static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar, + msdu_details = &msdu_link->msdu_link[0]; + + for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) { ++ if (!i && FIELD_GET(BUFFER_ADDR_INFO0_ADDR, ++ msdu_details[i].buf_addr_info.info0) == 0) ++ break; + if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR, + msdu_details[i].buf_addr_info.info0) == 0) { + msdu_desc_info = &msdu_details[i - 1].rx_msdu_info; +-- +2.53.0 + diff --git a/queue-6.6/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch b/queue-6.6/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch new file mode 100644 index 0000000000..1a0cece895 --- /dev/null +++ b/queue-6.6/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch @@ -0,0 +1,60 @@ +From b8724d8d883eb1b0f701b6a23ed13393caf0cb0c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 16:16:48 +0200 +Subject: wifi: ath11k: Flush the posted write after writing to + PCIE_SOC_GLOBAL_RESET + +From: Manivannan Sadhasivam + +[ Upstream commit 0fe8010fc5b147607fc19ba010ba469afc95f35f ] + +ath11k_pci_soc_global_reset() tries to reset the device by writing to the +PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure +that the write gets flushed to the device before the delay. + +This may lead to the delay on the host to be insufficient, if the posted +write doesn't reach the device before the delay. + +So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and +before the delay. + +Compile tested only. + +Fixes: f3c603d412b3 ("ath11k: reset MHI during power down and power up") +Reported-by: Alex Williamson +Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Reviewed-by: Raj Kumar Bhagat +Link: https://patch.msgid.link/20260623141649.41087-1-manivannan.sadhasivam@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c +index 09e65c5e55c4a9..966ba712ff9094 100644 +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -181,6 +181,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) + val |= PCIE_SOC_GLOBAL_RESET_V; + + ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); + + /* TODO: exact time to sleep is uncertain */ + delay = 10; +@@ -190,6 +192,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) + val &= ~PCIE_SOC_GLOBAL_RESET_V; + + ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); + + mdelay(delay); + +-- +2.53.0 + diff --git a/queue-6.6/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch b/queue-6.6/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch new file mode 100644 index 0000000000..bf5ef797c5 --- /dev/null +++ b/queue-6.6/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch @@ -0,0 +1,62 @@ +From f577dedbf25fa987ba15a3c2b54ea523448498f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 16:16:49 +0200 +Subject: wifi: ath12k: Flush the posted write after writing to + PCIE_SOC_GLOBAL_RESET + +From: Manivannan Sadhasivam + +[ Upstream commit 55f3aa06951cac78b0206bde961c8cf11929a27a ] + +ath12k_pci_soc_global_reset() tries to reset the device by writing to the +PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure +that the write gets flushed to the device before the delay. + +This may lead to the delay on the host to be insufficient, if the posted +write doesn't reach the device before the delay. + +So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and +before the delay. + +Compile tested only. +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1 + +Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") +Reported-by: Alex Williamson +Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Reviewed-by: Raj Kumar Bhagat +Tested-by: Raj Kumar Bhagat +Link: https://patch.msgid.link/20260623141649.41087-2-manivannan.sadhasivam@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c +index 7dfbabf0637d23..62be78de330011 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -211,6 +211,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab) + val |= PCIE_SOC_GLOBAL_RESET_V; + + ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET); + + /* TODO: exact time to sleep is uncertain */ + delay = 10; +@@ -220,6 +222,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab) + val &= ~PCIE_SOC_GLOBAL_RESET_V; + + ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET); + + mdelay(delay); + +-- +2.53.0 + diff --git a/queue-6.6/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch b/queue-6.6/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch new file mode 100644 index 0000000000..2d650963ad --- /dev/null +++ b/queue-6.6/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch @@ -0,0 +1,49 @@ +From 393440baaea57064418d655d55eeaaf7da435583 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:50:08 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware IE lengths in connect event + +From: Tristan Madani + +[ Upstream commit 6b47b29730de3232b919d8362749f6814c5f2a33 ] + +The firmware-controlled beacon_ie_len, assoc_req_len, and assoc_resp_len +fields in ath6kl_wmi_connect_event_rx() are not validated against the +buffer length. Their sum (up to 765) can exceed the actual WMI event +data, causing out-of-bounds reads during IE parsing and state corruption +of wmi->is_wmm_enabled. + +Add a check that the total IE length fits within the buffer. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20260421135009.348084-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index a572952dd4b903..447896b871c3e2 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -874,6 +874,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, + + ev = (struct wmi_connect_event *) datap; + ++ if (len < sizeof(*ev) + ev->beacon_ie_len + ++ ev->assoc_req_len + ev->assoc_resp_len) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, ++ "connect event: IE lengths %u+%u+%u exceed buffer %d\n", ++ ev->beacon_ie_len, ev->assoc_req_len, ++ ev->assoc_resp_len, len); ++ return -EINVAL; ++ } + if (vif->nw_type == AP_NETWORK) { + /* AP mode start/STA connected event */ + struct net_device *dev = vif->ndev; +-- +2.53.0 + diff --git a/queue-6.6/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch b/queue-6.6/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch new file mode 100644 index 0000000000..a36b497e7c --- /dev/null +++ b/queue-6.6/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch @@ -0,0 +1,53 @@ +From 19721576aeb072f97435f091e8bf7cffaf7b077b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jun 2026 23:29:07 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware num_msg in TX complete + handler + +From: Tristan Madani + +[ Upstream commit 3a21c89215cc18f1a97c5e5bfd1da6d4f3d44495 ] + +The firmware-controlled num_msg field (u8, 0-255) drives the loop in +ath6kl_wmi_tx_complete_event_rx() without validation against the buffer +length. This allows out-of-bounds reads of up to 1020 bytes past the +WMI event buffer when the firmware sends an inflated num_msg. + +Add a check that the buffer is large enough to hold the fixed struct +and the num_msg variable-length entries. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Link: https://patch.msgid.link/20260625232907.3620746-1-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index 3787b9fb007559..a572952dd4b903 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -484,6 +484,18 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) + + evt = (struct wmi_tx_complete_event *) datap; + ++ if (len < sizeof(*evt)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d\n", ++ len); ++ return -EINVAL; ++ } ++ ++ if (len < sizeof(*evt) + evt->num_msg * sizeof(struct tx_complete_msg_v1)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d for %u msgs\n", ++ len, evt->num_msg); ++ return -EINVAL; ++ } ++ + ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", + evt->num_msg, evt->msg_len, evt->msg_type); + +-- +2.53.0 + diff --git a/queue-6.6/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch b/queue-6.6/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch new file mode 100644 index 0000000000..0161604e39 --- /dev/null +++ b/queue-6.6/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch @@ -0,0 +1,90 @@ +From 30570ecd0c1ca6b6b82b1ed38cb5ea394c65d813 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 08:32:10 -0700 +Subject: wifi: ath9k: hif_usb: don't dereference hif_dev after re-arming + firmware request +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Cheng Yongkang + +[ Upstream commit dad9f96945d77ecd4708f730c06ef54dcd8cc057 ] + +ath9k_hif_request_firmware() re-arms an asynchronous firmware load via +request_firmware_nowait(), passing hif_dev as the completion context, and +then still dereferences hif_dev: + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", + hif_dev->fw_name); + +The re-armed callback ath9k_hif_usb_firmware_cb() runs on the "events" +workqueue and, when the firmware is missing, walks the retry chain into +ath9k_hif_usb_firmware_fail() -> complete_all(&hif_dev->fw_done). That +releases the wait_for_completion(&hif_dev->fw_done) in a concurrent +ath9k_hif_usb_disconnect(), which then kfree()s hif_dev. The trailing +dev_info() in the frame that re-armed the request can therefore read freed +memory (hif_dev->udev, the first field of struct hif_device_usb): + + BUG: KASAN: slab-use-after-free in ath9k_hif_request_firmware + Read of size 8 ... by task kworker/... + ath9k_hif_request_firmware + ath9k_hif_usb_firmware_cb drivers/net/wireless/ath/ath9k/hif_usb.c:1247 + request_firmware_work_func + Allocated by ...: + ath9k_hif_usb_probe drivers/net/wireless/ath/ath9k/hif_usb.c + Freed by ...: + ath9k_hif_usb_disconnect -> kfree drivers/net/wireless/ath/ath9k/hif_usb.c + +The fw_done barrier only makes disconnect wait for the firmware chain to +*terminate*; it does not protect the outer ath9k_hif_request_firmware() +frame that re-armed the request and keeps touching hif_dev afterwards. + +Drop the post-request dev_info(): it is the only use of hif_dev after the +async request is armed, and it is purely informational (the dev_err() on the +failure path runs only when request_firmware_nowait() did not arm a callback, +so hif_dev is still alive there). + +This was first reported by syzbot as a single, non-reproduced crash that was +later auto-obsoleted, and was independently rediscovered by the reFuzz fuzzer, +which produced a C reproducer (USB-gadget connect/disconnect of an ath9k_htc +device whose firmware download fails). The vulnerable code is unchanged and +still present in v7.1-rc6, where the slab-use-after-free reproduces under KASAN +once the (sub-microsecond) race window is widened. + +Fixes: e904cf6fe230 ("ath9k_htc: introduce support for different fw versions") +Reported-by: syzbot+50122cbc2874b1eb25b0@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=50122cbc2874b1eb25b0 +Signed-off-by: Cheng Yongkang +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260605153210.20471-1-1020691186@qq.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index ab728a70ed2796..110cf65b0f8804 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -1225,15 +1225,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, + ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, + &hif_dev->udev->dev, GFP_KERNEL, + hif_dev, ath9k_hif_usb_firmware_cb); +- if (ret) { ++ if (ret) + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Async request for firmware %s failed\n", + hif_dev->fw_name); +- return ret; +- } +- +- dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", +- hif_dev->fw_name); + + return ret; + } +-- +2.53.0 + diff --git a/queue-6.6/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch b/queue-6.6/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch new file mode 100644 index 0000000000..03079c753f --- /dev/null +++ b/queue-6.6/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch @@ -0,0 +1,69 @@ +From 8ae8861749f26d315e184c299651fcfd162169cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 May 2026 16:38:59 +0800 +Subject: wifi: brcmfmac: fix 802.1X-SHA256 call trace warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Shelley Yang + +[ Upstream commit 7cb34f6c4fe8a68af621d870abe63bfca2275dd6 ] + +Based on wpa_auth as 1x_256 mode, need to set up +"use_fwsup" with BRCMF_PROFILE_FWSUP_1X. +Or it will happen trace warning when call brcmf_cfg80211_set_pmk(). + +[ 4481.831101] ------------[ cut here ]------------ +[ 4481.831102] WARNING: CPU: 1 PID: 2997 at +drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:7242 brcmf_cfg80211_set_pmk+0x77/0xd0 [brcmfmac] +[...] +[ 4481.831202] Call Trace: +[ 4481.831204]   +[ 4481.831205]  nl80211_set_pmk+0x183/0x250 [cfg80211] +[ 4481.831233]  genl_family_rcv_msg_doit+0xea/0x150 +[ 4481.831237]  genl_rcv_msg+0x104/0x240 +[ 4481.831239]  ? cfg80211_probe_status+0x2c0/0x2c0 [cfg80211] +[ 4481.831257]  ? genl_family_rcv_msg_doit+0x150/0x150 +[ 4481.831259]  netlink_rcv_skb+0x4e/0x100 +[ 4481.831261]  genl_rcv+0x24/0x40 +[ 4481.831262]  netlink_unicast+0x236/0x380 +[ 4481.831264]  netlink_sendmsg+0x250/0x4b0 +[ 4481.831266]  sock_sendmsg+0x5c/0x70 +[ 4481.831269]  ____sys_sendmsg+0x236/0x2b0 +[ 4481.831271]  ? copy_msghdr_from_user+0x6d/0xa0 +[ 4481.831272]  ___sys_sendmsg+0x86/0xd0 +[ 4481.831274]  ? avc_has_perm+0x8c/0x1a0 +[ 4481.831276]  ? preempt_count_add+0x6a/0xa0 +[ 4481.831279]  ? sock_has_perm+0x82/0xa0 +[ 4481.831280]  __sys_sendmsg+0x57/0xa0 +[ 4481.831282]  do_syscall_64+0x38/0x90 +[ 4481.831284]  entry_SYSCALL_64_after_hwframe+0x63/0xcd +[ 4481.831286] RIP: 0033:0x7fd270d369b4 + +Fixes: 2526ff21aa77 ("brcmfmac: support 4-way handshake offloading for 802.1X") +Signed-off-by: Shelley Yang +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260525083859.581246-1-shelley.yang@infineon.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index c7f62226ebbcc5..7146e32717cfcf 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2122,7 +2122,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) + sme->crypto.akm_suites[0]); + return -EINVAL; + } +- } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { ++ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_1X_SHA256)) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + val = WPA2_AUTH_UNSPECIFIED; +-- +2.53.0 + diff --git a/queue-6.6/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch b/queue-6.6/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch new file mode 100644 index 0000000000..8062e0296e --- /dev/null +++ b/queue-6.6/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch @@ -0,0 +1,48 @@ +From a8b797c4a67deafbf20ae3a9a84929ee2c5e5fbb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:26 +0000 +Subject: wifi: carl9170: bound memcpy length in cmd callback to prevent OOB + read + +From: Tristan Madani + +[ Upstream commit 4cde55b2feff9504d1f993ab80e84e7ccb62791c ] + +When the firmware sends a command response with a length mismatch, +carl9170_cmd_callback() logs the mismatch and calls carl9170_restart() +but then falls through to memcpy(ar->readbuf, buffer + 4, len - 4). +Since len comes from the firmware and can exceed ar->readlen, this +copies more data than the readbuf was allocated for. + +Bound the memcpy to min(len - 4, ar->readlen) so that the response +is still completed -- avoiding repeated restarts from queued garbage -- +while preventing an overread past the response buffer. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-2-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 908c4c8b7f8256..9a25c2a540b95f 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -150,7 +150,8 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) + spin_lock(&ar->cmd_lock); + if (ar->readbuf) { + if (len >= 4) +- memcpy(ar->readbuf, buffer + 4, len - 4); ++ memcpy(ar->readbuf, buffer + 4, ++ min_t(u32, len - 4, ar->readlen)); + + ar->readbuf = NULL; + } +-- +2.53.0 + diff --git a/queue-6.6/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch b/queue-6.6/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch new file mode 100644 index 0000000000..c102280992 --- /dev/null +++ b/queue-6.6/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch @@ -0,0 +1,46 @@ +From 8ffecfd19856f35ea23f29b798029d18b36843d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:28 +0000 +Subject: wifi: carl9170: fix buffer overflow in rx_stream failover path + +From: Tristan Madani + +[ Upstream commit a1a21995c2e1cc2ca6b2226cfe4f5f018370182a ] + +The failover continuation in carl9170_rx_stream() copies the full tlen +from the second USB transfer instead of capping at rx_failover_missing +bytes. When both transfers are near maximum size, the total exceeds the +65535-byte failover SKB, triggering skb_over_panic. + +Limit the copy size to the missing byte count. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-4-tristmd@gmail.com +[Fix checkpatch CHECK:PARENTHESIS_ALIGNMENT] +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 9a25c2a540b95f..bda30b1f940459 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -918,7 +918,9 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) + } + } + +- skb_put_data(ar->rx_failover, tbuf, tlen); ++ skb_put_data(ar->rx_failover, tbuf, ++ min_t(unsigned int, tlen, ++ ar->rx_failover_missing)); + ar->rx_failover_missing -= tlen; + + if (ar->rx_failover_missing <= 0) { +-- +2.53.0 + diff --git a/queue-6.6/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch b/queue-6.6/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch new file mode 100644 index 0000000000..570dc3d55a --- /dev/null +++ b/queue-6.6/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch @@ -0,0 +1,42 @@ +From b213184cf45d84b693d6338a8a8831698bc1ddc3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:27 +0000 +Subject: wifi: carl9170: fix OOB read from off-by-two in TX status handler + +From: Tristan Madani + +[ Upstream commit a3f42f1049ad80c65560d2b078ad426c3134f78d ] + +The bounds check in carl9170_tx_process_status() uses +`i > ((cmd->hdr.len / 2) + 1)` which is off by two, allowing +2 extra iterations past valid _tx_status entries when the firmware- +controlled hdr.ext exceeds hdr.len/2. Fix by using the correct +comparison `i >= (cmd->hdr.len / 2)`. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c +index 88ef6e023f8266..d036ebb42c0d24 100644 +--- a/drivers/net/wireless/ath/carl9170/tx.c ++++ b/drivers/net/wireless/ath/carl9170/tx.c +@@ -693,7 +693,7 @@ void carl9170_tx_process_status(struct ar9170 *ar, + unsigned int i; + + for (i = 0; i < cmd->hdr.ext; i++) { +- if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) { ++ if (WARN_ON(i >= (cmd->hdr.len / 2))) { + print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE, + (void *) cmd, cmd->hdr.len + 4); + break; +-- +2.53.0 + diff --git a/queue-6.6/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch b/queue-6.6/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch new file mode 100644 index 0000000000..d6d059a929 --- /dev/null +++ b/queue-6.6/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch @@ -0,0 +1,50 @@ +From 8a829e0104a9239c5b91556a8a2784cfcce3915a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:08 +0300 +Subject: wifi: iwlwifi: mvm: fix read in wake packet notification handler + +From: Shahar Tzarfati + +[ Upstream commit 9d7657aae8c1579584c67b0b66114a6a98db8b2f ] + +In iwl_mvm_wowlan_store_wake_pkt(), packet_len was initialized from +notif->wake_packet_length before the explicit check that len >= +sizeof(*notif). + +Move the assignment of packet_len to after the size check so that +notif->wake_packet_length is only accessed once the payload length +has been validated. + +Fixes: 219ed58feda9 ("wifi: iwlwifi: mvm: Add support for wowlan wake packet notification") +Signed-off-by: Shahar Tzarfati +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.99d5cf85a528.Ic4aa736011d4fe88e0cd19723d1d48bb24642198@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +index ac304e21a36727..51abcd20ffbd60 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +@@ -2812,7 +2812,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, + struct iwl_wowlan_status_data *status, + u32 len) + { +- u32 data_size, packet_len = le32_to_cpu(notif->wake_packet_length); ++ u32 data_size, packet_len; + + if (len < sizeof(*notif)) { + IWL_ERR(mvm, "Invalid WoWLAN wake packet notification!\n"); +@@ -2831,6 +2831,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, + return -EIO; + } + ++ packet_len = le32_to_cpu(notif->wake_packet_length); + data_size = len - offsetof(struct iwl_wowlan_wake_pkt_notif, wake_packet); + + /* data_size got the padding from the notification, remove it. */ +-- +2.53.0 + diff --git a/queue-6.6/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch b/queue-6.6/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch new file mode 100644 index 0000000000..59442b09b4 --- /dev/null +++ b/queue-6.6/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch @@ -0,0 +1,56 @@ +From b2f76e64208c02c8098a147054be09ae916bf651 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:04 +0300 +Subject: wifi: iwlwifi: mvm: validate SAR GEO response payload size + +From: Pagadala Yesu Anjaneyulu + +[ Upstream commit 408d7da38272ce48e2db79b8a9895999f94d7655 ] + +The SAR GEO command response is cast to +iwl_geo_tx_power_profiles_resp without verifying the payload length. +A malformed or unexpected firmware response can lead to reading an +invalid structure layout. + +Add an explicit size check before accessing the response data and +return -EIO when the payload size is wrong. + +Fixes: f604324eefec ("iwlwifi: remove iwl_validate_sar_geo_profile() export") +Signed-off-by: Pagadala Yesu Anjaneyulu +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.7e749b7d374a.I4ef54548bff6c6e7c7a57bee771ac12508aad677@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +index c597492668fad5..d2ff33366b3c6c 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +@@ -908,12 +908,22 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) + return ret; + } + ++ if (IWL_FW_CHECK(mvm, ++ iwl_rx_packet_payload_len(cmd.resp_pkt) != ++ sizeof(*resp), ++ "Wrong size for iwl_geo_tx_power_profiles_resp: %d\n", ++ iwl_rx_packet_payload_len(cmd.resp_pkt))) { ++ ret = -EIO; ++ goto out; ++ } ++ + resp = (void *)cmd.resp_pkt->data; + ret = le32_to_cpu(resp->profile_idx); + + if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES_REV3)) + ret = -EIO; + ++out: + iwl_free_resp(&cmd); + return ret; + } +-- +2.53.0 + diff --git a/queue-6.6/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch b/queue-6.6/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch new file mode 100644 index 0000000000..dca9ea2e23 --- /dev/null +++ b/queue-6.6/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch @@ -0,0 +1,56 @@ +From d839a554fbbd6e2e046fa23d03d9ad7fee38e7a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:17:51 +1000 +Subject: wifi: mac80211: recalculate TIM when a station enters power save + +From: Andrew Pope + +[ Upstream commit a007a384c9eb17610f53a53e2f59944c31f1565a ] + +When an AP buffers frames for a station on its per-station TXQs and the +station subsequently enters power save, sta_ps_start() records the +buffered TIDs in txq_buffered_tids but does not update the TIM. The +station's TIM bit is only ever set when a further frame is buffered +while the station is already asleep +(ieee80211_tx_h_unicast_ps_buf() -> sta_info_recalc_tim()). + +If no further downlink frame arrives for that station the beacon +TIM never advertises the buffered traffic. A station relying on the +TIM then remains in doze indefinitely on top of a non-empty queue. Its +TXQs were removed from the scheduler's active list at PS entry, nothing +pages it, and the flow deadlocks until an unrelated event wakes the +station. + +Recalculate the TIM at the end of sta_ps_start(), so traffic +already buffered at PS entry is advertised immediately. +sta_info_recalc_tim() already consults txq_buffered_tids, which is +updated above, and is safe in this context (it is already called +from equivalent paths such as the tx handlers and +ieee80211_handle_filtered_frame()). + +Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation") +Signed-off-by: Andrew Pope +Link: https://patch.msgid.link/20260717011751.79524-1-andrew.pope@morsemicro.com +[add wifi: subject prefix] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index a716a055bff9a4..b0f975dbdde0da 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1568,6 +1568,8 @@ static void sta_ps_start(struct sta_info *sta) + else + clear_bit(tid, &sta->txq_buffered_tids); + } ++ ++ sta_info_recalc_tim(sta); + } + + static void sta_ps_end(struct sta_info *sta) +-- +2.53.0 + diff --git a/queue-6.6/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch b/queue-6.6/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch new file mode 100644 index 0000000000..04f9c9a68a --- /dev/null +++ b/queue-6.6/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch @@ -0,0 +1,75 @@ +From c05036d82677186226448bb32ded3d69d459d457 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 14:03:02 -0700 +Subject: wifi: mac80211: tear down new links on vif update error path + +From: Xiang Mei + +[ Upstream commit 952c02b33f56207a160421bcd61e7ac53c9c59ae ] + +When ieee80211_vif_update_links() adds new links it allocates a link +container for each and calls ieee80211_link_init() (which registers the +per-link debugfs files with file->private_data pointing into the container) +and ieee80211_link_setup(). If the subsequent drv_change_vif_links() fails, +the error path restores the old pointers and jumps to 'free', which frees +the new containers but never removes their debugfs entries or stops the +links. The debugfs files survive with file->private_data dangling at the +freed container, so a later open()+read() (e.g. link-1/txpower) +dereferences freed memory in ieee80211_if_read_link(), a use-after-free. + +The removal path already dismantles links correctly via +ieee80211_tear_down_links(), which removes each link's keys and debugfs +entries and calls ieee80211_link_stop(); the add path on the error branch +does not. Commit be1ba9ed221f ("wifi: mac80211: avoid weird state in error +path") hardened this same error path for the link-removal case +(new_links == 0) but left the newly-added links' teardown unaddressed. + +drv_change_vif_links() can fail at runtime on MLO drivers (internal +allocation / queue / firmware command failures). + +Remove the new links' debugfs entries and stop them before freeing. + + BUG: KASAN: slab-use-after-free in ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + Read of size 8 at addr ffff888011290000 by task exploit/145 + Call Trace: + ... + ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + short_proxy_read (fs/debugfs/file.c:373) + vfs_read (fs/read_write.c:572) + ksys_read (fs/read_write.c:716) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + ... + Oops: general protection fault, probably for non-canonical address 0xdffffc000000000a + RIP: 0010:ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + Kernel panic - not syncing: Fatal exception + +Fixes: 170cd6a66d9a ("wifi: mac80211: add netdev per-link debugfs data and driver hook") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/20260711210302.2098404-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/link.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/mac80211/link.c b/net/mac80211/link.c +index 2b44f1fe2031a9..f3980ee8173967 100644 +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -281,6 +281,10 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata, + memcpy(sdata->link, old_data, sizeof(old_data)); + memcpy(sdata->vif.link_conf, old, sizeof(old)); + ieee80211_set_vif_links_bitmaps(sdata, old_links, dormant_links); ++ for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { ++ ieee80211_link_debugfs_remove(&links[link_id]->data); ++ ieee80211_link_stop(&links[link_id]->data); ++ } + /* and free (only) the newly allocated links */ + memset(to_free, 0, sizeof(links)); + goto free; +-- +2.53.0 + diff --git a/queue-6.6/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch b/queue-6.6/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..2c9639addf --- /dev/null +++ b/queue-6.6/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,38 @@ +From de54dab2cfc51635202a8d1c5d8c148df48a6a8e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:24:59 +0200 +Subject: wifi: mt76: connac: fix possible NULL-pointer deref in + mt76_connac_mcu_uni_bss_he_tlv() + +From: Lorenzo Bianconi + +[ Upstream commit 2c1fb2335f5e3afb34f91bc07ecb63517c328090 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: d0e274af2f2e4 ("mt76: mt76_connac: create mcu library") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-1-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index a388078cdaa2ca..ef1e68154bb611 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -1406,6 +1406,8 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct bss_info_uni_he *he; + + cap = mt76_connac_get_he_phy_cap(phy, vif); ++ if (!cap) ++ return; + + he = (struct bss_info_uni_he *)tlv; + he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; +-- +2.53.0 + diff --git a/queue-6.6/wifi-mt76-mt7915-guard-he-capability-lookups.patch b/queue-6.6/wifi-mt76-mt7915-guard-he-capability-lookups.patch new file mode 100644 index 0000000000..48e7d815d8 --- /dev/null +++ b/queue-6.6/wifi-mt76-mt7915-guard-he-capability-lookups.patch @@ -0,0 +1,90 @@ +From d24e98b01ef1301433d6ff42926e05b2d0809fe4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 23:53:32 +0800 +Subject: wifi: mt76: mt7915: guard HE capability lookups + +From: Ruoyu Wang + +[ Upstream commit 8e9db062654a388d0fa587acbeeae68dd33eba41 ] + +mt7915_mcu_bss_he_tlv() and mt7915_mcu_sta_bfer_tlv() both run after +checking HE support, then dereference the HE PHY capability returned by +mt76_connac_get_he_phy_cap(). That helper can return NULL when no +capability entry matches the vif type. + +Fetch the capability before appending the TLV and skip the HE-specific +setup when no matching capability is available. + +Fixes: e6d557a78b60 ("mt76: mt7915: rely on mt76_connac_get_phy utilities") +Signed-off-by: Ruoyu Wang +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260620155332.81120-1-ruoyuw560@gmail.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +index f826089396e489..9ac95f14fdaf9f 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +@@ -545,6 +545,8 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!cap) ++ return; + + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he)); + +@@ -1125,13 +1127,12 @@ mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy, + } + + static void +-mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, +- struct mt7915_phy *phy, struct sta_rec_bf *bf) ++mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, ++ const struct ieee80211_sta_he_cap *vc, ++ struct sta_rec_bf *bf) + { + struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap; + struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; +- const struct ieee80211_sta_he_cap *vc = +- mt76_connac_get_he_phy_cap(phy->mt76, vif); + const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; + u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); + u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map); +@@ -1190,6 +1191,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_phy *phy = mvif->phy; ++ const struct ieee80211_sta_he_cap *vc = NULL; + int tx_ant = hweight8(phy->mt76->chainmask) - 1; + struct sta_rec_bf *bf; + struct tlv *tlv; +@@ -1208,6 +1210,12 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + if (!ebf && !dev->ibf) + return; + ++ if (sta->deflink.he_cap.has_he && ebf) { ++ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!vc) ++ return; ++ } ++ + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); + bf = (struct sta_rec_bf *)tlv; + +@@ -1216,7 +1224,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + * ht: iBF only, since mac80211 lacks of eBF support + */ + if (sta->deflink.he_cap.has_he && ebf) +- mt7915_mcu_sta_bfer_he(sta, vif, phy, bf); ++ mt7915_mcu_sta_bfer_he(sta, vc, bf); + else if (sta->deflink.vht_cap.vht_supported) + mt7915_mcu_sta_bfer_vht(sta, phy, bf, ebf); + else if (sta->deflink.ht_cap.ht_supported) +-- +2.53.0 + diff --git a/queue-6.6/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch b/queue-6.6/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch new file mode 100644 index 0000000000..4f0b7f7342 --- /dev/null +++ b/queue-6.6/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch @@ -0,0 +1,60 @@ +From 941ac448cdd245da1f8c822daa5be42d37387079 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:01 +0200 +Subject: wifi: mt76: mt7996: check pointer returned by + mt76_connac_get_he_phy_cap() + +From: Lorenzo Bianconi + +[ Upstream commit e858cf6bf99880343348ff1e8c942aaff1d9d592 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: 98686cd21624c ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-3-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +index 9f8c312b64d75c..ccbd9b9c409d82 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +@@ -583,6 +583,8 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!cap) ++ return; + + tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he)); + +@@ -1293,17 +1295,18 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, + { + struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap; + struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; +- const struct ieee80211_sta_he_cap *vc = +- mt76_connac_get_he_phy_cap(phy->mt76, vif); +- const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; + u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); + u8 nss_mcs = mt7996_mcu_get_sta_nss(mcs_map); ++ const struct ieee80211_he_cap_elem *ve; ++ const struct ieee80211_sta_he_cap *vc; + u8 snd_dim, sts; + ++ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif); + if (!vc) + return; + + bf->tx_mode = MT_PHY_TYPE_HE_SU; ++ ve = &vc->he_cap_elem; + + mt7996_mcu_sta_sounding_rate(bf); + +-- +2.53.0 + diff --git a/queue-6.6/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch b/queue-6.6/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..907aba9462 --- /dev/null +++ b/queue-6.6/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,51 @@ +From 9ce6a8163e777204b0ff09bcd85061d523159dea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:02 +0200 +Subject: wifi: mt76: mt7996: fix possible NULL-pointer deref in + mt7996_mcu_sta_bfer_eht() + +From: Lorenzo Bianconi + +[ Upstream commit 2fffc472bec490c8357defcee9c075ca74467352 ] + +mt76_connac_get_eht_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: ba01944adee9f ("wifi: mt76: mt7996: add EHT beamforming support") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-4-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +index ccbd9b9c409d82..2abc8d15ea8522 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +@@ -1360,14 +1360,18 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif, + struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap; + struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; + struct ieee80211_eht_mcs_nss_supp *eht_nss = &pc->eht_mcs_nss_supp; +- const struct ieee80211_sta_eht_cap *vc = +- mt76_connac_get_eht_phy_cap(phy->mt76, vif); +- const struct ieee80211_eht_cap_elem_fixed *ve = &vc->eht_cap_elem; + u8 nss_mcs = u8_get_bits(eht_nss->bw._80.rx_tx_mcs9_max_nss, + IEEE80211_EHT_MCS_NSS_RX) - 1; ++ const struct ieee80211_eht_cap_elem_fixed *ve; ++ const struct ieee80211_sta_eht_cap *vc; + u8 snd_dim, sts; + ++ vc = mt76_connac_get_eht_phy_cap(phy->mt76, vif); ++ if (!vc) ++ return; ++ + bf->tx_mode = MT_PHY_TYPE_EHT_MU; ++ ve = &vc->eht_cap_elem; + + mt7996_mcu_sta_sounding_rate(bf); + +-- +2.53.0 + diff --git a/queue-6.6/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch b/queue-6.6/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch new file mode 100644 index 0000000000..41978d3c83 --- /dev/null +++ b/queue-6.6/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch @@ -0,0 +1,104 @@ +From 37b4a0d9ade4e349e6f17326ad655fb1f1a0e3dc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 22:57:11 +0900 +Subject: wifi: mwifiex: bound uAP association event IEs to the event buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit f0858bfc7d3cab411a447b88e3ef970e575032c9 ] + +mwifiex_process_uap_event() handles EVENT_UAP_STA_ASSOC by exposing the +(re)association request IEs that the firmware copies into the event: + + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - (u8 *)&event->frame_control; + sinfo->assoc_req_ies_len = le16_to_cpu(event->len) - (u16)len; + +event->len is supplied by the device firmware and is never validated, +and the subtraction is unchecked. assoc_req_ies points into +adapter->event_body[MAX_EVENT_SIZE], a fixed-size array embedded in the +kmalloc()'d struct mwifiex_adapter. + +On the ap_11n_enabled path mwifiex_set_sta_ht_cap() walks these IEs with +cfg80211_find_ie(), whose for_each_element() loop dereferences each +element header. A firmware-reported event->len larger than the bytes +actually received makes assoc_req_ies_len describe IEs that extend past +event_body, so the walk reads out of the adapter slab object, a +slab-out-of-bounds read (KASAN: slab-out-of-bounds in cfg80211_find_ie). +An event->len smaller than the header instead makes the int subtraction +negative, which wraps to a huge size_t when stored in assoc_req_ies_len. +The same length is handed to cfg80211_new_sta(), so a more modest +over-claim can also copy stale event_body bytes into the +NL80211_CMD_NEW_STATION notification. + +A malicious or malfunctioning mwifiex device (USB/SDIO/PCIe) can deliver +such an event while the interface is in AP/uAP mode. + +Validate event->len before use: reject a length that underflows the +header or that would place the IEs outside the event_body[] buffer the +event was copied into. event->len here is struct mwifiex_assoc_event.len, +a payload field internal to this event, not the transport frame length, +so it is validated in this handler rather than at the generic +MWIFIEX_TYPE_EVENT receive path, which only sees the event cause and the +transport frame length. The bound is against event_body[MAX_EVENT_SIZE] +rather than the actually-received length because the transports store the +event differently (USB and SDIO leave the 4-byte event header in +event_skb, PCIe strips it via skb_pull), whereas event_body is the single +fixed buffer all of them copy the event into. This is the event-path +analogue of the receive-path bounds checks added in commit 119585281617 +("wifi: mwifiex: Fix OOB and integer underflow when rx packets"). + +Fixes: e568634ae7ac ("mwifiex: add AP event handling framework") +Signed-off-by: HE WEI (ギカク) +Reviewed-by: Francesco Dolcini +Link: https://patch.msgid.link/20260715135711.34688-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + .../net/wireless/marvell/mwifiex/uap_event.c | 24 +++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c +index 58ef5020a46a73..c7383abf064f50 100644 +--- a/drivers/net/wireless/marvell/mwifiex/uap_event.c ++++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c +@@ -123,11 +123,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) + len = ETH_ALEN; + + if (len != -1) { ++ u16 evt_len = le16_to_cpu(event->len); ++ + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - + (u8 *)&event->frame_control; +- sinfo->assoc_req_ies_len = +- le16_to_cpu(event->len) - (u16)len; ++ ++ /* ++ * event->len is reported by the device firmware ++ * and is not otherwise validated. Reject a ++ * length that underflows the header, or that ++ * would place the association request IEs ++ * outside the fixed-size event_body[] buffer the ++ * event was copied into; otherwise the IE walk ++ * in mwifiex_set_sta_ht_cap() reads past ++ * event_body and out of the adapter slab object. ++ */ ++ if (evt_len < len || ++ (u8 *)&event->frame_control + evt_len > ++ adapter->event_body + MAX_EVENT_SIZE) { ++ mwifiex_dbg(adapter, ERROR, ++ "invalid STA assoc event length\n"); ++ kfree(sinfo); ++ return -1; ++ } ++ sinfo->assoc_req_ies_len = evt_len - (u16)len; + } + } + cfg80211_new_sta(priv->netdev, event->sta_addr, sinfo, +-- +2.53.0 + diff --git a/queue-7.1/accel-ethosu-fix-element-size-accounting-for-cmd-str.patch b/queue-7.1/accel-ethosu-fix-element-size-accounting-for-cmd-str.patch new file mode 100644 index 0000000000..03c67efb16 --- /dev/null +++ b/queue-7.1/accel-ethosu-fix-element-size-accounting-for-cmd-str.patch @@ -0,0 +1,113 @@ +From bd8a39ccbf4eae7bc592114a0e0bb243b02a25f9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 18:14:47 -0500 +Subject: accel: ethosu: Fix element size accounting for cmd stream validation + +From: Rob Herring (Arm) + +[ Upstream commit 18a551482a4a326790698b273e76d7575a51a57d ] + +There are 2 issues with the element size handling in the command stream +validation which result in too small of a size calculated when the +element size is 16/32/64 bits. + +For NHWC format, the element size is simply missing from the +calculation. + +The bitfield for the element size is different between IFM/IFM2 and +OFM. IFM and IFM2 encode the precision in parameter bits 2:3, while OFM +uses bits 1:2. + +Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver") +Acked-by: Tomeu Vizoso +Link: https://patch.msgid.link/20260720231450.485221-1-robh@kernel.org +Signed-off-by: Rob Herring (Arm) +Signed-off-by: Sasha Levin +--- + drivers/accel/ethosu/ethosu_gem.c | 19 ++++++++++--------- + 1 file changed, 10 insertions(+), 9 deletions(-) + +diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c +index 3401883e207fc8..1daff32610c71b 100644 +--- a/drivers/accel/ethosu/ethosu_gem.c ++++ b/drivers/accel/ethosu/ethosu_gem.c +@@ -194,7 +194,7 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info, + + static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info, + struct feat_matrix *fm, +- u32 x, u32 y, u32 c) ++ u32 x, u32 y, u32 c, bool ofm) + { + u32 element_size, storage = fm->precision >> 14; + int tile = 0; +@@ -231,10 +231,11 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info, + + switch ((fm->precision >> 6) & 0x3) { // format + case 0: //nhwc: +- addr += x * fm->stride_x + c; ++ element_size = BIT((fm->precision >> (ofm ? 1 : 2)) & 0x3); ++ addr += x * fm->stride_x + c * element_size; + break; + case 1: //nhcwb16: +- element_size = BIT((fm->precision >> 1) & 0x3); ++ element_size = BIT((fm->precision >> (ofm ? 1 : 2)) & 0x3); + + addr += (c / 16) * fm->stride_c + (16 * x + (c & 0xf)) * element_size; + break; +@@ -268,7 +269,7 @@ static int calc_sizes(struct drm_device *ddev, + return -EINVAL; + + len = feat_matrix_length(info, &st->ifm, ifm_width, +- ifm_height, st->ifm.depth); ++ ifm_height, st->ifm.depth, false); + dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n", + op, st->ifm.region, st->ifm.base[0], len); + if (len == U64_MAX) +@@ -277,7 +278,7 @@ static int calc_sizes(struct drm_device *ddev, + + if (ifm2) { + len = feat_matrix_length(info, &st->ifm2, st->ifm.depth, +- 0, st->ofm.depth); ++ 0, st->ofm.depth, false); + dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n", + op, st->ifm2.region, st->ifm2.base[0], len); + if (len == U64_MAX) +@@ -309,7 +310,7 @@ static int calc_sizes(struct drm_device *ddev, + } + + len = feat_matrix_length(info, &st->ofm, st->ofm.width, +- st->ofm.height[2], st->ofm.depth); ++ st->ofm.height[2], st->ofm.depth, true); + dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n", + op, st->ofm.region, st->ofm.base[0], len); + if (len == U64_MAX) +@@ -333,7 +334,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, + depth = st->ifm.broadcast & 0x4 ? 0 : st->ofm.depth; + + len = feat_matrix_length(info, &st->ifm, width, +- height, depth); ++ height, depth, false); + dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n", + op, st->ifm.region, st->ifm.base[0], len); + if (len == U64_MAX) +@@ -346,7 +347,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, + depth = st->ifm2.broadcast & 0x4 ? 0 : st->ofm.depth; + + len = feat_matrix_length(info, &st->ifm2, width, +- height, depth); ++ height, depth, false); + dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n", + op, st->ifm2.region, st->ifm2.base[0], len); + if (len == U64_MAX) +@@ -354,7 +355,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, + } + + len = feat_matrix_length(info, &st->ofm, st->ofm.width, +- st->ofm.height[2], st->ofm.depth); ++ st->ofm.height[2], st->ofm.depth, true); + dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n", + op, st->ofm.region, st->ofm.base[0], len); + if (len == U64_MAX) +-- +2.53.0 + diff --git a/queue-7.1/accel-ethosu-handle-u85-internal-chaining-buffer.patch b/queue-7.1/accel-ethosu-handle-u85-internal-chaining-buffer.patch new file mode 100644 index 0000000000..f700257d6f --- /dev/null +++ b/queue-7.1/accel-ethosu-handle-u85-internal-chaining-buffer.patch @@ -0,0 +1,155 @@ +From 273e19d3742a04192808dbb02518092f55a686a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 18:14:48 -0500 +Subject: accel: ethosu: Handle U85 internal chaining buffer + +From: Rob Herring (Arm) + +[ Upstream commit 6b7e0066294d23ad1fd37f4326c32e8090fb8b65 ] + +The Ethos-U85 supports an internal chaining buffer as temporary storage +between some operations. When chaining is activated, the IFM/OFM region +setting selects a chaining buffer rather than a region, and the IFM/OFM +base addresses don't matter. In this case, the feature matrix size +calculations should be skipped. Otherwise, the command stream will be +intermittently rejected depending on prior feature matrix base +addresses. + +Fixes: 5a5e9c0228e6 ("accel: Add Arm Ethos-U NPU driver") +Acked-by: Tomeu Vizoso +Link: https://patch.msgid.link/20260720231450.485221-2-robh@kernel.org +Signed-off-by: Rob Herring (Arm) +Signed-off-by: Sasha Levin +--- + drivers/accel/ethosu/ethosu_gem.c | 35 +++++++++++++++++++++++-------- + 1 file changed, 26 insertions(+), 9 deletions(-) + +diff --git a/drivers/accel/ethosu/ethosu_gem.c b/drivers/accel/ethosu/ethosu_gem.c +index 1daff32610c71b..d50fed64d4d937 100644 +--- a/drivers/accel/ethosu/ethosu_gem.c ++++ b/drivers/accel/ethosu/ethosu_gem.c +@@ -192,7 +192,15 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info, + return len; + } + +-static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info, ++static bool feat_matrix_chained(struct ethosu_device *edev, struct feat_matrix *fm) ++{ ++ u32 storage = fm->precision >> 14; ++ ++ return !ethosu_is_u65(edev) && storage == 2; ++} ++ ++static u64 feat_matrix_length(struct ethosu_device *edev, ++ struct ethosu_validated_cmdstream_info *info, + struct feat_matrix *fm, + u32 x, u32 y, u32 c, bool ofm) + { +@@ -203,6 +211,9 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info, + if (fm->region < 0) + return U64_MAX; + ++ if (feat_matrix_chained(edev, fm)) ++ return 0; ++ + switch (storage) { + case 0: + if (x >= fm->width0 + 1) { +@@ -223,6 +234,8 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info, + tile = 1; + } + break; ++ default: ++ return U64_MAX; + } + if (fm->base[tile] == U64_MAX) + return U64_MAX; +@@ -251,6 +264,7 @@ static int calc_sizes(struct drm_device *ddev, + u16 op, struct cmd_state *st, + bool ifm, bool ifm2, bool weight, bool scale) + { ++ struct ethosu_device *edev = to_ethosu_device(ddev); + u64 len; + + if (ifm) { +@@ -268,7 +282,7 @@ static int calc_sizes(struct drm_device *ddev, + if (ifm_height < 0 || ifm_width < 0) + return -EINVAL; + +- len = feat_matrix_length(info, &st->ifm, ifm_width, ++ len = feat_matrix_length(edev, info, &st->ifm, ifm_width, + ifm_height, st->ifm.depth, false); + dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n", + op, st->ifm.region, st->ifm.base[0], len); +@@ -277,7 +291,7 @@ static int calc_sizes(struct drm_device *ddev, + } + + if (ifm2) { +- len = feat_matrix_length(info, &st->ifm2, st->ifm.depth, ++ len = feat_matrix_length(edev, info, &st->ifm2, st->ifm.depth, + 0, st->ofm.depth, false); + dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n", + op, st->ifm2.region, st->ifm2.base[0], len); +@@ -309,13 +323,14 @@ static int calc_sizes(struct drm_device *ddev, + st->scale[0].base + st->scale[0].length); + } + +- len = feat_matrix_length(info, &st->ofm, st->ofm.width, ++ len = feat_matrix_length(edev, info, &st->ofm, st->ofm.width, + st->ofm.height[2], st->ofm.depth, true); + dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n", + op, st->ofm.region, st->ofm.base[0], len); + if (len == U64_MAX) + return -EINVAL; +- info->output_region[st->ofm.region] = true; ++ if (!feat_matrix_chained(edev, &st->ofm)) ++ info->output_region[st->ofm.region] = true; + + return 0; + } +@@ -325,6 +340,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, + u16 op, struct cmd_state *st, + bool ifm, bool ifm2) + { ++ struct ethosu_device *edev = to_ethosu_device(ddev); + u32 height, width, depth; + u64 len; + +@@ -333,7 +349,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, + width = st->ifm.broadcast & 0x2 ? 0 : st->ofm.width; + depth = st->ifm.broadcast & 0x4 ? 0 : st->ofm.depth; + +- len = feat_matrix_length(info, &st->ifm, width, ++ len = feat_matrix_length(edev, info, &st->ifm, width, + height, depth, false); + dev_dbg(ddev->dev, "op %d: IFM:%d:0x%llx-0x%llx\n", + op, st->ifm.region, st->ifm.base[0], len); +@@ -346,7 +362,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, + width = st->ifm2.broadcast & 0x2 ? 0 : st->ofm.width; + depth = st->ifm2.broadcast & 0x4 ? 0 : st->ofm.depth; + +- len = feat_matrix_length(info, &st->ifm2, width, ++ len = feat_matrix_length(edev, info, &st->ifm2, width, + height, depth, false); + dev_dbg(ddev->dev, "op %d: IFM2:%d:0x%llx-0x%llx\n", + op, st->ifm2.region, st->ifm2.base[0], len); +@@ -354,13 +370,14 @@ static int calc_sizes_elemwise(struct drm_device *ddev, + return -EINVAL; + } + +- len = feat_matrix_length(info, &st->ofm, st->ofm.width, ++ len = feat_matrix_length(edev, info, &st->ofm, st->ofm.width, + st->ofm.height[2], st->ofm.depth, true); + dev_dbg(ddev->dev, "op %d: OFM:%d:0x%llx-0x%llx\n", + op, st->ofm.region, st->ofm.base[0], len); + if (len == U64_MAX) + return -EINVAL; +- info->output_region[st->ofm.region] = true; ++ if (!feat_matrix_chained(edev, &st->ofm)) ++ info->output_region[st->ofm.region] = true; + + return 0; + } +-- +2.53.0 + diff --git a/queue-7.1/alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch b/queue-7.1/alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch new file mode 100644 index 0000000000..225f9e4761 --- /dev/null +++ b/queue-7.1/alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch @@ -0,0 +1,60 @@ +From 64e7cb83059af9731ca5399c7ca69ca214fcf4cf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:36:25 +0800 +Subject: ALSA: hda: cs35l41: validate and free ACPI mute object + +From: Guangshuo Li + +[ Upstream commit 3b597d24dc0455ae926f1053f97c2725038fc3cd ] + +cs35l41_get_acpi_mute_state() evaluates a _DSM method to get the ACPI +mute state and reads the first byte from the returned object. + +However, the returned ACPI object is owned by the caller and is never +freed after use, so each successful query leaks the _DSM result object. + +The code also assumes that the returned object is a buffer with at least +one byte. A malformed firmware response can return a different object +type or an empty buffer, and the direct ret->buffer.pointer dereference +can then access an invalid pointer. + +Use the typed _DSM helper, validate that the returned buffer contains at +least one byte, and free the ACPI object after reading it. + +Fixes: 447106e92a0c ("ALSA: hda: cs35l41: Support mute notifications for CS35L41 HDA") +Signed-off-by: Guangshuo Li +Link: https://patch.msgid.link/20260708113625.752913-1-lgs201920130244@gmail.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/hda/codecs/side-codecs/cs35l41_hda.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.c b/sound/hda/codecs/side-codecs/cs35l41_hda.c +index 64a5bd895fd1e6..237059ef22f5c7 100644 +--- a/sound/hda/codecs/side-codecs/cs35l41_hda.c ++++ b/sound/hda/codecs/side-codecs/cs35l41_hda.c +@@ -1434,10 +1434,19 @@ static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle + guid_parse(CS35L41_UUID, &guid); + + if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) { +- ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL); ++ ret = acpi_evaluate_dsm_typed(handle, &guid, 0, ++ CS35L41_DSM_GET_MUTE, NULL, ++ ACPI_TYPE_BUFFER); ++ + if (!ret) + return -EINVAL; ++ if (!ret->buffer.length || !ret->buffer.pointer) { ++ ACPI_FREE(ret); ++ return -EINVAL; ++ } ++ + mute = *ret->buffer.pointer; ++ ACPI_FREE(ret); + dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute); + } + +-- +2.53.0 + diff --git a/queue-7.1/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch b/queue-7.1/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch new file mode 100644 index 0000000000..de997e42ab --- /dev/null +++ b/queue-7.1/amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch @@ -0,0 +1,58 @@ +From 8a096c088213c9679a84ad44893462b81e32c6c6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 15:20:06 +0530 +Subject: amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN + +From: Prashanth Kumar KR + +[ Upstream commit 4bf22afe53a1de4b44b04cf677fd5199089cbdff ] + +MAC_AUTO_SW (VR_MII_DIG_CTRL1 bit 9) enables automatic XPCS speed +mode switching after CL37 auto-negotiation and is only meaningful in +SGMII MAC mode. The original code unconditionally set this bit on +every call to xgbe_an37_set(), including when called from +xgbe_an37_disable() with enable=false. This left MAC_AUTO_SW=1 after +AN was disabled, causing the XPCS to autonomously switch speed from +stale AN state during subsequent mode changes, breaking SGMII speed +negotiation on 1G copper SFP modules. + +Patrick: This was breaking negotiation for all 1G SFP modules, +not just copper modules. + +Fixes: 42fd432fe6d3 ("amd-xgbe: align CL37 AN sequence as per databook") +Reported-by: Patrick Oppenlander +Link: https://lore.kernel.org/netdev/CAEg67GmFS0Q4oSZkz8zWdOzckSth9_vBPiOy6a7-d697C2w2Xg@mail.gmail.com +Signed-off-by: Prashanth Kumar KR +Tested-by: Patrick Oppenlander +Link: https://patch.msgid.link/20260709095006.3683940-1-prashanthkumar.k.r@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index fa0df61812076a..12770af031eb8b 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -267,9 +267,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, + + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); + +- reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); +- reg |= XGBE_VEND2_MAC_AUTO_SW; +- XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ if (pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) { ++ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); ++ if (enable) ++ reg |= XGBE_VEND2_MAC_AUTO_SW; ++ else ++ reg &= ~XGBE_VEND2_MAC_AUTO_SW; ++ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); ++ } + } + + static void xgbe_an37_restart(struct xgbe_prv_data *pdata) +-- +2.53.0 + diff --git a/queue-7.1/amt-make-the-head-writable-before-rewriting-the-l2-h.patch b/queue-7.1/amt-make-the-head-writable-before-rewriting-the-l2-h.patch new file mode 100644 index 0000000000..d6a1767795 --- /dev/null +++ b/queue-7.1/amt-make-the-head-writable-before-rewriting-the-l2-h.patch @@ -0,0 +1,67 @@ +From 8134a21c5da8216f4cf0fc76920e03edbd35ff56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:19:34 -0400 +Subject: amt: make the head writable before rewriting the L2 header + +From: Michael Bommarito + +[ Upstream commit 53969d704fa5b7c1751e277fac96bfc22b435eac ] + +amt_multicast_data_handler(), amt_membership_query_handler() and +amt_update_handler() rewrite the ethernet header of the decapsulated skb +in place (eth->h_proto, eth->h_dest and, for the query, also +eth->h_source) before handing it up the stack. The skb head may be +shared, for example when a packet tap has cloned it on the underlay +interface, so writing through it corrupts the other reader's copy. + +Call skb_cow_head() before the rewrite so the head is private. It is +placed before the pointers into the head are (re-)derived, so a +reallocation caused by the copy is picked up by those derivations. + +Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") +Signed-off-by: Michael Bommarito +Reviewed-by: Simon Horman +Reviewed-by: Taehee Yoo +Link: https://patch.msgid.link/20260711151934.2955226-3-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/amt.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/amt.c b/drivers/net/amt.c +index 00452d4ed3357b..a12ff8126c6986 100644 +--- a/drivers/net/amt.c ++++ b/drivers/net/amt.c +@@ -2320,6 +2320,9 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + skb_reset_mac_header(skb); + skb_pull(skb, sizeof(*eth)); + ++ if (skb_cow_head(skb, 0)) ++ return true; ++ + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + iph = ip_hdr(skb); +@@ -2396,6 +2399,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_network_header(skb); + eth = eth_hdr(skb); + ether_addr_copy(h_source, oeth->h_source); ++ if (skb_cow_head(skb, 0)) ++ return true; + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + +@@ -2521,6 +2526,9 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + ++ if (skb_cow_head(skb, 0)) ++ return true; ++ + iph = ip_hdr(skb); + if (iph->version == 4) { + if (ip_mc_check_igmp(skb)) { +-- +2.53.0 + diff --git a/queue-7.1/amt-re-read-skb-header-pointers-after-every-pull.patch b/queue-7.1/amt-re-read-skb-header-pointers-after-every-pull.patch new file mode 100644 index 0000000000..2114b3cac5 --- /dev/null +++ b/queue-7.1/amt-re-read-skb-header-pointers-after-every-pull.patch @@ -0,0 +1,367 @@ +From 383cb9aed2b9a64bfc82889d44db682e58f93923 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 11:19:33 -0400 +Subject: amt: re-read skb header pointers after every pull + +From: Michael Bommarito + +[ Upstream commit 3656a79f94c471827a08f2cacce5f94ad5e52c24 ] + +Several AMT receive and transmit paths cache a pointer into the skb head +(ip_hdr(), ipv6_hdr(), eth_hdr() or the AMT message header) and then call +a helper that can reallocate that head before the cached pointer is used +again. pskb_may_pull(), ip_mc_may_pull(), ipv6_mc_may_pull(), +iptunnel_pull_header(), ip_mc_check_igmp() and ipv6_mc_check_mld() can all +free the old head and move the data, so a pointer taken before the call +dangles afterwards and the later access is a use-after-free of the freed +head. + +The affected sites are: + + amt_rcv() caches ip_hdr() before amt_parse_type() pulls, then reads + iph->saddr. + + amt_dev_xmit() caches ip_hdr()/ipv6_hdr() before ip_mc_check_igmp()/ + ipv6_mc_check_mld() and pskb_may_pull(), then reads the group address. + + amt_multicast_data_handler() caches eth_hdr() before pskb_may_pull(), + then writes the L2 header. + + amt_membership_query_handler() caches the AMT header, the outer and + inner eth_hdr() and ip_hdr() before iptunnel_pull_header() and several + pulls, then reads and writes them. + + amt_igmpv3_report_handler() and amt_mldv2_report_handler() cache + ip_hdr()/ipv6_hdr() and the current group record and read the record + count from the report header inside the record loop, across the + *_mc_may_pull() calls. + + amt_update_handler() caches ip_hdr() and the AMT membership-update + header before pskb_may_pull(), iptunnel_pull_header(), + ip_mc_check_igmp() and the report handler, then reads iph->daddr and + amtmu->nonce / amtmu->response_mac. + +Fix each site by either snapshotting the scalar that is used after the +pull before the first pull runs, or re-deriving the header pointer from +the skb after the last pull that can move the head. Values that are +stable across the pull (source and group address, the response MAC and +nonce, the record count, the outer source MAC) are snapshotted; pointers +that are written through or read repeatedly are re-derived. + +Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") +Signed-off-by: Michael Bommarito +Reviewed-by: Simon Horman +Reviewed-by: Taehee Yoo +Link: https://patch.msgid.link/20260711151934.2955226-2-michael.bommarito@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/amt.c | 79 +++++++++++++++++++++++++++++++++-------------- + 1 file changed, 55 insertions(+), 24 deletions(-) + +diff --git a/drivers/net/amt.c b/drivers/net/amt.c +index 0f4ff41d053528..00452d4ed3357b 100644 +--- a/drivers/net/amt.c ++++ b/drivers/net/amt.c +@@ -1211,7 +1211,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + data = true; + } + v6 = false; +- group.ip4 = iph->daddr; ++ group.ip4 = ip_hdr(skb)->daddr; + #if IS_ENABLED(CONFIG_IPV6) + } else if (iph->version == 6) { + ip6h = ipv6_hdr(skb); +@@ -1235,7 +1235,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + data = true; + } + v6 = true; +- group.ip6 = ip6h->daddr; ++ group.ip6 = ipv6_hdr(skb)->daddr; + #endif + } else { + dev->stats.tx_errors++; +@@ -1278,12 +1278,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) + hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash], + node) { + if (!v6) { +- if (gnode->group_addr.ip4 == iph->daddr) ++ if (gnode->group_addr.ip4 == group.ip4) + goto found; + #if IS_ENABLED(CONFIG_IPV6) + } else { + if (ipv6_addr_equal(&gnode->group_addr.ip6, +- &ip6h->daddr)) ++ &group.ip6)) + goto found; + #endif + } +@@ -2000,14 +2000,18 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb, + struct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb); + int len = skb_transport_offset(skb) + sizeof(*ihrv3); + void *zero_grec = (void *)&igmpv3_zero_grec; +- struct iphdr *iph = ip_hdr(skb); + struct amt_group_node *gnode; + union amt_addr group, host; + struct igmpv3_grec *grec; ++ __be32 saddr; + u16 nsrcs; ++ u16 ngrec; + int i; + +- for (i = 0; i < ntohs(ihrv3->ngrec); i++) { ++ saddr = ip_hdr(skb)->saddr; ++ ngrec = ntohs(ihrv3->ngrec); ++ ++ for (i = 0; i < ngrec; i++) { + len += sizeof(*grec); + if (!ip_mc_may_pull(skb, len)) + break; +@@ -2019,10 +2023,13 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb, + if (!ip_mc_may_pull(skb, len)) + break; + ++ grec = (void *)(skb->data + len - sizeof(*grec) - ++ nsrcs * sizeof(__be32)); ++ + memset(&group, 0, sizeof(union amt_addr)); + group.ip4 = grec->grec_mca; + memset(&host, 0, sizeof(union amt_addr)); +- host.ip4 = iph->saddr; ++ host.ip4 = saddr; + gnode = amt_lookup_group(tunnel, &group, &host, false); + if (!gnode) { + gnode = amt_add_group(amt, tunnel, &group, &host, +@@ -2162,14 +2169,18 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb, + struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb); + int len = skb_transport_offset(skb) + sizeof(*mld2r); + void *zero_grec = (void *)&mldv2_zero_grec; +- struct ipv6hdr *ip6h = ipv6_hdr(skb); + struct amt_group_node *gnode; + union amt_addr group, host; + struct mld2_grec *grec; ++ struct in6_addr saddr; + u16 nsrcs; ++ u16 ngrec; + int i; + +- for (i = 0; i < ntohs(mld2r->mld2r_ngrec); i++) { ++ saddr = ipv6_hdr(skb)->saddr; ++ ngrec = ntohs(mld2r->mld2r_ngrec); ++ ++ for (i = 0; i < ngrec; i++) { + len += sizeof(*grec); + if (!ipv6_mc_may_pull(skb, len)) + break; +@@ -2181,10 +2192,13 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb, + if (!ipv6_mc_may_pull(skb, len)) + break; + ++ grec = (void *)(skb->data + len - sizeof(*grec) - ++ nsrcs * sizeof(struct in6_addr)); ++ + memset(&group, 0, sizeof(union amt_addr)); + group.ip6 = grec->grec_mca; + memset(&host, 0, sizeof(union amt_addr)); +- host.ip6 = ip6h->saddr; ++ host.ip6 = saddr; + gnode = amt_lookup_group(tunnel, &group, &host, true); + if (!gnode) { + gnode = amt_add_group(amt, tunnel, &group, &host, +@@ -2305,7 +2319,6 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + skb_push(skb, sizeof(*eth)); + skb_reset_mac_header(skb); + skb_pull(skb, sizeof(*eth)); +- eth = eth_hdr(skb); + + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; +@@ -2315,6 +2328,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!ipv4_is_multicast(iph->daddr)) + return true; + skb->protocol = htons(ETH_P_IP); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IP); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) +@@ -2328,6 +2342,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb) + if (!ipv6_addr_is_multicast(&ip6h->daddr)) + return true; + skb->protocol = htons(ETH_P_IPV6); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IPV6); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif +@@ -2351,10 +2366,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + struct sk_buff *skb) + { + struct amt_header_membership_query *amtmq; +- struct igmpv3_query *ihv3; + struct ethhdr *eth, *oeth; ++ struct igmpv3_query *ihv3; ++ u8 h_source[ETH_ALEN]; + struct iphdr *iph; + int hdr_size, len; ++ u64 response_mac; + + hdr_size = sizeof(*amtmq) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) +@@ -2367,6 +2384,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + if (amtmq->nonce != amt->nonce) + return true; + ++ response_mac = amtmq->response_mac; ++ + hdr_size -= sizeof(*eth); + if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false)) + return true; +@@ -2376,6 +2395,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_pull(skb, sizeof(*eth)); + skb_reset_network_header(skb); + eth = eth_hdr(skb); ++ ether_addr_copy(h_source, oeth->h_source); + if (!pskb_may_pull(skb, sizeof(*iph))) + return true; + +@@ -2388,6 +2408,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + sizeof(*ihv3))) + return true; + ++ iph = ip_hdr(skb); + if (!ipv4_is_multicast(iph->daddr)) + return true; + +@@ -2395,10 +2416,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS); + WRITE_ONCE(amt->ready4, true); +- amt->mac = amtmq->response_mac; ++ amt->mac = response_mac; + amt->req_cnt = 0; + amt->qi = ihv3->qqic; + skb->protocol = htons(ETH_P_IP); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IP); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) +@@ -2421,10 +2443,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + skb_reset_transport_header(skb); + skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS); + WRITE_ONCE(amt->ready6, true); +- amt->mac = amtmq->response_mac; ++ amt->mac = response_mac; + amt->req_cnt = 0; + amt->qi = mld2q->mld2q_qqic; + skb->protocol = htons(ETH_P_IPV6); ++ eth = eth_hdr(skb); + eth->h_proto = htons(ETH_P_IPV6); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif +@@ -2432,7 +2455,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, + return true; + } + +- ether_addr_copy(eth->h_source, oeth->h_source); ++ ether_addr_copy(eth->h_source, h_source); + skb->pkt_type = PACKET_MULTICAST; + skb->ip_summed = CHECKSUM_NONE; + len = skb->len; +@@ -2455,8 +2478,11 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + struct ethhdr *eth; + struct iphdr *iph; + int len, hdr_size; ++ u64 response_mac; ++ __be32 saddr; ++ __be32 nonce; + +- iph = ip_hdr(skb); ++ saddr = ip_hdr(skb)->saddr; + + hdr_size = sizeof(*amtmu) + sizeof(struct udphdr); + if (!pskb_may_pull(skb, hdr_size)) +@@ -2466,15 +2492,18 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + if (amtmu->reserved || amtmu->version) + return true; + ++ nonce = amtmu->nonce; ++ response_mac = amtmu->response_mac; ++ + if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false)) + return true; + + skb_reset_network_header(skb); + + list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) { +- if (tunnel->ip4 == iph->saddr) { +- if ((amtmu->nonce == tunnel->nonce && +- amtmu->response_mac == tunnel->mac)) { ++ if (tunnel->ip4 == saddr) { ++ if ((nonce == tunnel->nonce && ++ response_mac == tunnel->mac)) { + mod_delayed_work(amt_wq, &tunnel->gc_wq, + msecs_to_jiffies(amt_gmi(amt)) + * 3); +@@ -2508,6 +2537,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + eth = eth_hdr(skb); + skb->protocol = htons(ETH_P_IP); + eth->h_proto = htons(ETH_P_IP); ++ iph = ip_hdr(skb); + ip_eth_mc_map(iph->daddr, eth->h_dest); + #if IS_ENABLED(CONFIG_IPV6) + } else if (iph->version == 6) { +@@ -2527,6 +2557,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) + eth = eth_hdr(skb); + skb->protocol = htons(ETH_P_IPV6); + eth->h_proto = htons(ETH_P_IPV6); ++ ip6h = ipv6_hdr(skb); + ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); + #endif + } else { +@@ -2772,7 +2803,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb) + static int amt_rcv(struct sock *sk, struct sk_buff *skb) + { + struct amt_dev *amt; +- struct iphdr *iph; ++ __be32 saddr; + int type; + bool err; + +@@ -2785,7 +2816,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + } + + skb->dev = amt->dev; +- iph = ip_hdr(skb); ++ saddr = ip_hdr(skb)->saddr; + type = amt_parse_type(skb); + if (type == -1) { + err = true; +@@ -2795,7 +2826,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + if (amt->mode == AMT_MODE_GATEWAY) { + switch (type) { + case AMT_MSG_ADVERTISEMENT: +- if (iph->saddr != amt->discovery_ip) { ++ if (saddr != amt->discovery_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +@@ -2807,7 +2838,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + } + goto out; + case AMT_MSG_MULTICAST_DATA: +- if (iph->saddr != amt->remote_ip) { ++ if (saddr != amt->remote_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +@@ -2818,7 +2849,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) + else + goto out; + case AMT_MSG_MEMBERSHIP_QUERY: +- if (iph->saddr != amt->remote_ip) { ++ if (saddr != amt->remote_ip) { + netdev_dbg(amt->dev, "Invalid Relay IP\n"); + err = true; + goto drop; +-- +2.53.0 + diff --git a/queue-7.1/arm64-correct-value-returned-by-esr_elx_fsc_addrsz_n.patch b/queue-7.1/arm64-correct-value-returned-by-esr_elx_fsc_addrsz_n.patch new file mode 100644 index 0000000000..a72ef72293 --- /dev/null +++ b/queue-7.1/arm64-correct-value-returned-by-esr_elx_fsc_addrsz_n.patch @@ -0,0 +1,39 @@ +From 78d93e66d31aae455815ba212e8947b872912b04 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 14:48:35 +0100 +Subject: arm64: Correct value returned by ESR_ELx_FSC_ADDRSZ_nL() + +From: Steven Price + +[ Upstream commit b877075d0baa22c225842c2f19e3ea0a9cbcbe39 ] + +Address size fault, level -1 is encoded as 0b101001 or 0x29 according to +the Arm ARM. Correct the value to match the spec. This also matches the +offset of "level -1 address size fault" in the fault_info array in +fault.c. + +Fixes: fb8a3eba9c81 ("KVM: arm64: Only read HPFAR_EL2 when value is architecturally valid") +Signed-off-by: Steven Price +Reviewed-by: Marc Zyngier +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + arch/arm64/include/asm/esr.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h +index 7e86d400864e03..64e9bd137b603c 100644 +--- a/arch/arm64/include/asm/esr.h ++++ b/arch/arm64/include/asm/esr.h +@@ -131,7 +131,7 @@ + * Annoyingly, the negative levels for Address size faults aren't laid out + * contiguously (or in the desired order) + */ +-#define ESR_ELx_FSC_ADDRSZ_nL(n) ((n) == -1 ? 0x25 : 0x2C) ++#define ESR_ELx_FSC_ADDRSZ_nL(n) ((n) == -1 ? 0x29 : 0x2C) + #define ESR_ELx_FSC_ADDRSZ_L(n) ((n) < 0 ? ESR_ELx_FSC_ADDRSZ_nL(n) : \ + (ESR_ELx_FSC_ADDRSZ + (n))) + +-- +2.53.0 + diff --git a/queue-7.1/arm64-mm-check-the-requested-pfn-range-during-memory.patch b/queue-7.1/arm64-mm-check-the-requested-pfn-range-during-memory.patch new file mode 100644 index 0000000000..12756b03db --- /dev/null +++ b/queue-7.1/arm64-mm-check-the-requested-pfn-range-during-memory.patch @@ -0,0 +1,48 @@ +From f7f426e392f3d816a1023c3b7610bb87bfedf328 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 18:00:26 +0800 +Subject: arm64/mm: Check the requested PFN range during memory removal + +From: Richard Cheng + +[ Upstream commit 285f90a4d1141c7594f2368e19cbb307388eff30 ] + +prevent_memory_remove_notifier() advances pfn while scanning the requested +range for early memory. When the loop completes, pfn is at or beyond +end_pfn. Passing it to can_unmap_without_split() therefore checks a range +after the one being offlined. + +Consequently, a valid request can be rejected based on the following +range, while a request that would split a leaf mapping can be accepted if +the shifted range can be unmapped without a split. This was observed with +CXL DAX memory, where the final memory block was incorrectly allowed to +be offlined. + +Pass arg->start_pfn into can_unmap_without_split() so it checks the +requested range. + +Fixes: 95a58852b0e5 ("arm64/mm: Reject memory removal that splits a kernel leaf mapping") +Signed-off-by: Richard Cheng +Reviewed-by: Anshuman Khandual +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + arch/arm64/mm/mmu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c +index fd756390fe925c..fbbd31cd4cbd84 100644 +--- a/arch/arm64/mm/mmu.c ++++ b/arch/arm64/mm/mmu.c +@@ -2201,7 +2201,7 @@ static int prevent_memory_remove_notifier(struct notifier_block *nb, + } + } + +- if (!can_unmap_without_split(pfn, arg->nr_pages)) ++ if (!can_unmap_without_split(arg->start_pfn, arg->nr_pages)) + return NOTIFY_BAD; + + return NOTIFY_OK; +-- +2.53.0 + diff --git a/queue-7.1/arm_mpam-fix-mpamcfg_mbw_pbm-register-setting.patch b/queue-7.1/arm_mpam-fix-mpamcfg_mbw_pbm-register-setting.patch new file mode 100644 index 0000000000..e1e618ffe2 --- /dev/null +++ b/queue-7.1/arm_mpam-fix-mpamcfg_mbw_pbm-register-setting.patch @@ -0,0 +1,50 @@ +From edededd39ca9cdab8b21ea4a18b8a2d88eaa5879 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 6 Jun 2026 22:09:25 -0700 +Subject: arm_mpam: Fix MPAMCFG_MBW_PBM register setting + +From: Fenghua Yu + +[ Upstream commit 021118ce5ea954ec316d7e30bcf4506e12eb5222 ] + +MPAMCFG_MBW_PBM is written from cfg if cfg has the MBW partition feature. +It is reset when cfg does not have the MBW partition feature. + +But the register handling is reversed. This may cause an incorrect +register setting. For example, during an MPAM reset, reset_cfg is +empty (no MBW partition feature set), and cfg->mbw_pbm is 0. Instead of +resetting MPAMCFG_MBW_PBM to all 1's, the current logic will set it to +cfg->mbw_pbm, which is 0. + +Fix the issue by swapping the if/else branches. + +Fixes: a1cb6577f575 ("arm_mpam: Reset when feature configuration bit unset") +Reported-by: Matt Ochs +Signed-off-by: Fenghua Yu +Reviewed-by: Gavin Shan +Reviewed-by: Ben Horgan +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/resctrl/mpam_devices.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c +index 54e9da3158a89d..18ae935e8d51a5 100644 +--- a/drivers/resctrl/mpam_devices.c ++++ b/drivers/resctrl/mpam_devices.c +@@ -1563,9 +1563,9 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, + + if (mpam_has_feature(mpam_feat_mbw_part, rprops)) { + if (mpam_has_feature(mpam_feat_mbw_part, cfg)) +- mpam_reset_msc_bitmap(msc, MPAMCFG_MBW_PBM, rprops->mbw_pbm_bits); +- else + mpam_write_partsel_reg(msc, MBW_PBM, cfg->mbw_pbm); ++ else ++ mpam_reset_msc_bitmap(msc, MPAMCFG_MBW_PBM, rprops->mbw_pbm_bits); + } + + if (mpam_has_feature(mpam_feat_mbw_min, rprops)) { +-- +2.53.0 + diff --git a/queue-7.1/arm_mpam-fix-software-reset-values-of-mpamcfg_pri.patch b/queue-7.1/arm_mpam-fix-software-reset-values-of-mpamcfg_pri.patch new file mode 100644 index 0000000000..a4b5020402 --- /dev/null +++ b/queue-7.1/arm_mpam-fix-software-reset-values-of-mpamcfg_pri.patch @@ -0,0 +1,86 @@ +From e435b7399393eff78073afc6debd163110417e98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 May 2026 09:58:25 +0100 +Subject: arm_mpam: Fix software reset values of MPAMCFG_PRI + +From: Ben Horgan + +[ Upstream commit 9469764292e0d6825c9bf51d75682e3a623b9b6b ] + +Priority partitioning is not supported other than to set the per-PARTID +defaults in MPAMCFG_PRI, INTPRI and DSPRI, to the highest priority. When 0 +is the lowest priority, all ones is the highest priority. However, these +values are calculated with an extra higher bit set. + +Luckily, there is still no chance of setting functional bits incorrectly. +When the priority widths are maximal, this is ensured as the fields have +width 16 and a u16 holds the value for each field. When the widths are +smaller, the higher order bits beyond the advertised widths, +MPAMF_PRI_IDR.DSPRI_WD and MPAMF_PRI_IDR.INTPRI_WD, in the priority fields +INTPRI and DSPRI are not used to calculate the priority. It is not +specified whether these higher order bits are RAZ/WI or Res0 and so it is +desirable not to set them to avoid the chance of misleading reads. + +Correct the priority reset values. + +Fixes: 880df85d8673 ("arm_mpam: Probe and reset the rest of the features") +Signed-off-by: Ben Horgan +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/resctrl/mpam_devices.c | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c +index 988fc291241d23..54e9da3158a89d 100644 +--- a/drivers/resctrl/mpam_devices.c ++++ b/drivers/resctrl/mpam_devices.c +@@ -1535,12 +1535,9 @@ static u16 mpam_wa_t241_calc_min_from_max(struct mpam_props *props, + static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, + struct mpam_config *cfg) + { +- u32 pri_val = 0; + u16 cmax = MPAMCFG_CMAX_CMAX; + struct mpam_msc *msc = ris->vmsc->msc; + struct mpam_props *rprops = &ris->props; +- u16 dspri = GENMASK(rprops->dspri_wd, 0); +- u16 intpri = GENMASK(rprops->intpri_wd, 0); + + mutex_lock(&msc->part_sel_lock); + __mpam_part_sel(ris->ris_idx, partid, msc); +@@ -1605,16 +1602,25 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, + + if (mpam_has_feature(mpam_feat_intpri_part, rprops) || + mpam_has_feature(mpam_feat_dspri_part, rprops)) { +- /* aces high? */ +- if (!mpam_has_feature(mpam_feat_intpri_part_0_low, rprops)) +- intpri = 0; +- if (!mpam_has_feature(mpam_feat_dspri_part_0_low, rprops)) +- dspri = 0; ++ u32 pri_val = 0; ++ ++ if (mpam_has_feature(mpam_feat_intpri_part, rprops)) { ++ u16 intpri = GENMASK(rprops->intpri_wd - 1, 0); ++ ++ /* aces high? */ ++ if (!mpam_has_feature(mpam_feat_intpri_part_0_low, rprops)) ++ intpri = 0; + +- if (mpam_has_feature(mpam_feat_intpri_part, rprops)) + pri_val |= FIELD_PREP(MPAMCFG_PRI_INTPRI, intpri); +- if (mpam_has_feature(mpam_feat_dspri_part, rprops)) ++ } ++ if (mpam_has_feature(mpam_feat_dspri_part, rprops)) { ++ u16 dspri = GENMASK(rprops->dspri_wd - 1, 0); ++ ++ if (!mpam_has_feature(mpam_feat_dspri_part_0_low, rprops)) ++ dspri = 0; ++ + pri_val |= FIELD_PREP(MPAMCFG_PRI_DSPRI, dspri); ++ } + + mpam_write_partsel_reg(msc, PRI, pri_val); + } +-- +2.53.0 + diff --git a/queue-7.1/arm_mpam-guard-mbwu-state-before-adding-it-to-garbag.patch b/queue-7.1/arm_mpam-guard-mbwu-state-before-adding-it-to-garbag.patch new file mode 100644 index 0000000000..5004c63cc5 --- /dev/null +++ b/queue-7.1/arm_mpam-guard-mbwu-state-before-adding-it-to-garbag.patch @@ -0,0 +1,51 @@ +From 808b181dc333309a42a07ae83d8389e9ab1ebaeb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:23:23 +0800 +Subject: arm_mpam: guard MBWU state before adding it to garbage + +From: Guangshuo Li + +[ Upstream commit 977f52909c624210178a1247fab0b02b110c1106 ] + +__destroy_component_cfg() adds each RIS mbwu_state object to the MPAM +garbage list when destroying component configuration. + +However, mbwu_state is allocated per RIS and only for RISes with MBWU +monitors. A component can therefore have comp->cfg allocated while some +RISes still have ris->mbwu_state set to NULL. + +Passing a NULL mbwu_state to add_to_garbage() dereferences the NULL +pointer inside the macro. + +Skip RISes that do not have an mbwu_state object before adding them to +the garbage list. + +Fixes: 41e8a14950e1 ("arm_mpam: Track bandwidth counter state for power management") +Signed-off-by: Guangshuo Li +Reviewed-by: Ben Horgan +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/resctrl/mpam_devices.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c +index 18ae935e8d51a5..43dfce57fae1c1 100644 +--- a/drivers/resctrl/mpam_devices.c ++++ b/drivers/resctrl/mpam_devices.c +@@ -2595,8 +2595,10 @@ static void __destroy_component_cfg(struct mpam_component *comp) + msc = vmsc->msc; + + if (mpam_mon_sel_lock(msc)) { +- list_for_each_entry(ris, &vmsc->ris, vmsc_list) +- add_to_garbage(ris->mbwu_state); ++ list_for_each_entry(ris, &vmsc->ris, vmsc_list) { ++ if (ris->mbwu_state) ++ add_to_garbage(ris->mbwu_state); ++ } + mpam_mon_sel_unlock(msc); + } + } +-- +2.53.0 + diff --git a/queue-7.1/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch b/queue-7.1/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch new file mode 100644 index 0000000000..4b5d4cf026 --- /dev/null +++ b/queue-7.1/asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch @@ -0,0 +1,72 @@ +From 8ab851e0b905de89c86844e4034199db298ab980 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 18:06:20 +0800 +Subject: ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI + +From: Shengjiu Wang + +[ Upstream commit 0b604e886ece11b71c4daaeccc512c784b89b014 ] + +The bt-sco-pcm-wb DAI uses the same stream_name strings as bt-sco-pcm +("Playback" and "Capture"). This causes duplicate DAPM AIF widget +names within the same component, leading to debugfs warnings: + + debugfs: 'Playback' already exists in 'dapm' + debugfs: 'Capture' already exists in 'dapm' + +Give the wideband DAI distinct stream names ("WB Playback" and +"WB Capture") and add corresponding DAPM AIF widgets and routes for +them. + +Fixes: 5947e1b4992e ("ASoC: bt-sco: extend rate and add a general compatible string") +Assisted-by: VeroCoder:claude-sonnet-4-5 +Signed-off-by: Shengjiu Wang +Link: https://patch.msgid.link/20260715100620.1387159-1-shengjiu.wang@oss.nxp.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/bt-sco.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c +index 3afcef2dfa3529..c0bf45b76cb8c5 100644 +--- a/sound/soc/codecs/bt-sco.c ++++ b/sound/soc/codecs/bt-sco.c +@@ -17,11 +17,17 @@ static const struct snd_soc_dapm_widget bt_sco_widgets[] = { + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0, + SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_IN("BT_SCO_RX_WB", "WB Playback", 0, ++ SND_SOC_NOPM, 0, 0), ++ SND_SOC_DAPM_AIF_OUT("BT_SCO_TX_WB", "WB Capture", 0, ++ SND_SOC_NOPM, 0, 0), + }; + + static const struct snd_soc_dapm_route bt_sco_routes[] = { + { "BT_SCO_TX", NULL, "RX" }, + { "TX", NULL, "BT_SCO_RX" }, ++ { "BT_SCO_TX_WB", NULL, "RX" }, ++ { "TX", NULL, "BT_SCO_RX_WB" }, + }; + + static struct snd_soc_dai_driver bt_sco_dai[] = { +@@ -45,14 +51,14 @@ static struct snd_soc_dai_driver bt_sco_dai[] = { + { + .name = "bt-sco-pcm-wb", + .playback = { +- .stream_name = "Playback", ++ .stream_name = "WB Playback", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, + .capture = { +- .stream_name = "Capture", ++ .stream_name = "WB Capture", + .channels_min = 1, + .channels_max = 1, + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, +-- +2.53.0 + diff --git a/queue-7.1/asoc-cs35l56-fix-potential-probe-deadlock.patch b/queue-7.1/asoc-cs35l56-fix-potential-probe-deadlock.patch new file mode 100644 index 0000000000..9d2ede8910 --- /dev/null +++ b/queue-7.1/asoc-cs35l56-fix-potential-probe-deadlock.patch @@ -0,0 +1,111 @@ +From 5c3106e7ab30b6784cab372c5570d647d7c4001f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 14:20:44 +0100 +Subject: ASoC: cs35l56: Fix potential probe() deadlock + +From: Richard Fitzgerald + +[ Upstream commit 93c2a8ea2454b7b14eb378a58cad8a83c0ffc903 ] + +On I2C/SPI call cs35l56_init() before calling +snd_soc_register_component() to prevent the potential for a deadlock +on init_completion. + +For most buses all the hardware would be ready when probe() returns, +but on SoundWire, probe() must return before the SoundWire bus driver +will enumerate the device. All access to the registers must be deferred +until the driver receives an ATTACHED notification. But anything that +could return -EPROBE_DEFER must be called during probe, and that includes +snd_soc_register_component(). Because of that, on SoundWire the ASoC +component can be created before the registers are accssible, so +cs35l56_component_probe() waits for init_completion to signal that the +registers are accessible. + +On I2C/SPI this 2-stage startup isn't required so their probe() +functions simply called cs35l56_common_probe() and then cs35l56_init(). +The problem with this was that snd_soc_register_component() was still +called early. If this triggered ASoC to create the card, ASoC would call +cs35l56_component_probe() which waits on init_completion - but this would +be running inside the cs35l56 driver probe() so blocking it from reaching +the code that signals init_completion, causing a deadlock. + +Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Reported-by: Salman S. Tahir +Closes: https://lore.kernel.org/linux-sound/95c21574-97d5-4311-9263-9e174d22d22c@opensource.cirrus.com/T/#u +Tested-by: Salman S. Tahir +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260716132045.1469156-2-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56-i2c.c | 4 +--- + sound/soc/codecs/cs35l56-spi.c | 4 +--- + sound/soc/codecs/cs35l56.c | 15 +++++++++++++++ + 3 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c +index 0492ddc4102d80..8259714d8b2692 100644 +--- a/sound/soc/codecs/cs35l56-i2c.c ++++ b/sound/soc/codecs/cs35l56-i2c.c +@@ -55,9 +55,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client) + if (ret != 0) + return ret; + +- ret = cs35l56_init(cs35l56); +- if (ret == 0) +- ret = cs35l56_irq_request(&cs35l56->base, client->irq); ++ ret = cs35l56_irq_request(&cs35l56->base, client->irq); + if (ret < 0) + cs35l56_remove(cs35l56); + +diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c +index 9bc9b7c98390dc..b1eb924a5b6ccf 100644 +--- a/sound/soc/codecs/cs35l56-spi.c ++++ b/sound/soc/codecs/cs35l56-spi.c +@@ -44,9 +44,7 @@ static int cs35l56_spi_probe(struct spi_device *spi) + if (ret != 0) + return ret; + +- ret = cs35l56_init(cs35l56); +- if (ret == 0) +- ret = cs35l56_irq_request(&cs35l56->base, spi->irq); ++ ret = cs35l56_irq_request(&cs35l56->base, spi->irq); + if (ret < 0) + cs35l56_remove(cs35l56); + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index 033028a4734b50..001985e07d57c9 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -1975,6 +1975,16 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + goto err; + } + ++ /* ++ * On SoundWire the cs35l56_init() cannot be run until after the ++ * device has been enumerated by the SoundWire core. ++ */ ++ if (!cs35l56->sdw_peripheral) { ++ ret = cs35l56_init(cs35l56); ++ if (ret) ++ goto err_remove_wm_adsp; ++ } ++ + ret = snd_soc_register_component(cs35l56->base.dev, + &soc_component_dev_cs35l56, + cs35l56_dai, ARRAY_SIZE(cs35l56_dai)); +@@ -1989,6 +1999,11 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) + wm_adsp2_remove(&cs35l56->dsp); + + err: ++ if (pm_runtime_enabled(cs35l56->base.dev)) { ++ pm_runtime_dont_use_autosuspend(cs35l56->base.dev); ++ pm_runtime_disable(cs35l56->base.dev); ++ } ++ + gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0); + regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies); + +-- +2.53.0 + diff --git a/queue-7.1/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch b/queue-7.1/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch new file mode 100644 index 0000000000..e30d406bb1 --- /dev/null +++ b/queue-7.1/asoc-cs35l56-use-complete_all-to-signal-init_complet.patch @@ -0,0 +1,57 @@ +From 2171704861a249fde43e5c77cbf4de15ca061460 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 14:20:45 +0100 +Subject: ASoC: cs35l56: Use complete_all() to signal init_completion + +From: Richard Fitzgerald + +[ Upstream commit e0bffb63a2eda0af82ed7e6357ac67c2db990c21 ] + +In cs35l56_init() use complete_all() to signal init_completion instead +of complete(). + +cs35l56_init() was signaling init_completion using the complete() function. +This only releases ONE waiter. + +If cs35l56_component_probe() was called multiple times the first time +would consume that one signal, then future calls would timeout waiting for +the completion. This could happen if: + + - The component is probed, removed, then probed again without the cs35l56 + module being removed. + + - A call to component_probe() returns an error and ASoC calls it again + later. + +It should use complete_all() so that after it has been signaled it will +allow any code that waits on it to continue immediately. + +The one case where the driver must wait for initialization to run again is +when waiting for a reboot after firmware download, and here the code +correctly calls reinit_completion() first. + +Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56") +Signed-off-by: Richard Fitzgerald +Link: https://patch.msgid.link/20260716132045.1469156-3-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/cs35l56.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c +index 001985e07d57c9..ad0f88cc0fb4b6 100644 +--- a/sound/soc/codecs/cs35l56.c ++++ b/sound/soc/codecs/cs35l56.c +@@ -2089,7 +2089,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56) + return dev_err_probe(cs35l56->base.dev, ret, "Failed to write ASP1_CONTROL3\n"); + + cs35l56->base.init_done = true; +- complete(&cs35l56->init_completion); ++ complete_all(&cs35l56->init_completion); + + return 0; + } +-- +2.53.0 + diff --git a/queue-7.1/asoc-sun4i-codec-set-quirks.playback_only-for-h616-c.patch b/queue-7.1/asoc-sun4i-codec-set-quirks.playback_only-for-h616-c.patch new file mode 100644 index 0000000000..1439a2dcf5 --- /dev/null +++ b/queue-7.1/asoc-sun4i-codec-set-quirks.playback_only-for-h616-c.patch @@ -0,0 +1,39 @@ +From 110f207fdb6024d3d539ba79279355757242dee1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 19:33:03 +0800 +Subject: ASoC: sun4i-codec: Set quirks.playback_only for H616 codec + +From: Chen-Yu Tsai + +[ Upstream commit d9e96f859de3ea3e99bce927a988449a1816483c ] + +The H616 codec does not have capture capabilities. Set the +.playback_only quirks flag to denote this. + +This was somehow missing from the original driver patch, even though +the patch prior to it in the series added this quirk. + +Fixes: 9155c321a1d0 ("ASoC: sun4i-codec: support allwinner H616 codec") +Signed-off-by: Chen-Yu Tsai +Link: https://patch.msgid.link/20260714113304.270224-1-wens@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/sunxi/sun4i-codec.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c +index f4e22af594fa35..93f511fb61905e 100644 +--- a/sound/soc/sunxi/sun4i-codec.c ++++ b/sound/soc/sunxi/sun4i-codec.c +@@ -2237,6 +2237,7 @@ static const struct sun4i_codec_quirks sun50i_h616_codec_quirks = { + .reg_dac_fifoc = REG_FIELD(SUN50I_H616_CODEC_DAC_FIFOC, 0, 31), + .reg_dac_txdata = SUN8I_H3_CODEC_DAC_TXDATA, + .has_reset = true, ++ .playback_only = true, + .dma_max_burst = SUN4I_DMA_MAX_BURST, + }; + +-- +2.53.0 + diff --git a/queue-7.1/asoc-tas2781-bound-firmware-description-string-parsi.patch b/queue-7.1/asoc-tas2781-bound-firmware-description-string-parsi.patch new file mode 100644 index 0000000000..d6ae1e72ed --- /dev/null +++ b/queue-7.1/asoc-tas2781-bound-firmware-description-string-parsi.patch @@ -0,0 +1,153 @@ +From 42b7c49709ddfe1aca3d89059eb03ed9ff94c288 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 22:45:39 +0800 +Subject: ASoC: tas2781: bound firmware description string parsing + +From: Pengpeng Hou + +[ Upstream commit bc889dfcea9294a1eae7f8e2f3573a90764ae4d0 ] + +The TAS2781 firmware parser reads several variable-length description +strings with strlen() before checking that the string terminator is +present inside the firmware blob. A malformed firmware image without a +NUL terminator can therefore make the parser walk past the end of the +firmware buffer before the later size checks run. + +Add a small bounded string-length helper and use it for all description +fields that are parsed from the firmware buffer. Keep the existing size +checks for the fixed bytes that follow each string. + +Fixes: 915f5eadebd2 ("ASoC: tas2781: firmware lib") +Signed-off-by: Pengpeng Hou +Link: https://patch.msgid.link/20260706144540.93929-1-pengpeng@iscas.ac.cn +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/codecs/tas2781-fmwlib.c | 63 ++++++++++++++++++++++++++++--- + 1 file changed, 57 insertions(+), 6 deletions(-) + +diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c +index 885e0b6fed003a..583cda1f77fa24 100644 +--- a/sound/soc/codecs/tas2781-fmwlib.c ++++ b/sound/soc/codecs/tas2781-fmwlib.c +@@ -12,6 +12,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1099,13 +1100,42 @@ static int tasdevice_load_block_kernel( + return 0; + } + ++static int tasdevice_fw_strnlen(const struct firmware *fmw, int offset) ++{ ++ const u8 *start; ++ const u8 *nul; ++ size_t remaining; ++ size_t len; ++ ++ if (offset < 0 || offset >= fmw->size) ++ return -EINVAL; ++ ++ start = fmw->data + offset; ++ remaining = fmw->size - offset; ++ nul = memchr(start, '\0', remaining); ++ if (!nul) ++ return -EINVAL; ++ ++ len = nul - start; ++ if (len > INT_MAX) ++ return -EOVERFLOW; ++ ++ return len; ++} ++ + static int fw_parse_variable_hdr(struct tasdevice_priv + *tas_priv, struct tasdevice_dspfw_hdr *fw_hdr, + const struct firmware *fmw, int offset) + { + const unsigned char *buf = fmw->data; +- int len = strlen((char *)&buf[offset]); ++ int len; + ++ len = tasdevice_fw_strnlen(fmw, offset); ++ if (len < 0) { ++ dev_err(tas_priv->dev, "%s: Description error\n", __func__); ++ offset = len; ++ goto out; ++ } + len++; + + if (offset + len + 8 > fmw->size) { +@@ -1237,7 +1267,12 @@ static int fw_parse_data(struct tasdevice_fw *tas_fmw, + memcpy(img_data->name, &data[offset], 64); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_fmw->dev, "%s: Description error\n", __func__); ++ offset = n; ++ goto out; ++ } + n++; + if (offset + n + 2 > fmw->size) { + dev_err(tas_fmw->dev, "%s: Description error\n", __func__); +@@ -1308,7 +1343,12 @@ static int fw_parse_program_data(struct tasdevice_priv *tas_priv, + } + offset += 64; + +- n = strlen((char *)&buf[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + /* skip '\0' and 5 unused bytes */ + n += 6; + if (offset + n > fmw->size) { +@@ -1371,7 +1411,12 @@ static int fw_parse_configuration_data( + memcpy(config->name, &data[offset], 64); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + n += 15; + if (offset + n > fmw->size) { + dev_err(tas_priv->dev, "Description err\n"); +@@ -2133,7 +2178,8 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, + { + struct tasdevice_calibration *calibration; + unsigned char *data = (unsigned char *)fmw->data; +- unsigned int i, n; ++ unsigned int i; ++ int n; + + if (offset + 2 > fmw->size) { + dev_err(tas_priv->dev, "%s: Calibrations error\n", __func__); +@@ -2165,7 +2211,12 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv, + calibration = &(tas_fmw->calibrations[i]); + offset += 64; + +- n = strlen((char *)&data[offset]); ++ n = tasdevice_fw_strnlen(fmw, offset); ++ if (n < 0) { ++ dev_err(tas_priv->dev, "Description err\n"); ++ offset = n; ++ goto out; ++ } + /* skip '\0' and 2 unused bytes */ + n += 3; + if (offset + n > fmw->size) { +-- +2.53.0 + diff --git a/queue-7.1/bluetooth-btusb-validate-realtek-vendor-event-length.patch b/queue-7.1/bluetooth-btusb-validate-realtek-vendor-event-length.patch new file mode 100644 index 0000000000..b933154e47 --- /dev/null +++ b/queue-7.1/bluetooth-btusb-validate-realtek-vendor-event-length.patch @@ -0,0 +1,48 @@ +From 83f2e0f59767635ddd45253ca8501c9fe113581a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:47:17 +0800 +Subject: Bluetooth: btusb: validate Realtek vendor event length + +From: Pengpeng Hou + +[ Upstream commit df541cd485ff80a5ddc579d99687bc7506df9851 ] + +btusb_recv_event_realtek() reads the event code at data[0] and the Realtek +subevent code at data[2] before deciding whether to consume a vendor event +as a coredump. + +For example, the two-byte event ff 00 contains a complete vendor-event +header declaring zero parameters. The old classifier still reads a +nonexistent third byte and can misclassify the event as a coredump if the +adjacent byte is 0x34. + +Require the HCI event header and first parameter to be present before +inspecting the Realtek subevent code. Short events continue through the +normal HCI receive path, which owns their protocol validation. + +Fixes: 044014ce85a1 ("Bluetooth: btrtl: Add Realtek devcoredump support") +Signed-off-by: Pengpeng Hou +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + drivers/bluetooth/btusb.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c +index cc6392f8d98cd2..7f66e7c6e77ad4 100644 +--- a/drivers/bluetooth/btusb.c ++++ b/drivers/bluetooth/btusb.c +@@ -2765,7 +2765,9 @@ static int btusb_setup_realtek(struct hci_dev *hdev) + + static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb) + { +- if (skb->data[0] == HCI_VENDOR_PKT && skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) { ++ if (skb->len >= HCI_EVENT_HDR_SIZE + 1 && ++ skb->data[0] == HCI_VENDOR_PKT && ++ skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) { + struct rtk_dev_coredump_hdr hdr = { + .code = RTK_DEVCOREDUMP_CODE_MEMDUMP, + }; +-- +2.53.0 + diff --git a/queue-7.1/bnge-bng_re-fix-ring-id-widths.patch b/queue-7.1/bnge-bng_re-fix-ring-id-widths.patch new file mode 100644 index 0000000000..317212f76e --- /dev/null +++ b/queue-7.1/bnge-bng_re-fix-ring-id-widths.patch @@ -0,0 +1,394 @@ +From 1358be1d5b69357d4b1208864f1fb28b5d607c20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 12:07:31 +0530 +Subject: bnge/bng_re: fix ring ID widths + +From: Vikas Gupta + +[ Upstream commit b9e558976bb968162c35ddccdb076a77fc906993 ] + +Firmware requires more than 16 bits to address TX ring IDs for its +internal QP management. Widen the associated HSI ring ID fields to +32 bits. The values firmware assigns remain within 24 bits, bounded +by the hardware doorbell XID field. + +The fw_ring_id field belongs to bnge_ring_struct, a common struct +shared by all ring types, so widening it to u32 applies uniformly +across TX, RX, CP, and NQ rings but firmware assigns values within +16-bit range for all ring types except TX, which requires the wider +field. + +Note that, Thor Ultra hardware has not yet been deployed and no +firmware has been released to field, so backward compatibility +is not a concern. + +Fixes: 42d1c54d6248 ("bnge/bng_re: Add a new HSI") +Signed-off-by: Vikas Gupta +Reviewed-by: Siva Reddy Kallam +Reviewed-by: Dharmender Garg +Reviewed-by: Yendapally Reddy Dhananjaya Reddy +Link: https://patch.msgid.link/20260721063731.2622500-1-vikas.gupta@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/infiniband/hw/bng_re/bng_dev.c | 6 +-- + drivers/net/ethernet/broadcom/bnge/bnge.h | 1 + + .../ethernet/broadcom/bnge/bnge_hwrm_lib.c | 8 +-- + .../ethernet/broadcom/bnge/bnge_hwrm_lib.h | 2 +- + .../net/ethernet/broadcom/bnge/bnge_netdev.c | 50 +++++++++---------- + .../net/ethernet/broadcom/bnge/bnge_netdev.h | 4 +- + .../net/ethernet/broadcom/bnge/bnge_rmem.h | 2 +- + include/linux/bnge/hsi.h | 7 ++- + 8 files changed, 39 insertions(+), 41 deletions(-) + +diff --git a/drivers/infiniband/hw/bng_re/bng_dev.c b/drivers/infiniband/hw/bng_re/bng_dev.c +index 71a7ca2196ad88..311c8bc931603a 100644 +--- a/drivers/infiniband/hw/bng_re/bng_dev.c ++++ b/drivers/infiniband/hw/bng_re/bng_dev.c +@@ -113,7 +113,7 @@ static void bng_re_fill_fw_msg(struct bnge_fw_msg *fw_msg, void *msg, + } + + static int bng_re_net_ring_free(struct bng_re_dev *rdev, +- u16 fw_ring_id, int type) ++ u32 fw_ring_id, int type) + { + struct bnge_auxr_dev *aux_dev = rdev->aux_dev; + struct hwrm_ring_free_input req = {}; +@@ -123,7 +123,7 @@ static int bng_re_net_ring_free(struct bng_re_dev *rdev, + + bng_re_init_hwrm_hdr((void *)&req, HWRM_RING_FREE); + req.ring_type = type; +- req.ring_id = cpu_to_le16(fw_ring_id); ++ req.ring_id = cpu_to_le32(fw_ring_id); + bng_re_fill_fw_msg(&fw_msg, (void *)&req, sizeof(req), (void *)&resp, + sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT); + rc = bnge_send_msg(aux_dev, &fw_msg); +@@ -161,7 +161,7 @@ static int bng_re_net_ring_alloc(struct bng_re_dev *rdev, + sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT); + rc = bnge_send_msg(aux_dev, &fw_msg); + if (!rc) +- *fw_ring_id = le16_to_cpu(resp.ring_id); ++ *fw_ring_id = (u16)le32_to_cpu(resp.ring_id); + + return rc; + } +diff --git a/drivers/net/ethernet/broadcom/bnge/bnge.h b/drivers/net/ethernet/broadcom/bnge/bnge.h +index f21cff651fd44a..4479ccd071f532 100644 +--- a/drivers/net/ethernet/broadcom/bnge/bnge.h ++++ b/drivers/net/ethernet/broadcom/bnge/bnge.h +@@ -36,6 +36,7 @@ struct bnge_pf_info { + }; + + #define INVALID_HW_RING_ID ((u16)-1) ++#define INVALID_HW_RING_ID_32BIT (U32_MAX) + + enum { + BNGE_FW_CAP_SHORT_CMD = BIT_ULL(0), +diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +index 1c9cfec1b633fc..651c5e783516cc 100644 +--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c ++++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +@@ -1283,7 +1283,7 @@ int bnge_hwrm_stat_ctx_alloc(struct bnge_net *bn) + + int hwrm_ring_free_send_msg(struct bnge_net *bn, + struct bnge_ring_struct *ring, +- u32 ring_type, int cmpl_ring_id) ++ u32 ring_type, u32 cmpl_ring_id) + { + struct hwrm_ring_free_input *req; + struct bnge_dev *bd = bn->bd; +@@ -1295,7 +1295,7 @@ int hwrm_ring_free_send_msg(struct bnge_net *bn, + + req->cmpl_ring = cpu_to_le16(cmpl_ring_id); + req->ring_type = ring_type; +- req->ring_id = cpu_to_le16(ring->fw_ring_id); ++ req->ring_id = cpu_to_le32(ring->fw_ring_id); + + bnge_hwrm_req_hold(bd, req); + rc = bnge_hwrm_req_send(bd, req); +@@ -1317,7 +1317,7 @@ int hwrm_ring_alloc_send_msg(struct bnge_net *bn, + struct hwrm_ring_alloc_output *resp; + struct hwrm_ring_alloc_input *req; + struct bnge_dev *bd = bn->bd; +- u16 ring_id, flags = 0; ++ u32 ring_id, flags = 0; + int rc; + + rc = bnge_hwrm_req_init(bd, req, HWRM_RING_ALLOC); +@@ -1401,7 +1401,7 @@ int hwrm_ring_alloc_send_msg(struct bnge_net *bn, + + resp = bnge_hwrm_req_hold(bd, req); + rc = bnge_hwrm_req_send(bd, req); +- ring_id = le16_to_cpu(resp->ring_id); ++ ring_id = le32_to_cpu(resp->ring_id); + bnge_hwrm_req_drop(bd, req); + + exit: +diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h +index 3501de7a89b919..bf452e390d5bd1 100644 +--- a/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h ++++ b/drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h +@@ -50,7 +50,7 @@ int bnge_hwrm_cfa_l2_set_rx_mask(struct bnge_dev *bd, + void bnge_hwrm_stat_ctx_free(struct bnge_net *bn); + int bnge_hwrm_stat_ctx_alloc(struct bnge_net *bn); + int hwrm_ring_free_send_msg(struct bnge_net *bn, struct bnge_ring_struct *ring, +- u32 ring_type, int cmpl_ring_id); ++ u32 ring_type, u32 cmpl_ring_id); + int hwrm_ring_alloc_send_msg(struct bnge_net *bn, + struct bnge_ring_struct *ring, + u32 ring_type, u32 map_index); +diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +index 70768193004cb2..6f7ef506d4e18c 100644 +--- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c ++++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +@@ -1327,12 +1327,12 @@ static int bnge_alloc_core(struct bnge_net *bn) + return rc; + } + +-u16 bnge_cp_ring_for_rx(struct bnge_rx_ring_info *rxr) ++u32 bnge_cp_ring_for_rx(struct bnge_rx_ring_info *rxr) + { + return rxr->rx_cpr->ring_struct.fw_ring_id; + } + +-u16 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr) ++u32 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr) + { + return txr->tx_cpr->ring_struct.fw_ring_id; + } +@@ -1375,12 +1375,12 @@ static void bnge_init_nq_tree(struct bnge_net *bn) + struct bnge_nq_ring_info *nqr = &bn->bnapi[i]->nq_ring; + struct bnge_ring_struct *ring = &nqr->ring_struct; + +- ring->fw_ring_id = INVALID_HW_RING_ID; ++ ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + for (j = 0; j < nqr->cp_ring_count; j++) { + struct bnge_cp_ring_info *cpr = &nqr->cp_ring_arr[j]; + + ring = &cpr->ring_struct; +- ring->fw_ring_id = INVALID_HW_RING_ID; ++ ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + } + } + } +@@ -1637,7 +1637,7 @@ static void bnge_init_one_rx_ring_rxbd(struct bnge_net *bn, + + ring = &rxr->rx_ring_struct; + bnge_init_rxbd_pages(ring, type); +- ring->fw_ring_id = INVALID_HW_RING_ID; ++ ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + } + + static void bnge_init_one_agg_ring_rxbd(struct bnge_net *bn, +@@ -1647,7 +1647,7 @@ static void bnge_init_one_agg_ring_rxbd(struct bnge_net *bn, + u32 type; + + ring = &rxr->rx_agg_ring_struct; +- ring->fw_ring_id = INVALID_HW_RING_ID; ++ ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + if (bnge_is_agg_reqd(bn->bd)) { + type = ((u32)BNGE_RX_PAGE_SIZE << RX_BD_LEN_SHIFT) | + RX_BD_TYPE_RX_AGG_BD | RX_BD_FLAGS_SOP; +@@ -1708,7 +1708,7 @@ static void bnge_init_tx_rings(struct bnge_net *bn) + struct bnge_tx_ring_info *txr = &bn->tx_ring[i]; + struct bnge_ring_struct *ring = &txr->tx_ring_struct; + +- ring->fw_ring_id = INVALID_HW_RING_ID; ++ ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + + netif_queue_set_napi(bn->netdev, i, NETDEV_QUEUE_TYPE_TX, + &txr->bnapi->napi); +@@ -1867,7 +1867,7 @@ static int bnge_hwrm_rx_agg_ring_alloc(struct bnge_net *bn, + ring->fw_ring_id); + bnge_db_write(bn->bd, &rxr->rx_agg_db, rxr->rx_agg_prod); + bnge_db_write(bn->bd, &rxr->rx_db, rxr->rx_prod); +- bn->grp_info[grp_idx].agg_fw_ring_id = ring->fw_ring_id; ++ bn->grp_info[grp_idx].agg_fw_ring_id = (u16)ring->fw_ring_id; + + return 0; + } +@@ -1886,7 +1886,7 @@ static int bnge_hwrm_rx_ring_alloc(struct bnge_net *bn, + return rc; + + bnge_set_db(bn, &rxr->rx_db, type, map_idx, ring->fw_ring_id); +- bn->grp_info[map_idx].rx_fw_ring_id = ring->fw_ring_id; ++ bn->grp_info[map_idx].rx_fw_ring_id = (u16)ring->fw_ring_id; + + return 0; + } +@@ -1916,7 +1916,7 @@ static int bnge_hwrm_ring_alloc(struct bnge_net *bn) + bnge_set_db(bn, &nqr->nq_db, type, map_idx, ring->fw_ring_id); + bnge_db_nq(bn, &nqr->nq_db, nqr->nq_raw_cons); + enable_irq(vector); +- bn->grp_info[i].nq_fw_ring_id = ring->fw_ring_id; ++ bn->grp_info[i].nq_fw_ring_id = (u16)ring->fw_ring_id; + + if (!i) { + rc = bnge_hwrm_set_async_event_cr(bd, ring->fw_ring_id); +@@ -1986,15 +1986,13 @@ void bnge_fill_hw_rss_tbl(struct bnge_net *bn, struct bnge_vnic_info *vnic) + tbl_size = bnge_get_rxfh_indir_size(bd); + + for (i = 0; i < tbl_size; i++) { +- u16 ring_id, j; ++ u32 j; + + j = bd->rss_indir_tbl[i]; + rxr = &bn->rx_ring[j]; + +- ring_id = rxr->rx_ring_struct.fw_ring_id; +- *ring_tbl++ = cpu_to_le16(ring_id); +- ring_id = bnge_cp_ring_for_rx(rxr); +- *ring_tbl++ = cpu_to_le16(ring_id); ++ *ring_tbl++ = cpu_to_le16(rxr->rx_ring_struct.fw_ring_id); ++ *ring_tbl++ = cpu_to_le16(bnge_cp_ring_for_rx(rxr)); + } + } + +@@ -2285,7 +2283,7 @@ static void bnge_disable_int(struct bnge_net *bn) + nqr = &bnapi->nq_ring; + ring = &nqr->ring_struct; + +- if (ring->fw_ring_id != INVALID_HW_RING_ID) ++ if (ring->fw_ring_id != INVALID_HW_RING_ID_32BIT) + bnge_db_nq(bn, &nqr->nq_db, nqr->nq_raw_cons); + } + } +@@ -2401,7 +2399,7 @@ static void bnge_hwrm_rx_ring_free(struct bnge_net *bn, + u32 grp_idx = rxr->bnapi->index; + u32 cmpl_ring_id; + +- if (ring->fw_ring_id == INVALID_HW_RING_ID) ++ if (ring->fw_ring_id == INVALID_HW_RING_ID_32BIT) + return; + + cmpl_ring_id = bnge_cp_ring_for_rx(rxr); +@@ -2409,7 +2407,7 @@ static void bnge_hwrm_rx_ring_free(struct bnge_net *bn, + RING_FREE_REQ_RING_TYPE_RX, + close_path ? cmpl_ring_id : + INVALID_HW_RING_ID); +- ring->fw_ring_id = INVALID_HW_RING_ID; ++ ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + bn->grp_info[grp_idx].rx_fw_ring_id = INVALID_HW_RING_ID; + } + +@@ -2421,14 +2419,14 @@ static void bnge_hwrm_rx_agg_ring_free(struct bnge_net *bn, + u32 grp_idx = rxr->bnapi->index; + u32 cmpl_ring_id; + +- if (ring->fw_ring_id == INVALID_HW_RING_ID) ++ if (ring->fw_ring_id == INVALID_HW_RING_ID_32BIT) + return; + + cmpl_ring_id = bnge_cp_ring_for_rx(rxr); + hwrm_ring_free_send_msg(bn, ring, RING_FREE_REQ_RING_TYPE_RX_AGG, + close_path ? cmpl_ring_id : + INVALID_HW_RING_ID); +- ring->fw_ring_id = INVALID_HW_RING_ID; ++ ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + bn->grp_info[grp_idx].agg_fw_ring_id = INVALID_HW_RING_ID; + } + +@@ -2439,14 +2437,14 @@ static void bnge_hwrm_tx_ring_free(struct bnge_net *bn, + struct bnge_ring_struct *ring = &txr->tx_ring_struct; + u32 cmpl_ring_id; + +- if (ring->fw_ring_id == INVALID_HW_RING_ID) ++ if (ring->fw_ring_id == INVALID_HW_RING_ID_32BIT) + return; + + cmpl_ring_id = close_path ? bnge_cp_ring_for_tx(txr) : + INVALID_HW_RING_ID; + hwrm_ring_free_send_msg(bn, ring, RING_FREE_REQ_RING_TYPE_TX, + cmpl_ring_id); +- ring->fw_ring_id = INVALID_HW_RING_ID; ++ ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + } + + static void bnge_hwrm_cp_ring_free(struct bnge_net *bn, +@@ -2455,12 +2453,12 @@ static void bnge_hwrm_cp_ring_free(struct bnge_net *bn, + struct bnge_ring_struct *ring; + + ring = &cpr->ring_struct; +- if (ring->fw_ring_id == INVALID_HW_RING_ID) ++ if (ring->fw_ring_id == INVALID_HW_RING_ID_32BIT) + return; + + hwrm_ring_free_send_msg(bn, ring, RING_FREE_REQ_RING_TYPE_L2_CMPL, + INVALID_HW_RING_ID); +- ring->fw_ring_id = INVALID_HW_RING_ID; ++ ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + } + + static void bnge_hwrm_ring_free(struct bnge_net *bn, bool close_path) +@@ -2496,11 +2494,11 @@ static void bnge_hwrm_ring_free(struct bnge_net *bn, bool close_path) + bnge_hwrm_cp_ring_free(bn, &nqr->cp_ring_arr[j]); + + ring = &nqr->ring_struct; +- if (ring->fw_ring_id != INVALID_HW_RING_ID) { ++ if (ring->fw_ring_id != INVALID_HW_RING_ID_32BIT) { + hwrm_ring_free_send_msg(bn, ring, + RING_FREE_REQ_RING_TYPE_NQ, + INVALID_HW_RING_ID); +- ring->fw_ring_id = INVALID_HW_RING_ID; ++ ring->fw_ring_id = INVALID_HW_RING_ID_32BIT; + bn->grp_info[i].nq_fw_ring_id = INVALID_HW_RING_ID; + } + } +diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +index f4636b5b0cf3f0..d177919c2e1170 100644 +--- a/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h ++++ b/drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +@@ -630,8 +630,8 @@ struct bnge_l2_filter { + refcount_t refcnt; + }; + +-u16 bnge_cp_ring_for_rx(struct bnge_rx_ring_info *rxr); +-u16 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr); ++u32 bnge_cp_ring_for_rx(struct bnge_rx_ring_info *rxr); ++u32 bnge_cp_ring_for_tx(struct bnge_tx_ring_info *txr); + void bnge_fill_hw_rss_tbl(struct bnge_net *bn, struct bnge_vnic_info *vnic); + int bnge_alloc_rx_data(struct bnge_net *bn, struct bnge_rx_ring_info *rxr, + u16 prod, gfp_t gfp); +diff --git a/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h +index 341c7f81ed092b..bb0c79a1ee60f7 100644 +--- a/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h ++++ b/drivers/net/ethernet/broadcom/bnge/bnge_rmem.h +@@ -184,7 +184,7 @@ struct bnge_ctx_mem_info { + struct bnge_ring_struct { + struct bnge_ring_mem_info ring_mem; + +- u16 fw_ring_id; ++ u32 fw_ring_id; + union { + u16 grp_idx; + u16 map_idx; /* Used by NQs */ +diff --git a/include/linux/bnge/hsi.h b/include/linux/bnge/hsi.h +index 8ea13d5407eecd..1f7bd96415a527 100644 +--- a/include/linux/bnge/hsi.h ++++ b/include/linux/bnge/hsi.h +@@ -8317,8 +8317,7 @@ struct hwrm_ring_alloc_output { + __le16 req_type; + __le16 seq_id; + __le16 resp_len; +- __le16 ring_id; +- __le16 logical_ring_id; ++ __le32 ring_id; + u8 push_buffer_index; + #define RING_ALLOC_RESP_PUSH_BUFFER_INDEX_PING_BUFFER 0x0UL + #define RING_ALLOC_RESP_PUSH_BUFFER_INDEX_PONG_BUFFER 0x1UL +@@ -8345,10 +8344,10 @@ struct hwrm_ring_free_input { + u8 flags; + #define RING_FREE_REQ_FLAGS_VIRTIO_RING_VALID 0x1UL + #define RING_FREE_REQ_FLAGS_LAST RING_FREE_REQ_FLAGS_VIRTIO_RING_VALID +- __le16 ring_id; ++ __le16 unused_1; + __le32 prod_idx; + __le32 opaque; +- __le32 unused_1; ++ __le32 ring_id; + }; + + /* hwrm_ring_free_output (size:128b/16B) */ +-- +2.53.0 + diff --git a/queue-7.1/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch b/queue-7.1/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch new file mode 100644 index 0000000000..a47129b895 --- /dev/null +++ b/queue-7.1/bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch @@ -0,0 +1,75 @@ +From 3046734970293e8383d965ed7e014396380d149d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 09:06:22 +0800 +Subject: bonding: fix devconf_all NULL dereference when IPv6 is disabled + +From: Zhaolong Zhang + +[ Upstream commit 1c975de3343cdef506f2eecc833cc1f14b0401c4 ] + +When booting with the 'ipv6.disable=1' parameter, the devconf_all is +never initialized because inet6_init() exits before addrconf_init() is +called which initializes it. bond_send_validate(), however, will still +call bond_ns_send_all() even ipv6 is indeed disabled. It will lead to +NULL derefence of net->ipv6.devconf_all in ip6_pol_route(). + + BUG: kernel NULL pointer dereference, address: 000000000000000c + [...] + Workqueue: bond0 bond_arp_monitor [bonding] + RIP: 0010:ip6_pol_route+0x69/0x480 + [...] + Call Trace: + + ? srso_return_thunk+0x5/0x5f + ? __pfx_ip6_pol_route_output+0x10/0x10 + fib6_rule_lookup+0xfe/0x260 + ? wakeup_preempt+0x8a/0x90 + ? srso_return_thunk+0x5/0x5f + ? srso_return_thunk+0x5/0x5f + ? sched_balance_rq+0x369/0x810 + ip6_route_output_flags+0xd7/0x170 + bond_ns_send_all+0xde/0x280 [bonding] + bond_ab_arp_probe+0x296/0x320 [bonding] + ? srso_return_thunk+0x5/0x5f + bond_activebackup_arp_mon+0xb4/0x2c0 [bonding] + process_one_work+0x196/0x370 + worker_thread+0x1af/0x320 + ? srso_return_thunk+0x5/0x5f + ? __pfx_worker_thread+0x10/0x10 + kthread+0xe3/0x120 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x199/0x260 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Fix this by adding ipv6_mod_enabled() condition check in the caller. + +Fixes: 4e24be018eb9 ("bonding: add new parameter ns_targets") +Signed-off-by: Qianheng Peng +Signed-off-by: Zhaolong Zhang +Reviewed-by: Hangbin Liu +Link: https://patch.msgid.link/20260707010622.487333-1-zhangzl2013@126.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index cd9b0a6d652174..75abd6d9af3a4e 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -3446,7 +3446,8 @@ static void bond_send_validate(struct bonding *bond, struct slave *slave) + { + bond_arp_send_all(bond, slave); + #if IS_ENABLED(CONFIG_IPV6) +- bond_ns_send_all(bond, slave); ++ if (likely(ipv6_mod_enabled())) ++ bond_ns_send_all(bond, slave); + #endif + } + +-- +2.53.0 + diff --git a/queue-7.1/bpf-reject-redirect-helpers-without-a-bpf_net_contex.patch b/queue-7.1/bpf-reject-redirect-helpers-without-a-bpf_net_contex.patch new file mode 100644 index 0000000000..77d90e1476 --- /dev/null +++ b/queue-7.1/bpf-reject-redirect-helpers-without-a-bpf_net_contex.patch @@ -0,0 +1,122 @@ +From bbb6314f5ba10aa376f34bfdd58ccf82dddac920 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 20:56:07 +0200 +Subject: bpf: Reject redirect helpers without a bpf_net_context + +From: Daniel Borkmann + +[ Upstream commit 3f4920d165b29052255527d8ae7619e7ec132ece ] + +The bpf_redirect*() helpers and skb_do_redirect() obtain the per-task +bpf_redirect_info via bpf_net_ctx_get_ri(), which dereferences the +current->bpf_net_context unconditionally. That context is established +on the paths that run tc BPF such as sch_handle_{ingress,egress}(), +*except* for the case where {cls,act}_bpf was attached to a proper +qdisc. A program running from there reaches the NULL deref in two ways: + +* It calls bpf_redirect() directly, which dereferences the context at + the top of the helper: + + tc qdisc add dev eth0 root handle 1: red limit 1MB min 10KB max 20KB \ + avpkt 1000 burst 100 qevent early_drop block 10 + tc filter add block 10 pref 1 bpf obj redirect.o + +* It simply returns TC_ACT_REDIRECT without helper call: tcf_qevent_handle() + then dispatches to skb_do_redirect(), which dereferences the context + +Rather than extending bpf_net_context management into the qdisc path, +make the redirect helpers refuse to operate when no context exists, and +have tcf_qevent_handle() drop a TC_ACT_REDIRECT verdict instead of +calling skb_do_redirect(). Previous behaviour was a crash, so nothing +regresses by not supporting it. + +Fixes: 401cb7dae813 ("net: Reference bpf_redirect_info via task_struct on PREEMPT_RT.") +Fixes: 3625750f05ec ("net: sched: Introduce helpers for qevent blocks") +Signed-off-by: Daniel Borkmann +Reviewed-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/20260706185609.330006-2-daniel@iogearbox.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/filter.c | 17 +++++++++++------ + net/sched/cls_api.c | 6 ++---- + 2 files changed, 13 insertions(+), 10 deletions(-) + +diff --git a/net/core/filter.c b/net/core/filter.c +index f21aeff99cc983..66837e93d3f25d 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2552,11 +2552,13 @@ int skb_do_redirect(struct sk_buff *skb) + + BPF_CALL_2(bpf_redirect, u32, ifindex, u64, flags) + { +- struct bpf_redirect_info *ri = bpf_net_ctx_get_ri(); ++ struct bpf_redirect_info *ri; + +- if (unlikely(flags & (~(BPF_F_INGRESS) | BPF_F_REDIRECT_INTERNAL))) ++ if (unlikely(!bpf_net_ctx_get() || ++ (flags & (~(BPF_F_INGRESS) | BPF_F_REDIRECT_INTERNAL)))) + return TC_ACT_SHOT; + ++ ri = bpf_net_ctx_get_ri(); + ri->flags = flags; + ri->tgt_index = ifindex; + +@@ -2573,11 +2575,12 @@ static const struct bpf_func_proto bpf_redirect_proto = { + + BPF_CALL_2(bpf_redirect_peer, u32, ifindex, u64, flags) + { +- struct bpf_redirect_info *ri = bpf_net_ctx_get_ri(); ++ struct bpf_redirect_info *ri; + +- if (unlikely(flags)) ++ if (unlikely(!bpf_net_ctx_get() || flags)) + return TC_ACT_SHOT; + ++ ri = bpf_net_ctx_get_ri(); + ri->flags = BPF_F_PEER; + ri->tgt_index = ifindex; + +@@ -2595,11 +2598,13 @@ static const struct bpf_func_proto bpf_redirect_peer_proto = { + BPF_CALL_4(bpf_redirect_neigh, u32, ifindex, struct bpf_redir_neigh *, params, + int, plen, u64, flags) + { +- struct bpf_redirect_info *ri = bpf_net_ctx_get_ri(); ++ struct bpf_redirect_info *ri; + +- if (unlikely((plen && plen < sizeof(*params)) || flags)) ++ if (unlikely((plen && plen < sizeof(*params)) || ++ !bpf_net_ctx_get() || flags)) + return TC_ACT_SHOT; + ++ ri = bpf_net_ctx_get_ri(); + ri->flags = BPF_F_NEIGH | (plen ? BPF_F_NEXTHOP : 0); + ri->tgt_index = ifindex; + +diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c +index ffeea6db833747..523cf2a8bd1d6d 100644 +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -4046,6 +4046,8 @@ struct sk_buff *tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, stru + fl = rcu_dereference_bh(qe->filter_chain); + + switch (tcf_classify(skb, NULL, fl, &cl_res, false)) { ++ case TC_ACT_REDIRECT: ++ fallthrough; + case TC_ACT_SHOT: + qdisc_qstats_drop(sch); + __qdisc_drop(skb, to_free); +@@ -4057,10 +4059,6 @@ struct sk_buff *tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, stru + __qdisc_drop(skb, to_free); + *ret = __NET_XMIT_STOLEN; + return NULL; +- case TC_ACT_REDIRECT: +- skb_do_redirect(skb); +- *ret = __NET_XMIT_STOLEN; +- return NULL; + case TC_ACT_CONSUMED: + *ret = __NET_XMIT_STOLEN; + return NULL; +-- +2.53.0 + diff --git a/queue-7.1/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch b/queue-7.1/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch new file mode 100644 index 0000000000..3ce7ee8d35 --- /dev/null +++ b/queue-7.1/bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch @@ -0,0 +1,79 @@ +From 2b24e55d76393b67df75cdb79b76a35cf6481868 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jul 2026 18:38:56 +0800 +Subject: bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() + +From: Chengfeng Ye + +[ Upstream commit 2d66a033864e27ab8d5e44cb36f31d9d2413bee4 ] + +tcp_bpf_sendmsg() keeps msg_tx across sk_stream_wait_memory(), which +drops and reacquires the socket lock. Its error path tries to decide +whether msg_tx names the local temporary message by comparing it with +the current value of psock->cork. + +This comparison is unsafe when two threads send on the same socket: + + Thread A Thread B + msg_tx = psock->cork + sk_msg_alloc() fails + sk_stream_wait_memory() + releases the socket lock acquires the socket lock + completes the cork + psock->cork = NULL + frees the cork + reacquires the socket lock + msg_tx != psock->cork + sk_msg_free(msg_tx) + +The stale cork is therefore mistaken for the local temporary message +and freed again. KASAN reported: + + BUG: KASAN: slab-use-after-free in sk_msg_free+0x49/0x50 + Read of size 4 at addr ffff88810c908800 by task poc/90 + Call Trace: + sk_msg_free+0x49/0x50 + tcp_bpf_sendmsg+0x14f5/0x1cc0 + __sys_sendto+0x32c/0x3a0 + __x64_sys_sendto+0xdb/0x1b0 + Allocated by task 89: + __kasan_kmalloc+0x8f/0xa0 + tcp_bpf_sendmsg+0x16b3/0x1cc0 + Freed by task 91: + __kasan_slab_free+0x43/0x70 + kfree+0x131/0x3c0 + tcp_bpf_sendmsg+0xec3/0x1cc0 + +msg_tx can only name the stack-local tmp or the shared cork. Check for +tmp directly so a changed psock->cork cannot turn a shared message into +an apparent local one. + +Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") +Signed-off-by: Chengfeng Ye +Reviewed-by: Emil Tsalapatis +Reviewed-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/87fr18lmzo.fsf%40cloudflare.com/ +Link: https://lore.kernel.org/netdev/20260719161630.2901208-1-nicoyip.dev%40gmail.com/ [v1] +Link: https://patch.msgid.link/20260724103856.3399001-1-nicoyip.dev@gmail.com +Signed-off-by: Eduard Zingerman +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index cc0bd73f36b6d6..b9f03663336533 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -589,7 +589,7 @@ static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) + wait_for_memory: + err = sk_stream_wait_memory(sk, &timeo); + if (err) { +- if (msg_tx && msg_tx != psock->cork) ++ if (msg_tx == &tmp) + sk_msg_free(sk, msg_tx); + goto out_err; + } +-- +2.53.0 + diff --git a/queue-7.1/bpf-tcp-fix-double-sock-release-on-batch-realloc.patch b/queue-7.1/bpf-tcp-fix-double-sock-release-on-batch-realloc.patch new file mode 100644 index 0000000000..8295797c68 --- /dev/null +++ b/queue-7.1/bpf-tcp-fix-double-sock-release-on-batch-realloc.patch @@ -0,0 +1,70 @@ +From d72c6e72ae85402b6cbecd4a085315dcd259962d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:32:30 +0000 +Subject: bpf: tcp: fix double sock release on batch realloc + +From: Xiang Mei (Microsoft) + +[ Upstream commit 980a813452754f8001704744e92f7aa697c53dd3 ] + +bpf_iter_tcp_batch() releases the current batch via +bpf_iter_tcp_put_batch(), which drops the socket refs and rewrites +each slot with the socket cookie, then grows the batch. cur_sk/end_sk +are kept for bpf_iter_tcp_resume(), but on realloc failure the function +returns ERR_PTR() before resume runs, leaving cur_sk < end_sk over +slots that now hold cookies rather than sock pointers. +bpf_iter_tcp_seq_stop() then calls bpf_iter_tcp_put_batch() again and +dereferences a cookie as a struct sock. + +Empty the batch on the failure path so stop() does not release it +again. The sockets were already freed by the first +bpf_iter_tcp_put_batch(), so nothing leaks, and a later read() rescans +the bucket from the start instead of skipping it. The sibling +GFP_NOWAIT failure path still holds real socket references and is left +for stop() to release. + + BUG: KASAN: null-ptr-deref in __sock_gen_cookie + Read of size 8 at addr 0000000000000059 by task exploit + ... + __sock_gen_cookie (net/core/sock_diag.c:28) + bpf_iter_tcp_put_batch (net/ipv4/tcp_ipv4.c:2918) + bpf_iter_tcp_seq_stop (net/ipv4/tcp_ipv4.c:3270) + bpf_seq_read (kernel/bpf/bpf_iter.c:205) + vfs_read (fs/read_write.c:572) + ksys_read (fs/read_write.c:716) + do_syscall_64 + entry_SYSCALL_64_after_hwframe + Kernel panic - not syncing: Fatal exception + +Fixes: cdec67a489d4 ("bpf: tcp: Make sure iter->batch always contains a full bucket snapshot") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Eric Dumazet +Reviewed-by: Jordan Rife +Link: https://patch.msgid.link/20260713233230.3553593-1-xmei5@asu.edu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_ipv4.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index d5cd238358ef04..c7cf086cc6a1eb 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -3144,8 +3144,11 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq) + bpf_iter_tcp_put_batch(iter); + err = bpf_iter_tcp_realloc_batch(iter, expected * 3 / 2, + GFP_USER); +- if (err) ++ if (err) { ++ iter->cur_sk = 0; ++ iter->end_sk = 0; + return ERR_PTR(err); ++ } + + sk = bpf_iter_tcp_resume(seq); + if (!sk) +-- +2.53.0 + diff --git a/queue-7.1/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch b/queue-7.1/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch new file mode 100644 index 0000000000..630cd1b408 --- /dev/null +++ b/queue-7.1/btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch @@ -0,0 +1,55 @@ +From 49c609181b06ed891872d252f88285926a45af1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jun 2026 18:39:07 +0800 +Subject: btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8 + +From: You-Kai Zheng + +[ Upstream commit b95181f3929ff98949fa9460ca93eccebbf2d7fc ] + +The variable-sized buffer buf in struct btrfs_ioctl_search_args_v2 is +declared as __u64[], but it holds a packed byte stream of search results, +where all offsets into the buffer are in bytes. + +Declaring buf as __u64[] makes it easy for user space to write incorrect +pointer arithmetic: adding a byte offset directly to a __u64 pointer +scales the offset by 8, landing at byte position offset*8 instead of +offset. + +This recently caused an infinite loop in btrfs-progs: the accessor read +all-zero data from misaddressed items, which fed zeroed search keys back +into the ioctl loop and spun forever. The issue was worked around at the +time by disabling TREE_SEARCH_V2 entirely in btrfs-progs (d73e69824854: +"btrfs-progs: temporarily disable usage of v2 of search tree ioctl"). + +The kernel side already treats buf as a byte buffer, so change the +declaration to __u8[] to match the actual semantics and prevent similar +misuse in user space. The change is ABI compatible: both the structure size +and alignment are unchanged. + +Fixes: cc68a8a5a433 ("btrfs: new ioctl TREE_SEARCH_V2") +Reviewed-by: Qu Wenruo +Signed-off-by: You-Kai Zheng +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + include/uapi/linux/btrfs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h +index 9165154a274d94..16ff7beab9ca59 100644 +--- a/include/uapi/linux/btrfs.h ++++ b/include/uapi/linux/btrfs.h +@@ -598,7 +598,7 @@ struct btrfs_ioctl_search_args_v2 { + __u64 buf_size; /* in - size of buffer + * out - on EOVERFLOW: needed size + * to store item */ +- __u64 buf[]; /* out - found items */ ++ __u8 buf[]; /* out - found items */ + }; + + /* With a @src_length of zero, the range from @src_offset->EOF is cloned! */ +-- +2.53.0 + diff --git a/queue-7.1/btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch b/queue-7.1/btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch new file mode 100644 index 0000000000..d5ded26b21 --- /dev/null +++ b/queue-7.1/btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch @@ -0,0 +1,62 @@ +From 8710c5bacec351ab4c42a0adb03dab15b3f98514 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 30 Jun 2026 12:58:05 -0700 +Subject: btrfs: don't propagate EXTENT_FLAG_LOGGING to split extent maps + +From: Leo Martins + +[ Upstream commit 5eff4d5b17fa1950e80bfd1ba43dc0699e61a644 ] + +When btrfs_drop_extent_map_range() splits an extent map, the new split +maps inherit the original map's flags through a local 'flags' variable. +Commit f86f7a75e2fb ("btrfs: use the flags of an extent map to identify +the compression type") changed the EXTENT_FLAG_LOGGING clearing to +operate on em->flags instead of that local 'flags' copy, so a split of +an extent map that is currently being logged wrongly inherits +EXTENT_FLAG_LOGGING. + +The flag is then never cleared on the split, and when it is freed while +still on the inode's modified_extents list (for example by the extent +map shrinker) it trips the WARN_ON(!list_empty(&em->list)) in +btrfs_free_extent_map() and leads to a use-after-free. + +Clear EXTENT_FLAG_LOGGING from the local 'flags' copy used for the +splits and only clear EXTENT_FLAG_PINNED from em->flags, restoring the +behaviour prior to f86f7a75e2fb. + +CC: Jeff Layton +Link: https://lore.kernel.org/all/20260629-btrfs-skip-logging-v1-1-4e3a28c1acaf@kernel.org/ +Fixes: f86f7a75e2fb ("btrfs: use the flags of an extent map to identify the compression type") +Reviewed-by: Jeff Layton +Reviewed-by: Filipe Manana +Signed-off-by: Leo Martins +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_map.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c +index 6b79bff241f21d..a8bce1d4e92c80 100644 +--- a/fs/btrfs/extent_map.c ++++ b/fs/btrfs/extent_map.c +@@ -866,13 +866,13 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, + goto next; + } + +- flags = em->flags; + /* + * In case we split the extent map, we want to preserve the + * EXTENT_FLAG_LOGGING flag on our extent map, but we don't want + * it on the new extent maps. + */ +- em->flags &= ~(EXTENT_FLAG_PINNED | EXTENT_FLAG_LOGGING); ++ flags = em->flags & ~EXTENT_FLAG_LOGGING; ++ em->flags &= ~EXTENT_FLAG_PINNED; + modified = !list_empty(&em->list); + + /* +-- +2.53.0 + diff --git a/queue-7.1/btrfs-fix-u32-to-s64-type-conversion-in-dirty_metada.patch b/queue-7.1/btrfs-fix-u32-to-s64-type-conversion-in-dirty_metada.patch new file mode 100644 index 0000000000..54c81a3b47 --- /dev/null +++ b/queue-7.1/btrfs-fix-u32-to-s64-type-conversion-in-dirty_metada.patch @@ -0,0 +1,62 @@ +From bf9fcdfa42ad7eb28e4d6310233b28cf8d7a3f99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Jun 2026 15:08:43 +0800 +Subject: btrfs: fix u32 to s64 type conversion in dirty_metadata_bytes + accounting + +From: Dave Chen + +[ Upstream commit 8b5a09ceb61b18b1f0797cd30a549d7dc85d8d50 ] + +The percpu_counter dirty_metadata_bytes is updated by negating eb->len +and passing it to percpu_counter_add_batch(), whose amount parameter is +s64. Since commit 84cda1a6087d ("btrfs: cache folio size and shift in +extent_buffer"), eb->len is u32. The u32 result of -eb->len, when +widened to the s64 parameter, becomes a large positive value instead of +the intended negative value. For eb->len == 16384 the counter adds ++4294950912 instead of subtracting 16384. + +The counter therefore grows on every metadata writeback instead of +shrinking by the extent buffer size, permanently exceeding +BTRFS_DIRTY_METADATA_THRESH and causing __btrfs_btree_balance_dirty() +to trigger balance_dirty_pages_ratelimited() unconditionally, adding +unnecessary writeback pressure. + +Cast eb->len to s64 before negation at both call sites so the +subtraction is performed in signed 64-bit arithmetic. + +Reviewed-by: Filipe Manana +Fixes: 84cda1a6087d ("btrfs: cache folio size and shift in extent_buffer") +Signed-off-by: Dave Chen +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/extent_io.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index 2275189b786055..f0bfa8a6218a71 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -1963,7 +1963,7 @@ static noinline_for_stack bool lock_extent_buffer_for_io(struct extent_buffer *e + + btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN); + percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, +- -eb->len, ++ -(s64)eb->len, + fs_info->dirty_metadata_batch); + ret = true; + } else { +@@ -3778,7 +3778,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, + return; + + buffer_tree_clear_mark(eb, PAGECACHE_TAG_DIRTY); +- percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -eb->len, ++ percpu_counter_add_batch(&fs_info->dirty_metadata_bytes, -(s64)eb->len, + fs_info->dirty_metadata_batch); + + for (int i = 0; i < num_extent_folios(eb); i++) { +-- +2.53.0 + diff --git a/queue-7.1/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch b/queue-7.1/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch new file mode 100644 index 0000000000..3c00da4f3c --- /dev/null +++ b/queue-7.1/btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch @@ -0,0 +1,47 @@ +From 4ae261317c57fd88184bb9191b7e80c2e9ac315d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 03:17:28 +0000 +Subject: btrfs: free mapping node on duplicate reloc root insert + +From: Guanghui Yang <3497809730@qq.com> + +[ Upstream commit 6a8269b6459ed870a8156c106a0f597383907872 ] + +__add_reloc_root() allocates a mapping_node before inserting it into +rc->reloc_root_tree. If rb_simple_insert() finds an existing entry, it +returns the existing rb_node and leaves the newly allocated node unlinked. + +The error path then returns -EEXIST without freeing the new node. Since +the node was never inserted into reloc_root_tree, the later cleanup in +put_reloc_control() cannot find it either. + +Free the newly allocated node before returning -EEXIST. + +The callers currently assert that -EEXIST should not happen, so this is a +defensive cleanup for an unexpected duplicate insert path. If the path is +ever reached, the local allocation should still be released. + +Fixes: 57a304cfd43b ("btrfs: do not panic in __add_reloc_root") +Reviewed-by: Qu Wenruo +Signed-off-by: Guanghui Yang <3497809730@qq.com> +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/relocation.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c +index 6c826be4174934..37dd9c8b352fbc 100644 +--- a/fs/btrfs/relocation.c ++++ b/fs/btrfs/relocation.c +@@ -497,6 +497,7 @@ static int __add_reloc_root(struct btrfs_root *root) + btrfs_err(fs_info, + "Duplicate root found for start=%llu while inserting into relocation tree", + node->bytenr); ++ kfree(node); + return -EEXIST; + } + +-- +2.53.0 + diff --git a/queue-7.1/cifs-fix-cifsfileinfo-leak-on-kmalloc-failure-in-def.patch b/queue-7.1/cifs-fix-cifsfileinfo-leak-on-kmalloc-failure-in-def.patch new file mode 100644 index 0000000000..9393bdc8d5 --- /dev/null +++ b/queue-7.1/cifs-fix-cifsfileinfo-leak-on-kmalloc-failure-in-def.patch @@ -0,0 +1,149 @@ +From 6f5bae4a74e5954e3830bdf9c739a945f3cf4481 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 18:55:52 -0500 +Subject: cifs: fix cifsFileInfo leak on kmalloc failure in deferred close + drain paths + +From: Frank Sorenson + +[ Upstream commit c2f2e83e3bbc5483730fd4ee903182761f1ae50f ] + +In cifs_close_deferred_file(), cifs_close_all_deferred_files(), and +cifs_close_deferred_file_under_dentry(), when a pending deferred close +is cancelled via cancel_delayed_work(), the subsequent kmalloc_obj() to +add the file to the local processing list may fail under memory pressure. +The loop breaks immediately, but the cancelled work is no longer pending +(it would have called _cifsFileInfo_put()), and the cfile is never added +to file_head for processing. The cifsFileInfo reference and the open +server handle both leak. + +Fix by saving the cfile that failed allocation in a local variable, +breaking as before, and calling _cifsFileInfo_put() on it after +releasing the lock. Any files later in the iteration are unaffected +since their deferred work is still pending and will fire normally. + +Fixes: e3fc065682eb ("cifs: Deferred close performance improvements") +Signed-off-by: Frank Sorenson +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/misc.c | 45 ++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 39 insertions(+), 6 deletions(-) + +diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c +index 8afa746ee19e0d..ce9927b666af7a 100644 +--- a/fs/smb/client/misc.c ++++ b/fs/smb/client/misc.c +@@ -493,7 +493,7 @@ cifs_del_deferred_close(struct cifsFileInfo *cfile) + void + cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode) + { +- struct cifsFileInfo *cfile = NULL; ++ struct cifsFileInfo *cfile = NULL, *failed_cfile = NULL; + struct file_list *tmp_list, *tmp_next_list; + LIST_HEAD(file_head); + +@@ -510,8 +510,10 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode) + + tmp_list = kmalloc_obj(struct file_list, + GFP_ATOMIC); +- if (tmp_list == NULL) ++ if (tmp_list == NULL) { ++ failed_cfile = cfile; + break; ++ } + tmp_list->cfile = cfile; + list_add_tail(&tmp_list->list, &file_head); + } +@@ -519,6 +521,15 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode) + } + spin_unlock(&cifs_inode->open_file_lock); + ++ if (failed_cfile) { ++ if (OPEN_FMODE(failed_cfile->f_flags) & FMODE_WRITE) { ++ /* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ ++ smp_store_release(&CIFS_I(d_inode(failed_cfile->dentry))->time_last_write, ++ jiffies); ++ } ++ _cifsFileInfo_put(failed_cfile, false, false); ++ } ++ + list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) { + struct cifsFileInfo *cfile = tmp_list->cfile; + +@@ -536,7 +547,7 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode) + void + cifs_close_all_deferred_files(struct cifs_tcon *tcon) + { +- struct cifsFileInfo *cfile; ++ struct cifsFileInfo *cfile, *failed_cfile = NULL; + struct file_list *tmp_list, *tmp_next_list; + LIST_HEAD(file_head); + +@@ -550,8 +561,10 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon) + + tmp_list = kmalloc_obj(struct file_list, + GFP_ATOMIC); +- if (tmp_list == NULL) ++ if (tmp_list == NULL) { ++ failed_cfile = cfile; + break; ++ } + tmp_list->cfile = cfile; + list_add_tail(&tmp_list->list, &file_head); + } +@@ -559,6 +572,15 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon) + } + spin_unlock(&tcon->open_file_lock); + ++ if (failed_cfile) { ++ if (OPEN_FMODE(failed_cfile->f_flags) & FMODE_WRITE) { ++ /* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ ++ smp_store_release(&CIFS_I(d_inode(failed_cfile->dentry))->time_last_write, ++ jiffies); ++ } ++ _cifsFileInfo_put(failed_cfile, true, false); ++ } ++ + list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) { + struct cifsFileInfo *cfile = tmp_list->cfile; + +@@ -614,7 +636,7 @@ void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, + struct dentry *dentry) + { + struct file_list *tmp_list, *tmp_next_list; +- struct cifsFileInfo *cfile; ++ struct cifsFileInfo *cfile, *failed_cfile = NULL; + LIST_HEAD(file_head); + + spin_lock(&tcon->open_file_lock); +@@ -627,14 +649,25 @@ void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, + spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock); + + tmp_list = kmalloc_obj(struct file_list, GFP_ATOMIC); +- if (tmp_list == NULL) ++ if (tmp_list == NULL) { ++ failed_cfile = cfile; + break; ++ } + tmp_list->cfile = cfile; + list_add_tail(&tmp_list->list, &file_head); + } + } + spin_unlock(&tcon->open_file_lock); + ++ if (failed_cfile) { ++ if (OPEN_FMODE(failed_cfile->f_flags) & FMODE_WRITE) { ++ /* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ ++ smp_store_release(&CIFS_I(d_inode(failed_cfile->dentry))->time_last_write, ++ jiffies); ++ } ++ _cifsFileInfo_put(failed_cfile, true, false); ++ } ++ + list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) { + struct cifsFileInfo *cfile = tmp_list->cfile; + +-- +2.53.0 + diff --git a/queue-7.1/cifs-prevent-readdir-from-changing-file-size-due-to-.patch b/queue-7.1/cifs-prevent-readdir-from-changing-file-size-due-to-.patch new file mode 100644 index 0000000000..dd9ae4d379 --- /dev/null +++ b/queue-7.1/cifs-prevent-readdir-from-changing-file-size-due-to-.patch @@ -0,0 +1,282 @@ +From 94bb8f0a36becbccff8569195575e684ff704f75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 18:55:51 -0500 +Subject: cifs: prevent readdir from changing file size due to stale directory + metadata + +From: Frank Sorenson + +[ Upstream commit e8a8d54c2d508891c142a928fc7d298c4c8bd0dd ] + +Windows Server's directory enumeration metadata lags behind the actual +file size after a write+close or rename. A concurrent readdir() in the +window between close() returning to userspace and stat() being called +overwrites the correct cached i_size with the stale server value, causing +stat() to return the wrong size. + +Once _cifsFileInfo_put() removes the last writable handle from +openFileList, is_size_safe_to_change() permits readdir to overwrite +i_size. smb2_close_getattr() then stamps cifs_i->time = jiffies, making +the corrupt cached value appear fresh to the next stat(). + +The existing check (see Fixes:) only blocked stale size updates while +an active RW lease was held, not after the last writable handle closes. + +Add cifsInodeInfo->time_last_write, written via smp_store_release() at +writable close and on setattr/truncate. is_size_safe_to_change() checks +is_inode_writable() first (acquiring open_file_lock), then rejects a +readdir size update if time_last_write falls within acregmax jiffies. +The spinlock release in _cifsFileInfo_put() forms a store-release barrier +that pairs with the spin_lock() (load-acquire) in is_inode_writable(), +ensuring the subsequent smp_load_acquire() on time_last_write observes +any update from a concurrent close(). When a size update is rejected and +the server value differs from the cached one, cifs_i->time is cleared to +force a fresh QUERY_INFO on the next stat(). + +readdir is also blocked from changing i_size while writable handles are +open or an RW lease is held, even on direct-IO mounts. + +For deferred close (closetimeo > 0), time_last_write is refreshed at the +actual server close in smb2_deferred_work_close() and in the +cifs_close_deferred_file*() drain paths invoked by lease/oplock breaks +and tcon teardown, anchoring the protection window to the real close time +rather than the earlier userspace close. + +time_last_write == 0 skips the time_before() check to avoid false +positives near boot on 32-bit systems where jiffies starts close to +INITIAL_JIFFIES. + +Does not reproduce against Samba or with actimeo=0. + +Fixes: e4b61f3b1c67 ("cifs: prevent updating file size from server if we have a read/write lease") +Signed-off-by: Frank Sorenson +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/cifsfs.c | 1 + + fs/smb/client/cifsglob.h | 1 + + fs/smb/client/file.c | 69 +++++++++++++++++++++++++++++++++++++--- + fs/smb/client/inode.c | 6 ++++ + fs/smb/client/misc.c | 27 ++++++++++++++-- + 5 files changed, 96 insertions(+), 8 deletions(-) + +diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c +index d6c30f8552e081..95845c87745173 100644 +--- a/fs/smb/client/cifsfs.c ++++ b/fs/smb/client/cifsfs.c +@@ -438,6 +438,7 @@ cifs_alloc_inode(struct super_block *sb) + return NULL; + cifs_inode->cifsAttrs = ATTR_ARCHIVE; /* default */ + cifs_inode->time = 0; ++ cifs_inode->time_last_write = 0; + /* + * Until the file is open and we have gotten oplock info back from the + * server, can not assume caching of file data or metadata. +diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h +index 82e0adc1dabd05..c755d314a8193b 100644 +--- a/fs/smb/client/cifsglob.h ++++ b/fs/smb/client/cifsglob.h +@@ -1562,6 +1562,7 @@ struct cifsInodeInfo { + spinlock_t writers_lock; + unsigned int writers; /* Number of writers on this inode */ + unsigned long time; /* jiffies of last update of inode */ ++ unsigned long time_last_write; /* jiffies of last writable close or truncate */ + u64 uniqueid; /* server inode number */ + u64 createtime; /* creation time on server */ + __u8 lease_key[SMB2_LEASE_KEY_SIZE]; /* lease key for this inode */ +diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c +index a26a464d6242b6..9f7a878c93c930 100644 +--- a/fs/smb/client/file.c ++++ b/fs/smb/client/file.c +@@ -1423,11 +1423,21 @@ void smb2_deferred_work_close(struct work_struct *work) + { + struct cifsFileInfo *cfile = container_of(work, + struct cifsFileInfo, deferred.work); ++ struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); + +- spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock); ++ spin_lock(&cinode->deferred_lock); + cifs_del_deferred_close(cfile); + cfile->deferred_close_scheduled = false; +- spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock); ++ spin_unlock(&cinode->deferred_lock); ++ /* ++ * Refresh time_last_write immediately before the actual server close ++ * so the protection window is anchored to the real close time, not ++ * the earlier userspace close time stored by cifs_close(). ++ */ ++ if (OPEN_FMODE(cfile->f_flags) & FMODE_WRITE) { ++ /* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ ++ smp_store_release(&cinode->time_last_write, jiffies); ++ } + _cifsFileInfo_put(cfile, true, false); + } + +@@ -1457,6 +1467,10 @@ int cifs_close(struct inode *inode, struct file *file) + if (file->private_data != NULL) { + cfile = file->private_data; + file->private_data = NULL; ++ if (file->f_mode & FMODE_WRITE) { ++ /* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ ++ smp_store_release(&cinode->time_last_write, jiffies); ++ } + dclose = kmalloc_obj(struct cifs_deferred_close); + if ((cfile->status_file_deleted == false) && + (smb2_can_defer_close(inode, dclose))) { +@@ -3171,13 +3185,26 @@ static int is_inode_writable(struct cifsInodeInfo *cifs_inode) + bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file, + bool from_readdir) + { ++ struct cifs_sb_info *cifs_sb; ++ unsigned long tlw; ++ + if (!cifsInode) + return true; + ++ cifs_sb = CIFS_SB(cifsInode); ++ + if (is_inode_writable(cifsInode) || + ((cifsInode->oplock & CIFS_CACHE_RW_FLG) != 0 && from_readdir)) { + /* This inode is open for write at least once */ +- struct cifs_sb_info *cifs_sb = CIFS_SB(cifsInode); ++ ++ /* ++ * Readdir data is unreliable when we have writable handles or ++ * an exclusive lease -- never allow it to change i_size, even ++ * on direct-IO mounts where the server's directory metadata ++ * can still lag behind the actual file state. ++ */ ++ if (from_readdir) ++ return false; + + if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_DIRECT_IO) { + /* since no page cache to corrupt on directio +@@ -3189,8 +3216,40 @@ bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file, + return true; + + return false; +- } else +- return true; ++ } ++ ++ /* ++ * No writable handles open. Check whether we are within the attribute ++ * cache validity window of a recent local modification. ++ * ++ * For the close() path: cifs_close() calls smp_store_release() on ++ * time_last_write before _cifsFileInfo_put() removes the handle under ++ * open_file_lock. That spin_unlock() is a store-release that pairs ++ * with the spin_lock() (load-acquire) in is_inode_writable() above, ++ * so if is_inode_writable() returned false the smp_load_acquire() ++ * below is guaranteed to observe any time_last_write update from a ++ * concurrent close(). ++ * ++ * For the setattr/truncate paths: those callers use smp_store_release() ++ * directly; the smp_load_acquire() below pairs with that store. There ++ * is no shared lock between setattr and readdir, so this relies on ++ * acquire-release semantics alone. The store propagation latency on ++ * weakly-ordered architectures (nanoseconds) is negligible relative to ++ * the acregmax window (seconds) and the readdir RPC round-trip ++ * (milliseconds), making this a sound design choice in practice. ++ * ++ * time_last_write == 0 means the inode has never been written locally; ++ * skip the window check to avoid false positives near boot time when ++ * jiffies is still close to INITIAL_JIFFIES on 32-bit systems. ++ */ ++ if (from_readdir) { ++ /* Pairs with smp_store_release() at close and truncate sites. */ ++ tlw = smp_load_acquire(&cifsInode->time_last_write); ++ if (tlw && time_before(jiffies, tlw + cifs_sb->ctx->acregmax)) ++ return false; ++ } ++ ++ return true; + } + + void cifs_oplock_break(struct work_struct *work) +diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c +index 826d36ed13ec92..04470803e78a99 100644 +--- a/fs/smb/client/inode.c ++++ b/fs/smb/client/inode.c +@@ -237,6 +237,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr, + if (is_size_safe_to_change(cifs_i, fattr->cf_eof, from_readdir)) { + i_size_write(inode, fattr->cf_eof); + inode->i_blocks = CIFS_INO_BLOCKS(fattr->cf_bytes); ++ } else if (from_readdir && i_size_read(inode) != fattr->cf_eof) { ++ cifs_i->time = 0; + } + + if (S_ISLNK(fattr->cf_mode) && fattr->cf_symlink_target) { +@@ -3269,6 +3271,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) + + if ((attrs->ia_valid & ATTR_SIZE) && + attrs->ia_size != i_size_read(inode)) { ++ /* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ ++ smp_store_release(&cifsInode->time_last_write, jiffies); + truncate_setsize(inode, attrs->ia_size); + netfs_resize_file(&cifsInode->netfs, attrs->ia_size, true); + fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size); +@@ -3470,6 +3474,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) + + if ((attrs->ia_valid & ATTR_SIZE) && + attrs->ia_size != i_size_read(inode)) { ++ /* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ ++ smp_store_release(&cifsInode->time_last_write, jiffies); + truncate_setsize(inode, attrs->ia_size); + netfs_resize_file(&cifsInode->netfs, attrs->ia_size, true); + fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size); +diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c +index f8bc1b8d3fdeae..8afa746ee19e0d 100644 +--- a/fs/smb/client/misc.c ++++ b/fs/smb/client/misc.c +@@ -520,7 +520,14 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode) + spin_unlock(&cifs_inode->open_file_lock); + + list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) { +- _cifsFileInfo_put(tmp_list->cfile, false, false); ++ struct cifsFileInfo *cfile = tmp_list->cfile; ++ ++ if (OPEN_FMODE(cfile->f_flags) & FMODE_WRITE) { ++ /* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ ++ smp_store_release(&CIFS_I(d_inode(cfile->dentry))->time_last_write, ++ jiffies); ++ } ++ _cifsFileInfo_put(cfile, false, false); + list_del(&tmp_list->list); + kfree(tmp_list); + } +@@ -553,7 +560,14 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon) + spin_unlock(&tcon->open_file_lock); + + list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) { +- _cifsFileInfo_put(tmp_list->cfile, true, false); ++ struct cifsFileInfo *cfile = tmp_list->cfile; ++ ++ if (OPEN_FMODE(cfile->f_flags) & FMODE_WRITE) { ++ /* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ ++ smp_store_release(&CIFS_I(d_inode(cfile->dentry))->time_last_write, ++ jiffies); ++ } ++ _cifsFileInfo_put(cfile, true, false); + list_del(&tmp_list->list); + kfree(tmp_list); + } +@@ -622,7 +636,14 @@ void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, + spin_unlock(&tcon->open_file_lock); + + list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) { +- _cifsFileInfo_put(tmp_list->cfile, true, false); ++ struct cifsFileInfo *cfile = tmp_list->cfile; ++ ++ if (OPEN_FMODE(cfile->f_flags) & FMODE_WRITE) { ++ /* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ ++ smp_store_release(&CIFS_I(d_inode(cfile->dentry))->time_last_write, ++ jiffies); ++ } ++ _cifsFileInfo_put(cfile, true, false); + list_del(&tmp_list->list); + kfree(tmp_list); + } +-- +2.53.0 + diff --git a/queue-7.1/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch b/queue-7.1/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..d0c9c04820 --- /dev/null +++ b/queue-7.1/dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,48 @@ +From d0eb22c1acb657e160eff82d155c716370896ce0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:17:37 +0800 +Subject: dpaa2-eth: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit b4b201cc93ff70150853aba03e14d314d1980ca0 ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The Ethernet connect path stores that +device in mac->mc_dev and keeps it for the lifetime of the connected MAC +object. + +However, the disconnect path only disconnects and closes the MAC before +freeing the dpaa2_mac object. It does not drop the endpoint device +reference stored in mac->mc_dev, so every successful connect leaks that +device reference when the MAC is later disconnected. + +Drop the endpoint device reference after closing the MAC and before +freeing the dpaa2_mac object. + +Fixes: 719479230893 ("dpaa2-eth: add MAC/PHY support through phylink") +Signed-off-by: Guangshuo Li +Reviewed-by: Ioana Ciornei +Reviewed-by: Ioana Ciornei +Link: https://patch.msgid.link/20260708111738.750391-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index 9335703768a9b6..764d2a09668f56 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -4732,6 +4732,7 @@ static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-7.1/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch b/queue-7.1/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch new file mode 100644 index 0000000000..860d85e6c5 --- /dev/null +++ b/queue-7.1/dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch @@ -0,0 +1,46 @@ +From 185e7f32d5211f9d11bd7ac8794c49b983c550a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:10:25 +0800 +Subject: dpaa2-switch: put MAC endpoint device on disconnect + +From: Guangshuo Li + +[ Upstream commit 4c1eabbef7a1707635652e956e39db1269c3af2b ] + +fsl_mc_get_endpoint() returns the MAC endpoint device with a reference +taken through device_find_child(). The switch port connect path stores +that device in mac->mc_dev and keeps it for the lifetime of the connected +MAC object. + +However, the disconnect path only closes the MAC and frees the dpaa2_mac +object. It does not drop the endpoint device reference stored in +mac->mc_dev, so every successful connect leaks that device reference when +the MAC is later disconnected. + +Drop the endpoint device reference before freeing the dpaa2_mac object. + +Fixes: 84cba72956fd ("dpaa2-switch: integrate the MAC endpoint support") +Signed-off-by: Guangshuo Li +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708111025.749311-1-lgs201920130244@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +index fa4e4f47978234..9f465033331d31 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +@@ -1511,6 +1511,7 @@ static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv) + dpaa2_mac_disconnect(mac); + + dpaa2_mac_close(mac); ++ put_device(&mac->mc_dev->dev); + kfree(mac); + } + +-- +2.53.0 + diff --git a/queue-7.1/drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch b/queue-7.1/drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch new file mode 100644 index 0000000000..a1863b1f51 --- /dev/null +++ b/queue-7.1/drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch @@ -0,0 +1,42 @@ +From 485a5a83a4a069b041474cf6ac7eb25cf22f9294 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 11:05:21 +0000 +Subject: drivers/virt: pkvm: Fix end calculation in mmio_guard_ioremap_hook() + +From: Mostafa Saleh + +[ Upstream commit 62c740f823a8e47ffe56e45a7472c27cf988e2f6 ] + +Sashiko (locally) reports a logical issues in mmio_guard_ioremap_hook() + +mmio_guard_ioremap_hook() attempts to handle unaligned addresses and +sizes. However, aligning the start address before adding the size, might +shift the end to the page before. + +Fixes: 0f1269495800 ("drivers/virt: pkvm: Intercept ioremap using pKVM MMIO_GUARD hypercall") +Signed-off-by: Mostafa Saleh +Reviewed-by: Catalin Marinas +Tested-by: Aneesh Kumar K.V (Arm) +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c +index 4230b817a80bd8..d66291def0f408 100644 +--- a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c ++++ b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c +@@ -82,8 +82,8 @@ static int mmio_guard_ioremap_hook(phys_addr_t phys, size_t size, + if (protval != PROT_DEVICE_nGnRE && protval != PROT_DEVICE_nGnRnE) + return 0; + ++ end = PAGE_ALIGN(phys + size); + phys = PAGE_ALIGN_DOWN(phys); +- end = phys + PAGE_ALIGN(size); + + while (phys < end) { + const int func_id = ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_FUNC_ID; +-- +2.53.0 + diff --git a/queue-7.1/drm-i915-backlight-remove-dp_edp_backlight_aux_enabl.patch b/queue-7.1/drm-i915-backlight-remove-dp_edp_backlight_aux_enabl.patch new file mode 100644 index 0000000000..551e69f19e --- /dev/null +++ b/queue-7.1/drm-i915-backlight-remove-dp_edp_backlight_aux_enabl.patch @@ -0,0 +1,57 @@ +From cb5d2f4279789a5336c6914dff7f18f1f2d97590 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 08:39:59 +0530 +Subject: drm/i915/backlight: Remove DP_EDP_BACKLIGHT_AUX_ENABLE_CAP check for + DPCD backlight +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Suraj Kandpal + +[ Upstream commit a411ea4a87162898d2a0547fdfb721ddb7626be3 ] + +Turns out some panels allow only AUX based backlight +by just setting the DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP and +not setting the DP_EDP_BACKLIGHT_AUX_ENABLE_CAP. +If we make DP_EDP_BACKLIGHT_AUX_ENABLE_CAP a necessity for AUX +based DPCD backlight these panels loose the ability to manipulate +backlight via AUX, especially ones with no PWM controller. +Remove this check from function so that panels who do not advertise +DP_EDP_BACKLIGHT_AUX_ENABLE_CAP but advertise +DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP are able to manipulate +backlight again. + +Fixes: ed8be780bdbc ("drm/i915/backlight: Fix VESA backlight possible check condition") +Closes: https://gitlab.freedesktop.org/drm/i915/kernel/-/work_items/16507 +Signed-off-by: Suraj Kandpal +Reviewed-by: Michał Grzelak +Link: https://patch.msgid.link/20260716030959.436430-1-suraj.kandpal@intel.com +(cherry picked from commit 7d594b24c915afb4b0c5fb8875403253daef5b24) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +index 7a6c07f6aaeb4b..266e042e00237c 100644 +--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c ++++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +@@ -615,12 +615,7 @@ check_if_vesa_backlight_possible(struct intel_dp *intel_dp) + int ret; + u8 bit_min, bit_max; + +- /* +- * Since we only support Fully AUX Based VESA Backlight interface make sure +- * backlight enable is possible via AUX along with backlight adjustment +- */ +- if (!(intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP && +- intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) ++ if (!(intel_dp->edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) + return false; + + ret = drm_dp_dpcd_read_byte(&intel_dp->aux, DP_EDP_PWMGEN_BIT_COUNT_CAP_MIN, &bit_min); +-- +2.53.0 + diff --git a/queue-7.1/drm-panel-fix-unmet-dependency-bug-for-drm_panel_him.patch b/queue-7.1/drm-panel-fix-unmet-dependency-bug-for-drm_panel_him.patch new file mode 100644 index 0000000000..e7fdde52b2 --- /dev/null +++ b/queue-7.1/drm-panel-fix-unmet-dependency-bug-for-drm_panel_him.patch @@ -0,0 +1,50 @@ +From e198bf64f09400de19a75d01cf32f0072fa2a3a1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 00:42:30 +0100 +Subject: drm/panel: fix unmet dependency bug for DRM_PANEL_HIMAX_HX83121A + +From: Julian Braha + +[ Upstream commit aaa5be0258db1709e254b4150af5c2fa5518c548 ] + +Currently, DRM_PANEL_HIMAX_HX83121A selects DRM_DISPLAY_DSC_HELPER +without also ensuring DRM_DISPLAY_HELPER is enabled, causing an unmet +dependency: + +WARNING: unmet direct dependencies detected for DRM_DISPLAY_DSC_HELPER + Depends on [n]: HAS_IOMEM [=y] && DRM [=m] && DRM_DISPLAY_HELPER [=n] + Selected by [m]: + - DRM_PANEL_HIMAX_HX83121A [=m] && HAS_IOMEM [=y] && DRM [=m] && DRM_PANEL [=y] && OF [=y] && DRM_MIPI_DSI [=y] && BACKLIGHT_CLASS_DEVICE [=m] + - DRM_PANEL_ILITEK_ILI9882T [=m] && HAS_IOMEM [=y] && DRM [=m] && DRM_PANEL [=y] && OF [=y] && DRM_MIPI_DSI [=y] && BACKLIGHT_CLASS_DEVICE [=m] + +Many other DRM_PANEL_* options select DRM_DISPLAY_HELPER when selecting +DRM_DISPLAY_DSC_HELPER, let's do the same here. + +This unmet dependency bug was found by kconfirm, a static analysis tool +for Kconfig. + +Fixes: defab7b01e08 ("drm/panel: hx83121a: select DRM_DISPLAY_DSC_HELPER") +Signed-off-by: Julian Braha +Reviewed-by: Neil Armstrong +Signed-off-by: Neil Armstrong +Link: https://patch.msgid.link/20260711234230.2236041-1-julianbraha@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig +index db2bd4d02377bb..adab94b3ebdfd7 100644 +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -208,6 +208,7 @@ config DRM_PANEL_HIMAX_HX83121A + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE ++ select DRM_DISPLAY_HELPER + select DRM_DISPLAY_DSC_HELPER + select DRM_KMS_HELPER + help +-- +2.53.0 + diff --git a/queue-7.1/drm-panel-ilitek-ili9882t-fix-unmet-dependency-for-d.patch b/queue-7.1/drm-panel-ilitek-ili9882t-fix-unmet-dependency-for-d.patch new file mode 100644 index 0000000000..5d6fa6b4b4 --- /dev/null +++ b/queue-7.1/drm-panel-ilitek-ili9882t-fix-unmet-dependency-for-d.patch @@ -0,0 +1,44 @@ +From bc7f8dc6cbd1ae372dbd1126b06a531f157ca70e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 01:26:32 +0100 +Subject: drm/panel: ilitek-ili9882t: fix unmet dependency for + DRM_PANEL_ILITEK_ILI9882T + +From: Julian Braha + +[ Upstream commit fc03f930bd9fd7c09617e41b1743e50ba659707c ] + +Currently, DRM_PANEL_ILITEK_ILI9882T selects DRM_DISPLAY_DSC_HELPER +without ensuring DRM_DISPLAY_HELPER is also enabled, causing an unmet +dependency and build failure. + +Other similar options select DRM_DISPLAY_HELPER, let's do the same here. + +This unmet dependency bug was found by kconfirm, a static analysis tool +for Kconfig. + +Fixes: 68e28facbc8a ("drm/panel: ilitek-ili9882t: Select DRM_DISPLAY_DSC_HELPER") +Signed-off-by: Julian Braha +Reviewed-by: Neil Armstrong +Signed-off-by: Neil Armstrong +Link: https://patch.msgid.link/20260712002632.2323484-1-julianbraha@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig +index b2153e04a59af7..abc954dff88bc4 100644 +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -308,6 +308,7 @@ config DRM_PANEL_ILITEK_ILI9882T + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE ++ select DRM_DISPLAY_HELPER + select DRM_DISPLAY_DSC_HELPER + help + Say Y if you want to enable support for panels based on the +-- +2.53.0 + diff --git a/queue-7.1/drm-panel-s6e3ha8-fix-unmet-dependency-on-drm_displa.patch b/queue-7.1/drm-panel-s6e3ha8-fix-unmet-dependency-on-drm_displa.patch new file mode 100644 index 0000000000..050d38075f --- /dev/null +++ b/queue-7.1/drm-panel-s6e3ha8-fix-unmet-dependency-on-drm_displa.patch @@ -0,0 +1,43 @@ +From 43b3ca44b3d3acd2610afd751e5f9c38ced3ac7e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 01:15:14 +0100 +Subject: drm/panel: s6e3ha8: fix unmet dependency on DRM_DISPLAY_HELPER + +From: Julian Braha + +[ Upstream commit 3667bc164849fee4f1b18b182bdfe643f758ca17 ] + +Currently, DRM_PANEL_SAMSUNG_S6E3HA8 selects DRM_DISPLAY_DSC_HELPER +without ensuring its dependency, DRM_DISPLAY_HELPER, is enabled, +causing an unmet dependency. + +Let's select DRM_DISPLAY_HELPER as other similar options do. + +This unmet dependency bug was found by kconfirm, a static analysis tool +for Kconfig. + +Fixes: fd3b2c5f40a1 ("drm/panel: s6e3ha8: select CONFIG_DRM_DISPLAY_DSC_HELPER") +Signed-off-by: Julian Braha +Reviewed-by: Neil Armstrong +Signed-off-by: Neil Armstrong +Link: https://patch.msgid.link/20260712001514.2318597-1-julianbraha@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/panel/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig +index abc954dff88bc4..db2bd4d02377bb 100644 +--- a/drivers/gpu/drm/panel/Kconfig ++++ b/drivers/gpu/drm/panel/Kconfig +@@ -915,6 +915,7 @@ config DRM_PANEL_SAMSUNG_S6E3HA8 + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE ++ select DRM_DISPLAY_HELPER + select DRM_DISPLAY_DSC_HELPER + help + Say Y or M here if you want to enable support for the +-- +2.53.0 + diff --git a/queue-7.1/drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch b/queue-7.1/drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch new file mode 100644 index 0000000000..e7002a40c0 --- /dev/null +++ b/queue-7.1/drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch @@ -0,0 +1,108 @@ +From e5146b78f70e87e591c62b094d70ae4af28fc36b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2026 17:07:43 +0200 +Subject: drm/tests: shmem: Set DMA mask to 64-bit in drm_gem_shmem +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: José Expósito + +[ Upstream commit b04a248cfa6cfa1e7dc9ce91cb1eb88b1a70dd69 ] + +drm_gem_shmem_test_purge [1] and drm_gem_shmem_test_get_pages_sgt [2] +intermittently fail on ppc64le and s390x CI systems with a DMA address +overflow: + + DMA addr 0x0000000100307000+4096 overflow (mask ffffffff, bus limit 0) + WARNING: kernel/dma/direct.h:114 dma_direct_map_sg+0x778/0x920 + + drm_gem_shmem_test_purge: ASSERTION FAILED at + drivers/gpu/drm/tests/drm_gem_shmem_test.c:330 + Expected sgt is not error, but is: -5 + +The call chain leading to the failure is: + + drm_gem_shmem_test_purge() / drm_gem_shmem_test_get_pages_sgt() + drm_gem_shmem_get_pages_sgt() + drm_gem_shmem_get_pages_sgt_locked() [drm_gem_shmem_helper.c] + dma_map_sgtable() [mapping.c] + __dma_map_sg_attrs() + dma_direct_map_sg() [direct.c] + dma_direct_map_phys() [kernel/dma/direct.h] + dma_capable() Checks addr against DMA mask + -> FAILS: addr > 0xFFFFFFFF + +The root cause is that KUnit devices are initialized with a 32-bit DMA +mask (DMA_BIT_MASK(32)) in lib/kunit/device.c. On ppc64le and s390x +systems with physical memory above 4GB, page allocations can land at +addresses that exceed this mask. When drm_gem_shmem_get_pages_sgt() +attempts to DMA-map these pages via dma_map_sgtable(), the DMA layer +rejects the mapping because the physical address overflows the 32-bit +mask. + +The failure is intermittent because pages may or may not be allocated +above 4GB on any given run depend on memory pressure. + +Fix by setting a 64-bit DMA mask on the device before calling +drm_gem_shmem_get_pages_sgt() for all tests, following the same pattern +already used in drm_gem_shmem_test_obj_create_private(). + +[1] https://s3.amazonaws.com/arr-cki-prod-trusted-artifacts/trusted-artifacts/2643976103/test_s390x/15128551935/artifacts/jobwatch/logs/recipes/21561049/tasks/220716793/results/1014626315/logs/dmesg.log +[2] https://s3.amazonaws.com/arr-cki-prod-trusted-artifacts/trusted-artifacts/2643976103/test_ppc64le/15128551933/artifacts/jobwatch/logs/recipes/21561041/tasks/220716705/results/1014628163/logs/dmesg.log + +Fixes: 93032ae634d4 ("drm/test: add a test suite for GEM objects backed by shmem") +Closes: https://datawarehouse.cki-project.org/issue/5345 +Closes: https://datawarehouse.cki-project.org/issue/3184 +Assisted-by: Claude:claude-4.6-opus +Reviewed-by: Thomas Zimmermann +Signed-off-by: José Expósito +Link: https://patch.msgid.link/20260703150808.3832-1-jose.exposito89@gmail.com +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/tests/drm_gem_shmem_test.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +diff --git a/drivers/gpu/drm/tests/drm_gem_shmem_test.c b/drivers/gpu/drm/tests/drm_gem_shmem_test.c +index 44a1901092497e..5e69ff1d1ad673 100644 +--- a/drivers/gpu/drm/tests/drm_gem_shmem_test.c ++++ b/drivers/gpu/drm/tests/drm_gem_shmem_test.c +@@ -95,13 +95,9 @@ static void drm_gem_shmem_test_obj_create_private(struct kunit *test) + sg_init_one(sgt->sgl, buf, TEST_SIZE); + + /* +- * Set the DMA mask to 64-bits and map the sgtables +- * otherwise drm_gem_shmem_free will cause a warning +- * on debug kernels. ++ * Map the sgtables otherwise drm_gem_shmem_free will cause a warning on ++ * debug kernels. + */ +- ret = dma_set_mask(drm_dev->dev, DMA_BIT_MASK(64)); +- KUNIT_ASSERT_EQ(test, ret, 0); +- + ret = dma_map_sgtable(drm_dev->dev, sgt, DMA_BIDIRECTIONAL, 0); + KUNIT_ASSERT_EQ(test, ret, 0); + +@@ -352,11 +348,19 @@ static int drm_gem_shmem_test_init(struct kunit *test) + { + struct device *dev; + struct drm_device *drm_dev; ++ int ret; + + /* Allocate a parent device */ + dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + ++ /* ++ * Set the DMA mask to 64-bits to avoid intermittent failures calling ++ * drm_gem_shmem_get_pages_sgt(). ++ */ ++ ret = dma_set_mask(dev, DMA_BIT_MASK(64)); ++ KUNIT_ASSERT_EQ(test, ret, 0); ++ + /* + * The DRM core will automatically initialize the GEM core and create + * a DRM Memory Manager object which provides an address space pool +-- +2.53.0 + diff --git a/queue-7.1/drm-vc4-hvs-v3d-fix-null-dereference-in-unbind.patch b/queue-7.1/drm-vc4-hvs-v3d-fix-null-dereference-in-unbind.patch new file mode 100644 index 0000000000..8b6b47854e --- /dev/null +++ b/queue-7.1/drm-vc4-hvs-v3d-fix-null-dereference-in-unbind.patch @@ -0,0 +1,61 @@ +From 377933368385d03048e55ecaddf25070c0aa270e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:38:19 +0200 +Subject: drm/vc4: hvs/v3d: Fix null dereference in unbind +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Gregor Herburger + +[ Upstream commit 7dc3680b7ffe01add3e9299fde8471d2dd53a8ae ] + +The hvs and v3d drivers use dev_get_drvdata(master) in their unbind +functions. Since the vc4-drm gets removed before its dependent drivers +(vc4_hvs/vc4_v3d) the vc4_hvs_unbind/vc4_v3d_unbind functions try to +get drvdata of its master and fails with a null dereference error. + +Use the data pointer passed to the unbind functions directly instead of +dev_get_drvdata(master). This avoids using potentially freed memory. + +Fixes: d3f5168a0810 ("drm/vc4: Bind and initialize the V3D engine.") +Fixes: c8b75bca92cb ("drm/vc4: Add KMS support for Raspberry Pi.") +Signed-off-by: Gregor Herburger +Link: https://patch.msgid.link/20260721-rpi-vc4-fix-v2-1-b813dcd01dc7@linutronix.de +Reviewed-by: Maíra Canal +Signed-off-by: Maíra Canal +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/vc4/vc4_hvs.c | 2 +- + drivers/gpu/drm/vc4/vc4_v3d.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c +index ee8d0738501b87..89359d1900087d 100644 +--- a/drivers/gpu/drm/vc4/vc4_hvs.c ++++ b/drivers/gpu/drm/vc4/vc4_hvs.c +@@ -1752,7 +1752,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) + static void vc4_hvs_unbind(struct device *dev, struct device *master, + void *data) + { +- struct drm_device *drm = dev_get_drvdata(master); ++ struct drm_device *drm = data; + struct vc4_dev *vc4 = to_vc4_dev(drm); + struct vc4_hvs *hvs = vc4->hvs; + struct drm_mm_node *node, *next; +diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c +index d31b906cb8e787..f32410420d3e4d 100644 +--- a/drivers/gpu/drm/vc4/vc4_v3d.c ++++ b/drivers/gpu/drm/vc4/vc4_v3d.c +@@ -494,7 +494,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data) + static void vc4_v3d_unbind(struct device *dev, struct device *master, + void *data) + { +- struct drm_device *drm = dev_get_drvdata(master); ++ struct drm_device *drm = data; + struct vc4_dev *vc4 = to_vc4_dev(drm); + + vc4_irq_uninstall(drm); +-- +2.53.0 + diff --git a/queue-7.1/drm-xe-i2c-allow-per-domain-unique-id.patch b/queue-7.1/drm-xe-i2c-allow-per-domain-unique-id.patch new file mode 100644 index 0000000000..3f9ef60090 --- /dev/null +++ b/queue-7.1/drm-xe-i2c-allow-per-domain-unique-id.patch @@ -0,0 +1,58 @@ +From 0f53eb7b07d3cce76dea3feb7e2ef9320443085b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:04:38 +0530 +Subject: drm/xe/i2c: Allow per domain unique id +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Raag Jadav + +[ Upstream commit 5d8ed6b64220ad629aade5f174e3f690c37435f9 ] + +PCI bus, device and function can be same for devices existing across +different domains. Allow per domain unique identifier while registering +platform device to prevent name conflict. + +Fixes: f0e53aadd702 ("drm/xe: Support for I2C attached MCUs") +Signed-off-by: Raag Jadav +Reviewed-by: Heikki Krogerus +Link: https://patch.msgid.link/20260721113438.651100-1-raag.jadav@intel.com +Signed-off-by: Matt Roper +(cherry picked from commit a79f6abc8b516b5bd906e2eca8121e3549ee163f) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_i2c.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/gpu/drm/xe/xe_i2c.c b/drivers/gpu/drm/xe/xe_i2c.c +index 706783863d07d6..f05f23221c1b7b 100644 +--- a/drivers/gpu/drm/xe/xe_i2c.c ++++ b/drivers/gpu/drm/xe/xe_i2c.c +@@ -95,18 +95,21 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c) + struct platform_device *pdev; + struct fwnode_handle *fwnode; + int ret; ++ u32 id; + + fwnode = fwnode_create_software_node(xe_i2c_adapter_properties, NULL); + if (IS_ERR(fwnode)) + return PTR_ERR(fwnode); + ++ id = (pci_domain_nr(pci->bus) << 16) | pci_dev_id(pci); ++ + /* + * Not using platform_device_register_full() here because we don't have + * a handle to the platform_device before it returns. xe_i2c_notifier() + * uses that handle, but it may be called before + * platform_device_register_full() is done. + */ +- pdev = platform_device_alloc(adapter_name, pci_dev_id(pci)); ++ pdev = platform_device_alloc(adapter_name, id); + if (!pdev) { + ret = -ENOMEM; + goto err_fwnode_remove; +-- +2.53.0 + diff --git a/queue-7.1/drm-xe-vf-add-drm_dev-guards-when-detaching-ccs-read.patch b/queue-7.1/drm-xe-vf-add-drm_dev-guards-when-detaching-ccs-read.patch new file mode 100644 index 0000000000..35dc86d7f8 --- /dev/null +++ b/queue-7.1/drm-xe-vf-add-drm_dev-guards-when-detaching-ccs-read.patch @@ -0,0 +1,183 @@ +From 45d88f90b8203bcf41ed5d164bde42e0d32d8599 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 10:52:14 +0530 +Subject: drm/xe/vf: Add drm_dev guards when detaching CCS read/write buffers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Satyanarayana K V P + +[ Upstream commit 4c92afb4c143526d340545ca581e88e6952ea511 ] + +CCS read/write buffers are freed during BO destruction. In some cases, +BOs may be destroyed after the device is unbound but while the DRM +structure remains valid, leading to NULL pointer dereferences when +accessing device resources. + +BUG: kernel NULL pointer dereference, address: 0000000000000000 +PGD 0 P4D 0 +Oops: Oops: 0000 [#1] SMP NOPTI +CPU: 0 UID: 0 PID: 9376 Comm: xe_pat Not tainted 7.2.0-rc2+ #1 PREEMPT(lazy) +RIP: 0010:xe_sriov_vf_ccs_rw_update_bb_addr+0x4d/0xa0 [xe] +RSP: 0018:ffffcf304110b9c8 EFLAGS: 00010246 +RAX: ffff8a85c38a0a00 RBX: 00000000810ef000 RCX: 0000000000000000 +RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8a85c39c1888 +RBP: ffffcf304110b9e8 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000000 R12: ffff8a85c39c1888 +R13: 0000000000000000 R14: ffff8a85c39b4f28 R15: ffff8a85c3885000 +FS: 0000000000000000(0000) GS:ffff8a878b809000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000000000 CR3: 000000010314a002 CR4: 0000000000772ef0 +PKRU: 55555554 +Call Trace: + + xe_migrate_ccs_rw_copy_clear+0x98/0x120 [xe] + xe_sriov_vf_ccs_detach_bo+0x2c/0x60 [xe] + xe_ttm_bo_delete_mem_notify+0xc8/0xe0 [xe] + ttm_bo_cleanup_memtype_use+0x26/0x80 [ttm] + ttm_bo_release+0x29e/0x2d0 [ttm] + ttm_bo_fini+0x39/0x70 [ttm] + xe_gem_object_free+0x1f/0x30 [xe] + drm_gem_object_free+0x1d/0x40 + ttm_bo_vm_close+0x5f/0x90 [ttm] + remove_vma+0x2c/0x70 + tear_down_vmas+0x63/0xf0 + exit_mmap+0x20d/0x3f0 + __mmput+0x45/0x170 + mmput+0x31/0x40 + do_exit+0x2ba/0xac0 + do_group_exit+0x2d/0xb0 + __x64_sys_exit_group+0x18/0x20 + x64_sys_call+0x14a0/0x2390 + do_syscall_64+0xdd/0x640 + ? count_memcg_events+0xea/0x240 + ? handle_mm_fault+0x1ec/0x2f0 + +Fixes: 864690cf4dd6 ("drm/xe/vf: Attach and detach CCS copy commands with BO") +Signed-off-by: Satyanarayana K V P +Cc: Matthew Brost +Cc: Michal Wajdeczko +Reviewed-by: Matthew Brost +Signed-off-by: Matthew Brost +Link: https://patch.msgid.link/20260721052215.2267228-2-satyanarayana.k.v.p@intel.com +(cherry picked from commit 1ae415a6eefe5004954a1d352b1718faca8844ef) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_migrate.c | 16 ++++++++++------ + drivers/gpu/drm/xe/xe_migrate.h | 3 ++- + drivers/gpu/drm/xe/xe_sriov_vf_ccs.c | 14 ++++++++++++-- + 3 files changed, 24 insertions(+), 9 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c +index f4160e844b4c33..5dd03d4cbf5bb2 100644 +--- a/drivers/gpu/drm/xe/xe_migrate.c ++++ b/drivers/gpu/drm/xe/xe_migrate.c +@@ -1292,6 +1292,7 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + * content. + * @src_bo: The buffer object @src is currently bound to. + * @read_write : Creates BB commands for CCS read/write. ++ * @bound: Device is bound + * + * Directly clearing the BB lacks atomicity and can lead to undefined + * behavior if the vCPU is halted mid-operation during the clearing +@@ -1304,7 +1305,8 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + * Returns: None. + */ + void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, +- enum xe_sriov_vf_ccs_rw_ctxs read_write) ++ enum xe_sriov_vf_ccs_rw_ctxs read_write, ++ bool bound) + { + struct xe_mem_pool_node *bb = src_bo->bb_ccs[read_write]; + struct xe_device *xe = xe_bo_device(src_bo); +@@ -1318,13 +1320,15 @@ void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, + bb_pool = ctx->mem.ccs_bb_pool; + + scoped_guard(mutex, xe_mem_pool_bo_swap_guard(bb_pool)) { +- xe_mem_pool_swap_shadow_locked(bb_pool); ++ if (bound) { ++ xe_mem_pool_swap_shadow_locked(bb_pool); + +- cs = xe_mem_pool_node_cpu_addr(bb); +- memset(cs, MI_NOOP, bb->sa_node.size); +- xe_sriov_vf_ccs_rw_update_bb_addr(ctx); ++ cs = xe_mem_pool_node_cpu_addr(bb); ++ memset(cs, MI_NOOP, bb->sa_node.size); ++ xe_sriov_vf_ccs_rw_update_bb_addr(ctx); + +- xe_mem_pool_sync_shadow_locked(bb); ++ xe_mem_pool_sync_shadow_locked(bb); ++ } + xe_mem_pool_free_node(bb); + src_bo->bb_ccs[read_write] = NULL; + } +diff --git a/drivers/gpu/drm/xe/xe_migrate.h b/drivers/gpu/drm/xe/xe_migrate.h +index 7761c02b4d86d6..0bcc122c1c3434 100644 +--- a/drivers/gpu/drm/xe/xe_migrate.h ++++ b/drivers/gpu/drm/xe/xe_migrate.h +@@ -142,7 +142,8 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, + enum xe_sriov_vf_ccs_rw_ctxs read_write); + + void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, +- enum xe_sriov_vf_ccs_rw_ctxs read_write); ++ enum xe_sriov_vf_ccs_rw_ctxs read_write, ++ bool bound); + + struct xe_lrc *xe_migrate_lrc(struct xe_migrate *migrate); + struct xe_exec_queue *xe_migrate_exec_queue(struct xe_migrate *migrate); +diff --git a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +index 6787564629c65f..a8c831fbee3b5a 100644 +--- a/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c ++++ b/drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +@@ -3,6 +3,8 @@ + * Copyright © 2025 Intel Corporation + */ + ++#include ++ + #include "instructions/xe_mi_commands.h" + #include "instructions/xe_gpu_commands.h" + #include "xe_bb.h" +@@ -446,7 +448,7 @@ int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem) + */ + for_each_ccs_rw_ctx(ctx_id) { + if (bo->bb_ccs[ctx_id]) +- xe_migrate_ccs_rw_copy_clear(bo, ctx_id); ++ xe_migrate_ccs_rw_copy_clear(bo, ctx_id, true); + } + return err; + } +@@ -466,19 +468,27 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo) + struct xe_device *xe = xe_bo_device(bo); + enum xe_sriov_vf_ccs_rw_ctxs ctx_id; + struct xe_mem_pool_node *bb; ++ bool bound; ++ int idx; + + xe_assert(xe, IS_VF_CCS_READY(xe)); + + if (!xe_bo_has_valid_ccs_bb(bo)) + return 0; + ++ bound = drm_dev_enter(&xe->drm, &idx); ++ + for_each_ccs_rw_ctx(ctx_id) { + bb = bo->bb_ccs[ctx_id]; + if (!bb) + continue; + +- xe_migrate_ccs_rw_copy_clear(bo, ctx_id); ++ xe_migrate_ccs_rw_copy_clear(bo, ctx_id, bound); + } ++ ++ if (bound) ++ drm_dev_exit(idx); ++ + return 0; + } + +-- +2.53.0 + diff --git a/queue-7.1/drm-xe-vm-fix-svm-leak-on-resv-obj-alloc-failure-in-.patch b/queue-7.1/drm-xe-vm-fix-svm-leak-on-resv-obj-alloc-failure-in-.patch new file mode 100644 index 0000000000..970977dfc7 --- /dev/null +++ b/queue-7.1/drm-xe-vm-fix-svm-leak-on-resv-obj-alloc-failure-in-.patch @@ -0,0 +1,75 @@ +From 8b68a41395a64f4158250abb48f7d2b46489d836 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 20:55:14 +0000 +Subject: drm/xe/vm: Fix SVM leak on resv obj alloc failure in xe_vm_create() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Shuicheng Lin + +[ Upstream commit d2c6800ad1802bed72a6de1416536737f114f1d6 ] + +Commit 9e9787414882 ("drm/xe/userptr: replace xe_hmm with gpusvm") made +xe_svm_init() unconditional in xe_vm_create() and extended it to also +initialize a "simple" gpusvm state for non-fault-mode VMs. The matching +xe_svm_fini() call in xe_vm_close_and_put() was updated to run +unconditionally, but the error unwind path in xe_vm_create() was not. + +On the drm_gpuvm_resv_object_alloc() failure path, xe_svm_init() has +already succeeded but xe_svm_fini() is only called when +XE_VM_FLAG_FAULT_MODE is set. For non-fault-mode VMs this leaves +vm->svm.gpusvm partially initialized and leaks the resources allocated +by drm_gpusvm_init(). + +For fault-mode VMs, xe_svm_init() additionally acquires the pagemap +owner via drm_pagemap_acquire_owner() and the pagemaps via +xe_svm_get_pagemaps(). Those resources are released by xe_svm_close(), +not xe_svm_fini(). On the same error path, xe_svm_close() is not +called either, so fault-mode VMs leak the pagemap owner and pagemaps. + +Fix both leaks: + +- Call xe_svm_fini() unconditionally on the err_svm_fini path, matching + the unconditional xe_svm_init() call. Move the vm->size = 0 + assignment out of the conditional so the xe_vm_is_closed() assert in + xe_svm_fini() (and xe_svm_close()) holds for both modes. + +- Call xe_svm_close() for fault-mode VMs before xe_svm_fini(), matching + the ordering used in xe_vm_close_and_put(). + +Fixes: 9e9787414882 ("drm/xe/userptr: replace xe_hmm with gpusvm") +Cc: Matthew Auld +Assisted-by: Claude:claude-opus-4.7 +Reviewed-by: Matthew Brost +Link: https://patch.msgid.link/20260721205516.4058959-2-shuicheng.lin@intel.com +Signed-off-by: Shuicheng Lin +(cherry picked from commit ca2a3587d577ba764e0fe628fb676244fc33ddd4) +Signed-off-by: Thomas Hellström +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/xe/xe_vm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c +index ab6cc1f0a78949..aec3c2a60d5888 100644 +--- a/drivers/gpu/drm/xe/xe_vm.c ++++ b/drivers/gpu/drm/xe/xe_vm.c +@@ -1810,10 +1810,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef) + return ERR_PTR(err); + + err_svm_fini: +- if (flags & XE_VM_FLAG_FAULT_MODE) { +- vm->size = 0; /* close the vm */ +- xe_svm_fini(vm); +- } ++ vm->size = 0; /* close the vm */ ++ if (flags & XE_VM_FLAG_FAULT_MODE) ++ xe_svm_close(vm); ++ xe_svm_fini(vm); + err_no_resv: + mutex_destroy(&vm->snap_mutex); + for_each_tile(tile, xe, id) +-- +2.53.0 + diff --git a/queue-7.1/drop_monitor-fix-size-calculations-for-64-bit-attrib.patch b/queue-7.1/drop_monitor-fix-size-calculations-for-64-bit-attrib.patch new file mode 100644 index 0000000000..63be656db6 --- /dev/null +++ b/queue-7.1/drop_monitor-fix-size-calculations-for-64-bit-attrib.patch @@ -0,0 +1,68 @@ +From 75039ab16f9b9d626f69156c53bd2c1acf7de865 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 14:17:42 +0000 +Subject: drop_monitor: fix size calculations for 64-bit attributes + +From: Eric Dumazet + +[ Upstream commit 7089f7ab99c89f443c92d8fcc585e63f2727f0b3 ] + +net_dm_packet_report_fill() and net_dm_hw_packet_report_fill() use +nla_put_u64_64bit() to append 64-bit attributes (NET_DM_ATTR_PC and +NET_DM_ATTR_TIMESTAMP). + +On 32-bit architectures without CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS, +nla_put_u64_64bit() may append a 4-byte NET_DM_ATTR_PAD attribute for +64-bit alignment. + +However, net_dm_packet_report_size() and net_dm_hw_packet_report_size() +used nla_total_size(sizeof(u64)) instead of nla_total_size_64bit(sizeof(u64)), +budgeting 12 bytes instead of up to 16 bytes. + +This under-estimation of SKB size can lead to an skb_over_panic() when +__nla_reserve() or skb_put() is subsequently called. + +Fix this by using nla_total_size_64bit(sizeof(u64)) in both size calculations. + +Fixes: ca30707dee2b ("drop_monitor: Add packet alert mode") +Fixes: 5e58109b1ea4 ("drop_monitor: Add support for packet alert mode for hardware drops") +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20260722141743.3266924-2-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/drop_monitor.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c +index afcd8ba411b6ac..61d6679b074eef 100644 +--- a/net/core/drop_monitor.c ++++ b/net/core/drop_monitor.c +@@ -566,13 +566,13 @@ static size_t net_dm_packet_report_size(size_t payload_len) + /* NET_DM_ATTR_ORIGIN */ + nla_total_size(sizeof(u16)) + + /* NET_DM_ATTR_PC */ +- nla_total_size(sizeof(u64)) + ++ nla_total_size_64bit(sizeof(u64)) + + /* NET_DM_ATTR_SYMBOL */ + nla_total_size(NET_DM_MAX_SYMBOL_LEN + 1) + + /* NET_DM_ATTR_IN_PORT */ + net_dm_in_port_size() + + /* NET_DM_ATTR_TIMESTAMP */ +- nla_total_size(sizeof(u64)) + ++ nla_total_size_64bit(sizeof(u64)) + + /* NET_DM_ATTR_ORIG_LEN */ + nla_total_size(sizeof(u32)) + + /* NET_DM_ATTR_PROTO */ +@@ -766,7 +766,7 @@ net_dm_hw_packet_report_size(size_t payload_len, + /* NET_DM_ATTR_FLOW_ACTION_COOKIE */ + net_dm_flow_action_cookie_size(hw_metadata) + + /* NET_DM_ATTR_TIMESTAMP */ +- nla_total_size(sizeof(u64)) + ++ nla_total_size_64bit(sizeof(u64)) + + /* NET_DM_ATTR_ORIG_LEN */ + nla_total_size(sizeof(u32)) + + /* NET_DM_ATTR_PROTO */ +-- +2.53.0 + diff --git a/queue-7.1/drop_monitor-perform-u64_stats-updates-under-irq-dis.patch b/queue-7.1/drop_monitor-perform-u64_stats-updates-under-irq-dis.patch new file mode 100644 index 0000000000..5fed6b6b9e --- /dev/null +++ b/queue-7.1/drop_monitor-perform-u64_stats-updates-under-irq-dis.patch @@ -0,0 +1,65 @@ +From 636d1eeed98cb77049986aece68d6d53608f8ae7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 14:17:43 +0000 +Subject: drop_monitor: perform u64_stats updates under IRQ-disabled section + +From: Eric Dumazet + +[ Upstream commit fd098a23bf8fda7eae48db9b06e7c34fc4d228fa ] + +In net_dm_packet_trace_kfree_skb_hit() and net_dm_hw_trap_packet_probe(), +u64_stats_update_begin() / u64_stats_inc() / u64_stats_update_end() were +called after spin_unlock_irqrestore(&...drop_queue.lock, flags), when local +IRQs had already been re-enabled. + +Tracepoint probes can execute in IRQ or softirq context. On 32-bit +architectures, u64_stats_update_begin() disables preemption but not interrupts, +relying on seqcount writes. If a nested interrupt occurs on the same CPU during +the 64-bit stats update, the reentrant seqcount update can corrupt the +seqcount state or stats value. + +Fix this by performing the 64-bit per-CPU stats update before releasing +drop_queue.lock via spin_unlock_irqrestore(), ensuring local interrupts remain +disabled during the u64_stats update. + +Fixes: e9feb58020f9 ("drop_monitor: Expose tail drop counter") +Fixes: 5e58109b1ea4 ("drop_monitor: Add support for packet alert mode for hardware drops") +Signed-off-by: Eric Dumazet +Link: https://patch.msgid.link/20260722141743.3266924-3-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/drop_monitor.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c +index 61d6679b074eef..5df3e18ebaf74a 100644 +--- a/net/core/drop_monitor.c ++++ b/net/core/drop_monitor.c +@@ -530,10 +530,10 @@ static void net_dm_packet_trace_kfree_skb_hit(void *ignore, + return; + + unlock_free: +- spin_unlock_irqrestore(&data->drop_queue.lock, flags); + u64_stats_update_begin(&data->stats.syncp); + u64_stats_inc(&data->stats.dropped); + u64_stats_update_end(&data->stats.syncp); ++ spin_unlock_irqrestore(&data->drop_queue.lock, flags); + consume_skb(nskb); + } + +@@ -997,10 +997,10 @@ net_dm_hw_trap_packet_probe(void *ignore, const struct devlink *devlink, + return; + + unlock_free: +- spin_unlock_irqrestore(&hw_data->drop_queue.lock, flags); + u64_stats_update_begin(&hw_data->stats.syncp); + u64_stats_inc(&hw_data->stats.dropped); + u64_stats_update_end(&hw_data->stats.syncp); ++ spin_unlock_irqrestore(&hw_data->drop_queue.lock, flags); + net_dm_hw_metadata_free(n_hw_metadata); + free: + consume_skb(nskb); +-- +2.53.0 + diff --git a/queue-7.1/firewire-net-fix-fragmented-datagram-reassembly.patch b/queue-7.1/firewire-net-fix-fragmented-datagram-reassembly.patch new file mode 100644 index 0000000000..82e8e998cb --- /dev/null +++ b/queue-7.1/firewire-net-fix-fragmented-datagram-reassembly.patch @@ -0,0 +1,99 @@ +From 5ee58ae103275730d4bdb4f6feb57854f69bd56b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 23:04:54 +0800 +Subject: firewire: net: Fix fragmented datagram reassembly + +From: Ruoyu Wang + +[ Upstream commit d52a13adbb8ccbab99cd3bad36804e87d8b5c052 ] + +fwnet_frag_new() keeps a sorted list of received fragments for a partial +datagram. When a new fragment is adjacent to an existing fragment, the +code checks whether the new fragment also closes the gap to the next or +previous list entry. + +Those neighbor lookups currently assume that the current fragment always +has a real next or previous fragment. At a list edge, the next or +previous entry is the list head, not a struct fwnet_fragment_info. + +The gap checks also compare against the old edge of the current fragment +instead of the edge after adding the new fragment. As a result, a +fragment that bridges two existing ranges may leave two adjacent ranges +unmerged, so fwnet_pd_is_complete() can miss a complete datagram. + +Check for the list head before looking up the neighboring fragment, and +compare the neighbor against the new fragment's far edge when deciding +whether to merge all three ranges. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: c76acec6d551 ("firewire: add IPv4 support") +Signed-off-by: Ruoyu Wang +Link: https://lore.kernel.org/r/20260707150454.2265951-1-ruoyuw560@gmail.com +Signed-off-by: Takashi Sakamoto +Signed-off-by: Sasha Levin +--- + drivers/firewire/net.c | 39 +++++++++++++++++++++------------------ + 1 file changed, 21 insertions(+), 18 deletions(-) + +diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c +index 82b3b6d9ed2df6..2a0727935d7367 100644 +--- a/drivers/firewire/net.c ++++ b/drivers/firewire/net.c +@@ -298,31 +298,34 @@ static struct fwnet_fragment_info *fwnet_frag_new( + if (fi->offset + fi->len == offset) { + /* The new fragment can be tacked on to the end */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.next, +- struct fwnet_fragment_info, fi_link); +- if (fi->offset + fi->len == fi2->offset) { +- /* glue fragments together */ +- fi->len += len + fi2->len; +- list_del(&fi2->fi_link); +- kfree(fi2); +- } else { +- fi->len += len; ++ if (!list_is_last(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_next_entry(fi, fi_link); ++ if (offset + len == fi2->offset) { ++ /* glue fragments together */ ++ fi->len += len + fi2->len; ++ list_del(&fi2->fi_link); ++ kfree(fi2); ++ ++ return fi; ++ } + } ++ fi->len += len; + + return fi; + } + if (offset + len == fi->offset) { + /* The new fragment can be tacked on to the beginning */ + /* Did the new fragment plug a hole? */ +- fi2 = list_entry(fi->fi_link.prev, +- struct fwnet_fragment_info, fi_link); +- if (fi2->offset + fi2->len == fi->offset) { +- /* glue fragments together */ +- fi2->len += fi->len + len; +- list_del(&fi->fi_link); +- kfree(fi); +- +- return fi2; ++ if (!list_is_first(&fi->fi_link, &pd->fi_list)) { ++ fi2 = list_prev_entry(fi, fi_link); ++ if (fi2->offset + fi2->len == offset) { ++ /* glue fragments together */ ++ fi2->len += fi->len + len; ++ list_del(&fi->fi_link); ++ kfree(fi); ++ ++ return fi2; ++ } + } + fi->offset = offset; + fi->len += len; +-- +2.53.0 + diff --git a/queue-7.1/geneve-ensure-the-skb-is-writable-before-fixing-its-.patch b/queue-7.1/geneve-ensure-the-skb-is-writable-before-fixing-its-.patch new file mode 100644 index 0000000000..4c7cd4224b --- /dev/null +++ b/queue-7.1/geneve-ensure-the-skb-is-writable-before-fixing-its-.patch @@ -0,0 +1,64 @@ +From 94023e5a299bc7e33b4595e88d1e4c53331fd068 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 14:50:00 +0200 +Subject: geneve: ensure the skb is writable before fixing its headers + +From: Antoine Tenart + +[ Upstream commit 447ec540233c60d6af4d68a164a5bc8ce7e975c1 ] + +Make sure the IPv4/6 and UDP headers are writable before fixing them up in +geneve_post_decap_hint. As skb_ensure_writable can reallocate the skb linear +area, reload the GRO hint header pointer and only set the IPv4/6 header ones +after the call. + +Fixes: fd0dd796576e ("geneve: use GRO hint option in the RX path") +Reported-by: Sashiko +Closes: https://sashiko.dev/#/patchset/20260529144713.780938-1-atenart%40kernel.org +Signed-off-by: Antoine Tenart +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260709125000.141092-1-atenart@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/geneve.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c +index e9102548ac438d..29041175b7b80c 100644 +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -585,6 +585,7 @@ static int geneve_post_decap_hint(const struct sock *sk, struct sk_buff *skb, + struct iphdr *iph; + struct udphdr *uh; + __be16 p; ++ int err; + + hint_off = geneve_sk_gro_hint_off(sk, *geneveh, &p, &len); + if (!hint_off) +@@ -609,12 +610,20 @@ static int geneve_post_decap_hint(const struct sock *sk, struct sk_buff *skb, + !geneve_opt_gro_hint_validate(skb->data, gro_hint))) + return -EINVAL; + +- ipv6h = (void *)skb->data + gro_hint->nested_nh_offset; +- iph = (struct iphdr *)ipv6h; + total_len = skb->len - gro_hint->nested_nh_offset; + if (total_len >= GRO_LEGACY_MAX_SIZE) + return -E2BIG; + ++ err = skb_ensure_writable(skb, gro_hint->nested_tp_offset + sizeof(*uh)); ++ if (unlikely(err)) ++ return err; ++ ++ *geneveh = geneve_hdr(skb); ++ gro_hint = geneve_opt_gro_hint(*geneveh, hint_off); ++ ++ ipv6h = (void *)skb->data + gro_hint->nested_nh_offset; ++ iph = (struct iphdr *)ipv6h; ++ + /* + * After stripping the outer encap, the packet still carries a + * tunnel encapsulation: the nested one. +-- +2.53.0 + diff --git a/queue-7.1/geneve-fix-hint-header-definition-wrt-endianness.patch b/queue-7.1/geneve-fix-hint-header-definition-wrt-endianness.patch new file mode 100644 index 0000000000..8737c24662 --- /dev/null +++ b/queue-7.1/geneve-fix-hint-header-definition-wrt-endianness.patch @@ -0,0 +1,50 @@ +From 271a7274ecb8c6220cd5af12aadaa3221a039f92 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 14:48:00 +0200 +Subject: geneve: fix hint header definition wrt endianness + +From: Antoine Tenart + +[ Upstream commit 751bfa982b4a6de8275a552804f6971adcf08473 ] + +Bitfields are packed differently depending on the endianness, take it into +account in the GRO hint header definition. + +Fixes: e0a12cbf262b ("geneve: add GRO hint output path") +Reported-by: Sashiko +Closes: https://sashiko.dev/#/patchset/20260529144713.780938-1-atenart%40kernel.org +Signed-off-by: Antoine Tenart +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260709124801.140632-1-atenart@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/geneve.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c +index c55bdb805a644f..e9102548ac438d 100644 +--- a/drivers/net/geneve.c ++++ b/drivers/net/geneve.c +@@ -43,8 +43,17 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN"); + #define GENEVE_OPT_GRO_HINT_LEN 1 + + struct geneve_opt_gro_hint { ++#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 inner_proto_id:2, +- nested_is_v6:1; ++ nested_is_v6:1, ++ rsvd:5; ++#elif defined(__BIG_ENDIAN_BITFIELD) ++ u8 rsvd:5, ++ nested_is_v6:1, ++ inner_proto_id:2; ++#else ++#error "Please fix " ++#endif + u8 nested_nh_offset; + u8 nested_tp_offset; + u8 nested_hdr_len; +-- +2.53.0 + diff --git a/queue-7.1/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch b/queue-7.1/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch new file mode 100644 index 0000000000..e3a49e24c0 --- /dev/null +++ b/queue-7.1/gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch @@ -0,0 +1,58 @@ +From 1cf8278c9a56bc581ddde60b6ebeb5640adb2c16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 23:07:24 +0000 +Subject: gtp: check skb_pull_data() return in gtp1u_send_echo_resp() + +From: Xiang Mei (Microsoft) + +[ Upstream commit cd170f051dba9ac146fabcd1b91726487c0cb9fa ] + +gtp1u_send_echo_resp() ignores skb_pull_data()'s return value. Its +caller gtp1u_udp_encap_recv() only guarantees 16 bytes (udphdr + +gtp1_header), but the pull requests 20 (gtp1_header_long + udphdr). For +a 16-19 byte echo request the pull fails and returns NULL without +advancing skb->data; execution continues, and the following skb_push() +plus the IP header pushed by iptunnel_xmit() move skb->data below +skb->head, tripping skb_under_panic(). + +Fix it by dropping the packet when skb_pull_data() fails. + + skbuff: skb_under_panic: ... + kernel BUG at net/core/skbuff.c:214! + Call Trace: + skb_push (net/core/skbuff.c:2648) + iptunnel_xmit (net/ipv4/ip_tunnel_core.c:82) + gtp_encap_recv (drivers/net/gtp.c:701 drivers/net/gtp.c:808 drivers/net/gtp.c:920) + udp_queue_rcv_one_skb (net/ipv4/udp.c:2388) + ... + Kernel panic - not syncing: Fatal exception in interrupt + +Fixes: 9af41cc33471 ("gtp: Implement GTP echo response") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Link: https://patch.msgid.link/20260710230724.942574-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/gtp.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index c0e38878af51b3..9a12cc53da0021 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -669,8 +669,9 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb) + return -1; + + /* pull GTP and UDP headers */ +- skb_pull_data(skb, +- sizeof(struct gtp1_header_long) + sizeof(struct udphdr)); ++ if (!skb_pull_data(skb, sizeof(struct gtp1_header_long) + ++ sizeof(struct udphdr))) ++ return -1; + + gtp_pkt = skb_push(skb, sizeof(struct gtp1u_packet)); + memset(gtp_pkt, 0, sizeof(struct gtp1u_packet)); +-- +2.53.0 + diff --git a/queue-7.1/gtp-parse-extension-headers-before-reading-inner-pro.patch b/queue-7.1/gtp-parse-extension-headers-before-reading-inner-pro.patch new file mode 100644 index 0000000000..2ccf3a43d9 --- /dev/null +++ b/queue-7.1/gtp-parse-extension-headers-before-reading-inner-pro.patch @@ -0,0 +1,67 @@ +From fce7b29f1a36ada979736858ecd0224b164b3e8a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 12:22:44 +0800 +Subject: gtp: parse extension headers before reading inner protocol + +From: Zhixing Chen + +[ Upstream commit 96e37e2f618e931aa97af95e707dcdfb1ec41264 ] + +GTPv1-U packets may carry a chain of extension headers before the inner +IP packet. The receive path already parses and skips these extension +headers, but it currently reads the inner protocol before doing so. + +As a result, the first extension header byte is interpreted as the inner +IP version. Packets with extension headers are then dropped before PDP +lookup. + +Parse the extension header chain before calling gtp_inner_proto(), so the +inner protocol is read from the actual inner IP header. + +Fixes: c75fc0b9e5be ("gtp: identify tunnel via GTP device + GTP version + TEID + family") +Signed-off-by: Zhixing Chen +Link: https://patch.msgid.link/20260708042244.120898-1-running910@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/gtp.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index a60ef32b35b825..c0e38878af51b3 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -826,13 +826,17 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) + if (!pskb_may_pull(skb, hdrlen)) + return -1; + ++ gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); ++ ++ if (gtp1->flags & GTP1_F_EXTHDR && ++ gtp_parse_exthdrs(skb, &hdrlen) < 0) ++ return -1; ++ + if (gtp_inner_proto(skb, hdrlen, &inner_proto) < 0) { + netdev_dbg(gtp->dev, "GTP packet does not encapsulate an IP packet\n"); + return -1; + } + +- gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr)); +- + pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid), + gtp_proto_to_family(inner_proto)); + if (!pctx) { +@@ -840,10 +844,6 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb) + return 1; + } + +- if (gtp1->flags & GTP1_F_EXTHDR && +- gtp_parse_exthdrs(skb, &hdrlen) < 0) +- return -1; +- + return gtp_rx(pctx, skb, hdrlen, gtp->role, inner_proto); + } + +-- +2.53.0 + diff --git a/queue-7.1/hinic-remove-unused-ethtool-rss-user-configuration-b.patch b/queue-7.1/hinic-remove-unused-ethtool-rss-user-configuration-b.patch new file mode 100644 index 0000000000..7f1444d6e4 --- /dev/null +++ b/queue-7.1/hinic-remove-unused-ethtool-rss-user-configuration-b.patch @@ -0,0 +1,83 @@ +From 49aa026a3bbf3d5f863205a825c623673fffcc85 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:53:53 +0800 +Subject: hinic: remove unused ethtool RSS user configuration buffers + +From: Chenguang Zhao + +[ Upstream commit fe0c002928c6749b7f4a726f6f600f6dd70280ea ] + +rss_indir_user and rss_hkey_user are allocated and filled in +__set_rss_rxfh() when the user configures RSS via ethtool, but +nothing ever reads them. hinic_get_rxfh() fetches the state from +the device, and the hardware is programmed from the original +indir/key arguments. These buffers only leaked on driver unload. + +Drop the unused allocations, memcpys, and struct fields. + +Fixes: 4fdc51bb4e92 ("hinic: add support for rss parameters with ethtool") +Signed-off-by: Chenguang Zhao +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260722025353.328179-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/huawei/hinic/hinic_dev.h | 2 -- + .../net/ethernet/huawei/hinic/hinic_ethtool.c | 21 ------------------- + 2 files changed, 23 deletions(-) + +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +index 52ea97c818b8ec..d9ab94910a2a79 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h ++++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h +@@ -104,8 +104,6 @@ struct hinic_dev { + u16 num_rss; + u16 rss_limit; + struct hinic_rss_type rss_type; +- u8 *rss_hkey_user; +- s32 *rss_indir_user; + struct hinic_intr_coal_info *rx_intr_coalesce; + struct hinic_intr_coal_info *tx_intr_coalesce; + struct hinic_sriov_info sriov_info; +diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +index a8b129ce1b7e9f..f75e8563f23aee 100644 +--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c ++++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +@@ -1064,17 +1064,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + int err; + + if (indir) { +- if (!nic_dev->rss_indir_user) { +- nic_dev->rss_indir_user = +- kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE, +- GFP_KERNEL); +- if (!nic_dev->rss_indir_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_indir_user, indir, +- sizeof(u32) * HINIC_RSS_INDIR_SIZE); +- + err = hinic_rss_set_indir_tbl(nic_dev, + nic_dev->rss_tmpl_idx, indir); + if (err) +@@ -1082,16 +1071,6 @@ static int __set_rss_rxfh(struct net_device *netdev, + } + + if (key) { +- if (!nic_dev->rss_hkey_user) { +- nic_dev->rss_hkey_user = +- kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL); +- +- if (!nic_dev->rss_hkey_user) +- return -ENOMEM; +- } +- +- memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE); +- + err = hinic_rss_set_template_tbl(nic_dev, + nic_dev->rss_tmpl_idx, key); + if (err) +-- +2.53.0 + diff --git a/queue-7.1/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch b/queue-7.1/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch new file mode 100644 index 0000000000..b924d9ab84 --- /dev/null +++ b/queue-7.1/hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch @@ -0,0 +1,42 @@ +From 03429de9689c1016bba552516c126e7805a9f10b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 15:05:05 +0200 +Subject: hwmon: (asus-ec-sensors) add missed handle for ENOMEM + +From: Eugene Shalygin + +[ Upstream commit 9813c1f49efeadbcb17e4a41972350ac783f9cac ] + +Add missing return value check in the setup function. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260712130602.1256700-2-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index 181fbb9511794c..7c281c6005ec62 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -1460,9 +1460,11 @@ static int asus_ec_probe(struct platform_device *pdev) + if (!nr_count[type]) + continue; + +- asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, +- nr_count[type], type, +- hwmon_attributes[type]); ++ status = asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev, ++ nr_count[type], type, ++ hwmon_attributes[type]); ++ if (status) ++ return status; + *ptr_asus_ec_ci++ = asus_ec_hwmon_chan++; + } + +-- +2.53.0 + diff --git a/queue-7.1/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch b/queue-7.1/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch new file mode 100644 index 0000000000..415be00f31 --- /dev/null +++ b/queue-7.1/hwmon-asus-ec-sensors-fix-ec-read-intervals.patch @@ -0,0 +1,60 @@ +From b4d7d79ae9aae91074549d67b27eb1ab9af4005b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 13:05:03 +0200 +Subject: hwmon: (asus-ec-sensors) fix EC read intervals + +From: Eugene Shalygin + +[ Upstream commit 60710b2af13b81da71b429d3f8b19dd70310729d ] + +Take INITIAL_JIFFIES into account when setting up next update time. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260712110650.1240071-2-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index d0a58207b00d3b..181fbb9511794c 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -974,7 +974,7 @@ struct ec_sensors_data { + /* sorted list of unique register banks */ + u8 banks[ASUS_EC_MAX_BANK + 1]; + /* in jiffies */ +- unsigned long last_updated; ++ u64 next_update; + struct lock_data lock_data; + /* number of board EC sensors */ + u8 nr_sensors; +@@ -1243,13 +1243,12 @@ static int get_cached_value_or_update(const struct device *dev, + int sensor_index, + struct ec_sensors_data *state, s32 *value) + { +- if (time_after(jiffies, state->last_updated + HZ)) { ++ if (time_after64(get_jiffies_64(), state->next_update)) { + if (update_ec_sensors(dev, state)) { + dev_err(dev, "update_ec_sensors() failure\n"); + return -EIO; + } +- +- state->last_updated = jiffies; ++ state->next_update = get_jiffies_64() + HZ; + } + + *value = state->sensors[sensor_index].cached_value; +@@ -1367,6 +1366,7 @@ static int asus_ec_probe(struct platform_device *pdev) + if (!ec_data) + return -ENOMEM; + ++ ec_data->next_update = INITIAL_JIFFIES; + dev_set_drvdata(dev, ec_data); + ec_data->board_info = pboard_info; + +-- +2.53.0 + diff --git a/queue-7.1/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch b/queue-7.1/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch new file mode 100644 index 0000000000..7fac49de36 --- /dev/null +++ b/queue-7.1/hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch @@ -0,0 +1,37 @@ +From c1026906ba78e8d7abcb9cdae68d8185fcbcf1e0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 09:42:07 +0200 +Subject: hwmon: (asus-ec-sensors) fix looping over banks while reading from EC + +From: Eugene Shalygin + +[ Upstream commit e741d13cc2abfc6fccebe2008057aa52e285223e ] + +Do not assume there are only bank 0 and bank 1 available, just use '!=' +for bank comparison. + +Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC") +Signed-off-by: Eugene Shalygin +Link: https://lore.kernel.org/r/20260711074217.554656-1-eugene.shalygin@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/asus-ec-sensors.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c +index b5d97a27f80d32..d0a58207b00d3b 100644 +--- a/drivers/hwmon/asus-ec-sensors.c ++++ b/drivers/hwmon/asus-ec-sensors.c +@@ -1154,7 +1154,7 @@ static int asus_ec_block_read(const struct device *dev, + } + for (ireg = 0; ireg < ec->nr_registers; ireg++) { + reg_bank = register_bank(ec->registers[ireg]); +- if (reg_bank < bank) { ++ if (reg_bank != bank) { + continue; + } + ec_read(register_index(ec->registers[ireg]), +-- +2.53.0 + diff --git a/queue-7.1/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch b/queue-7.1/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch new file mode 100644 index 0000000000..c6daea4103 --- /dev/null +++ b/queue-7.1/hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch @@ -0,0 +1,41 @@ +From f8977d97cdf65d46fd5a0b8d699faceaa6830cfe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 17:52:54 -0700 +Subject: hwmon: (corsair-cpro) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 94c87871b051d7ad758828a805215a2ec194512a ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 40c3a44542257 ("hwmon: add Corsair Commander Pro driver") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-cpro.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c +index b6e508e43fa17f..8354a002f4c5e1 100644 +--- a/drivers/hwmon/corsair-cpro.c ++++ b/drivers/hwmon/corsair-cpro.c +@@ -645,6 +645,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id) + + out_hw_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-7.1/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch b/queue-7.1/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..d4d5e8a5c8 --- /dev/null +++ b/queue-7.1/hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,89 @@ +From c81cc0e5fa0886bbb38d713e5e2acaa6c316a198 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Apr 2026 12:12:26 +0800 +Subject: hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop + +From: Edward Adam Davis + +[ Upstream commit 9ab8656548cd737b98d0b19c4253aff8d68e97f4 ] + +hid_hw_stop() does not stop the device IO. + +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +corsairpsu_probe(). If the probe operation fails after "io start" has +been initiated, this race condition will result in a uaf vulnerability +[1]. + +CPU0 CPU1 +==== ==== +corsairpsu_probe() + hid_device_io_start() + ... unlock driver_input_lock + hid_hw_stop() + kfree(hidraw) __hid_input_report() + ... acquire driver_input_lock + hid_report_raw_event() + hidraw_report_event() + ... access hidraw's list_lock // trigger uaf + +Consequently, when corsairpsu_probe() fails and hid_hw_stop() needs to +be executed, the io_started flag is first cleared while holding the +driver_input_lock to prevent potential race conditions involving input +reports. + +[1] +BUG: KASAN: slab-use-after-free in rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56 +Call Trace: + hidraw_report_event+0x5d/0x3a0 drivers/hid/hidraw.c:577 + hid_report_raw_event+0x311/0x1730 drivers/hid/hid-core.c:2076 + __hid_input_report drivers/hid/hid-core.c:2152 [inline] + hid_input_report+0x44e/0x580 drivers/hid/hid-core.c:2174 + hid_irq_in+0x47e/0x6d0 drivers/hid/usbhid/hid-core.c:286 + __usb_hcd_giveback_urb+0x3b3/0x5e0 drivers/usb/core/hcd.c:1657 + dummy_timer+0x8a9/0x47d0 drivers/usb/gadget/udc/dummy_hcd.c:2005 + +Allocated by task 10: + hidraw_connect+0x57/0x430 drivers/hid/hidraw.c:606 + hid_connect+0x5bf/0x19d0 drivers/hid/hid-core.c:2277 + hid_hw_start+0xa8/0x120 drivers/hid/hid-core.c:2387 + corsairpsu_probe+0xd9/0x3c0 drivers/hwmon/corsair-psu.c:782 + +Freed by task 10: + hidraw_disconnect+0x4f/0x60 drivers/hid/hidraw.c:662 + hid_disconnect drivers/hid/hid-core.c:2362 [inline] + hid_hw_stop+0x101/0x1e0 drivers/hid/hid-core.c:2407 + corsairpsu_probe+0x327/0x3c0 drivers/hwmon/corsair-psu.c:826 + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Fixes: d115b51e0e56 ("hwmon: add Corsair PSU HID controller driver") +Reported-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=9eebf5f6544c5e873858 +Tested-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com +Signed-off-by: Edward Adam Davis +Link: https://lore.kernel.org/r/tencent_BB7C33EB9EA41B7B4B5F1B8B25C0BA13BB08@qq.com +[groeck: Updated subject and description; + call hid_device_io_stop() only if IO has been started] +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/corsair-psu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c +index 76f3e1da68d09e..ce958cdaef58a3 100644 +--- a/drivers/hwmon/corsair-psu.c ++++ b/drivers/hwmon/corsair-psu.c +@@ -822,6 +822,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id + + fail_and_close: + hid_hw_close(hdev); ++ hid_device_io_stop(hdev); + fail_and_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-7.1/hwmon-drop-unused-i2c-driver_data.patch b/queue-7.1/hwmon-drop-unused-i2c-driver_data.patch new file mode 100644 index 0000000000..8267d60251 --- /dev/null +++ b/queue-7.1/hwmon-drop-unused-i2c-driver_data.patch @@ -0,0 +1,92 @@ +From dda9f2ce54d3733e2baea2176629df0fca378edf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 May 2026 18:44:57 +0200 +Subject: hwmon: Drop unused i2c driver_data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König (The Capable Hub) + +[ Upstream commit b3de407ae66ffef6290a31363205e9751db0537a ] + +The four drivers all don't make use of the value that was explicitly +assigned to the .driver_data member. Drop the assignment. + +While touching these lines also make the assignments use named +initializers and drop a comma after the end-of-list marker. + +Signed-off-by: Uwe Kleine-König (The Capable Hub) +Reviewed-by: Chris Packham # For +Link: https://lore.kernel.org/r/e8ceb3931975813545a8b478cc1a71b4ede9a6c0.1778688803.git.u.kleine-koenig@baylibre.com +Signed-off-by: Guenter Roeck +Stable-dep-of: af01dab0c39a ("hwmon: (pmbus/max34440) block unsupported VIN and IIN limit registers") +Signed-off-by: Sasha Levin +--- + drivers/hwmon/lm80.c | 4 ++-- + drivers/hwmon/pmbus/aps-379.c | 4 ++-- + drivers/hwmon/pmbus/lt3074.c | 4 ++-- + drivers/hwmon/tsc1641.c | 2 +- + 4 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c +index 63c7831bd3e11b..002c669182e153 100644 +--- a/drivers/hwmon/lm80.c ++++ b/drivers/hwmon/lm80.c +@@ -622,8 +622,8 @@ static int lm80_probe(struct i2c_client *client) + */ + + static const struct i2c_device_id lm80_id[] = { +- { "lm80", 0 }, +- { "lm96080", 1 }, ++ { "lm80" }, ++ { "lm96080" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm80_id); +diff --git a/drivers/hwmon/pmbus/aps-379.c b/drivers/hwmon/pmbus/aps-379.c +index 7d46cd647e20aa..3ec0940ae56444 100644 +--- a/drivers/hwmon/pmbus/aps-379.c ++++ b/drivers/hwmon/pmbus/aps-379.c +@@ -100,8 +100,8 @@ static struct pmbus_driver_info aps_379_info = { + }; + + static const struct i2c_device_id aps_379_id[] = { +- { "aps-379", 0 }, +- {}, ++ { .name = "aps-379" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, aps_379_id); + +diff --git a/drivers/hwmon/pmbus/lt3074.c b/drivers/hwmon/pmbus/lt3074.c +index 3704dbe7b54ab8..ed932ddb4f77b6 100644 +--- a/drivers/hwmon/pmbus/lt3074.c ++++ b/drivers/hwmon/pmbus/lt3074.c +@@ -95,8 +95,8 @@ static int lt3074_probe(struct i2c_client *client) + } + + static const struct i2c_device_id lt3074_id[] = { +- { "lt3074", 0 }, +- {} ++ { .name = "lt3074" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, lt3074_id); + +diff --git a/drivers/hwmon/tsc1641.c b/drivers/hwmon/tsc1641.c +index 2b5d34bab146df..fc53cd5bb6e099 100644 +--- a/drivers/hwmon/tsc1641.c ++++ b/drivers/hwmon/tsc1641.c +@@ -721,7 +721,7 @@ static int tsc1641_probe(struct i2c_client *client) + } + + static const struct i2c_device_id tsc1641_id[] = { +- { "tsc1641", 0 }, ++ { .name = "tsc1641" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, tsc1641_id); +-- +2.53.0 + diff --git a/queue-7.1/hwmon-gigabyte_waterforce-stop-device-io-before-call.patch b/queue-7.1/hwmon-gigabyte_waterforce-stop-device-io-before-call.patch new file mode 100644 index 0000000000..2183cd4a4e --- /dev/null +++ b/queue-7.1/hwmon-gigabyte_waterforce-stop-device-io-before-call.patch @@ -0,0 +1,51 @@ +From 3d1cf9fca2f1748a10abbdd7ba16d80fe198ac0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 17:59:10 -0700 +Subject: hwmon: (gigabyte_waterforce) Stop device IO before calling + hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit ff0c5c53d08274e200b48a4d53aa078265e873cb ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 42ac68e3d4ba0 ("hwmon: Add driver for Gigabyte AORUS Waterforce AIO coolers") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/gigabyte_waterforce.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/hwmon/gigabyte_waterforce.c b/drivers/hwmon/gigabyte_waterforce.c +index 27487e215bddff..4eea05f8b569c2 100644 +--- a/drivers/hwmon/gigabyte_waterforce.c ++++ b/drivers/hwmon/gigabyte_waterforce.c +@@ -371,13 +371,15 @@ static int waterforce_probe(struct hid_device *hdev, const struct hid_device_id + if (IS_ERR(priv->hwmon_dev)) { + ret = PTR_ERR(priv->hwmon_dev); + hid_err(hdev, "hwmon registration failed with %d\n", ret); +- goto fail_and_close; ++ goto fail_and_io_stop; + } + + waterforce_debugfs_init(priv); + + return 0; + ++fail_and_io_stop: ++ hid_device_io_stop(hdev); + fail_and_close: + hid_hw_close(hdev); + fail_and_stop: +-- +2.53.0 + diff --git a/queue-7.1/hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch b/queue-7.1/hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch new file mode 100644 index 0000000000..27702b213d --- /dev/null +++ b/queue-7.1/hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch @@ -0,0 +1,59 @@ +From ec6a4344094f14c3fc80cc9b2108fe792fe40856 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:01:58 -0700 +Subject: hwmon: (nzxt-kraken3) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit f151d0143ac4e086f92f52328ebdbdc50933d8ef ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: f3b4b146eb107 ("hwmon: Add driver for NZXT Kraken X and Z series AIO CPU coolers") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/nzxt-kraken3.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/hwmon/nzxt-kraken3.c b/drivers/hwmon/nzxt-kraken3.c +index d00409bcab93ad..05525406c5fbb5 100644 +--- a/drivers/hwmon/nzxt-kraken3.c ++++ b/drivers/hwmon/nzxt-kraken3.c +@@ -948,7 +948,7 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id + ret = kraken3_init_device(hdev); + if (ret < 0) { + hid_err(hdev, "device init failed with %d\n", ret); +- goto fail_and_close; ++ goto fail_and_stop_io; + } + + ret = kraken3_get_fw_ver(hdev); +@@ -960,13 +960,15 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id + if (IS_ERR(priv->hwmon_dev)) { + ret = PTR_ERR(priv->hwmon_dev); + hid_err(hdev, "hwmon registration failed with %d\n", ret); +- goto fail_and_close; ++ goto fail_and_stop_io; + } + + kraken3_debugfs_init(priv, device_name); + + return 0; + ++fail_and_stop_io: ++ hid_device_io_stop(hdev); + fail_and_close: + hid_hw_close(hdev); + fail_and_stop: +-- +2.53.0 + diff --git a/queue-7.1/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch b/queue-7.1/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch new file mode 100644 index 0000000000..189f142bb8 --- /dev/null +++ b/queue-7.1/hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch @@ -0,0 +1,42 @@ +From f4f346140bff6f499e08e0b273074ee21a6b0319 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 18:00:32 -0700 +Subject: hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop + +From: Guenter Roeck + +[ Upstream commit 59d104b54b0b42e30fd2a68d24ee5c49dcc54d1e ] + +Calling hid_hw_stop() does not stop the device IO. +This results in a race condition between hid_input_report() and the point +immediately following the execution of hid_device_io_start() within +the driver probe function. If the probe operation fails after "io start" +has been initiated, this race condition will result in a UAF vulnerability. + +Fix the problem by calling hid_device_io_stop() before calling +hid_hw_stop(). + +Reported-by: Sashiko +Fixes: 53e68c20aeb1e ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2") +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/nzxt-smart2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c +index 58ef9fa0184be4..e2316c46629d61 100644 +--- a/drivers/hwmon/nzxt-smart2.c ++++ b/drivers/hwmon/nzxt-smart2.c +@@ -768,7 +768,7 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev, + + out_hw_close: + hid_hw_close(hdev); +- ++ hid_device_io_stop(hdev); + out_hw_stop: + hid_hw_stop(hdev); + return ret; +-- +2.53.0 + diff --git a/queue-7.1/hwmon-occ-validate-poll-response-sensor-blocks.patch b/queue-7.1/hwmon-occ-validate-poll-response-sensor-blocks.patch new file mode 100644 index 0000000000..a19077f16f --- /dev/null +++ b/queue-7.1/hwmon-occ-validate-poll-response-sensor-blocks.patch @@ -0,0 +1,118 @@ +From a633df2b01c48d029b13f23480988a2e472c53ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:58:26 +0800 +Subject: hwmon: occ: validate poll response sensor blocks + +From: Pengpeng Hou + +[ Upstream commit 70e76e700fc6c46afb4e17aec099a1ea089b4a22 ] + +The OCC poll response parser walks a counted list of sensor data blocks. +It used the static backing-array capacity as the parse boundary, but a +transport response makes only data_length bytes current and valid. A +truncated response can therefore make the parser consume a block header or +block extent outside the current response. + +Use data_length as the parent boundary, prove the fixed poll header and +each current block header before reading them, and prove the complete block +before advancing. Keep parsed sensor metadata local until the complete +response has passed validation, then publish it. Propagate +malformed-response errors before publishing the OCC as active. + +Fixes: aa195fe49b03 ("hwmon (occ): Parse OCC poll response") +Signed-off-by: Pengpeng Hou +Link: https://lore.kernel.org/r/20260720115826.14813-1-pengpeng@iscas.ac.cn +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/occ/common.c | 38 ++++++++++++++++++++++++++++++-------- + 1 file changed, 30 insertions(+), 8 deletions(-) + +diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c +index e18e80e832fd3f..175208d712b06e 100644 +--- a/drivers/hwmon/occ/common.c ++++ b/drivers/hwmon/occ/common.c +@@ -1052,32 +1052,49 @@ static int occ_setup_sensor_attrs(struct occ *occ) + } + + /* only need to do this once at startup, as OCC won't change sensors on us */ +-static void occ_parse_poll_response(struct occ *occ) ++static int occ_parse_poll_response(struct occ *occ) + { + unsigned int i, old_offset, offset = 0, size = 0; ++ u16 data_length; + struct occ_sensor *sensor; +- struct occ_sensors *sensors = &occ->sensors; ++ struct occ_sensors parsed = {}; ++ struct occ_sensors *sensors = &parsed; + struct occ_response *resp = &occ->resp; + struct occ_poll_response *poll = + (struct occ_poll_response *)&resp->data[0]; + struct occ_poll_response_header *header = &poll->header; + struct occ_sensor_data_block *block = &poll->block; + ++ data_length = get_unaligned_be16(&resp->data_length); ++ if (data_length < sizeof(*header) || data_length > OCC_RESP_DATA_BYTES) { ++ dev_err(occ->bus_dev, "invalid OCC poll response length %u\n", ++ data_length); ++ return -EMSGSIZE; ++ } ++ + dev_info(occ->bus_dev, "OCC found, code level: %.16s\n", + header->occ_code_level); + + for (i = 0; i < header->num_sensor_data_blocks; ++i) { + block = (struct occ_sensor_data_block *)((u8 *)block + offset); ++ if (size + sizeof(*header) + sizeof(block->header) > ++ data_length) { ++ dev_err(occ->bus_dev, ++ "truncated OCC sensor block header\n"); ++ return -EMSGSIZE; ++ } ++ + old_offset = offset; + offset = (block->header.num_sensors * + block->header.sensor_length) + sizeof(block->header); +- size += offset; + + /* validate all the length/size fields */ +- if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) { +- dev_warn(occ->bus_dev, "exceeded response buffer\n"); +- return; ++ if (size + sizeof(*header) + offset > data_length) { ++ dev_err(occ->bus_dev, ++ "exceeded OCC poll response length\n"); ++ return -EMSGSIZE; + } ++ size += offset; + + dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n", + old_offset, offset - 1, block->header.eye_catcher, +@@ -1107,6 +1124,9 @@ static void occ_parse_poll_response(struct occ *occ) + + dev_dbg(occ->bus_dev, "Max resp size: %u+%zd=%zd\n", size, + sizeof(*header), size + sizeof(*header)); ++ occ->sensors = parsed; ++ ++ return 0; + } + + int occ_active(struct occ *occ, bool active) +@@ -1138,10 +1158,12 @@ int occ_active(struct occ *occ, bool active) + goto unlock; + } + +- occ->active = true; + occ->next_update = jiffies + OCC_UPDATE_FREQUENCY; +- occ_parse_poll_response(occ); ++ rc = occ_parse_poll_response(occ); ++ if (rc) ++ goto unlock; + ++ occ->active = true; + rc = occ_setup_sensor_attrs(occ); + if (rc) { + dev_err(occ->bus_dev, +-- +2.53.0 + diff --git a/queue-7.1/hwmon-pmbus-max34440-add-support-adpm12250.patch b/queue-7.1/hwmon-pmbus-max34440-add-support-adpm12250.patch new file mode 100644 index 0000000000..db441b170c --- /dev/null +++ b/queue-7.1/hwmon-pmbus-max34440-add-support-adpm12250.patch @@ -0,0 +1,187 @@ +From 3033f53b1e1c38aeec6ac91ced6458ff3b808a5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Jun 2026 09:12:10 +0800 +Subject: hwmon: (pmbus/max34440): add support adpm12250 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alexis Czezar Torreno + +[ Upstream commit 479bfeba2eb62666cd4b981c8e721c61dcf36e7d ] + +ADPM12250 is a quarter brick DC/DC Power Module. It is a high power +non-isolated converter capable of delivering regulated 12V with +continuous power level of 2500W. Uses PMBus. + +Signed-off-by: Alexis Czezar Torreno +Reviewed-by: Nuno Sá +Link: https://lore.kernel.org/r/20260610-dev-adpm12250-v1-1-422760bb80da@analog.com +Signed-off-by: Guenter Roeck +Stable-dep-of: af01dab0c39a ("hwmon: (pmbus/max34440) block unsupported VIN and IIN limit registers") +Signed-off-by: Sasha Levin +--- + Documentation/hwmon/max34440.rst | 27 ++++++++++++------- + drivers/hwmon/pmbus/max34440.c | 45 +++++++++++++++++++++++++++++--- + 2 files changed, 60 insertions(+), 12 deletions(-) + +diff --git a/Documentation/hwmon/max34440.rst b/Documentation/hwmon/max34440.rst +index d6d4fbc863d96c..e7421f4dbf38fc 100644 +--- a/Documentation/hwmon/max34440.rst ++++ b/Documentation/hwmon/max34440.rst +@@ -19,6 +19,14 @@ Supported chips: + + Datasheet: - + ++ * ADI ADPM12250 ++ ++ Prefixes: 'adpm12250' ++ ++ Addresses scanned: - ++ ++ Datasheet: - ++ + * Maxim MAX34440 + + Prefixes: 'max34440' +@@ -87,11 +95,11 @@ This driver supports multiple devices: hardware monitoring for Maxim MAX34440 + PMBus 6-Channel Power-Supply Manager, MAX34441 PMBus 5-Channel Power-Supply + Manager and Intelligent Fan Controller, and MAX34446 PMBus Power-Supply Data + Logger; PMBus Voltage Monitor and Sequencers for MAX34451, MAX34460, and +-MAX34461; PMBus DC/DC Power Module ADPM12160, and ADPM12200. The MAX34451 +-supports monitoring voltage or current of 12 channels based on GIN pins. The +-MAX34460 supports 12 voltage channels, and the MAX34461 supports 16 voltage +-channels. The ADPM12160, and ADPM12200 also monitors both input and output +-of voltage and current. ++MAX34461; PMBus DC/DC Power Module ADPM12160, ADPM12200, and ADPM12250. The ++MAX34451 supports monitoring voltage or current of 12 channels based on GIN ++pins. The MAX34460 supports 12 voltage channels, and the MAX34461 supports 16 ++voltage channels. The ADPM12160, ADPM12200, and ADPM12250 also monitors both ++input and output of voltage and current. + + The driver is a client driver to the core PMBus driver. Please see + Documentation/hwmon/pmbus.rst for details on PMBus client drivers. +@@ -149,7 +157,7 @@ in[1-6]_reset_history Write any value to reset history. + .. note:: + + - MAX34446 only supports in[1-4]. +- - ADPM12160, and ADPM12200 only supports in[1-2]. Label is "vin1" ++ - ADPM12160, ADPM12200, and ADPM12250 only supports in[1-2]. Label is "vin1" + and "vout1" respectively. + + Curr +@@ -172,8 +180,9 @@ curr[1-6]_reset_history Write any value to reset history. + + - in6 and curr6 attributes only exist for MAX34440. + - MAX34446 only supports curr[1-4]. +- - For ADPM12160, and ADPM12200, curr[1] is "iin1" and curr[2-6] +- are "iout[1-5]". ++ - For ADPM12160, ADPM12200, and ADPM12250, curr[1] is "iin1" ++ - For ADPM12160, and ADPM12200 curr[2-6] are "iout[1-5]". ++ - For ADPM12250, curr[2-4] are "iout[1-3]". + + Power + ~~~~~ +@@ -209,7 +218,7 @@ temp[1-8]_reset_history Write any value to reset history. + .. note:: + - temp7 and temp8 attributes only exist for MAX34440. + - MAX34446 only supports temp[1-3]. +- - ADPM12160, and ADPM12200 only supports temp[1]. ++ - ADPM12160, ADPM12200, and ADPM12250 only supports temp[1]. + + + .. note:: +diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c +index 4525b9fc562674..74876d2207fbe4 100644 +--- a/drivers/hwmon/pmbus/max34440.c ++++ b/drivers/hwmon/pmbus/max34440.c +@@ -18,6 +18,7 @@ + enum chips { + adpm12160, + adpm12200, ++ adpm12250, + max34440, + max34441, + max34446, +@@ -97,7 +98,8 @@ static int max34440_read_word_data(struct i2c_client *client, int page, + break; + case PMBUS_VIRT_READ_IOUT_AVG: + if (data->id != max34446 && data->id != max34451 && +- data->id != adpm12160 && data->id != adpm12200) ++ data->id != adpm12160 && data->id != adpm12200 && ++ data->id != adpm12250) + return -ENXIO; + ret = pmbus_read_word_data(client, page, phase, + MAX34446_MFR_IOUT_AVG); +@@ -182,7 +184,8 @@ static int max34440_write_word_data(struct i2c_client *client, int page, + ret = pmbus_write_word_data(client, page, + MAX34440_MFR_IOUT_PEAK, 0); + if (!ret && (data->id == max34446 || data->id == max34451 || +- data->id == adpm12160 || data->id == adpm12200)) ++ data->id == adpm12160 || data->id == adpm12200 || ++ data->id == adpm12250)) + ret = pmbus_write_word_data(client, page, + MAX34446_MFR_IOUT_AVG, 0); + +@@ -399,6 +402,40 @@ static struct pmbus_driver_info max34440_info[] = { + .read_word_data = max34440_read_word_data, + .write_word_data = max34440_write_word_data, + }, ++ [adpm12250] = { ++ .pages = 19, ++ .format[PSC_VOLTAGE_IN] = direct, ++ .format[PSC_VOLTAGE_OUT] = direct, ++ .format[PSC_CURRENT_IN] = direct, ++ .format[PSC_CURRENT_OUT] = direct, ++ .format[PSC_TEMPERATURE] = direct, ++ .m[PSC_VOLTAGE_IN] = 125, ++ .b[PSC_VOLTAGE_IN] = 0, ++ .R[PSC_VOLTAGE_IN] = 0, ++ .m[PSC_VOLTAGE_OUT] = 125, ++ .b[PSC_VOLTAGE_OUT] = 0, ++ .R[PSC_VOLTAGE_OUT] = 0, ++ .m[PSC_CURRENT_IN] = 250, ++ .b[PSC_CURRENT_IN] = 0, ++ .R[PSC_CURRENT_IN] = -1, ++ .m[PSC_CURRENT_OUT] = 250, ++ .b[PSC_CURRENT_OUT] = 0, ++ .R[PSC_CURRENT_OUT] = -1, ++ .m[PSC_TEMPERATURE] = 1, ++ .b[PSC_TEMPERATURE] = 0, ++ .R[PSC_TEMPERATURE] = 2, ++ /* absent func below [18] are not for monitoring */ ++ .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, ++ .func[4] = PMBUS_HAVE_STATUS_IOUT, ++ .func[5] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, ++ .func[6] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, ++ .func[9] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT, ++ .func[10] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT, ++ .func[14] = PMBUS_HAVE_IOUT, ++ .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, ++ .read_word_data = max34440_read_word_data, ++ .write_word_data = max34440_write_word_data, ++ }, + [max34440] = { + .pages = 14, + .format[PSC_VOLTAGE_IN] = direct, +@@ -635,7 +672,8 @@ static int max34440_probe(struct i2c_client *client) + rv = max34451_set_supported_funcs(client, data); + if (rv) + return rv; +- } else if (data->id == adpm12160 || data->id == adpm12200) { ++ } else if (data->id == adpm12160 || data->id == adpm12200 || ++ data->id == adpm12250) { + data->iout_oc_fault_limit = PMBUS_IOUT_OC_FAULT_LIMIT; + data->iout_oc_warn_limit = PMBUS_IOUT_OC_WARN_LIMIT; + } +@@ -646,6 +684,7 @@ static int max34440_probe(struct i2c_client *client) + static const struct i2c_device_id max34440_id[] = { + { .name = "adpm12160", .driver_data = adpm12160 }, + { .name = "adpm12200", .driver_data = adpm12200 }, ++ { .name = "adpm12250", .driver_data = adpm12250 }, + { .name = "max34440", .driver_data = max34440 }, + { .name = "max34441", .driver_data = max34441 }, + { .name = "max34446", .driver_data = max34446 }, +-- +2.53.0 + diff --git a/queue-7.1/hwmon-pmbus-max34440-block-unsupported-vin-and-iin-l.patch b/queue-7.1/hwmon-pmbus-max34440-block-unsupported-vin-and-iin-l.patch new file mode 100644 index 0000000000..72d9b65836 --- /dev/null +++ b/queue-7.1/hwmon-pmbus-max34440-block-unsupported-vin-and-iin-l.patch @@ -0,0 +1,161 @@ +From 42780b18d8164b42ace5e3d546e76ba66ca5b61e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 16:25:11 +0800 +Subject: hwmon: (pmbus/max34440) block unsupported VIN and IIN limit registers + +From: Alexis Czezar Torreno + +[ Upstream commit af01dab0c39a7aefc47a109201e4134ea6bd3005 ] + +MAX34451 and ADPM chips do not support standard PMBus VIN/IIN limit +registers, manufacturer specific min/max registers, or undercurrent +or undertemperature fault limits. STATUS_BYTE and STATUS_OTHER are also +not available. Accessing these non-existent registers during driver +initialization triggers a CML error and asserts ALERT. Handled by +blocking these functions during read/write. + +Fixes: 7a001dbab4ad ("hwmon: (pmbus/max34440) Add support for MAX34451.") +Fixes: 629cf8f6c23a ("hwmon: (pmbus/max34440) Add support for ADPM12160") +Fixes: 2e0b52f1ae88 ("hwmon: (pmbus/max34440): add support adpm12200") +Fixes: 479bfeba2eb6 ("hwmon: (pmbus/max34440): add support adpm12250") +Signed-off-by: Alexis Czezar Torreno +Link: https://lore.kernel.org/r/20260716-max34451_fixes-v1-1-a941b27eaecb@analog.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/hwmon/pmbus/max34440.c | 80 ++++++++++++++++++++++++++++++++++ + 1 file changed, 80 insertions(+) + +diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c +index 74876d2207fbe4..e56057e9273c16 100644 +--- a/drivers/hwmon/pmbus/max34440.c ++++ b/drivers/hwmon/pmbus/max34440.c +@@ -88,6 +88,33 @@ static int max34440_read_word_data(struct i2c_client *client, int page, + ret = pmbus_read_word_data(client, page, phase, + data->iout_oc_warn_limit); + break; ++ case PMBUS_VIN_OV_FAULT_LIMIT: ++ case PMBUS_VIN_OV_WARN_LIMIT: ++ case PMBUS_VIN_UV_WARN_LIMIT: ++ case PMBUS_VIN_UV_FAULT_LIMIT: ++ case PMBUS_MFR_VIN_MIN: ++ case PMBUS_MFR_VIN_MAX: ++ case PMBUS_IIN_OC_WARN_LIMIT: ++ case PMBUS_IIN_OC_FAULT_LIMIT: ++ case PMBUS_MFR_IIN_MAX: ++ case PMBUS_MFR_VOUT_MIN: ++ case PMBUS_MFR_VOUT_MAX: ++ case PMBUS_IOUT_UC_FAULT_LIMIT: ++ case PMBUS_MFR_IOUT_MAX: ++ case PMBUS_UT_WARN_LIMIT: ++ case PMBUS_UT_FAULT_LIMIT: ++ case PMBUS_MFR_MAX_TEMP_1: ++ /* ++ * MAX34451/ADPM family do not support VIN/IIN limit registers, ++ * manufacturer-specific min/max registers, or undercurrent/ ++ * undertemperature fault limits. Accessing these triggers CML ++ * error and asserts ALERT. ++ */ ++ if (data->id == max34451 || data->id == adpm12160 || ++ data->id == adpm12200 || data->id == adpm12250) ++ return -ENXIO; ++ ret = -ENODATA; ++ break; + case PMBUS_VIRT_READ_VOUT_MIN: + ret = pmbus_read_word_data(client, page, phase, + MAX34440_MFR_VOUT_MIN); +@@ -244,6 +271,51 @@ static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) + return ret; + } + ++static int max34451_read_byte_data(struct i2c_client *client, int page, int reg) ++{ ++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client); ++ const struct max34440_data *data = to_max34440_data(info); ++ ++ switch (reg) { ++ case PMBUS_STATUS_BYTE: ++ case PMBUS_STATUS_OTHER: ++ /* ++ * MAX34451/ADPM family do not support STATUS_BYTE or ++ * STATUS_OTHER registers. Accessing them triggers CML ++ * error and asserts ALERT. ++ */ ++ if (data->id == max34451 || data->id == adpm12160 || ++ data->id == adpm12200 || data->id == adpm12250) ++ return -ENXIO; ++ return -ENODATA; ++ default: ++ return -ENODATA; ++ } ++} ++ ++static int max34451_write_byte_data(struct i2c_client *client, int page, ++ int reg, u8 byte) ++{ ++ const struct pmbus_driver_info *info = pmbus_get_driver_info(client); ++ const struct max34440_data *data = to_max34440_data(info); ++ ++ switch (reg) { ++ case PMBUS_STATUS_BYTE: ++ case PMBUS_STATUS_OTHER: ++ /* ++ * MAX34451/ADPM family do not support STATUS_BYTE or ++ * STATUS_OTHER registers. Writing to them triggers CML ++ * error and asserts ALERT. ++ */ ++ if (data->id == max34451 || data->id == adpm12160 || ++ data->id == adpm12200 || data->id == adpm12250) ++ return -ENXIO; ++ return -ENODATA; ++ default: ++ return -ENODATA; ++ } ++} ++ + static int max34451_set_supported_funcs(struct i2c_client *client, + struct max34440_data *data) + { +@@ -363,7 +435,9 @@ static struct pmbus_driver_info max34440_info[] = { + .func[9] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT, + .func[10] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT, + .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, ++ .read_byte_data = max34451_read_byte_data, + .read_word_data = max34440_read_word_data, ++ .write_byte_data = max34451_write_byte_data, + .write_word_data = max34440_write_word_data, + }, + [adpm12200] = { +@@ -399,7 +473,9 @@ static struct pmbus_driver_info max34440_info[] = { + .func[10] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT, + .func[14] = PMBUS_HAVE_IOUT, + .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, ++ .read_byte_data = max34451_read_byte_data, + .read_word_data = max34440_read_word_data, ++ .write_byte_data = max34451_write_byte_data, + .write_word_data = max34440_write_word_data, + }, + [adpm12250] = { +@@ -433,7 +509,9 @@ static struct pmbus_driver_info max34440_info[] = { + .func[10] = PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT, + .func[14] = PMBUS_HAVE_IOUT, + .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, ++ .read_byte_data = max34451_read_byte_data, + .read_word_data = max34440_read_word_data, ++ .write_byte_data = max34451_write_byte_data, + .write_word_data = max34440_write_word_data, + }, + [max34440] = { +@@ -581,7 +659,9 @@ static struct pmbus_driver_info max34440_info[] = { + .func[18] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .func[19] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, + .func[20] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, ++ .read_byte_data = max34451_read_byte_data, + .read_word_data = max34440_read_word_data, ++ .write_byte_data = max34451_write_byte_data, + .write_word_data = max34440_write_word_data, + .page_change_delay = MAX34440_PAGE_CHANGE_DELAY, + }, +-- +2.53.0 + diff --git a/queue-7.1/hwmon-use-named-initializers-for-arrays-of-i2c_devic.patch b/queue-7.1/hwmon-use-named-initializers-for-arrays-of-i2c_devic.patch new file mode 100644 index 0000000000..13bad983b8 --- /dev/null +++ b/queue-7.1/hwmon-use-named-initializers-for-arrays-of-i2c_devic.patch @@ -0,0 +1,3626 @@ +From fe130f02a5812ee280d71fa4202b9f0e31f316be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 May 2026 18:44:58 +0200 +Subject: hwmon: Use named initializers for arrays of i2c_device_data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Uwe Kleine-König (The Capable Hub) + +[ Upstream commit 4a9e6a9230c88a71916301b9fe6627413ebc2574 ] + +While being less compact, using named initializers allows to more easily +see which members of the structs are assigned which value without having +to lookup the declaration of the struct. And it's also more robust +against changes to the struct definition. + +The mentioned robustness is relevant for a planned change to struct +i2c_device_id that replaces .driver_data by an anonymous union. + +While touching all these arrays, unify indention and usage of commas. + +This patch doesn't modify the compiled arrays, only their representation +in source form benefits. The former was confirmed with x86 and arm64 +builds. + +Signed-off-by: Uwe Kleine-König (The Capable Hub) +Link: https://lore.kernel.org/r/65b77bcd452752c36d866069cc5790b26d2bf8dc.1778688803.git.u.kleine-koenig@baylibre.com +Signed-off-by: Guenter Roeck +Stable-dep-of: af01dab0c39a ("hwmon: (pmbus/max34440) block unsupported VIN and IIN limit registers") +Signed-off-by: Sasha Levin +--- + drivers/hwmon/ad7414.c | 4 +- + drivers/hwmon/ad7418.c | 6 +- + drivers/hwmon/adc128d818.c | 2 +- + drivers/hwmon/adm1025.c | 4 +- + drivers/hwmon/adm1026.c | 2 +- + drivers/hwmon/adm1029.c | 2 +- + drivers/hwmon/adm1031.c | 4 +- + drivers/hwmon/adm1177.c | 4 +- + drivers/hwmon/adm9240.c | 6 +- + drivers/hwmon/ads7828.c | 4 +- + drivers/hwmon/adt7410.c | 8 +-- + drivers/hwmon/adt7411.c | 2 +- + drivers/hwmon/adt7462.c | 2 +- + drivers/hwmon/adt7470.c | 2 +- + drivers/hwmon/adt7475.c | 8 +-- + drivers/hwmon/aht10.c | 8 +-- + drivers/hwmon/amc6821.c | 2 +- + drivers/hwmon/asb100.c | 2 +- + drivers/hwmon/asc7621.c | 6 +- + drivers/hwmon/atxp1.c | 2 +- + drivers/hwmon/chipcap2.c | 16 ++--- + drivers/hwmon/dme1737.c | 4 +- + drivers/hwmon/ds1621.c | 10 +-- + drivers/hwmon/ds620.c | 4 +- + drivers/hwmon/emc1403.c | 24 +++---- + drivers/hwmon/emc2103.c | 2 +- + drivers/hwmon/emc2305.c | 8 +-- + drivers/hwmon/emc6w201.c | 2 +- + drivers/hwmon/f75375s.c | 6 +- + drivers/hwmon/fschmd.c | 14 ++-- + drivers/hwmon/ftsteutates.c | 2 +- + drivers/hwmon/g760a.c | 2 +- + drivers/hwmon/g762.c | 6 +- + drivers/hwmon/gl518sm.c | 2 +- + drivers/hwmon/gl520sm.c | 2 +- + drivers/hwmon/hih6130.c | 2 +- + drivers/hwmon/hs3001.c | 4 +- + drivers/hwmon/htu31.c | 2 +- + drivers/hwmon/ina209.c | 2 +- + drivers/hwmon/ina238.c | 12 ++-- + drivers/hwmon/ina2xx.c | 16 ++--- + drivers/hwmon/ina3221.c | 2 +- + drivers/hwmon/isl28022.c | 2 +- + drivers/hwmon/jc42.c | 2 +- + drivers/hwmon/lineage-pem.c | 4 +- + drivers/hwmon/lm63.c | 6 +- + drivers/hwmon/lm73.c | 2 +- + drivers/hwmon/lm75.c | 62 ++++++++-------- + drivers/hwmon/lm77.c | 2 +- + drivers/hwmon/lm78.c | 4 +- + drivers/hwmon/lm80.c | 4 +- + drivers/hwmon/lm83.c | 4 +- + drivers/hwmon/lm85.c | 24 +++---- + drivers/hwmon/lm87.c | 4 +- + drivers/hwmon/lm90.c | 96 ++++++++++++------------- + drivers/hwmon/lm92.c | 6 +- + drivers/hwmon/lm93.c | 4 +- + drivers/hwmon/lm95234.c | 4 +- + drivers/hwmon/lm95241.c | 4 +- + drivers/hwmon/lm95245.c | 4 +- + drivers/hwmon/ltc2945.c | 2 +- + drivers/hwmon/ltc2947-i2c.c | 4 +- + drivers/hwmon/ltc2990.c | 4 +- + drivers/hwmon/ltc2991.c | 4 +- + drivers/hwmon/ltc2992.c | 4 +- + drivers/hwmon/ltc4151.c | 2 +- + drivers/hwmon/ltc4215.c | 2 +- + drivers/hwmon/ltc4222.c | 2 +- + drivers/hwmon/ltc4245.c | 2 +- + drivers/hwmon/ltc4260.c | 2 +- + drivers/hwmon/ltc4261.c | 4 +- + drivers/hwmon/max127.c | 2 +- + drivers/hwmon/max16065.c | 12 ++-- + drivers/hwmon/max1619.c | 2 +- + drivers/hwmon/max1668.c | 6 +- + drivers/hwmon/max31730.c | 2 +- + drivers/hwmon/max31760.c | 2 +- + drivers/hwmon/max31790.c | 2 +- + drivers/hwmon/max31827.c | 6 +- + drivers/hwmon/max6620.c | 2 +- + drivers/hwmon/max6621.c | 2 +- + drivers/hwmon/max6639.c | 2 +- + drivers/hwmon/max6650.c | 4 +- + drivers/hwmon/max6697.c | 20 +++--- + drivers/hwmon/mc34vr500.c | 4 +- + drivers/hwmon/mcp3021.c | 4 +- + drivers/hwmon/nct6775-i2c.c | 26 +++---- + drivers/hwmon/nct7802.c | 2 +- + drivers/hwmon/nct7904.c | 4 +- + drivers/hwmon/pcf8591.c | 2 +- + drivers/hwmon/pmbus/acbel-fsg032.c | 4 +- + drivers/hwmon/pmbus/adm1266.c | 2 +- + drivers/hwmon/pmbus/adm1275.c | 20 +++--- + drivers/hwmon/pmbus/bel-pfe.c | 6 +- + drivers/hwmon/pmbus/bpa-rs600.c | 6 +- + drivers/hwmon/pmbus/crps.c | 4 +- + drivers/hwmon/pmbus/delta-ahe50dc-fan.c | 2 +- + drivers/hwmon/pmbus/dps920ab.c | 4 +- + drivers/hwmon/pmbus/fsp-3y.c | 4 +- + drivers/hwmon/pmbus/hac300s.c | 4 +- + drivers/hwmon/pmbus/ibm-cffps.c | 8 +-- + drivers/hwmon/pmbus/ina233.c | 4 +- + drivers/hwmon/pmbus/inspur-ipsps.c | 4 +- + drivers/hwmon/pmbus/ir35221.c | 4 +- + drivers/hwmon/pmbus/ir36021.c | 4 +- + drivers/hwmon/pmbus/ir38064.c | 10 +-- + drivers/hwmon/pmbus/irps5401.c | 4 +- + drivers/hwmon/pmbus/isl68137.c | 96 ++++++++++++------------- + drivers/hwmon/pmbus/lm25066.c | 10 +-- + drivers/hwmon/pmbus/lt7182s.c | 4 +- + drivers/hwmon/pmbus/ltc2978.c | 60 ++++++++-------- + drivers/hwmon/pmbus/ltc3815.c | 2 +- + drivers/hwmon/pmbus/max15301.c | 8 +-- + drivers/hwmon/pmbus/max16064.c | 4 +- + drivers/hwmon/pmbus/max16601.c | 10 +-- + drivers/hwmon/pmbus/max17616.c | 2 +- + drivers/hwmon/pmbus/max20730.c | 10 +-- + drivers/hwmon/pmbus/max20751.c | 4 +- + drivers/hwmon/pmbus/max31785.c | 8 +-- + drivers/hwmon/pmbus/max34440.c | 18 ++--- + drivers/hwmon/pmbus/max8688.c | 2 +- + drivers/hwmon/pmbus/mp2856.c | 6 +- + drivers/hwmon/pmbus/mp2888.c | 4 +- + drivers/hwmon/pmbus/mp2891.c | 2 +- + drivers/hwmon/pmbus/mp2925.c | 6 +- + drivers/hwmon/pmbus/mp29502.c | 4 +- + drivers/hwmon/pmbus/mp2975.c | 8 +-- + drivers/hwmon/pmbus/mp2993.c | 2 +- + drivers/hwmon/pmbus/mp5920.c | 2 +- + drivers/hwmon/pmbus/mp5926.c | 4 +- + drivers/hwmon/pmbus/mp5990.c | 4 +- + drivers/hwmon/pmbus/mp9941.c | 2 +- + drivers/hwmon/pmbus/mp9945.c | 4 +- + drivers/hwmon/pmbus/mpq7932.c | 6 +- + drivers/hwmon/pmbus/mpq8785.c | 10 +-- + drivers/hwmon/pmbus/pim4328.c | 18 ++--- + drivers/hwmon/pmbus/pli1209bc.c | 4 +- + drivers/hwmon/pmbus/pm6764tr.c | 4 +- + drivers/hwmon/pmbus/pmbus.c | 60 ++++++++-------- + drivers/hwmon/pmbus/pxe1610.c | 8 +-- + drivers/hwmon/pmbus/q54sj108a2.c | 8 +-- + drivers/hwmon/pmbus/stef48h28.c | 4 +- + drivers/hwmon/pmbus/stpddc60.c | 6 +- + drivers/hwmon/pmbus/tda38640.c | 4 +- + drivers/hwmon/pmbus/tps25990.c | 4 +- + drivers/hwmon/pmbus/tps40422.c | 4 +- + drivers/hwmon/pmbus/tps53679.c | 18 ++--- + drivers/hwmon/pmbus/tps546d24.c | 4 +- + drivers/hwmon/pmbus/ucd9000.c | 16 ++--- + drivers/hwmon/pmbus/ucd9200.c | 18 ++--- + drivers/hwmon/pmbus/xdp710.c | 2 +- + drivers/hwmon/pmbus/xdp720.c | 4 +- + drivers/hwmon/pmbus/xdpe12284.c | 8 +-- + drivers/hwmon/pmbus/xdpe152c4.c | 6 +- + drivers/hwmon/pmbus/xdpe1a2g7b.c | 6 +- + drivers/hwmon/pmbus/zl6100.c | 44 ++++++------ + drivers/hwmon/powr1220.c | 4 +- + drivers/hwmon/pt5161l.c | 4 +- + drivers/hwmon/sbtsi_temp.c | 4 +- + drivers/hwmon/sg2042-mcu.c | 2 +- + drivers/hwmon/sht21.c | 6 +- + drivers/hwmon/sht3x.c | 8 +-- + drivers/hwmon/sht4x.c | 4 +- + drivers/hwmon/shtc1.c | 6 +- + drivers/hwmon/smsc47m192.c | 2 +- + drivers/hwmon/spd5118.c | 2 +- + drivers/hwmon/stts751.c | 2 +- + drivers/hwmon/tc654.c | 6 +- + drivers/hwmon/tc74.c | 4 +- + drivers/hwmon/thmc50.c | 4 +- + drivers/hwmon/tmp102.c | 2 +- + drivers/hwmon/tmp103.c | 2 +- + drivers/hwmon/tmp108.c | 8 +-- + drivers/hwmon/tmp401.c | 10 +-- + drivers/hwmon/tmp421.c | 10 +-- + drivers/hwmon/tmp464.c | 4 +- + drivers/hwmon/tmp513.c | 4 +- + drivers/hwmon/w83773g.c | 2 +- + drivers/hwmon/w83781d.c | 8 +-- + drivers/hwmon/w83791d.c | 2 +- + drivers/hwmon/w83792d.c | 2 +- + drivers/hwmon/w83793.c | 2 +- + drivers/hwmon/w83795.c | 4 +- + drivers/hwmon/w83l785ts.c | 2 +- + drivers/hwmon/w83l786ng.c | 2 +- + 185 files changed, 684 insertions(+), 684 deletions(-) + +diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c +index f0b17e59827f91..c2df631ae93a39 100644 +--- a/drivers/hwmon/ad7414.c ++++ b/drivers/hwmon/ad7414.c +@@ -205,8 +205,8 @@ static int ad7414_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ad7414_id[] = { +- { "ad7414" }, +- {} ++ { .name = "ad7414" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ad7414_id); + +diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c +index 7a132accdf8a3f..a0c9cf5e12cc40 100644 +--- a/drivers/hwmon/ad7418.c ++++ b/drivers/hwmon/ad7418.c +@@ -281,9 +281,9 @@ static int ad7418_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ad7418_id[] = { +- { "ad7416", ad7416 }, +- { "ad7417", ad7417 }, +- { "ad7418", ad7418 }, ++ { .name = "ad7416", .driver_data = ad7416 }, ++ { .name = "ad7417", .driver_data = ad7417 }, ++ { .name = "ad7418", .driver_data = ad7418 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ad7418_id); +diff --git a/drivers/hwmon/adc128d818.c b/drivers/hwmon/adc128d818.c +index 5e805d4ee76ab4..e45adc0b84d1c0 100644 +--- a/drivers/hwmon/adc128d818.c ++++ b/drivers/hwmon/adc128d818.c +@@ -480,7 +480,7 @@ static int adc128_probe(struct i2c_client *client) + } + + static const struct i2c_device_id adc128_id[] = { +- { "adc128d818" }, ++ { .name = "adc128d818" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adc128_id); +diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c +index 389382d54752e4..ccac7ba601e99d 100644 +--- a/drivers/hwmon/adm1025.c ++++ b/drivers/hwmon/adm1025.c +@@ -548,8 +548,8 @@ static int adm1025_probe(struct i2c_client *client) + } + + static const struct i2c_device_id adm1025_id[] = { +- { "adm1025", adm1025 }, +- { "ne1619", ne1619 }, ++ { .name = "adm1025", .driver_data = adm1025 }, ++ { .name = "ne1619", .driver_data = ne1619 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adm1025_id); +diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c +index c38c932e5d2af6..3ad82c01f81d5e 100644 +--- a/drivers/hwmon/adm1026.c ++++ b/drivers/hwmon/adm1026.c +@@ -1857,7 +1857,7 @@ static int adm1026_probe(struct i2c_client *client) + } + + static const struct i2c_device_id adm1026_id[] = { +- { "adm1026" }, ++ { .name = "adm1026" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adm1026_id); +diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c +index 71eea8ae51b95f..6cb0a238e059b9 100644 +--- a/drivers/hwmon/adm1029.c ++++ b/drivers/hwmon/adm1029.c +@@ -382,7 +382,7 @@ static int adm1029_probe(struct i2c_client *client) + } + + static const struct i2c_device_id adm1029_id[] = { +- { "adm1029" }, ++ { .name = "adm1029" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adm1029_id); +diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c +index 343118532cdb4f..24d0d4146c8774 100644 +--- a/drivers/hwmon/adm1031.c ++++ b/drivers/hwmon/adm1031.c +@@ -1055,8 +1055,8 @@ static int adm1031_probe(struct i2c_client *client) + } + + static const struct i2c_device_id adm1031_id[] = { +- { "adm1030", adm1030 }, +- { "adm1031", adm1031 }, ++ { .name = "adm1030", .driver_data = adm1030 }, ++ { .name = "adm1031", .driver_data = adm1031 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adm1031_id); +diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c +index 7888afe8dafd66..dc4d8a214d1b48 100644 +--- a/drivers/hwmon/adm1177.c ++++ b/drivers/hwmon/adm1177.c +@@ -246,8 +246,8 @@ static int adm1177_probe(struct i2c_client *client) + } + + static const struct i2c_device_id adm1177_id[] = { +- {"adm1177"}, +- {} ++ { .name = "adm1177" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, adm1177_id); + +diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c +index 86f6044b5bd04d..586650e8d043f8 100644 +--- a/drivers/hwmon/adm9240.c ++++ b/drivers/hwmon/adm9240.c +@@ -794,9 +794,9 @@ static int adm9240_probe(struct i2c_client *client) + } + + static const struct i2c_device_id adm9240_id[] = { +- { "adm9240", adm9240 }, +- { "ds1780", ds1780 }, +- { "lm81", lm81 }, ++ { .name = "adm9240", .driver_data = adm9240 }, ++ { .name = "ds1780", .driver_data = ds1780 }, ++ { .name = "lm81", .driver_data = lm81 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adm9240_id); +diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c +index 7f43565ca28416..149cfcec78dcc2 100644 +--- a/drivers/hwmon/ads7828.c ++++ b/drivers/hwmon/ads7828.c +@@ -176,8 +176,8 @@ static int ads7828_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ads7828_device_ids[] = { +- { "ads7828", ads7828 }, +- { "ads7830", ads7830 }, ++ { .name = "ads7828", .driver_data = ads7828 }, ++ { .name = "ads7830", .driver_data = ads7830 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ads7828_device_ids); +diff --git a/drivers/hwmon/adt7410.c b/drivers/hwmon/adt7410.c +index 73b196a78f3a09..0aa7ce0a04be0d 100644 +--- a/drivers/hwmon/adt7410.c ++++ b/drivers/hwmon/adt7410.c +@@ -89,10 +89,10 @@ static int adt7410_i2c_probe(struct i2c_client *client) + } + + static const struct i2c_device_id adt7410_ids[] = { +- { "adt7410" }, +- { "adt7420" }, +- { "adt7422" }, +- {} ++ { .name = "adt7410" }, ++ { .name = "adt7420" }, ++ { .name = "adt7422" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, adt7410_ids); + +diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c +index b9991a69e6c60e..5dce2a70172588 100644 +--- a/drivers/hwmon/adt7411.c ++++ b/drivers/hwmon/adt7411.c +@@ -670,7 +670,7 @@ static int adt7411_probe(struct i2c_client *client) + } + + static const struct i2c_device_id adt7411_id[] = { +- { "adt7411" }, ++ { .name = "adt7411" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adt7411_id); +diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c +index 174dfee47f7a78..5101d30ed9c682 100644 +--- a/drivers/hwmon/adt7462.c ++++ b/drivers/hwmon/adt7462.c +@@ -1809,7 +1809,7 @@ static int adt7462_probe(struct i2c_client *client) + } + + static const struct i2c_device_id adt7462_id[] = { +- { "adt7462" }, ++ { .name = "adt7462" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adt7462_id); +diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c +index dbee6926fa0555..664349756dc2bf 100644 +--- a/drivers/hwmon/adt7470.c ++++ b/drivers/hwmon/adt7470.c +@@ -1296,7 +1296,7 @@ static void adt7470_remove(struct i2c_client *client) + } + + static const struct i2c_device_id adt7470_id[] = { +- { "adt7470" }, ++ { .name = "adt7470" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adt7470_id); +diff --git a/drivers/hwmon/adt7475.c b/drivers/hwmon/adt7475.c +index 8cefa14e1633b9..7fb96f5395fa63 100644 +--- a/drivers/hwmon/adt7475.c ++++ b/drivers/hwmon/adt7475.c +@@ -165,10 +165,10 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; + enum chips { adt7473, adt7475, adt7476, adt7490 }; + + static const struct i2c_device_id adt7475_id[] = { +- { "adt7473", adt7473 }, +- { "adt7475", adt7475 }, +- { "adt7476", adt7476 }, +- { "adt7490", adt7490 }, ++ { .name = "adt7473", .driver_data = adt7473 }, ++ { .name = "adt7475", .driver_data = adt7475 }, ++ { .name = "adt7476", .driver_data = adt7476 }, ++ { .name = "adt7490", .driver_data = adt7490 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adt7475_id); +diff --git a/drivers/hwmon/aht10.c b/drivers/hwmon/aht10.c +index 66955395d05839..6c263cb577666c 100644 +--- a/drivers/hwmon/aht10.c ++++ b/drivers/hwmon/aht10.c +@@ -55,10 +55,10 @@ + enum aht10_variant { aht10, aht20, dht20}; + + static const struct i2c_device_id aht10_id[] = { +- { "aht10", aht10 }, +- { "aht20", aht20 }, +- { "dht20", dht20 }, +- { }, ++ { .name = "aht10", .driver_data = aht10 }, ++ { .name = "aht20", .driver_data = aht20 }, ++ { .name = "dht20", .driver_data = dht20 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, aht10_id); + +diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c +index d5f864b360b03b..bbc0542a7d380a 100644 +--- a/drivers/hwmon/amc6821.c ++++ b/drivers/hwmon/amc6821.c +@@ -1083,7 +1083,7 @@ static int amc6821_probe(struct i2c_client *client) + } + + static const struct i2c_device_id amc6821_id[] = { +- { "amc6821" }, ++ { .name = "amc6821" }, + { } + }; + +diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c +index 14e7737866c25b..5f5c945051665b 100644 +--- a/drivers/hwmon/asb100.c ++++ b/drivers/hwmon/asb100.c +@@ -213,7 +213,7 @@ static struct asb100_data *asb100_update_device(struct device *dev); + static void asb100_init_client(struct i2c_client *client); + + static const struct i2c_device_id asb100_id[] = { +- { "asb100" }, ++ { .name = "asb100" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, asb100_id); +diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c +index 87e1867008499b..e8145bb13ab34a 100644 +--- a/drivers/hwmon/asc7621.c ++++ b/drivers/hwmon/asc7621.c +@@ -1179,9 +1179,9 @@ static void asc7621_remove(struct i2c_client *client) + } + + static const struct i2c_device_id asc7621_id[] = { +- {"asc7621", asc7621}, +- {"asc7621a", asc7621a}, +- {}, ++ { .name = "asc7621", .driver_data = asc7621 }, ++ { .name = "asc7621a", .driver_data = asc7621a }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, asc7621_id); +diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c +index 1c7e9a98b757c3..f5de4894f0a2e3 100644 +--- a/drivers/hwmon/atxp1.c ++++ b/drivers/hwmon/atxp1.c +@@ -278,7 +278,7 @@ static int atxp1_probe(struct i2c_client *client) + }; + + static const struct i2c_device_id atxp1_id[] = { +- { "atxp1" }, ++ { .name = "atxp1" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, atxp1_id); +diff --git a/drivers/hwmon/chipcap2.c b/drivers/hwmon/chipcap2.c +index 645b8c2e704e6b..4aecf463180fd7 100644 +--- a/drivers/hwmon/chipcap2.c ++++ b/drivers/hwmon/chipcap2.c +@@ -736,14 +736,14 @@ static void cc2_remove(struct i2c_client *client) + } + + static const struct i2c_device_id cc2_id[] = { +- { "cc2d23" }, +- { "cc2d23s" }, +- { "cc2d25" }, +- { "cc2d25s" }, +- { "cc2d33" }, +- { "cc2d33s" }, +- { "cc2d35" }, +- { "cc2d35s" }, ++ { .name = "cc2d23" }, ++ { .name = "cc2d23s" }, ++ { .name = "cc2d25" }, ++ { .name = "cc2d25s" }, ++ { .name = "cc2d33" }, ++ { .name = "cc2d33s" }, ++ { .name = "cc2d35" }, ++ { .name = "cc2d35s" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, cc2_id); +diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c +index 3d4057309950dc..7e839308e58fa3 100644 +--- a/drivers/hwmon/dme1737.c ++++ b/drivers/hwmon/dme1737.c +@@ -2515,8 +2515,8 @@ static void dme1737_i2c_remove(struct i2c_client *client) + } + + static const struct i2c_device_id dme1737_id[] = { +- { "dme1737", dme1737 }, +- { "sch5027", sch5027 }, ++ { .name = "dme1737", .driver_data = dme1737 }, ++ { .name = "sch5027", .driver_data = sch5027 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, dme1737_id); +diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c +index 42ec34cb8a5f87..0618f6de9679c4 100644 +--- a/drivers/hwmon/ds1621.c ++++ b/drivers/hwmon/ds1621.c +@@ -367,11 +367,11 @@ static int ds1621_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ds1621_id[] = { +- { "ds1621", ds1621 }, +- { "ds1625", ds1625 }, +- { "ds1631", ds1631 }, +- { "ds1721", ds1721 }, +- { "ds1731", ds1731 }, ++ { .name = "ds1621", .driver_data = ds1621 }, ++ { .name = "ds1625", .driver_data = ds1625 }, ++ { .name = "ds1631", .driver_data = ds1631 }, ++ { .name = "ds1721", .driver_data = ds1721 }, ++ { .name = "ds1731", .driver_data = ds1731 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ds1621_id); +diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c +index ce397042d90b86..25287f0fa4c2e4 100644 +--- a/drivers/hwmon/ds620.c ++++ b/drivers/hwmon/ds620.c +@@ -233,8 +233,8 @@ static int ds620_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ds620_id[] = { +- {"ds620"}, +- {} ++ { .name = "ds620" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, ds620_id); +diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c +index 964a8cb278f16a..cd753b38709f25 100644 +--- a/drivers/hwmon/emc1403.c ++++ b/drivers/hwmon/emc1403.c +@@ -639,18 +639,18 @@ static const struct hwmon_chip_info emc1403_chip_info = { + + /* Last digit of chip name indicates number of channels */ + static const struct i2c_device_id emc1403_idtable[] = { +- { "emc1402", emc1402 }, +- { "emc1403", emc1403 }, +- { "emc1404", emc1404 }, +- { "emc1412", emc1402 }, +- { "emc1413", emc1403 }, +- { "emc1414", emc1404 }, +- { "emc1422", emc1402 }, +- { "emc1423", emc1403 }, +- { "emc1424", emc1404 }, +- { "emc1428", emc1428 }, +- { "emc1438", emc1428 }, +- { "emc1442", emc1402 }, ++ { .name = "emc1402", .driver_data = emc1402 }, ++ { .name = "emc1403", .driver_data = emc1403 }, ++ { .name = "emc1404", .driver_data = emc1404 }, ++ { .name = "emc1412", .driver_data = emc1402 }, ++ { .name = "emc1413", .driver_data = emc1403 }, ++ { .name = "emc1414", .driver_data = emc1404 }, ++ { .name = "emc1422", .driver_data = emc1402 }, ++ { .name = "emc1423", .driver_data = emc1403 }, ++ { .name = "emc1424", .driver_data = emc1404 }, ++ { .name = "emc1428", .driver_data = emc1428 }, ++ { .name = "emc1438", .driver_data = emc1428 }, ++ { .name = "emc1442", .driver_data = emc1402 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, emc1403_idtable); +diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c +index 9b8e925af03002..27dc149a3ed995 100644 +--- a/drivers/hwmon/emc2103.c ++++ b/drivers/hwmon/emc2103.c +@@ -624,7 +624,7 @@ emc2103_probe(struct i2c_client *client) + } + + static const struct i2c_device_id emc2103_ids[] = { +- { "emc2103" }, ++ { .name = "emc2103" }, + { /* LIST END */ } + }; + MODULE_DEVICE_TABLE(i2c, emc2103_ids); +diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c +index 64b213e1451e70..8fcdac6cfb24dc 100644 +--- a/drivers/hwmon/emc2305.c ++++ b/drivers/hwmon/emc2305.c +@@ -59,10 +59,10 @@ enum emc230x_product_id { + }; + + static const struct i2c_device_id emc2305_ids[] = { +- { "emc2305" }, +- { "emc2303" }, +- { "emc2302" }, +- { "emc2301" }, ++ { .name = "emc2305" }, ++ { .name = "emc2303" }, ++ { .name = "emc2302" }, ++ { .name = "emc2301" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, emc2305_ids); +diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c +index 1100c6e5daa775..c13ea874868356 100644 +--- a/drivers/hwmon/emc6w201.c ++++ b/drivers/hwmon/emc6w201.c +@@ -464,7 +464,7 @@ static int emc6w201_probe(struct i2c_client *client) + } + + static const struct i2c_device_id emc6w201_id[] = { +- { "emc6w201" }, ++ { .name = "emc6w201" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, emc6w201_id); +diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c +index 7e867f13242013..cc3a9612f2c0af 100644 +--- a/drivers/hwmon/f75375s.c ++++ b/drivers/hwmon/f75375s.c +@@ -877,9 +877,9 @@ static int f75375_detect(struct i2c_client *client, + } + + static const struct i2c_device_id f75375_id[] = { +- { "f75373", f75373 }, +- { "f75375", f75375 }, +- { "f75387", f75387 }, ++ { .name = "f75373", .driver_data = f75373 }, ++ { .name = "f75375", .driver_data = f75375 }, ++ { .name = "f75387", .driver_data = f75387 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, f75375_id); +diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c +index 1211fa2259e52e..019fc32bf3181a 100644 +--- a/drivers/hwmon/fschmd.c ++++ b/drivers/hwmon/fschmd.c +@@ -225,13 +225,13 @@ static struct fschmd_data *fschmd_update_device(struct device *dev); + */ + + static const struct i2c_device_id fschmd_id[] = { +- { "fscpos", fscpos }, +- { "fscher", fscher }, +- { "fscscy", fscscy }, +- { "fschrc", fschrc }, +- { "fschmd", fschmd }, +- { "fschds", fschds }, +- { "fscsyl", fscsyl }, ++ { .name = "fscpos", .driver_data = fscpos }, ++ { .name = "fscher", .driver_data = fscher }, ++ { .name = "fscscy", .driver_data = fscscy }, ++ { .name = "fschrc", .driver_data = fschrc }, ++ { .name = "fschmd", .driver_data = fschmd }, ++ { .name = "fschds", .driver_data = fschds }, ++ { .name = "fscsyl", .driver_data = fscsyl }, + { } + }; + MODULE_DEVICE_TABLE(i2c, fschmd_id); +diff --git a/drivers/hwmon/ftsteutates.c b/drivers/hwmon/ftsteutates.c +index 08dcc6a7fb6255..06be120a349d63 100644 +--- a/drivers/hwmon/ftsteutates.c ++++ b/drivers/hwmon/ftsteutates.c +@@ -49,7 +49,7 @@ + static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; + + static const struct i2c_device_id fts_id[] = { +- { "ftsteutates" }, ++ { .name = "ftsteutates" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, fts_id); +diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c +index 39ae8f82641761..e2166ee7628607 100644 +--- a/drivers/hwmon/g760a.c ++++ b/drivers/hwmon/g760a.c +@@ -197,7 +197,7 @@ static int g760a_probe(struct i2c_client *client) + } + + static const struct i2c_device_id g760a_id[] = { +- { "g760a" }, ++ { .name = "g760a" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, g760a_id); +diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c +index 4fa3aa1271daa8..407cf7af4fdd91 100644 +--- a/drivers/hwmon/g762.c ++++ b/drivers/hwmon/g762.c +@@ -44,9 +44,9 @@ + #define DRVNAME "g762" + + static const struct i2c_device_id g762_id[] = { +- { "g761" }, +- { "g762" }, +- { "g763" }, ++ { .name = "g761" }, ++ { .name = "g762" }, ++ { .name = "g763" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, g762_id); +diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c +index 9c68bc0139503c..742c130cec7f1a 100644 +--- a/drivers/hwmon/gl518sm.c ++++ b/drivers/hwmon/gl518sm.c +@@ -642,7 +642,7 @@ static int gl518_probe(struct i2c_client *client) + } + + static const struct i2c_device_id gl518_id[] = { +- { "gl518sm" }, ++ { .name = "gl518sm" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, gl518_id); +diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c +index 972f4f8caa2b7a..f4fe39912ee292 100644 +--- a/drivers/hwmon/gl520sm.c ++++ b/drivers/hwmon/gl520sm.c +@@ -885,7 +885,7 @@ static int gl520_probe(struct i2c_client *client) + } + + static const struct i2c_device_id gl520_id[] = { +- { "gl520sm" }, ++ { .name = "gl520sm" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, gl520_id); +diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c +index 85af8299150a52..7984be1e706d55 100644 +--- a/drivers/hwmon/hih6130.c ++++ b/drivers/hwmon/hih6130.c +@@ -233,7 +233,7 @@ static int hih6130_probe(struct i2c_client *client) + + /* Device ID table */ + static const struct i2c_device_id hih6130_id[] = { +- { "hih6130" }, ++ { .name = "hih6130" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, hih6130_id); +diff --git a/drivers/hwmon/hs3001.c b/drivers/hwmon/hs3001.c +index 50c6c15f8b180b..b263cbeca0747f 100644 +--- a/drivers/hwmon/hs3001.c ++++ b/drivers/hwmon/hs3001.c +@@ -169,8 +169,8 @@ static const struct hwmon_chip_info hs3001_chip_info = { + + /* device ID table */ + static const struct i2c_device_id hs3001_ids[] = { +- { "hs3001" }, +- { }, ++ { .name = "hs3001" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, hs3001_ids); +diff --git a/drivers/hwmon/htu31.c b/drivers/hwmon/htu31.c +index 7521a371aa6cdf..5d2cdbdb773b07 100644 +--- a/drivers/hwmon/htu31.c ++++ b/drivers/hwmon/htu31.c +@@ -322,7 +322,7 @@ static int htu31_probe(struct i2c_client *client) + } + + static const struct i2c_device_id htu31_id[] = { +- { "htu31" }, ++ { .name = "htu31" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, htu31_id); +diff --git a/drivers/hwmon/ina209.c b/drivers/hwmon/ina209.c +index a116f1600e810f..39aca2cdf27f7f 100644 +--- a/drivers/hwmon/ina209.c ++++ b/drivers/hwmon/ina209.c +@@ -569,7 +569,7 @@ static void ina209_remove(struct i2c_client *client) + } + + static const struct i2c_device_id ina209_id[] = { +- { "ina209" }, ++ { .name = "ina209" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ina209_id); +diff --git a/drivers/hwmon/ina238.c b/drivers/hwmon/ina238.c +index ff67b03189f73c..c20dd164a6a6c9 100644 +--- a/drivers/hwmon/ina238.c ++++ b/drivers/hwmon/ina238.c +@@ -837,12 +837,12 @@ static int ina238_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ina238_id[] = { +- { "ina228", ina228 }, +- { "ina237", ina237 }, +- { "ina238", ina238 }, +- { "ina700", ina700 }, +- { "ina780", ina780 }, +- { "sq52206", sq52206 }, ++ { .name = "ina228", .driver_data = ina228 }, ++ { .name = "ina237", .driver_data = ina237 }, ++ { .name = "ina238", .driver_data = ina238 }, ++ { .name = "ina700", .driver_data = ina700 }, ++ { .name = "ina780", .driver_data = ina780 }, ++ { .name = "sq52206", .driver_data = sq52206 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ina238_id); +diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c +index 613ffb622b7c42..32bf4595bcb482 100644 +--- a/drivers/hwmon/ina2xx.c ++++ b/drivers/hwmon/ina2xx.c +@@ -1000,14 +1000,14 @@ static int ina2xx_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ina2xx_id[] = { +- { "ina219", ina219 }, +- { "ina220", ina219 }, +- { "ina226", ina226 }, +- { "ina230", ina226 }, +- { "ina231", ina226 }, +- { "ina234", ina234 }, +- { "ina260", ina260 }, +- { "sy24655", sy24655 }, ++ { .name = "ina219", .driver_data = ina219 }, ++ { .name = "ina220", .driver_data = ina219 }, ++ { .name = "ina226", .driver_data = ina226 }, ++ { .name = "ina230", .driver_data = ina226 }, ++ { .name = "ina231", .driver_data = ina226 }, ++ { .name = "ina234", .driver_data = ina234 }, ++ { .name = "ina260", .driver_data = ina260 }, ++ { .name = "sy24655", .driver_data = sy24655 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ina2xx_id); +diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c +index 5ecc68dcf16987..3ab5de3a111029 100644 +--- a/drivers/hwmon/ina3221.c ++++ b/drivers/hwmon/ina3221.c +@@ -1002,7 +1002,7 @@ static const struct of_device_id ina3221_of_match_table[] = { + MODULE_DEVICE_TABLE(of, ina3221_of_match_table); + + static const struct i2c_device_id ina3221_ids[] = { +- { "ina3221" }, ++ { .name = "ina3221" }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(i2c, ina3221_ids); +diff --git a/drivers/hwmon/isl28022.c b/drivers/hwmon/isl28022.c +index 96fcfbfff48f4c..0c60d2ef28f5dd 100644 +--- a/drivers/hwmon/isl28022.c ++++ b/drivers/hwmon/isl28022.c +@@ -475,7 +475,7 @@ static int isl28022_probe(struct i2c_client *client) + } + + static const struct i2c_device_id isl28022_ids[] = { +- { "isl28022" }, ++ { .name = "isl28022" }, + { /* LIST END */ } + }; + MODULE_DEVICE_TABLE(i2c, isl28022_ids); +diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c +index 6549dc54378124..77fece680358d9 100644 +--- a/drivers/hwmon/jc42.c ++++ b/drivers/hwmon/jc42.c +@@ -579,7 +579,7 @@ static const struct dev_pm_ops jc42_dev_pm_ops = { + #endif /* CONFIG_PM */ + + static const struct i2c_device_id jc42_id[] = { +- { "jc42" }, ++ { .name = "jc42" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, jc42_id); +diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c +index 64a335a64a2ebe..2553e49f840158 100644 +--- a/drivers/hwmon/lineage-pem.c ++++ b/drivers/hwmon/lineage-pem.c +@@ -502,8 +502,8 @@ static int pem_probe(struct i2c_client *client) + } + + static const struct i2c_device_id pem_id[] = { +- {"lineage_pem"}, +- {} ++ { .name = "lineage_pem" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, pem_id); + +diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c +index 30500b4d222129..a0d77a7386a9de 100644 +--- a/drivers/hwmon/lm63.c ++++ b/drivers/hwmon/lm63.c +@@ -1152,9 +1152,9 @@ static int lm63_probe(struct i2c_client *client) + */ + + static const struct i2c_device_id lm63_id[] = { +- { "lm63", lm63 }, +- { "lm64", lm64 }, +- { "lm96163", lm96163 }, ++ { .name = "lm63", .driver_data = lm63 }, ++ { .name = "lm64", .driver_data = lm64 }, ++ { .name = "lm96163", .driver_data = lm96163 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm63_id); +diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c +index 581b01572e1bd5..63ee67481a16c2 100644 +--- a/drivers/hwmon/lm73.c ++++ b/drivers/hwmon/lm73.c +@@ -220,7 +220,7 @@ lm73_probe(struct i2c_client *client) + } + + static const struct i2c_device_id lm73_ids[] = { +- { "lm73" }, ++ { .name = "lm73" }, + { /* LIST END */ } + }; + MODULE_DEVICE_TABLE(i2c, lm73_ids); +diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c +index c283443e363b42..05293383f9cc2d 100644 +--- a/drivers/hwmon/lm75.c ++++ b/drivers/hwmon/lm75.c +@@ -816,37 +816,37 @@ static int lm75_i2c_probe(struct i2c_client *client) + } + + static const struct i2c_device_id lm75_i2c_ids[] = { +- { "adt75", adt75, }, +- { "as6200", as6200, }, +- { "at30ts74", at30ts74, }, +- { "ds1775", ds1775, }, +- { "ds75", ds75, }, +- { "ds7505", ds7505, }, +- { "g751", g751, }, +- { "lm75", lm75, }, +- { "lm75a", lm75a, }, +- { "lm75b", lm75b, }, +- { "max6625", max6625, }, +- { "max6626", max6626, }, +- { "max31725", max31725, }, +- { "max31726", max31725, }, +- { "mcp980x", mcp980x, }, +- { "p3t1750", p3t1750, }, +- { "p3t1755", p3t1755, }, +- { "pct2075", pct2075, }, +- { "stds75", stds75, }, +- { "stlm75", stlm75, }, +- { "tcn75", tcn75, }, +- { "tmp100", tmp100, }, +- { "tmp101", tmp101, }, +- { "tmp105", tmp105, }, +- { "tmp112", tmp112, }, +- { "tmp175", tmp175, }, +- { "tmp275", tmp275, }, +- { "tmp75", tmp75, }, +- { "tmp75b", tmp75b, }, +- { "tmp75c", tmp75c, }, +- { "tmp1075", tmp1075, }, ++ { .name = "adt75", .driver_data = adt75 }, ++ { .name = "as6200", .driver_data = as6200 }, ++ { .name = "at30ts74", .driver_data = at30ts74 }, ++ { .name = "ds1775", .driver_data = ds1775 }, ++ { .name = "ds75", .driver_data = ds75 }, ++ { .name = "ds7505", .driver_data = ds7505 }, ++ { .name = "g751", .driver_data = g751 }, ++ { .name = "lm75", .driver_data = lm75 }, ++ { .name = "lm75a", .driver_data = lm75a }, ++ { .name = "lm75b", .driver_data = lm75b }, ++ { .name = "max6625", .driver_data = max6625 }, ++ { .name = "max6626", .driver_data = max6626 }, ++ { .name = "max31725", .driver_data = max31725 }, ++ { .name = "max31726", .driver_data = max31725 }, ++ { .name = "mcp980x", .driver_data = mcp980x }, ++ { .name = "p3t1750", .driver_data = p3t1750 }, ++ { .name = "p3t1755", .driver_data = p3t1755 }, ++ { .name = "pct2075", .driver_data = pct2075 }, ++ { .name = "stds75", .driver_data = stds75 }, ++ { .name = "stlm75", .driver_data = stlm75 }, ++ { .name = "tcn75", .driver_data = tcn75 }, ++ { .name = "tmp100", .driver_data = tmp100 }, ++ { .name = "tmp101", .driver_data = tmp101 }, ++ { .name = "tmp105", .driver_data = tmp105 }, ++ { .name = "tmp112", .driver_data = tmp112 }, ++ { .name = "tmp175", .driver_data = tmp175 }, ++ { .name = "tmp275", .driver_data = tmp275 }, ++ { .name = "tmp75", .driver_data = tmp75 }, ++ { .name = "tmp75b", .driver_data = tmp75b }, ++ { .name = "tmp75c", .driver_data = tmp75c }, ++ { .name = "tmp1075", .driver_data = tmp1075 }, + { /* LIST END */ } + }; + MODULE_DEVICE_TABLE(i2c, lm75_i2c_ids); +diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c +index 80f7a6a3f9a29d..96c5c2584d37e7 100644 +--- a/drivers/hwmon/lm77.c ++++ b/drivers/hwmon/lm77.c +@@ -337,7 +337,7 @@ static int lm77_probe(struct i2c_client *client) + } + + static const struct i2c_device_id lm77_id[] = { +- { "lm77" }, ++ { .name = "lm77" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm77_id); +diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c +index 9378a47bf5afa9..e4834f9eca6a24 100644 +--- a/drivers/hwmon/lm78.c ++++ b/drivers/hwmon/lm78.c +@@ -649,8 +649,8 @@ static int lm78_i2c_probe(struct i2c_client *client) + } + + static const struct i2c_device_id lm78_i2c_id[] = { +- { "lm78", lm78 }, +- { "lm79", lm79 }, ++ { .name = "lm78", .driver_data = lm78 }, ++ { .name = "lm79", .driver_data = lm79 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm78_i2c_id); +diff --git a/drivers/hwmon/lm80.c b/drivers/hwmon/lm80.c +index 002c669182e153..94f3dabaaa6f62 100644 +--- a/drivers/hwmon/lm80.c ++++ b/drivers/hwmon/lm80.c +@@ -622,8 +622,8 @@ static int lm80_probe(struct i2c_client *client) + */ + + static const struct i2c_device_id lm80_id[] = { +- { "lm80" }, +- { "lm96080" }, ++ { .name = "lm80" }, ++ { .name = "lm96080" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm80_id); +diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c +index f800fe2ef18b85..8d49df8c9314fd 100644 +--- a/drivers/hwmon/lm83.c ++++ b/drivers/hwmon/lm83.c +@@ -443,8 +443,8 @@ static int lm83_probe(struct i2c_client *client) + */ + + static const struct i2c_device_id lm83_id[] = { +- { "lm83", lm83 }, +- { "lm82", lm82 }, ++ { .name = "lm83", .driver_data = lm83 }, ++ { .name = "lm82", .driver_data = lm82 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm83_id); +diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c +index 1c244ed75122ea..c56e164d61c185 100644 +--- a/drivers/hwmon/lm85.c ++++ b/drivers/hwmon/lm85.c +@@ -1618,18 +1618,18 @@ static int lm85_probe(struct i2c_client *client) + } + + static const struct i2c_device_id lm85_id[] = { +- { "adm1027", adm1027 }, +- { "adt7463", adt7463 }, +- { "adt7468", adt7468 }, +- { "lm85", lm85 }, +- { "lm85b", lm85 }, +- { "lm85c", lm85 }, +- { "lm96000", lm96000 }, +- { "emc6d100", emc6d100 }, +- { "emc6d101", emc6d100 }, +- { "emc6d102", emc6d102 }, +- { "emc6d103", emc6d103 }, +- { "emc6d103s", emc6d103s }, ++ { .name = "adm1027", .driver_data = adm1027 }, ++ { .name = "adt7463", .driver_data = adt7463 }, ++ { .name = "adt7468", .driver_data = adt7468 }, ++ { .name = "lm85", .driver_data = lm85 }, ++ { .name = "lm85b", .driver_data = lm85 }, ++ { .name = "lm85c", .driver_data = lm85 }, ++ { .name = "lm96000", .driver_data = lm96000 }, ++ { .name = "emc6d100", .driver_data = emc6d100 }, ++ { .name = "emc6d101", .driver_data = emc6d100 }, ++ { .name = "emc6d102", .driver_data = emc6d102 }, ++ { .name = "emc6d103", .driver_data = emc6d103 }, ++ { .name = "emc6d103s", .driver_data = emc6d103s }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm85_id); +diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c +index 37bf2d1d3d0998..c09074f447083d 100644 +--- a/drivers/hwmon/lm87.c ++++ b/drivers/hwmon/lm87.c +@@ -981,8 +981,8 @@ static int lm87_probe(struct i2c_client *client) + */ + + static const struct i2c_device_id lm87_id[] = { +- { "lm87" }, +- { "adm1024" }, ++ { .name = "lm87" }, ++ { .name = "adm1024" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm87_id); +diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c +index 1eeb608e59039d..c78c96e1bd83fd 100644 +--- a/drivers/hwmon/lm90.c ++++ b/drivers/hwmon/lm90.c +@@ -243,54 +243,54 @@ enum chips { adm1023, adm1032, adt7461, adt7461a, adt7481, + */ + + static const struct i2c_device_id lm90_id[] = { +- { "adm1020", max1617 }, +- { "adm1021", max1617 }, +- { "adm1023", adm1023 }, +- { "adm1032", adm1032 }, +- { "adt7421", adt7461a }, +- { "adt7461", adt7461 }, +- { "adt7461a", adt7461a }, +- { "adt7481", adt7481 }, +- { "adt7482", adt7481 }, +- { "adt7483a", adt7481 }, +- { "g781", g781 }, +- { "gl523sm", max1617 }, +- { "lm84", lm84 }, +- { "lm86", lm90 }, +- { "lm89", lm90 }, +- { "lm90", lm90 }, +- { "lm99", lm99 }, +- { "max1617", max1617 }, +- { "max6642", max6642 }, +- { "max6646", max6646 }, +- { "max6647", max6646 }, +- { "max6648", max6648 }, +- { "max6649", max6646 }, +- { "max6654", max6654 }, +- { "max6657", max6657 }, +- { "max6658", max6657 }, +- { "max6659", max6659 }, +- { "max6680", max6680 }, +- { "max6681", max6680 }, +- { "max6690", max6654 }, +- { "max6692", max6648 }, +- { "max6695", max6696 }, +- { "max6696", max6696 }, +- { "mc1066", max1617 }, +- { "nct1008", adt7461a }, +- { "nct210", nct210 }, +- { "nct214", nct72 }, +- { "nct218", nct72 }, +- { "nct72", nct72 }, +- { "nct7716", nct7716 }, +- { "nct7717", nct7717 }, +- { "nct7718", nct7718 }, +- { "ne1618", ne1618 }, +- { "w83l771", w83l771 }, +- { "sa56004", sa56004 }, +- { "thmc10", max1617 }, +- { "tmp451", tmp451 }, +- { "tmp461", tmp461 }, ++ { .name = "adm1020", .driver_data = max1617 }, ++ { .name = "adm1021", .driver_data = max1617 }, ++ { .name = "adm1023", .driver_data = adm1023 }, ++ { .name = "adm1032", .driver_data = adm1032 }, ++ { .name = "adt7421", .driver_data = adt7461a }, ++ { .name = "adt7461", .driver_data = adt7461 }, ++ { .name = "adt7461a", .driver_data = adt7461a }, ++ { .name = "adt7481", .driver_data = adt7481 }, ++ { .name = "adt7482", .driver_data = adt7481 }, ++ { .name = "adt7483a", .driver_data = adt7481 }, ++ { .name = "g781", .driver_data = g781 }, ++ { .name = "gl523sm", .driver_data = max1617 }, ++ { .name = "lm84", .driver_data = lm84 }, ++ { .name = "lm86", .driver_data = lm90 }, ++ { .name = "lm89", .driver_data = lm90 }, ++ { .name = "lm90", .driver_data = lm90 }, ++ { .name = "lm99", .driver_data = lm99 }, ++ { .name = "max1617", .driver_data = max1617 }, ++ { .name = "max6642", .driver_data = max6642 }, ++ { .name = "max6646", .driver_data = max6646 }, ++ { .name = "max6647", .driver_data = max6646 }, ++ { .name = "max6648", .driver_data = max6648 }, ++ { .name = "max6649", .driver_data = max6646 }, ++ { .name = "max6654", .driver_data = max6654 }, ++ { .name = "max6657", .driver_data = max6657 }, ++ { .name = "max6658", .driver_data = max6657 }, ++ { .name = "max6659", .driver_data = max6659 }, ++ { .name = "max6680", .driver_data = max6680 }, ++ { .name = "max6681", .driver_data = max6680 }, ++ { .name = "max6690", .driver_data = max6654 }, ++ { .name = "max6692", .driver_data = max6648 }, ++ { .name = "max6695", .driver_data = max6696 }, ++ { .name = "max6696", .driver_data = max6696 }, ++ { .name = "mc1066", .driver_data = max1617 }, ++ { .name = "nct1008", .driver_data = adt7461a }, ++ { .name = "nct210", .driver_data = nct210 }, ++ { .name = "nct214", .driver_data = nct72 }, ++ { .name = "nct218", .driver_data = nct72 }, ++ { .name = "nct72", .driver_data = nct72 }, ++ { .name = "nct7716", .driver_data = nct7716 }, ++ { .name = "nct7717", .driver_data = nct7717 }, ++ { .name = "nct7718", .driver_data = nct7718 }, ++ { .name = "ne1618", .driver_data = ne1618 }, ++ { .name = "w83l771", .driver_data = w83l771 }, ++ { .name = "sa56004", .driver_data = sa56004 }, ++ { .name = "thmc10", .driver_data = max1617 }, ++ { .name = "tmp451", .driver_data = tmp451 }, ++ { .name = "tmp461", .driver_data = tmp461 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm90_id); +diff --git a/drivers/hwmon/lm92.c b/drivers/hwmon/lm92.c +index 91a6b7525bb675..4aadbabc27bb92 100644 +--- a/drivers/hwmon/lm92.c ++++ b/drivers/hwmon/lm92.c +@@ -405,10 +405,10 @@ static int lm92_probe(struct i2c_client *client) + * Module and driver stuff + */ + +-/* .driver_data is limit register resolution */ ++/* .driver_data is limit register resolution */ + static const struct i2c_device_id lm92_id[] = { +- { "lm92", 13 }, +- { "max6635", 9 }, ++ { .name = "lm92", .driver_data = 13 }, ++ { .name = "max6635", .driver_data = 9 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm92_id); +diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c +index be4853fad80fdb..d58a3c2a859304 100644 +--- a/drivers/hwmon/lm93.c ++++ b/drivers/hwmon/lm93.c +@@ -2624,8 +2624,8 @@ static int lm93_probe(struct i2c_client *client) + } + + static const struct i2c_device_id lm93_id[] = { +- { "lm93" }, +- { "lm94" }, ++ { .name = "lm93" }, ++ { .name = "lm94" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm93_id); +diff --git a/drivers/hwmon/lm95234.c b/drivers/hwmon/lm95234.c +index 387b3ba81dbfc1..74f280b90e3e9c 100644 +--- a/drivers/hwmon/lm95234.c ++++ b/drivers/hwmon/lm95234.c +@@ -532,8 +532,8 @@ static int lm95234_probe(struct i2c_client *client) + + /* Driver data (common to all clients) */ + static const struct i2c_device_id lm95234_id[] = { +- { "lm95233", lm95233 }, +- { "lm95234", lm95234 }, ++ { .name = "lm95233", .driver_data = lm95233 }, ++ { .name = "lm95234", .driver_data = lm95234 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm95234_id); +diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c +index 456381b0938e75..0cb0edb3845db0 100644 +--- a/drivers/hwmon/lm95241.c ++++ b/drivers/hwmon/lm95241.c +@@ -441,8 +441,8 @@ static int lm95241_probe(struct i2c_client *client) + + /* Driver data (common to all clients) */ + static const struct i2c_device_id lm95241_id[] = { +- { "lm95231" }, +- { "lm95241" }, ++ { .name = "lm95231" }, ++ { .name = "lm95241" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm95241_id); +diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c +index 9ed300c6b5f70a..11553391f54b1e 100644 +--- a/drivers/hwmon/lm95245.c ++++ b/drivers/hwmon/lm95245.c +@@ -546,8 +546,8 @@ static int lm95245_probe(struct i2c_client *client) + + /* Driver data (common to all clients) */ + static const struct i2c_device_id lm95245_id[] = { +- { "lm95235" }, +- { "lm95245" }, ++ { .name = "lm95235" }, ++ { .name = "lm95245" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm95245_id); +diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c +index 3e0e0e0687bdd5..b521100afe53a0 100644 +--- a/drivers/hwmon/ltc2945.c ++++ b/drivers/hwmon/ltc2945.c +@@ -508,7 +508,7 @@ static int ltc2945_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ltc2945_id[] = { +- {"ltc2945"}, ++ { .name = "ltc2945" }, + { } + }; + +diff --git a/drivers/hwmon/ltc2947-i2c.c b/drivers/hwmon/ltc2947-i2c.c +index 176d710706dd9b..e07d33983d5ce3 100644 +--- a/drivers/hwmon/ltc2947-i2c.c ++++ b/drivers/hwmon/ltc2947-i2c.c +@@ -27,8 +27,8 @@ static int ltc2947_probe(struct i2c_client *i2c) + } + + static const struct i2c_device_id ltc2947_id[] = { +- {"ltc2947"}, +- {} ++ { .name = "ltc2947" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ltc2947_id); + +diff --git a/drivers/hwmon/ltc2990.c b/drivers/hwmon/ltc2990.c +index f1c1933c52cf4f..a2725e4b2f2136 100644 +--- a/drivers/hwmon/ltc2990.c ++++ b/drivers/hwmon/ltc2990.c +@@ -259,8 +259,8 @@ static int ltc2990_i2c_probe(struct i2c_client *i2c) + } + + static const struct i2c_device_id ltc2990_i2c_id[] = { +- { "ltc2990" }, +- {} ++ { .name = "ltc2990" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ltc2990_i2c_id); + +diff --git a/drivers/hwmon/ltc2991.c b/drivers/hwmon/ltc2991.c +index 6d5d4cb846daf3..bc8d803e8cc90d 100644 +--- a/drivers/hwmon/ltc2991.c ++++ b/drivers/hwmon/ltc2991.c +@@ -409,8 +409,8 @@ static const struct of_device_id ltc2991_of_match[] = { + MODULE_DEVICE_TABLE(of, ltc2991_of_match); + + static const struct i2c_device_id ltc2991_i2c_id[] = { +- { "ltc2991" }, +- {} ++ { .name = "ltc2991" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ltc2991_i2c_id); + +diff --git a/drivers/hwmon/ltc2992.c b/drivers/hwmon/ltc2992.c +index 2617c4538af91d..43b6029c084048 100644 +--- a/drivers/hwmon/ltc2992.c ++++ b/drivers/hwmon/ltc2992.c +@@ -948,8 +948,8 @@ static const struct of_device_id ltc2992_of_match[] = { + MODULE_DEVICE_TABLE(of, ltc2992_of_match); + + static const struct i2c_device_id ltc2992_i2c_id[] = { +- {"ltc2992"}, +- {} ++ { .name = "ltc2992" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ltc2992_i2c_id); + +diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c +index fa66eda78efe4f..fa7c57aae5f5fb 100644 +--- a/drivers/hwmon/ltc4151.c ++++ b/drivers/hwmon/ltc4151.c +@@ -188,7 +188,7 @@ static int ltc4151_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ltc4151_id[] = { +- { "ltc4151" }, ++ { .name = "ltc4151" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ltc4151_id); +diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c +index cce452711cec4d..3d439fbbbef93d 100644 +--- a/drivers/hwmon/ltc4215.c ++++ b/drivers/hwmon/ltc4215.c +@@ -245,7 +245,7 @@ static int ltc4215_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ltc4215_id[] = { +- { "ltc4215" }, ++ { .name = "ltc4215" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ltc4215_id); +diff --git a/drivers/hwmon/ltc4222.c b/drivers/hwmon/ltc4222.c +index f7eb007fd766bf..4fc69be5f2bc95 100644 +--- a/drivers/hwmon/ltc4222.c ++++ b/drivers/hwmon/ltc4222.c +@@ -200,7 +200,7 @@ static int ltc4222_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ltc4222_id[] = { +- {"ltc4222"}, ++ { .name = "ltc4222" }, + { } + }; + +diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c +index e8131a48bda7f7..d87aa9c32c8730 100644 +--- a/drivers/hwmon/ltc4245.c ++++ b/drivers/hwmon/ltc4245.c +@@ -461,7 +461,7 @@ static int ltc4245_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ltc4245_id[] = { +- { "ltc4245" }, ++ { .name = "ltc4245" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ltc4245_id); +diff --git a/drivers/hwmon/ltc4260.c b/drivers/hwmon/ltc4260.c +index 9750dc9aa336d4..37a85125d619c8 100644 +--- a/drivers/hwmon/ltc4260.c ++++ b/drivers/hwmon/ltc4260.c +@@ -163,7 +163,7 @@ static int ltc4260_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ltc4260_id[] = { +- {"ltc4260"}, ++ { .name = "ltc4260" }, + { } + }; + +diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c +index 2cd218a6a3be7b..a2e52ca0b06e1c 100644 +--- a/drivers/hwmon/ltc4261.c ++++ b/drivers/hwmon/ltc4261.c +@@ -222,8 +222,8 @@ static int ltc4261_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ltc4261_id[] = { +- {"ltc4261"}, +- {} ++ { .name = "ltc4261" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, ltc4261_id); +diff --git a/drivers/hwmon/max127.c b/drivers/hwmon/max127.c +index 5102d86d2619a6..b294e86d52d16e 100644 +--- a/drivers/hwmon/max127.c ++++ b/drivers/hwmon/max127.c +@@ -312,7 +312,7 @@ static int max127_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max127_id[] = { +- { "max127" }, ++ { .name = "max127" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max127_id); +diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c +index 43fbb9b26b102b..f8b4217542203d 100644 +--- a/drivers/hwmon/max16065.c ++++ b/drivers/hwmon/max16065.c +@@ -592,12 +592,12 @@ static int max16065_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max16065_id[] = { +- { "max16065", max16065 }, +- { "max16066", max16066 }, +- { "max16067", max16067 }, +- { "max16068", max16068 }, +- { "max16070", max16070 }, +- { "max16071", max16071 }, ++ { .name = "max16065", .driver_data = max16065 }, ++ { .name = "max16066", .driver_data = max16066 }, ++ { .name = "max16067", .driver_data = max16067 }, ++ { .name = "max16068", .driver_data = max16068 }, ++ { .name = "max16070", .driver_data = max16070 }, ++ { .name = "max16071", .driver_data = max16071 }, + { } + }; + +diff --git a/drivers/hwmon/max1619.c b/drivers/hwmon/max1619.c +index 9b6d03cff4df5f..77ef39e8ae7e31 100644 +--- a/drivers/hwmon/max1619.c ++++ b/drivers/hwmon/max1619.c +@@ -366,7 +366,7 @@ static int max1619_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max1619_id[] = { +- { "max1619" }, ++ { .name = "max1619" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max1619_id); +diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c +index a8197a86f55908..32548f56409ce3 100644 +--- a/drivers/hwmon/max1668.c ++++ b/drivers/hwmon/max1668.c +@@ -293,9 +293,9 @@ static int max1668_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max1668_id[] = { +- { "max1668", 5 }, +- { "max1805", 3 }, +- { "max1989", 5 }, ++ { .name = "max1668", .driver_data = 5 }, ++ { .name = "max1805", .driver_data = 3 }, ++ { .name = "max1989", .driver_data = 5 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max1668_id); +diff --git a/drivers/hwmon/max31730.c b/drivers/hwmon/max31730.c +index 2f4b419b6c9e38..d132be2d6487d0 100644 +--- a/drivers/hwmon/max31730.c ++++ b/drivers/hwmon/max31730.c +@@ -345,7 +345,7 @@ max31730_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max31730_ids[] = { +- { "max31730" }, ++ { .name = "max31730" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max31730_ids); +diff --git a/drivers/hwmon/max31760.c b/drivers/hwmon/max31760.c +index 127e31ca3c8737..8d3be064b02518 100644 +--- a/drivers/hwmon/max31760.c ++++ b/drivers/hwmon/max31760.c +@@ -555,7 +555,7 @@ static const struct of_device_id max31760_of_match[] = { + MODULE_DEVICE_TABLE(of, max31760_of_match); + + static const struct i2c_device_id max31760_id[] = { +- {"max31760"}, ++ { .name = "max31760" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max31760_id); +diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c +index 4f6171a17d9f1f..db8a0f6f18294b 100644 +--- a/drivers/hwmon/max31790.c ++++ b/drivers/hwmon/max31790.c +@@ -517,7 +517,7 @@ static int max31790_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max31790_id[] = { +- { "max31790" }, ++ { .name = "max31790" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max31790_id); +diff --git a/drivers/hwmon/max31827.c b/drivers/hwmon/max31827.c +index 9b2e56c040df1a..6a7048fdd8ab7a 100644 +--- a/drivers/hwmon/max31827.c ++++ b/drivers/hwmon/max31827.c +@@ -463,9 +463,9 @@ static struct attribute *max31827_attrs[] = { + ATTRIBUTE_GROUPS(max31827); + + static const struct i2c_device_id max31827_i2c_ids[] = { +- { "max31827", max31827 }, +- { "max31828", max31828 }, +- { "max31829", max31829 }, ++ { .name = "max31827", .driver_data = max31827 }, ++ { .name = "max31828", .driver_data = max31828 }, ++ { .name = "max31829", .driver_data = max31829 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max31827_i2c_ids); +diff --git a/drivers/hwmon/max6620.c b/drivers/hwmon/max6620.c +index 4316dcdd03fc21..100acf357b5f5b 100644 +--- a/drivers/hwmon/max6620.c ++++ b/drivers/hwmon/max6620.c +@@ -474,7 +474,7 @@ static int max6620_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max6620_id[] = { +- { "max6620" }, ++ { .name = "max6620" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max6620_id); +diff --git a/drivers/hwmon/max6621.c b/drivers/hwmon/max6621.c +index a7066f3a0bb4e5..e86ec6d237ca63 100644 +--- a/drivers/hwmon/max6621.c ++++ b/drivers/hwmon/max6621.c +@@ -537,7 +537,7 @@ static int max6621_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max6621_id[] = { +- { MAX6621_DRV_NAME }, ++ { .name = MAX6621_DRV_NAME }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max6621_id); +diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c +index 163d31f17bd49a..dd5f4b3b128dae 100644 +--- a/drivers/hwmon/max6639.c ++++ b/drivers/hwmon/max6639.c +@@ -778,7 +778,7 @@ static int max6639_resume(struct device *dev) + } + + static const struct i2c_device_id max6639_id[] = { +- {"max6639"}, ++ { .name = "max6639" }, + { } + }; + +diff --git a/drivers/hwmon/max6650.c b/drivers/hwmon/max6650.c +index 56b8157885bbfd..f0140ef9c40ee1 100644 +--- a/drivers/hwmon/max6650.c ++++ b/drivers/hwmon/max6650.c +@@ -807,8 +807,8 @@ static int max6650_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max6650_id[] = { +- { "max6650", 1 }, +- { "max6651", 4 }, ++ { .name = "max6650", .driver_data = 1 }, ++ { .name = "max6651", .driver_data = 4 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max6650_id); +diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c +index dd906cf491cae7..c864093f015c02 100644 +--- a/drivers/hwmon/max6697.c ++++ b/drivers/hwmon/max6697.c +@@ -564,16 +564,16 @@ static int max6697_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max6697_id[] = { +- { "max6581", max6581 }, +- { "max6602", max6602 }, +- { "max6622", max6622 }, +- { "max6636", max6636 }, +- { "max6689", max6689 }, +- { "max6693", max6693 }, +- { "max6694", max6694 }, +- { "max6697", max6697 }, +- { "max6698", max6698 }, +- { "max6699", max6699 }, ++ { .name = "max6581", .driver_data = max6581 }, ++ { .name = "max6602", .driver_data = max6602 }, ++ { .name = "max6622", .driver_data = max6622 }, ++ { .name = "max6636", .driver_data = max6636 }, ++ { .name = "max6689", .driver_data = max6689 }, ++ { .name = "max6693", .driver_data = max6693 }, ++ { .name = "max6694", .driver_data = max6694 }, ++ { .name = "max6697", .driver_data = max6697 }, ++ { .name = "max6698", .driver_data = max6698 }, ++ { .name = "max6699", .driver_data = max6699 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max6697_id); +diff --git a/drivers/hwmon/mc34vr500.c b/drivers/hwmon/mc34vr500.c +index 84458e4533d860..8cb9d5c09033f0 100644 +--- a/drivers/hwmon/mc34vr500.c ++++ b/drivers/hwmon/mc34vr500.c +@@ -235,8 +235,8 @@ static int mc34vr500_probe(struct i2c_client *client) + } + + static const struct i2c_device_id mc34vr500_id[] = { +- { "mc34vr500" }, +- { }, ++ { .name = "mc34vr500" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, mc34vr500_id); + +diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c +index bcddf6804d3abe..d6b0ebf27941f5 100644 +--- a/drivers/hwmon/mcp3021.c ++++ b/drivers/hwmon/mcp3021.c +@@ -177,8 +177,8 @@ static int mcp3021_probe(struct i2c_client *client) + } + + static const struct i2c_device_id mcp3021_id[] = { +- { "mcp3021", mcp3021 }, +- { "mcp3221", mcp3221 }, ++ { .name = "mcp3021", .driver_data = mcp3021 }, ++ { .name = "mcp3221", .driver_data = mcp3221 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, mcp3021_id); +diff --git a/drivers/hwmon/nct6775-i2c.c b/drivers/hwmon/nct6775-i2c.c +index ba71d776a2911b..07783910c05882 100644 +--- a/drivers/hwmon/nct6775-i2c.c ++++ b/drivers/hwmon/nct6775-i2c.c +@@ -93,19 +93,19 @@ static const struct of_device_id __maybe_unused nct6775_i2c_of_match[] = { + MODULE_DEVICE_TABLE(of, nct6775_i2c_of_match); + + static const struct i2c_device_id nct6775_i2c_id[] = { +- { "nct6106", nct6106 }, +- { "nct6116", nct6116 }, +- { "nct6775", nct6775 }, +- { "nct6776", nct6776 }, +- { "nct6779", nct6779 }, +- { "nct6791", nct6791 }, +- { "nct6792", nct6792 }, +- { "nct6793", nct6793 }, +- { "nct6795", nct6795 }, +- { "nct6796", nct6796 }, +- { "nct6797", nct6797 }, +- { "nct6798", nct6798 }, +- { "nct6799", nct6799 }, ++ { .name = "nct6106", .driver_data = nct6106 }, ++ { .name = "nct6116", .driver_data = nct6116 }, ++ { .name = "nct6775", .driver_data = nct6775 }, ++ { .name = "nct6776", .driver_data = nct6776 }, ++ { .name = "nct6779", .driver_data = nct6779 }, ++ { .name = "nct6791", .driver_data = nct6791 }, ++ { .name = "nct6792", .driver_data = nct6792 }, ++ { .name = "nct6793", .driver_data = nct6793 }, ++ { .name = "nct6795", .driver_data = nct6795 }, ++ { .name = "nct6796", .driver_data = nct6796 }, ++ { .name = "nct6797", .driver_data = nct6797 }, ++ { .name = "nct6798", .driver_data = nct6798 }, ++ { .name = "nct6799", .driver_data = nct6799 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, nct6775_i2c_id); +diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c +index 8c9351da12c6e7..9c3e169547a9a1 100644 +--- a/drivers/hwmon/nct7802.c ++++ b/drivers/hwmon/nct7802.c +@@ -1193,7 +1193,7 @@ static const unsigned short nct7802_address_list[] = { + }; + + static const struct i2c_device_id nct7802_idtable[] = { +- { "nct7802" }, ++ { .name = "nct7802" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, nct7802_idtable); +diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c +index 2fa091720c79b1..976b8a008e4480 100644 +--- a/drivers/hwmon/nct7904.c ++++ b/drivers/hwmon/nct7904.c +@@ -1146,8 +1146,8 @@ static int nct7904_probe(struct i2c_client *client) + } + + static const struct i2c_device_id nct7904_id[] = { +- {"nct7904"}, +- {} ++ { .name = "nct7904" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, nct7904_id); + +diff --git a/drivers/hwmon/pcf8591.c b/drivers/hwmon/pcf8591.c +index 167d2fe4d5432c..c0220ebfd4b60d 100644 +--- a/drivers/hwmon/pcf8591.c ++++ b/drivers/hwmon/pcf8591.c +@@ -285,7 +285,7 @@ static int pcf8591_read_channel(struct device *dev, int channel) + } + + static const struct i2c_device_id pcf8591_id[] = { +- { "pcf8591" }, ++ { .name = "pcf8591" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, pcf8591_id); +diff --git a/drivers/hwmon/pmbus/acbel-fsg032.c b/drivers/hwmon/pmbus/acbel-fsg032.c +index 9f07fb4abaffd4..d283005d92ae74 100644 +--- a/drivers/hwmon/pmbus/acbel-fsg032.c ++++ b/drivers/hwmon/pmbus/acbel-fsg032.c +@@ -49,8 +49,8 @@ static void acbel_fsg032_init_debugfs(struct i2c_client *client) + } + + static const struct i2c_device_id acbel_fsg032_id[] = { +- { "acbel_fsg032" }, +- {} ++ { .name = "acbel_fsg032" }, ++ { } + }; + + static struct pmbus_driver_info acbel_fsg032_info = { +diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c +index 6f6ad7b20e9a90..360a7730b80701 100644 +--- a/drivers/hwmon/pmbus/adm1266.c ++++ b/drivers/hwmon/pmbus/adm1266.c +@@ -510,7 +510,7 @@ static const struct of_device_id adm1266_of_match[] = { + MODULE_DEVICE_TABLE(of, adm1266_of_match); + + static const struct i2c_device_id adm1266_id[] = { +- { "adm1266" }, ++ { .name = "adm1266" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adm1266_id); +diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c +index 43baa5ded35e50..cf7790bef652dc 100644 +--- a/drivers/hwmon/pmbus/adm1275.c ++++ b/drivers/hwmon/pmbus/adm1275.c +@@ -478,16 +478,16 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) + } + + static const struct i2c_device_id adm1275_id[] = { +- { "adm1075", adm1075 }, +- { "adm1272", adm1272 }, +- { "adm1273", adm1273 }, +- { "adm1275", adm1275 }, +- { "adm1276", adm1276 }, +- { "adm1278", adm1278 }, +- { "adm1281", adm1281 }, +- { "adm1293", adm1293 }, +- { "adm1294", adm1294 }, +- { "mc09c", sq24905c }, ++ { .name = "adm1075", .driver_data = adm1075 }, ++ { .name = "adm1272", .driver_data = adm1272 }, ++ { .name = "adm1273", .driver_data = adm1273 }, ++ { .name = "adm1275", .driver_data = adm1275 }, ++ { .name = "adm1276", .driver_data = adm1276 }, ++ { .name = "adm1278", .driver_data = adm1278 }, ++ { .name = "adm1281", .driver_data = adm1281 }, ++ { .name = "adm1293", .driver_data = adm1293 }, ++ { .name = "adm1294", .driver_data = adm1294 }, ++ { .name = "mc09c", .driver_data = sq24905c }, + { } + }; + MODULE_DEVICE_TABLE(i2c, adm1275_id); +diff --git a/drivers/hwmon/pmbus/bel-pfe.c b/drivers/hwmon/pmbus/bel-pfe.c +index 6499556f735b42..9e3dc9d29c5628 100644 +--- a/drivers/hwmon/pmbus/bel-pfe.c ++++ b/drivers/hwmon/pmbus/bel-pfe.c +@@ -106,9 +106,9 @@ static int pfe_pmbus_probe(struct i2c_client *client) + } + + static const struct i2c_device_id pfe_device_id[] = { +- {"pfe1100", pfe1100}, +- {"pfe3000", pfe3000}, +- {} ++ { .name = "pfe1100", .driver_data = pfe1100 }, ++ { .name = "pfe3000", .driver_data = pfe3000 }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, pfe_device_id); +diff --git a/drivers/hwmon/pmbus/bpa-rs600.c b/drivers/hwmon/pmbus/bpa-rs600.c +index 6c3875ba37a081..e364dcb59dd427 100644 +--- a/drivers/hwmon/pmbus/bpa-rs600.c ++++ b/drivers/hwmon/pmbus/bpa-rs600.c +@@ -147,9 +147,9 @@ static struct pmbus_driver_info bpa_rs600_info = { + }; + + static const struct i2c_device_id bpa_rs600_id[] = { +- { "bpa-rs600", bpa_rs600 }, +- { "bpd-rs600", bpd_rs600 }, +- {}, ++ { .name = "bpa-rs600", .driver_data = bpa_rs600 }, ++ { .name = "bpd-rs600", .driver_data = bpd_rs600 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, bpa_rs600_id); + +diff --git a/drivers/hwmon/pmbus/crps.c b/drivers/hwmon/pmbus/crps.c +index 164b33fed312f6..266ec89475190c 100644 +--- a/drivers/hwmon/pmbus/crps.c ++++ b/drivers/hwmon/pmbus/crps.c +@@ -10,8 +10,8 @@ + #include "pmbus.h" + + static const struct i2c_device_id crps_id[] = { +- { "intel_crps185" }, +- {} ++ { .name = "intel_crps185" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, crps_id); + +diff --git a/drivers/hwmon/pmbus/delta-ahe50dc-fan.c b/drivers/hwmon/pmbus/delta-ahe50dc-fan.c +index 3850eaea75da2a..2df655b20ea57d 100644 +--- a/drivers/hwmon/pmbus/delta-ahe50dc-fan.c ++++ b/drivers/hwmon/pmbus/delta-ahe50dc-fan.c +@@ -103,7 +103,7 @@ static int ahe50dc_fan_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ahe50dc_fan_id[] = { +- { "ahe50dc_fan" }, ++ { .name = "ahe50dc_fan" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ahe50dc_fan_id); +diff --git a/drivers/hwmon/pmbus/dps920ab.c b/drivers/hwmon/pmbus/dps920ab.c +index 325111a955e616..0d2901c314c2b9 100644 +--- a/drivers/hwmon/pmbus/dps920ab.c ++++ b/drivers/hwmon/pmbus/dps920ab.c +@@ -191,8 +191,8 @@ static const struct of_device_id __maybe_unused dps920ab_of_match[] = { + MODULE_DEVICE_TABLE(of, dps920ab_of_match); + + static const struct i2c_device_id dps920ab_device_id[] = { +- { "dps920ab" }, +- {} ++ { .name = "dps920ab" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, dps920ab_device_id); + +diff --git a/drivers/hwmon/pmbus/fsp-3y.c b/drivers/hwmon/pmbus/fsp-3y.c +index cad4d233000365..44cf2db9364b93 100644 +--- a/drivers/hwmon/pmbus/fsp-3y.c ++++ b/drivers/hwmon/pmbus/fsp-3y.c +@@ -271,8 +271,8 @@ static int fsp3y_probe(struct i2c_client *client) + } + + static const struct i2c_device_id fsp3y_id[] = { +- {"ym2151e", ym2151e}, +- {"yh5151e", yh5151e}, ++ { .name = "ym2151e", .driver_data = ym2151e }, ++ { .name = "yh5151e", .driver_data = yh5151e }, + { } + }; + MODULE_DEVICE_TABLE(i2c, fsp3y_id); +diff --git a/drivers/hwmon/pmbus/hac300s.c b/drivers/hwmon/pmbus/hac300s.c +index a073db1cfe2e49..761e53890ebc4b 100644 +--- a/drivers/hwmon/pmbus/hac300s.c ++++ b/drivers/hwmon/pmbus/hac300s.c +@@ -112,8 +112,8 @@ static const struct of_device_id hac300s_of_match[] = { + MODULE_DEVICE_TABLE(of, hac300s_of_match); + + static const struct i2c_device_id hac300s_id[] = { +- {"hac300s", 0}, +- {} ++ { .name = "hac300s" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, hac300s_id); + +diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c +index 6c7256d997f46b..aad94bcb9ceb5f 100644 +--- a/drivers/hwmon/pmbus/ibm-cffps.c ++++ b/drivers/hwmon/pmbus/ibm-cffps.c +@@ -472,10 +472,10 @@ static struct pmbus_platform_data ibm_cffps_pdata = { + }; + + static const struct i2c_device_id ibm_cffps_id[] = { +- { "ibm_cffps1", cffps1 }, +- { "ibm_cffps2", cffps2 }, +- { "ibm_cffps", cffps_unknown }, +- {} ++ { .name = "ibm_cffps1", .driver_data = cffps1 }, ++ { .name = "ibm_cffps2", .driver_data = cffps2 }, ++ { .name = "ibm_cffps", .driver_data = cffps_unknown }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ibm_cffps_id); + +diff --git a/drivers/hwmon/pmbus/ina233.c b/drivers/hwmon/pmbus/ina233.c +index 652087589c55a6..c72aa258b7c678 100644 +--- a/drivers/hwmon/pmbus/ina233.c ++++ b/drivers/hwmon/pmbus/ina233.c +@@ -168,8 +168,8 @@ static int ina233_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ina233_id[] = { +- {"ina233", 0}, +- {} ++ { .name = "ina233" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ina233_id); + +diff --git a/drivers/hwmon/pmbus/inspur-ipsps.c b/drivers/hwmon/pmbus/inspur-ipsps.c +index 074e0f164ee1c9..57c0fc16909cfb 100644 +--- a/drivers/hwmon/pmbus/inspur-ipsps.c ++++ b/drivers/hwmon/pmbus/inspur-ipsps.c +@@ -197,8 +197,8 @@ static int ipsps_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ipsps_id[] = { +- { "ipsps1" }, +- {} ++ { .name = "ipsps1" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ipsps_id); + +diff --git a/drivers/hwmon/pmbus/ir35221.c b/drivers/hwmon/pmbus/ir35221.c +index 46d8f334d49a45..b2120fc76f4092 100644 +--- a/drivers/hwmon/pmbus/ir35221.c ++++ b/drivers/hwmon/pmbus/ir35221.c +@@ -126,8 +126,8 @@ static int ir35221_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ir35221_id[] = { +- {"ir35221"}, +- {} ++ { .name = "ir35221" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, ir35221_id); +diff --git a/drivers/hwmon/pmbus/ir36021.c b/drivers/hwmon/pmbus/ir36021.c +index 34ce15fc708bcd..0dce4c3f666f5a 100644 +--- a/drivers/hwmon/pmbus/ir36021.c ++++ b/drivers/hwmon/pmbus/ir36021.c +@@ -51,8 +51,8 @@ static int ir36021_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ir36021_id[] = { +- { "ir36021" }, +- {}, ++ { .name = "ir36021" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ir36021_id); + +diff --git a/drivers/hwmon/pmbus/ir38064.c b/drivers/hwmon/pmbus/ir38064.c +index 7b4188e8bf4830..47ce88e9d13a31 100644 +--- a/drivers/hwmon/pmbus/ir38064.c ++++ b/drivers/hwmon/pmbus/ir38064.c +@@ -53,11 +53,11 @@ static int ir38064_probe(struct i2c_client *client) + } + + static const struct i2c_device_id ir38064_id[] = { +- {"ir38060"}, +- {"ir38064"}, +- {"ir38164"}, +- {"ir38263"}, +- {} ++ { .name = "ir38060" }, ++ { .name = "ir38064" }, ++ { .name = "ir38164" }, ++ { .name = "ir38263" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, ir38064_id); +diff --git a/drivers/hwmon/pmbus/irps5401.c b/drivers/hwmon/pmbus/irps5401.c +index 43674c64841d5c..1694b96d7abf97 100644 +--- a/drivers/hwmon/pmbus/irps5401.c ++++ b/drivers/hwmon/pmbus/irps5401.c +@@ -44,8 +44,8 @@ static int irps5401_probe(struct i2c_client *client) + } + + static const struct i2c_device_id irps5401_id[] = { +- {"irps5401"}, +- {} ++ { .name = "irps5401" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, irps5401_id); +diff --git a/drivers/hwmon/pmbus/isl68137.c b/drivers/hwmon/pmbus/isl68137.c +index 21d047b577a479..2f7f825bfb69e0 100644 +--- a/drivers/hwmon/pmbus/isl68137.c ++++ b/drivers/hwmon/pmbus/isl68137.c +@@ -409,54 +409,54 @@ static int isl68137_probe(struct i2c_client *client) + } + + static const struct i2c_device_id raa_dmpvr_id[] = { +- {"isl68137", raa_dmpvr1_2rail}, +- {"isl68220", raa_dmpvr2_2rail}, +- {"isl68221", raa_dmpvr2_3rail}, +- {"isl68222", raa_dmpvr2_2rail}, +- {"isl68223", raa_dmpvr2_2rail}, +- {"isl68224", raa_dmpvr2_3rail}, +- {"isl68225", raa_dmpvr2_2rail}, +- {"isl68226", raa_dmpvr2_3rail}, +- {"isl68227", raa_dmpvr2_1rail}, +- {"isl68229", raa_dmpvr2_3rail}, +- {"isl68233", raa_dmpvr2_2rail}, +- {"isl68239", raa_dmpvr2_3rail}, +- +- {"isl69222", raa_dmpvr2_2rail}, +- {"isl69223", raa_dmpvr2_3rail}, +- {"isl69224", raa_dmpvr2_2rail}, +- {"isl69225", raa_dmpvr2_2rail}, +- {"isl69227", raa_dmpvr2_3rail}, +- {"isl69228", raa_dmpvr2_3rail}, +- {"isl69234", raa_dmpvr2_2rail}, +- {"isl69236", raa_dmpvr2_2rail}, +- {"isl69239", raa_dmpvr2_3rail}, +- {"isl69242", raa_dmpvr2_2rail}, +- {"isl69243", raa_dmpvr2_1rail}, +- {"isl69247", raa_dmpvr2_2rail}, +- {"isl69248", raa_dmpvr2_2rail}, +- {"isl69254", raa_dmpvr2_2rail}, +- {"isl69255", raa_dmpvr2_2rail}, +- {"isl69256", raa_dmpvr2_2rail}, +- {"isl69259", raa_dmpvr2_2rail}, +- {"isl69260", raa_dmpvr2_2rail}, +- {"isl69268", raa_dmpvr2_2rail}, +- {"isl69269", raa_dmpvr2_3rail}, +- {"isl69298", raa_dmpvr2_2rail}, +- +- {"raa228000", raa_dmpvr2_hv}, +- {"raa228004", raa_dmpvr2_hv}, +- {"raa228006", raa_dmpvr2_hv}, +- {"raa228228", raa_dmpvr2_2rail_nontc}, +- {"raa228244", raa_dmpvr2_2rail_nontc}, +- {"raa228246", raa_dmpvr2_2rail_nontc}, +- {"raa228942", raa_dmpvr2_2rail_nontc}, +- {"raa228943", raa_dmpvr2_2rail_nontc}, +- {"raa229001", raa_dmpvr2_2rail}, +- {"raa229004", raa_dmpvr2_2rail}, +- {"raa229141", raa_dmpvr2_2rail_pmbus}, +- {"raa229621", raa_dmpvr2_2rail}, +- {} ++ { .name = "isl68137", .driver_data = raa_dmpvr1_2rail }, ++ { .name = "isl68220", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl68221", .driver_data = raa_dmpvr2_3rail }, ++ { .name = "isl68222", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl68223", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl68224", .driver_data = raa_dmpvr2_3rail }, ++ { .name = "isl68225", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl68226", .driver_data = raa_dmpvr2_3rail }, ++ { .name = "isl68227", .driver_data = raa_dmpvr2_1rail }, ++ { .name = "isl68229", .driver_data = raa_dmpvr2_3rail }, ++ { .name = "isl68233", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl68239", .driver_data = raa_dmpvr2_3rail }, ++ ++ { .name = "isl69222", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69223", .driver_data = raa_dmpvr2_3rail }, ++ { .name = "isl69224", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69225", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69227", .driver_data = raa_dmpvr2_3rail }, ++ { .name = "isl69228", .driver_data = raa_dmpvr2_3rail }, ++ { .name = "isl69234", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69236", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69239", .driver_data = raa_dmpvr2_3rail }, ++ { .name = "isl69242", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69243", .driver_data = raa_dmpvr2_1rail }, ++ { .name = "isl69247", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69248", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69254", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69255", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69256", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69259", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69260", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69268", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "isl69269", .driver_data = raa_dmpvr2_3rail }, ++ { .name = "isl69298", .driver_data = raa_dmpvr2_2rail }, ++ ++ { .name = "raa228000", .driver_data = raa_dmpvr2_hv }, ++ { .name = "raa228004", .driver_data = raa_dmpvr2_hv }, ++ { .name = "raa228006", .driver_data = raa_dmpvr2_hv }, ++ { .name = "raa228228", .driver_data = raa_dmpvr2_2rail_nontc }, ++ { .name = "raa228244", .driver_data = raa_dmpvr2_2rail_nontc }, ++ { .name = "raa228246", .driver_data = raa_dmpvr2_2rail_nontc }, ++ { .name = "raa228942", .driver_data = raa_dmpvr2_2rail_nontc }, ++ { .name = "raa228943", .driver_data = raa_dmpvr2_2rail_nontc }, ++ { .name = "raa229001", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "raa229004", .driver_data = raa_dmpvr2_2rail }, ++ { .name = "raa229141", .driver_data = raa_dmpvr2_2rail_pmbus }, ++ { .name = "raa229621", .driver_data = raa_dmpvr2_2rail }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, raa_dmpvr_id); +diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c +index dd7275a67a0abe..0f7df7e2c9c5ba 100644 +--- a/drivers/hwmon/pmbus/lm25066.c ++++ b/drivers/hwmon/pmbus/lm25066.c +@@ -442,11 +442,11 @@ static const struct regulator_desc lm25066_reg_desc[] = { + #endif + + static const struct i2c_device_id lm25066_id[] = { +- {"lm25056", lm25056}, +- {"lm25066", lm25066}, +- {"lm5064", lm5064}, +- {"lm5066", lm5066}, +- {"lm5066i", lm5066i}, ++ { .name = "lm25056", .driver_data = lm25056 }, ++ { .name = "lm25066", .driver_data = lm25066 }, ++ { .name = "lm5064", .driver_data = lm5064 }, ++ { .name = "lm5066", .driver_data = lm5066 }, ++ { .name = "lm5066i", .driver_data = lm5066i }, + { } + }; + MODULE_DEVICE_TABLE(i2c, lm25066_id); +diff --git a/drivers/hwmon/pmbus/lt7182s.c b/drivers/hwmon/pmbus/lt7182s.c +index 9d6d50f39bd653..f8971a786f25aa 100644 +--- a/drivers/hwmon/pmbus/lt7182s.c ++++ b/drivers/hwmon/pmbus/lt7182s.c +@@ -168,8 +168,8 @@ static int lt7182s_probe(struct i2c_client *client) + } + + static const struct i2c_device_id lt7182s_id[] = { +- { "lt7182s" }, +- {} ++ { .name = "lt7182s" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, lt7182s_id); + +diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c +index d69a5e675e80ed..10877b0867fd61 100644 +--- a/drivers/hwmon/pmbus/ltc2978.c ++++ b/drivers/hwmon/pmbus/ltc2978.c +@@ -538,36 +538,36 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page, + } + + static const struct i2c_device_id ltc2978_id[] = { +- {"lt7170", lt7170}, +- {"lt7171", lt7171}, +- {"ltc2972", ltc2972}, +- {"ltc2974", ltc2974}, +- {"ltc2975", ltc2975}, +- {"ltc2977", ltc2977}, +- {"ltc2978", ltc2978}, +- {"ltc2979", ltc2979}, +- {"ltc2980", ltc2980}, +- {"ltc3880", ltc3880}, +- {"ltc3882", ltc3882}, +- {"ltc3883", ltc3883}, +- {"ltc3884", ltc3884}, +- {"ltc3886", ltc3886}, +- {"ltc3887", ltc3887}, +- {"ltc3889", ltc3889}, +- {"ltc7132", ltc7132}, +- {"ltc7841", ltc7841}, +- {"ltc7880", ltc7880}, +- {"ltm2987", ltm2987}, +- {"ltm4664", ltm4664}, +- {"ltm4673", ltm4673}, +- {"ltm4675", ltm4675}, +- {"ltm4676", ltm4676}, +- {"ltm4677", ltm4677}, +- {"ltm4678", ltm4678}, +- {"ltm4680", ltm4680}, +- {"ltm4686", ltm4686}, +- {"ltm4700", ltm4700}, +- {} ++ { .name = "lt7170", .driver_data = lt7170 }, ++ { .name = "lt7171", .driver_data = lt7171 }, ++ { .name = "ltc2972", .driver_data = ltc2972 }, ++ { .name = "ltc2974", .driver_data = ltc2974 }, ++ { .name = "ltc2975", .driver_data = ltc2975 }, ++ { .name = "ltc2977", .driver_data = ltc2977 }, ++ { .name = "ltc2978", .driver_data = ltc2978 }, ++ { .name = "ltc2979", .driver_data = ltc2979 }, ++ { .name = "ltc2980", .driver_data = ltc2980 }, ++ { .name = "ltc3880", .driver_data = ltc3880 }, ++ { .name = "ltc3882", .driver_data = ltc3882 }, ++ { .name = "ltc3883", .driver_data = ltc3883 }, ++ { .name = "ltc3884", .driver_data = ltc3884 }, ++ { .name = "ltc3886", .driver_data = ltc3886 }, ++ { .name = "ltc3887", .driver_data = ltc3887 }, ++ { .name = "ltc3889", .driver_data = ltc3889 }, ++ { .name = "ltc7132", .driver_data = ltc7132 }, ++ { .name = "ltc7841", .driver_data = ltc7841 }, ++ { .name = "ltc7880", .driver_data = ltc7880 }, ++ { .name = "ltm2987", .driver_data = ltm2987 }, ++ { .name = "ltm4664", .driver_data = ltm4664 }, ++ { .name = "ltm4673", .driver_data = ltm4673 }, ++ { .name = "ltm4675", .driver_data = ltm4675 }, ++ { .name = "ltm4676", .driver_data = ltm4676 }, ++ { .name = "ltm4677", .driver_data = ltm4677 }, ++ { .name = "ltm4678", .driver_data = ltm4678 }, ++ { .name = "ltm4680", .driver_data = ltm4680 }, ++ { .name = "ltm4686", .driver_data = ltm4686 }, ++ { .name = "ltm4700", .driver_data = ltm4700 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ltc2978_id); + +diff --git a/drivers/hwmon/pmbus/ltc3815.c b/drivers/hwmon/pmbus/ltc3815.c +index 824c16a75e2c01..0219d03adb0377 100644 +--- a/drivers/hwmon/pmbus/ltc3815.c ++++ b/drivers/hwmon/pmbus/ltc3815.c +@@ -143,7 +143,7 @@ static int ltc3815_write_word_data(struct i2c_client *client, int page, + } + + static const struct i2c_device_id ltc3815_id[] = { +- {"ltc3815"}, ++ { .name = "ltc3815" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, ltc3815_id); +diff --git a/drivers/hwmon/pmbus/max15301.c b/drivers/hwmon/pmbus/max15301.c +index d5810b88ea8d8d..4c36f1ea27ee65 100644 +--- a/drivers/hwmon/pmbus/max15301.c ++++ b/drivers/hwmon/pmbus/max15301.c +@@ -23,10 +23,10 @@ + #include "pmbus.h" + + static const struct i2c_device_id max15301_id[] = { +- { "bmr461" }, +- { "max15301" }, +- { "max15303" }, +- {} ++ { .name = "bmr461" }, ++ { .name = "max15301" }, ++ { .name = "max15303" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, max15301_id); + +diff --git a/drivers/hwmon/pmbus/max16064.c b/drivers/hwmon/pmbus/max16064.c +index eb84915c2a83de..351a1f53599945 100644 +--- a/drivers/hwmon/pmbus/max16064.c ++++ b/drivers/hwmon/pmbus/max16064.c +@@ -91,8 +91,8 @@ static int max16064_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max16064_id[] = { +- {"max16064"}, +- {} ++ { .name = "max16064" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, max16064_id); +diff --git a/drivers/hwmon/pmbus/max16601.c b/drivers/hwmon/pmbus/max16601.c +index 36dc13424d9290..3dd1f6fd003b89 100644 +--- a/drivers/hwmon/pmbus/max16601.c ++++ b/drivers/hwmon/pmbus/max16601.c +@@ -263,11 +263,11 @@ static void max16601_remove(void *_data) + } + + static const struct i2c_device_id max16601_id[] = { +- {"max16508", max16508}, +- {"max16600", max16600}, +- {"max16601", max16601}, +- {"max16602", max16602}, +- {} ++ { .name = "max16508", .driver_data = max16508 }, ++ { .name = "max16600", .driver_data = max16600 }, ++ { .name = "max16601", .driver_data = max16601 }, ++ { .name = "max16602", .driver_data = max16602 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, max16601_id); + +diff --git a/drivers/hwmon/pmbus/max17616.c b/drivers/hwmon/pmbus/max17616.c +index 1d4a0ddb95bb6e..744fa5aefe9388 100644 +--- a/drivers/hwmon/pmbus/max17616.c ++++ b/drivers/hwmon/pmbus/max17616.c +@@ -46,7 +46,7 @@ static int max17616_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max17616_id[] = { +- { "max17616" }, ++ { .name = "max17616" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, max17616_id); +diff --git a/drivers/hwmon/pmbus/max20730.c b/drivers/hwmon/pmbus/max20730.c +index fe03164788dfa2..4031f894e6ae7e 100644 +--- a/drivers/hwmon/pmbus/max20730.c ++++ b/drivers/hwmon/pmbus/max20730.c +@@ -751,11 +751,11 @@ static int max20730_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max20730_id[] = { +- { "max20710", max20710 }, +- { "max20730", max20730 }, +- { "max20734", max20734 }, +- { "max20743", max20743 }, +- { }, ++ { .name = "max20710", .driver_data = max20710 }, ++ { .name = "max20730", .driver_data = max20730 }, ++ { .name = "max20734", .driver_data = max20734 }, ++ { .name = "max20743", .driver_data = max20743 }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, max20730_id); +diff --git a/drivers/hwmon/pmbus/max20751.c b/drivers/hwmon/pmbus/max20751.c +index ac8c431221338b..e85676433dca11 100644 +--- a/drivers/hwmon/pmbus/max20751.c ++++ b/drivers/hwmon/pmbus/max20751.c +@@ -32,8 +32,8 @@ static int max20751_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max20751_id[] = { +- {"max20751"}, +- {} ++ { .name = "max20751" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, max20751_id); +diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c +index 3caa76bcbeb5ea..bdcce810a4792c 100644 +--- a/drivers/hwmon/pmbus/max31785.c ++++ b/drivers/hwmon/pmbus/max31785.c +@@ -447,10 +447,10 @@ static int max31785_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max31785_id[] = { +- { "max31785" }, +- { "max31785a" }, +- { "max31785b" }, +- { }, ++ { .name = "max31785" }, ++ { .name = "max31785a" }, ++ { .name = "max31785b" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, max31785_id); +diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c +index cc96bb22f8f5a0..4525b9fc562674 100644 +--- a/drivers/hwmon/pmbus/max34440.c ++++ b/drivers/hwmon/pmbus/max34440.c +@@ -644,15 +644,15 @@ static int max34440_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max34440_id[] = { +- {"adpm12160", adpm12160}, +- {"adpm12200", adpm12200}, +- {"max34440", max34440}, +- {"max34441", max34441}, +- {"max34446", max34446}, +- {"max34451", max34451}, +- {"max34460", max34460}, +- {"max34461", max34461}, +- {} ++ { .name = "adpm12160", .driver_data = adpm12160 }, ++ { .name = "adpm12200", .driver_data = adpm12200 }, ++ { .name = "max34440", .driver_data = max34440 }, ++ { .name = "max34441", .driver_data = max34441 }, ++ { .name = "max34446", .driver_data = max34446 }, ++ { .name = "max34451", .driver_data = max34451 }, ++ { .name = "max34460", .driver_data = max34460 }, ++ { .name = "max34461", .driver_data = max34461 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, max34440_id); + +diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c +index b3a2a7492bbfcf..212b28fa4bf226 100644 +--- a/drivers/hwmon/pmbus/max8688.c ++++ b/drivers/hwmon/pmbus/max8688.c +@@ -171,7 +171,7 @@ static int max8688_probe(struct i2c_client *client) + } + + static const struct i2c_device_id max8688_id[] = { +- {"max8688"}, ++ { .name = "max8688" }, + { } + }; + +diff --git a/drivers/hwmon/pmbus/mp2856.c b/drivers/hwmon/pmbus/mp2856.c +index e83c70a3583f80..3d6621e36fd398 100644 +--- a/drivers/hwmon/pmbus/mp2856.c ++++ b/drivers/hwmon/pmbus/mp2856.c +@@ -54,9 +54,9 @@ static const int mp2856_max_phases[][MP2856_PAGE_NUM] = { + }; + + static const struct i2c_device_id mp2856_id[] = { +- {"mp2856", mp2856}, +- {"mp2857", mp2857}, +- {} ++ { .name = "mp2856", .driver_data = mp2856 }, ++ { .name = "mp2857", .driver_data = mp2857 }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, mp2856_id); +diff --git a/drivers/hwmon/pmbus/mp2888.c b/drivers/hwmon/pmbus/mp2888.c +index 772a623ca7d0a1..c5f35daa3fe11e 100644 +--- a/drivers/hwmon/pmbus/mp2888.c ++++ b/drivers/hwmon/pmbus/mp2888.c +@@ -378,8 +378,8 @@ static int mp2888_probe(struct i2c_client *client) + } + + static const struct i2c_device_id mp2888_id[] = { +- {"mp2888"}, +- {} ++ { .name = "mp2888" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, mp2888_id); +diff --git a/drivers/hwmon/pmbus/mp2891.c b/drivers/hwmon/pmbus/mp2891.c +index f8f4c91ec23ccd..316c1fc0d6ccf1 100644 +--- a/drivers/hwmon/pmbus/mp2891.c ++++ b/drivers/hwmon/pmbus/mp2891.c +@@ -572,7 +572,7 @@ static int mp2891_probe(struct i2c_client *client) + } + + static const struct i2c_device_id mp2891_id[] = { +- { "mp2891" }, ++ { .name = "mp2891" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, mp2891_id); +diff --git a/drivers/hwmon/pmbus/mp2925.c b/drivers/hwmon/pmbus/mp2925.c +index ad094842cf2d73..0a58b1ffd79108 100644 +--- a/drivers/hwmon/pmbus/mp2925.c ++++ b/drivers/hwmon/pmbus/mp2925.c +@@ -305,9 +305,9 @@ static int mp2925_probe(struct i2c_client *client) + } + + static const struct i2c_device_id mp2925_id[] = { +- {"mp2925"}, +- {"mp2929"}, +- {} ++ { .name = "mp2925" }, ++ { .name = "mp2929" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, mp2925_id); + +diff --git a/drivers/hwmon/pmbus/mp29502.c b/drivers/hwmon/pmbus/mp29502.c +index 7241373f155770..afc5e8c07e2598 100644 +--- a/drivers/hwmon/pmbus/mp29502.c ++++ b/drivers/hwmon/pmbus/mp29502.c +@@ -642,8 +642,8 @@ static int mp29502_probe(struct i2c_client *client) + } + + static const struct i2c_device_id mp29502_id[] = { +- {"mp29502", 0}, +- {} ++ { .name = "mp29502", .driver_data = 0 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, mp29502_id); + +diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c +index d0bc47b12cb07d..dca7e2fbcb441d 100644 +--- a/drivers/hwmon/pmbus/mp2975.c ++++ b/drivers/hwmon/pmbus/mp2975.c +@@ -1082,10 +1082,10 @@ static const struct of_device_id mp2975_of_match[] = { + MODULE_DEVICE_TABLE(of, mp2975_of_match); + + static const struct i2c_device_id mp2975_id[] = { +- {"mp2971", (kernel_ulong_t)&mp2975_ddinfo[mp2971]}, +- {"mp2973", (kernel_ulong_t)&mp2975_ddinfo[mp2973]}, +- {"mp2975", (kernel_ulong_t)&mp2975_ddinfo[mp2975]}, +- {} ++ { .name = "mp2971", .driver_data = (kernel_ulong_t)&mp2975_ddinfo[mp2971] }, ++ { .name = "mp2973", .driver_data = (kernel_ulong_t)&mp2975_ddinfo[mp2973] }, ++ { .name = "mp2975", .driver_data = (kernel_ulong_t)&mp2975_ddinfo[mp2975] }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, mp2975_id); + +diff --git a/drivers/hwmon/pmbus/mp2993.c b/drivers/hwmon/pmbus/mp2993.c +index 81c84fc8ed47d2..3a6a6c55a1f17d 100644 +--- a/drivers/hwmon/pmbus/mp2993.c ++++ b/drivers/hwmon/pmbus/mp2993.c +@@ -233,7 +233,7 @@ static int mp2993_probe(struct i2c_client *client) + } + + static const struct i2c_device_id mp2993_id[] = { +- { "mp2993" }, ++ { .name = "mp2993" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, mp2993_id); +diff --git a/drivers/hwmon/pmbus/mp5920.c b/drivers/hwmon/pmbus/mp5920.c +index 319ae2721bcf45..b803f3ddf8ea17 100644 +--- a/drivers/hwmon/pmbus/mp5920.c ++++ b/drivers/hwmon/pmbus/mp5920.c +@@ -66,7 +66,7 @@ static const struct of_device_id mp5920_of_match[] = { + MODULE_DEVICE_TABLE(of, mp5920_of_match); + + static const struct i2c_device_id mp5920_id[] = { +- { "mp5920" }, ++ { .name = "mp5920" }, + { } + }; + +diff --git a/drivers/hwmon/pmbus/mp5926.c b/drivers/hwmon/pmbus/mp5926.c +index f0d1b30c70134d..a40647472b1601 100644 +--- a/drivers/hwmon/pmbus/mp5926.c ++++ b/drivers/hwmon/pmbus/mp5926.c +@@ -157,8 +157,8 @@ static int mp5926_probe(struct i2c_client *client) + } + + static const struct i2c_device_id mp5926_id[] = { +- { "mp5926", 0 }, +- {} ++ { .name = "mp5926", .driver_data = 0 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, mp5926_id); + +diff --git a/drivers/hwmon/pmbus/mp5990.c b/drivers/hwmon/pmbus/mp5990.c +index 9a4ee79712cfcf..f8a5d1b42ff7ab 100644 +--- a/drivers/hwmon/pmbus/mp5990.c ++++ b/drivers/hwmon/pmbus/mp5990.c +@@ -148,8 +148,8 @@ static struct pmbus_driver_info mp5998_info = { + }; + + static const struct i2c_device_id mp5990_id[] = { +- {"mp5990", mp5990}, +- {"mp5998", mp5998}, ++ { .name = "mp5990", .driver_data = mp5990 }, ++ { .name = "mp5998", .driver_data = mp5998 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, mp5990_id); +diff --git a/drivers/hwmon/pmbus/mp9941.c b/drivers/hwmon/pmbus/mp9941.c +index 42ca6748777afd..d9049d326c809d 100644 +--- a/drivers/hwmon/pmbus/mp9941.c ++++ b/drivers/hwmon/pmbus/mp9941.c +@@ -291,7 +291,7 @@ static int mp9941_probe(struct i2c_client *client) + } + + static const struct i2c_device_id mp9941_id[] = { +- { "mp9941" }, ++ { .name = "mp9941" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, mp9941_id); +diff --git a/drivers/hwmon/pmbus/mp9945.c b/drivers/hwmon/pmbus/mp9945.c +index 34822e0de8128f..199480d855157f 100644 +--- a/drivers/hwmon/pmbus/mp9945.c ++++ b/drivers/hwmon/pmbus/mp9945.c +@@ -215,8 +215,8 @@ static int mp9945_probe(struct i2c_client *client) + } + + static const struct i2c_device_id mp9945_id[] = { +- {"mp9945"}, +- {} ++ { .name = "mp9945" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, mp9945_id); + +diff --git a/drivers/hwmon/pmbus/mpq7932.c b/drivers/hwmon/pmbus/mpq7932.c +index 8f10e37a7a7677..f49610adff89c4 100644 +--- a/drivers/hwmon/pmbus/mpq7932.c ++++ b/drivers/hwmon/pmbus/mpq7932.c +@@ -145,9 +145,9 @@ static const struct of_device_id mpq7932_of_match[] = { + MODULE_DEVICE_TABLE(of, mpq7932_of_match); + + static const struct i2c_device_id mpq7932_id[] = { +- { "mpq2286", }, +- { "mpq7932", }, +- { }, ++ { .name = "mpq2286" }, ++ { .name = "mpq7932" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, mpq7932_id); + +diff --git a/drivers/hwmon/pmbus/mpq8785.c b/drivers/hwmon/pmbus/mpq8785.c +index 87bd039c77b9b3..bbde55028290a9 100644 +--- a/drivers/hwmon/pmbus/mpq8785.c ++++ b/drivers/hwmon/pmbus/mpq8785.c +@@ -110,11 +110,11 @@ static struct pmbus_driver_info mpq8785_info = { + }; + + static const struct i2c_device_id mpq8785_id[] = { +- { "mpm3695", mpm3695 }, +- { "mpm3695-25", mpm3695_25 }, +- { "mpm82504", mpm82504 }, +- { "mpq8785", mpq8785 }, +- { }, ++ { .name = "mpm3695", .driver_data = mpm3695 }, ++ { .name = "mpm3695-25", .driver_data = mpm3695_25 }, ++ { .name = "mpm82504", .driver_data = mpm82504 }, ++ { .name = "mpq8785", .driver_data = mpq8785 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, mpq8785_id); + +diff --git a/drivers/hwmon/pmbus/pim4328.c b/drivers/hwmon/pmbus/pim4328.c +index aa98284bbdd847..9056dc387e878f 100644 +--- a/drivers/hwmon/pmbus/pim4328.c ++++ b/drivers/hwmon/pmbus/pim4328.c +@@ -39,15 +39,15 @@ struct pim4328_data { + #define PIM4328_MFR_READ_STATUS 0xd0 + + static const struct i2c_device_id pim4328_id[] = { +- {"bmr455", pim4328}, +- {"pim4006", pim4006}, +- {"pim4106", pim4006}, +- {"pim4206", pim4006}, +- {"pim4306", pim4006}, +- {"pim4328", pim4328}, +- {"pim4406", pim4006}, +- {"pim4820", pim4820}, +- {} ++ { .name = "bmr455", .driver_data = pim4328 }, ++ { .name = "pim4006", .driver_data = pim4006 }, ++ { .name = "pim4106", .driver_data = pim4006 }, ++ { .name = "pim4206", .driver_data = pim4006 }, ++ { .name = "pim4306", .driver_data = pim4006 }, ++ { .name = "pim4328", .driver_data = pim4328 }, ++ { .name = "pim4406", .driver_data = pim4006 }, ++ { .name = "pim4820", .driver_data = pim4820 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, pim4328_id); + +diff --git a/drivers/hwmon/pmbus/pli1209bc.c b/drivers/hwmon/pmbus/pli1209bc.c +index 569b61dc1a32a6..d5ab085a227303 100644 +--- a/drivers/hwmon/pmbus/pli1209bc.c ++++ b/drivers/hwmon/pmbus/pli1209bc.c +@@ -117,8 +117,8 @@ static int pli1209bc_probe(struct i2c_client *client) + } + + static const struct i2c_device_id pli1209bc_id[] = { +- {"pli1209bc"}, +- {} ++ { .name = "pli1209bc" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, pli1209bc_id); +diff --git a/drivers/hwmon/pmbus/pm6764tr.c b/drivers/hwmon/pmbus/pm6764tr.c +index c96c0aecb920a8..613654b15b4a1f 100644 +--- a/drivers/hwmon/pmbus/pm6764tr.c ++++ b/drivers/hwmon/pmbus/pm6764tr.c +@@ -48,8 +48,8 @@ static int pm6764tr_probe(struct i2c_client *client) + } + + static const struct i2c_device_id pm6764tr_id[] = { +- {"pm6764tr"}, +- {} ++ { .name = "pm6764tr" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, pm6764tr_id); + +diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c +index d1844c7a51eef6..34945ccd3afc67 100644 +--- a/drivers/hwmon/pmbus/pmbus.c ++++ b/drivers/hwmon/pmbus/pmbus.c +@@ -213,36 +213,36 @@ static const struct pmbus_device_info pmbus_info_one_status = { + * Use driver_data to set the number of pages supported by the chip. + */ + static const struct i2c_device_id pmbus_id[] = { +- {"adp4000", (kernel_ulong_t)&pmbus_info_one}, +- {"bmr310", (kernel_ulong_t)&pmbus_info_one_status}, +- {"bmr453", (kernel_ulong_t)&pmbus_info_one}, +- {"bmr454", (kernel_ulong_t)&pmbus_info_one}, +- {"bmr456", (kernel_ulong_t)&pmbus_info_one}, +- {"bmr457", (kernel_ulong_t)&pmbus_info_one}, +- {"bmr458", (kernel_ulong_t)&pmbus_info_one_status}, +- {"bmr480", (kernel_ulong_t)&pmbus_info_one_status}, +- {"bmr490", (kernel_ulong_t)&pmbus_info_one_status}, +- {"bmr491", (kernel_ulong_t)&pmbus_info_one_status}, +- {"bmr492", (kernel_ulong_t)&pmbus_info_one}, +- {"dps460", (kernel_ulong_t)&pmbus_info_one_skip}, +- {"dps650ab", (kernel_ulong_t)&pmbus_info_one_skip}, +- {"dps800", (kernel_ulong_t)&pmbus_info_one_skip}, +- {"max20796", (kernel_ulong_t)&pmbus_info_one}, +- {"mdt040", (kernel_ulong_t)&pmbus_info_one}, +- {"ncp4200", (kernel_ulong_t)&pmbus_info_one}, +- {"ncp4208", (kernel_ulong_t)&pmbus_info_one}, +- {"pdt003", (kernel_ulong_t)&pmbus_info_one}, +- {"pdt006", (kernel_ulong_t)&pmbus_info_one}, +- {"pdt012", (kernel_ulong_t)&pmbus_info_one}, +- {"pmbus", (kernel_ulong_t)&pmbus_info_zero}, +- {"sgd009", (kernel_ulong_t)&pmbus_info_one_skip}, +- {"tps40400", (kernel_ulong_t)&pmbus_info_one}, +- {"tps544b20", (kernel_ulong_t)&pmbus_info_one}, +- {"tps544b25", (kernel_ulong_t)&pmbus_info_one}, +- {"tps544c20", (kernel_ulong_t)&pmbus_info_one}, +- {"tps544c25", (kernel_ulong_t)&pmbus_info_one}, +- {"udt020", (kernel_ulong_t)&pmbus_info_one}, +- {} ++ { .name = "adp4000", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "bmr310", .driver_data = (kernel_ulong_t)&pmbus_info_one_status }, ++ { .name = "bmr453", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "bmr454", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "bmr456", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "bmr457", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "bmr458", .driver_data = (kernel_ulong_t)&pmbus_info_one_status }, ++ { .name = "bmr480", .driver_data = (kernel_ulong_t)&pmbus_info_one_status }, ++ { .name = "bmr490", .driver_data = (kernel_ulong_t)&pmbus_info_one_status }, ++ { .name = "bmr491", .driver_data = (kernel_ulong_t)&pmbus_info_one_status }, ++ { .name = "bmr492", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "dps460", .driver_data = (kernel_ulong_t)&pmbus_info_one_skip }, ++ { .name = "dps650ab", .driver_data = (kernel_ulong_t)&pmbus_info_one_skip }, ++ { .name = "dps800", .driver_data = (kernel_ulong_t)&pmbus_info_one_skip }, ++ { .name = "max20796", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "mdt040", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "ncp4200", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "ncp4208", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "pdt003", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "pdt006", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "pdt012", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "pmbus", .driver_data = (kernel_ulong_t)&pmbus_info_zero }, ++ { .name = "sgd009", .driver_data = (kernel_ulong_t)&pmbus_info_one_skip }, ++ { .name = "tps40400", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "tps544b20", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "tps544b25", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "tps544c20", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "tps544c25", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { .name = "udt020", .driver_data = (kernel_ulong_t)&pmbus_info_one }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, pmbus_id); +diff --git a/drivers/hwmon/pmbus/pxe1610.c b/drivers/hwmon/pmbus/pxe1610.c +index 24c1f961c76689..6ba2b3e0e565b7 100644 +--- a/drivers/hwmon/pmbus/pxe1610.c ++++ b/drivers/hwmon/pmbus/pxe1610.c +@@ -130,10 +130,10 @@ static int pxe1610_probe(struct i2c_client *client) + } + + static const struct i2c_device_id pxe1610_id[] = { +- {"pxe1610"}, +- {"pxe1110"}, +- {"pxm1310"}, +- {} ++ { .name = "pxe1610" }, ++ { .name = "pxe1110" }, ++ { .name = "pxm1310" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, pxe1610_id); +diff --git a/drivers/hwmon/pmbus/q54sj108a2.c b/drivers/hwmon/pmbus/q54sj108a2.c +index a368cfa9d45ac2..ecac405d753620 100644 +--- a/drivers/hwmon/pmbus/q54sj108a2.c ++++ b/drivers/hwmon/pmbus/q54sj108a2.c +@@ -270,10 +270,10 @@ static const struct file_operations q54sj108a2_fops = { + }; + + static const struct i2c_device_id q54sj108a2_id[] = { +- { "q54sj108a2", q54sj108a2 }, +- { "q54sn120a1", q54sj108a2 }, +- { "q54sw120a7", q54sj108a2 }, +- { }, ++ { .name = "q54sj108a2", .driver_data = q54sj108a2 }, ++ { .name = "q54sn120a1", .driver_data = q54sj108a2 }, ++ { .name = "q54sw120a7", .driver_data = q54sj108a2 }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, q54sj108a2_id); +diff --git a/drivers/hwmon/pmbus/stef48h28.c b/drivers/hwmon/pmbus/stef48h28.c +index 4bde2215697cba..8e48dd3ba74bf3 100644 +--- a/drivers/hwmon/pmbus/stef48h28.c ++++ b/drivers/hwmon/pmbus/stef48h28.c +@@ -48,8 +48,8 @@ static int stef48h28_probe(struct i2c_client *client) + } + + static const struct i2c_device_id stef48h28_id[] = { +- {"stef48h28"}, +- {} ++ { .name = "stef48h28" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, stef48h28_id); + +diff --git a/drivers/hwmon/pmbus/stpddc60.c b/drivers/hwmon/pmbus/stpddc60.c +index 5cb905ed8ae5f0..b5ce7f975eea49 100644 +--- a/drivers/hwmon/pmbus/stpddc60.c ++++ b/drivers/hwmon/pmbus/stpddc60.c +@@ -18,9 +18,9 @@ + #define STPDDC60_MFR_UV_LIMIT_OFFSET 0xe6 + + static const struct i2c_device_id stpddc60_id[] = { +- {"stpddc60"}, +- {"bmr481"}, +- {} ++ { .name = "stpddc60" }, ++ { .name = "bmr481" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, stpddc60_id); + +diff --git a/drivers/hwmon/pmbus/tda38640.c b/drivers/hwmon/pmbus/tda38640.c +index d902d39f49f4d7..8039266333700c 100644 +--- a/drivers/hwmon/pmbus/tda38640.c ++++ b/drivers/hwmon/pmbus/tda38640.c +@@ -195,8 +195,8 @@ static int tda38640_probe(struct i2c_client *client) + } + + static const struct i2c_device_id tda38640_id[] = { +- {"tda38640"}, +- {} ++ { .name = "tda38640" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, tda38640_id); + +diff --git a/drivers/hwmon/pmbus/tps25990.c b/drivers/hwmon/pmbus/tps25990.c +index 05c6288ecafccb..9d318e6509abf6 100644 +--- a/drivers/hwmon/pmbus/tps25990.c ++++ b/drivers/hwmon/pmbus/tps25990.c +@@ -387,8 +387,8 @@ static const struct pmbus_driver_info tps25990_base_info = { + }; + + static const struct i2c_device_id tps25990_i2c_id[] = { +- { "tps25990" }, +- {} ++ { .name = "tps25990" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, tps25990_i2c_id); + +diff --git a/drivers/hwmon/pmbus/tps40422.c b/drivers/hwmon/pmbus/tps40422.c +index 7c9fedaa068c0b..f7be075dc70702 100644 +--- a/drivers/hwmon/pmbus/tps40422.c ++++ b/drivers/hwmon/pmbus/tps40422.c +@@ -31,8 +31,8 @@ static int tps40422_probe(struct i2c_client *client) + } + + static const struct i2c_device_id tps40422_id[] = { +- {"tps40422"}, +- {} ++ { .name = "tps40422" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, tps40422_id); +diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c +index 94258e8cfd903b..31e54608b3c9c0 100644 +--- a/drivers/hwmon/pmbus/tps53679.c ++++ b/drivers/hwmon/pmbus/tps53679.c +@@ -291,15 +291,15 @@ static int tps53679_probe(struct i2c_client *client) + } + + static const struct i2c_device_id tps53679_id[] = { +- {"bmr474", tps53676}, +- {"tps53647", tps53647}, +- {"tps53667", tps53667}, +- {"tps53676", tps53676}, +- {"tps53679", tps53679}, +- {"tps53681", tps53681}, +- {"tps53685", tps53685}, +- {"tps53688", tps53688}, +- {} ++ { .name = "bmr474", .driver_data = tps53676 }, ++ { .name = "tps53647", .driver_data = tps53647 }, ++ { .name = "tps53667", .driver_data = tps53667 }, ++ { .name = "tps53676", .driver_data = tps53676 }, ++ { .name = "tps53679", .driver_data = tps53679 }, ++ { .name = "tps53681", .driver_data = tps53681 }, ++ { .name = "tps53685", .driver_data = tps53685 }, ++ { .name = "tps53688", .driver_data = tps53688 }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, tps53679_id); +diff --git a/drivers/hwmon/pmbus/tps546d24.c b/drivers/hwmon/pmbus/tps546d24.c +index 44d7a6df1dbdfc..4222ff355e02b4 100644 +--- a/drivers/hwmon/pmbus/tps546d24.c ++++ b/drivers/hwmon/pmbus/tps546d24.c +@@ -42,8 +42,8 @@ static int tps546d24_probe(struct i2c_client *client) + } + + static const struct i2c_device_id tps546d24_id[] = { +- {"tps546d24"}, +- {} ++ { .name = "tps546d24" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, tps546d24_id); + +diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c +index 9b5d34a110ba5e..f76c2913c9caec 100644 +--- a/drivers/hwmon/pmbus/ucd9000.c ++++ b/drivers/hwmon/pmbus/ucd9000.c +@@ -143,14 +143,14 @@ static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg) + } + + static const struct i2c_device_id ucd9000_id[] = { +- {"ucd9000", ucd9000}, +- {"ucd90120", ucd90120}, +- {"ucd90124", ucd90124}, +- {"ucd90160", ucd90160}, +- {"ucd90320", ucd90320}, +- {"ucd9090", ucd9090}, +- {"ucd90910", ucd90910}, +- {} ++ { .name = "ucd9000", .driver_data = ucd9000 }, ++ { .name = "ucd90120", .driver_data = ucd90120 }, ++ { .name = "ucd90124", .driver_data = ucd90124 }, ++ { .name = "ucd90160", .driver_data = ucd90160 }, ++ { .name = "ucd90320", .driver_data = ucd90320 }, ++ { .name = "ucd9090", .driver_data = ucd9090 }, ++ { .name = "ucd90910", .driver_data = ucd90910 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ucd9000_id); + +diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c +index f68adaf4a110e0..5e07bba111a162 100644 +--- a/drivers/hwmon/pmbus/ucd9200.c ++++ b/drivers/hwmon/pmbus/ucd9200.c +@@ -22,15 +22,15 @@ enum chips { ucd9200, ucd9220, ucd9222, ucd9224, ucd9240, ucd9244, ucd9246, + ucd9248 }; + + static const struct i2c_device_id ucd9200_id[] = { +- {"ucd9200", ucd9200}, +- {"ucd9220", ucd9220}, +- {"ucd9222", ucd9222}, +- {"ucd9224", ucd9224}, +- {"ucd9240", ucd9240}, +- {"ucd9244", ucd9244}, +- {"ucd9246", ucd9246}, +- {"ucd9248", ucd9248}, +- {} ++ { .name = "ucd9200", .driver_data = ucd9200 }, ++ { .name = "ucd9220", .driver_data = ucd9220 }, ++ { .name = "ucd9222", .driver_data = ucd9222 }, ++ { .name = "ucd9224", .driver_data = ucd9224 }, ++ { .name = "ucd9240", .driver_data = ucd9240 }, ++ { .name = "ucd9244", .driver_data = ucd9244 }, ++ { .name = "ucd9246", .driver_data = ucd9246 }, ++ { .name = "ucd9248", .driver_data = ucd9248 }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, ucd9200_id); + +diff --git a/drivers/hwmon/pmbus/xdp710.c b/drivers/hwmon/pmbus/xdp710.c +index 660bbfe16e1e9d..494dbe45ebc6b5 100644 +--- a/drivers/hwmon/pmbus/xdp710.c ++++ b/drivers/hwmon/pmbus/xdp710.c +@@ -110,7 +110,7 @@ static const struct of_device_id xdp710_of_match[] = { + }; + + static const struct i2c_device_id xdp710_id[] = { +- {"xdp710"}, ++ { .name = "xdp710" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, xdp710_id); +diff --git a/drivers/hwmon/pmbus/xdp720.c b/drivers/hwmon/pmbus/xdp720.c +index 8729a771f21667..60491e9217bfb9 100644 +--- a/drivers/hwmon/pmbus/xdp720.c ++++ b/drivers/hwmon/pmbus/xdp720.c +@@ -106,8 +106,8 @@ static const struct of_device_id xdp720_of_match[] = { + MODULE_DEVICE_TABLE(of, xdp720_of_match); + + static const struct i2c_device_id xdp720_id[] = { +- { "xdp720" }, +- {} ++ { .name = "xdp720" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, xdp720_id); + +diff --git a/drivers/hwmon/pmbus/xdpe12284.c b/drivers/hwmon/pmbus/xdpe12284.c +index f3aa6339d60d0f..ed93e17ce8d512 100644 +--- a/drivers/hwmon/pmbus/xdpe12284.c ++++ b/drivers/hwmon/pmbus/xdpe12284.c +@@ -164,10 +164,10 @@ static int xdpe122_probe(struct i2c_client *client) + } + + static const struct i2c_device_id xdpe122_id[] = { +- {"xdpe11280"}, +- {"xdpe12254"}, +- {"xdpe12284"}, +- {} ++ { .name = "xdpe11280" }, ++ { .name = "xdpe12254" }, ++ { .name = "xdpe12284" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, xdpe122_id); +diff --git a/drivers/hwmon/pmbus/xdpe152c4.c b/drivers/hwmon/pmbus/xdpe152c4.c +index 67a3d5fe1dafad..b557d2971d5f24 100644 +--- a/drivers/hwmon/pmbus/xdpe152c4.c ++++ b/drivers/hwmon/pmbus/xdpe152c4.c +@@ -44,9 +44,9 @@ static int xdpe152_probe(struct i2c_client *client) + } + + static const struct i2c_device_id xdpe152_id[] = { +- {"xdpe152c4"}, +- {"xdpe15284"}, +- {} ++ { .name = "xdpe152c4" }, ++ { .name = "xdpe15284" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, xdpe152_id); +diff --git a/drivers/hwmon/pmbus/xdpe1a2g7b.c b/drivers/hwmon/pmbus/xdpe1a2g7b.c +index 1755e3522ede54..971e7b73752ea1 100644 +--- a/drivers/hwmon/pmbus/xdpe1a2g7b.c ++++ b/drivers/hwmon/pmbus/xdpe1a2g7b.c +@@ -87,9 +87,9 @@ static int xdpe1a2g7b_probe(struct i2c_client *client) + } + + static const struct i2c_device_id xdpe1a2g7b_id[] = { +- { "xdpe1a2g5b" }, +- { "xdpe1a2g7b" }, +- {} ++ { .name = "xdpe1a2g5b" }, ++ { .name = "xdpe1a2g7b" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, xdpe1a2g7b_id); +diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c +index 97be69630cfbb4..5db2a7818d165e 100644 +--- a/drivers/hwmon/pmbus/zl6100.c ++++ b/drivers/hwmon/pmbus/zl6100.c +@@ -250,28 +250,28 @@ static int zl6100_write_word_data(struct i2c_client *client, int page, int reg, + } + + static const struct i2c_device_id zl6100_id[] = { +- {"bmr450", zl2005}, +- {"bmr451", zl2005}, +- {"bmr462", zl2008}, +- {"bmr463", zl2008}, +- {"bmr464", zl2008}, +- {"bmr465", zls4009}, +- {"bmr466", zls1003}, +- {"bmr467", zls4009}, +- {"bmr469", zl8802}, +- {"zl2004", zl2004}, +- {"zl2005", zl2005}, +- {"zl2006", zl2006}, +- {"zl2008", zl2008}, +- {"zl2105", zl2105}, +- {"zl2106", zl2106}, +- {"zl6100", zl6100}, +- {"zl6105", zl6105}, +- {"zl8802", zl8802}, +- {"zl9101", zl9101}, +- {"zl9117", zl9117}, +- {"zls1003", zls1003}, +- {"zls4009", zls4009}, ++ { .name = "bmr450", .driver_data = zl2005 }, ++ { .name = "bmr451", .driver_data = zl2005 }, ++ { .name = "bmr462", .driver_data = zl2008 }, ++ { .name = "bmr463", .driver_data = zl2008 }, ++ { .name = "bmr464", .driver_data = zl2008 }, ++ { .name = "bmr465", .driver_data = zls4009 }, ++ { .name = "bmr466", .driver_data = zls1003 }, ++ { .name = "bmr467", .driver_data = zls4009 }, ++ { .name = "bmr469", .driver_data = zl8802 }, ++ { .name = "zl2004", .driver_data = zl2004 }, ++ { .name = "zl2005", .driver_data = zl2005 }, ++ { .name = "zl2006", .driver_data = zl2006 }, ++ { .name = "zl2008", .driver_data = zl2008 }, ++ { .name = "zl2105", .driver_data = zl2105 }, ++ { .name = "zl2106", .driver_data = zl2106 }, ++ { .name = "zl6100", .driver_data = zl6100 }, ++ { .name = "zl6105", .driver_data = zl6105 }, ++ { .name = "zl8802", .driver_data = zl8802 }, ++ { .name = "zl9101", .driver_data = zl9101 }, ++ { .name = "zl9117", .driver_data = zl9117 }, ++ { .name = "zls1003", .driver_data = zls1003 }, ++ { .name = "zls4009", .driver_data = zls4009 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, zl6100_id); +diff --git a/drivers/hwmon/powr1220.c b/drivers/hwmon/powr1220.c +index 06a2c56016d117..6e211601ea26b7 100644 +--- a/drivers/hwmon/powr1220.c ++++ b/drivers/hwmon/powr1220.c +@@ -306,8 +306,8 @@ static int powr1220_probe(struct i2c_client *client) + } + + static const struct i2c_device_id powr1220_ids[] = { +- { "powr1014", powr1014, }, +- { "powr1220", powr1220, }, ++ { .name = "powr1014", .driver_data = powr1014 }, ++ { .name = "powr1220", .driver_data = powr1220 }, + { } + }; + +diff --git a/drivers/hwmon/pt5161l.c b/drivers/hwmon/pt5161l.c +index 89d4da8aa4c093..2b408a69b085c1 100644 +--- a/drivers/hwmon/pt5161l.c ++++ b/drivers/hwmon/pt5161l.c +@@ -617,8 +617,8 @@ static const struct acpi_device_id __maybe_unused pt5161l_acpi_match[] = { + MODULE_DEVICE_TABLE(acpi, pt5161l_acpi_match); + + static const struct i2c_device_id pt5161l_id[] = { +- { "pt5161l" }, +- {} ++ { .name = "pt5161l" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, pt5161l_id); + +diff --git a/drivers/hwmon/sbtsi_temp.c b/drivers/hwmon/sbtsi_temp.c +index c5b2488c4c7f74..c28f8625cd3a49 100644 +--- a/drivers/hwmon/sbtsi_temp.c ++++ b/drivers/hwmon/sbtsi_temp.c +@@ -221,8 +221,8 @@ static int sbtsi_probe(struct i2c_client *client) + } + + static const struct i2c_device_id sbtsi_id[] = { +- {"sbtsi"}, +- {} ++ { .name = "sbtsi" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, sbtsi_id); + +diff --git a/drivers/hwmon/sg2042-mcu.c b/drivers/hwmon/sg2042-mcu.c +index 105131c4acf787..591f5f572fe4ce 100644 +--- a/drivers/hwmon/sg2042-mcu.c ++++ b/drivers/hwmon/sg2042-mcu.c +@@ -333,7 +333,7 @@ static int sg2042_mcu_i2c_probe(struct i2c_client *client) + } + + static const struct i2c_device_id sg2042_mcu_id[] = { +- { "sg2042-hwmon-mcu" }, ++ { .name = "sg2042-hwmon-mcu" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, sg2042_mcu_id); +diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c +index 627d35070a420a..085492669eeb99 100644 +--- a/drivers/hwmon/sht21.c ++++ b/drivers/hwmon/sht21.c +@@ -275,9 +275,9 @@ static int sht21_probe(struct i2c_client *client) + + /* Device ID table */ + static const struct i2c_device_id sht21_id[] = { +- { "sht20" }, +- { "sht21" }, +- { "sht25" }, ++ { .name = "sht20" }, ++ { .name = "sht21" }, ++ { .name = "sht25" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, sht21_id); +diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c +index 08306ccb6d0bef..c2f6b73aa7f34a 100644 +--- a/drivers/hwmon/sht3x.c ++++ b/drivers/hwmon/sht3x.c +@@ -931,10 +931,10 @@ static int sht3x_probe(struct i2c_client *client) + + /* device ID table */ + static const struct i2c_device_id sht3x_ids[] = { +- {"sht3x", sht3x}, +- {"sts3x", sts3x}, +- {"sht85", sht3x}, +- {} ++ { .name = "sht3x", .driver_data = sht3x }, ++ { .name = "sts3x", .driver_data = sts3x }, ++ { .name = "sht85", .driver_data = sht3x }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, sht3x_ids); +diff --git a/drivers/hwmon/sht4x.c b/drivers/hwmon/sht4x.c +index 5abe1227e109ed..9cace0e8acdabc 100644 +--- a/drivers/hwmon/sht4x.c ++++ b/drivers/hwmon/sht4x.c +@@ -424,8 +424,8 @@ static int sht4x_probe(struct i2c_client *client) + } + + static const struct i2c_device_id sht4x_id[] = { +- { "sht4x" }, +- { }, ++ { .name = "sht4x" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, sht4x_id); + +diff --git a/drivers/hwmon/shtc1.c b/drivers/hwmon/shtc1.c +index 2ac906e8e17332..362a73cf661b20 100644 +--- a/drivers/hwmon/shtc1.c ++++ b/drivers/hwmon/shtc1.c +@@ -257,9 +257,9 @@ static int shtc1_probe(struct i2c_client *client) + + /* device ID table */ + static const struct i2c_device_id shtc1_id[] = { +- { "shtc1", shtc1 }, +- { "shtw1", shtc1 }, +- { "shtc3", shtc3 }, ++ { .name = "shtc1", .driver_data = shtc1 }, ++ { .name = "shtw1", .driver_data = shtc1 }, ++ { .name = "shtc3", .driver_data = shtc3 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, shtc1_id); +diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c +index 21103af4e1395a..1429b66e09b07d 100644 +--- a/drivers/hwmon/smsc47m192.c ++++ b/drivers/hwmon/smsc47m192.c +@@ -618,7 +618,7 @@ static int smsc47m192_probe(struct i2c_client *client) + } + + static const struct i2c_device_id smsc47m192_id[] = { +- { "smsc47m192" }, ++ { .name = "smsc47m192" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, smsc47m192_id); +diff --git a/drivers/hwmon/spd5118.c b/drivers/hwmon/spd5118.c +index 5da44571b6a0ce..cc40661cab211a 100644 +--- a/drivers/hwmon/spd5118.c ++++ b/drivers/hwmon/spd5118.c +@@ -746,7 +746,7 @@ static int spd5118_i2c_probe(struct i2c_client *client) + } + + static const struct i2c_device_id spd5118_i2c_id[] = { +- { "spd5118" }, ++ { .name = "spd5118" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, spd5118_i2c_id); +diff --git a/drivers/hwmon/stts751.c b/drivers/hwmon/stts751.c +index f9e8b2869164a3..ce23681f79810a 100644 +--- a/drivers/hwmon/stts751.c ++++ b/drivers/hwmon/stts751.c +@@ -72,7 +72,7 @@ static const int stts751_intervals[] = { + }; + + static const struct i2c_device_id stts751_id[] = { +- { "stts751" }, ++ { .name = "stts751" }, + { } + }; + +diff --git a/drivers/hwmon/tc654.c b/drivers/hwmon/tc654.c +index 39fe5836f237f2..4b22e305b203ea 100644 +--- a/drivers/hwmon/tc654.c ++++ b/drivers/hwmon/tc654.c +@@ -550,9 +550,9 @@ static int tc654_probe(struct i2c_client *client) + } + + static const struct i2c_device_id tc654_id[] = { +- {"tc654"}, +- {"tc655"}, +- {} ++ { .name = "tc654" }, ++ { .name = "tc655" }, ++ { } + }; + + MODULE_DEVICE_TABLE(i2c, tc654_id); +diff --git a/drivers/hwmon/tc74.c b/drivers/hwmon/tc74.c +index 7fb7b50ad1adbf..e9113519be5355 100644 +--- a/drivers/hwmon/tc74.c ++++ b/drivers/hwmon/tc74.c +@@ -151,8 +151,8 @@ static int tc74_probe(struct i2c_client *client) + } + + static const struct i2c_device_id tc74_id[] = { +- { "tc74" }, +- {} ++ { .name = "tc74" }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, tc74_id); + +diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c +index 0cbdb91698b1f7..b385ef64af7542 100644 +--- a/drivers/hwmon/thmc50.c ++++ b/drivers/hwmon/thmc50.c +@@ -407,8 +407,8 @@ static int thmc50_probe(struct i2c_client *client) + } + + static const struct i2c_device_id thmc50_id[] = { +- { "adm1022", adm1022 }, +- { "thmc50", thmc50 }, ++ { .name = "adm1022", .driver_data = adm1022 }, ++ { .name = "thmc50", .driver_data = thmc50 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, thmc50_id); +diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c +index 3aa1a3fbeaa92d..500286676174ee 100644 +--- a/drivers/hwmon/tmp102.c ++++ b/drivers/hwmon/tmp102.c +@@ -395,7 +395,7 @@ static int tmp102_resume(struct device *dev) + static DEFINE_SIMPLE_DEV_PM_OPS(tmp102_dev_pm_ops, tmp102_suspend, tmp102_resume); + + static const struct i2c_device_id tmp102_id[] = { +- { "tmp102" }, ++ { .name = "tmp102" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, tmp102_id); +diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c +index 221bba8a215d83..f13d2476757514 100644 +--- a/drivers/hwmon/tmp103.c ++++ b/drivers/hwmon/tmp103.c +@@ -194,7 +194,7 @@ static int tmp103_resume(struct device *dev) + static DEFINE_SIMPLE_DEV_PM_OPS(tmp103_dev_pm_ops, tmp103_suspend, tmp103_resume); + + static const struct i2c_device_id tmp103_id[] = { +- { "tmp103" }, ++ { .name = "tmp103" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, tmp103_id); +diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c +index 3ea5f6485744d7..1c4a58855e2d27 100644 +--- a/drivers/hwmon/tmp108.c ++++ b/drivers/hwmon/tmp108.c +@@ -537,10 +537,10 @@ static int tmp108_resume(struct device *dev) + static DEFINE_SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume); + + static const struct i2c_device_id tmp108_i2c_ids[] = { +- { "p3t1035", (unsigned long)&p3t1035_data }, +- { "p3t1085", (unsigned long)&tmp108_data }, +- { "tmp108", (unsigned long)&tmp108_data }, +- {} ++ { .name = "p3t1035", .driver_data = (unsigned long)&p3t1035_data }, ++ { .name = "p3t1085", .driver_data = (unsigned long)&tmp108_data }, ++ { .name = "tmp108", .driver_data = (unsigned long)&tmp108_data }, ++ { } + }; + MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids); + +diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c +index 07f596581c6eb7..a09225a87355dd 100644 +--- a/drivers/hwmon/tmp401.c ++++ b/drivers/hwmon/tmp401.c +@@ -90,11 +90,11 @@ static const u8 TMP432_STATUS_REG[] = { + */ + + static const struct i2c_device_id tmp401_id[] = { +- { "tmp401", tmp401 }, +- { "tmp411", tmp411 }, +- { "tmp431", tmp431 }, +- { "tmp432", tmp432 }, +- { "tmp435", tmp435 }, ++ { .name = "tmp401", .driver_data = tmp401 }, ++ { .name = "tmp411", .driver_data = tmp411 }, ++ { .name = "tmp431", .driver_data = tmp431 }, ++ { .name = "tmp432", .driver_data = tmp432 }, ++ { .name = "tmp435", .driver_data = tmp435 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, tmp401_id); +diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c +index 2ea9d3e9553db8..ed00ccfdd7b3ee 100644 +--- a/drivers/hwmon/tmp421.c ++++ b/drivers/hwmon/tmp421.c +@@ -56,11 +56,11 @@ static const u8 TMP421_TEMP_LSB[MAX_CHANNELS] = { 0x10, 0x11, 0x12, 0x13 }; + #define TMP442_DEVICE_ID 0x42 + + static const struct i2c_device_id tmp421_id[] = { +- { "tmp421", 2 }, +- { "tmp422", 3 }, +- { "tmp423", 4 }, +- { "tmp441", 2 }, +- { "tmp442", 3 }, ++ { .name = "tmp421", .driver_data = 2 }, ++ { .name = "tmp422", .driver_data = 3 }, ++ { .name = "tmp423", .driver_data = 4 }, ++ { .name = "tmp441", .driver_data = 2 }, ++ { .name = "tmp442", .driver_data = 3 }, + { } + }; + MODULE_DEVICE_TABLE(i2c, tmp421_id); +diff --git a/drivers/hwmon/tmp464.c b/drivers/hwmon/tmp464.c +index 98f2576d94c670..c3e031044d1e71 100644 +--- a/drivers/hwmon/tmp464.c ++++ b/drivers/hwmon/tmp464.c +@@ -65,8 +65,8 @@ static const u8 TMP464_THERM2_LIMIT[MAX_CHANNELS] = { + #define TMP468_DEVICE_ID 0x0468 + + static const struct i2c_device_id tmp464_id[] = { +- { "tmp464", TMP464_NUM_CHANNELS }, +- { "tmp468", TMP468_NUM_CHANNELS }, ++ { .name = "tmp464", .driver_data = TMP464_NUM_CHANNELS }, ++ { .name = "tmp468", .driver_data = TMP468_NUM_CHANNELS }, + { } + }; + MODULE_DEVICE_TABLE(i2c, tmp464_id); +diff --git a/drivers/hwmon/tmp513.c b/drivers/hwmon/tmp513.c +index 5acbfd7d088dd5..b160aa045f89dd 100644 +--- a/drivers/hwmon/tmp513.c ++++ b/drivers/hwmon/tmp513.c +@@ -611,8 +611,8 @@ static int tmp51x_init(struct tmp51x_data *data) + } + + static const struct i2c_device_id tmp51x_id[] = { +- { "tmp512", TMP512_MAX_CHANNELS }, +- { "tmp513", TMP513_MAX_CHANNELS }, ++ { .name = "tmp512", .driver_data = TMP512_MAX_CHANNELS }, ++ { .name = "tmp513", .driver_data = TMP513_MAX_CHANNELS }, + { } + }; + MODULE_DEVICE_TABLE(i2c, tmp51x_id); +diff --git a/drivers/hwmon/w83773g.c b/drivers/hwmon/w83773g.c +index 401a28f55f931f..54224dac10aef6 100644 +--- a/drivers/hwmon/w83773g.c ++++ b/drivers/hwmon/w83773g.c +@@ -34,7 +34,7 @@ static const u8 W83773_OFFSET_MSB[2] = { 0x11, 0x15 }; + + /* this is the number of sensors in the device */ + static const struct i2c_device_id w83773_id[] = { +- { "w83773g" }, ++ { .name = "w83773g" }, + { } + }; + +diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c +index f664c2152a6dee..c40f84e5346964 100644 +--- a/drivers/hwmon/w83781d.c ++++ b/drivers/hwmon/w83781d.c +@@ -1559,10 +1559,10 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) + } + + static const struct i2c_device_id w83781d_ids[] = { +- { "w83781d", w83781d, }, +- { "w83782d", w83782d, }, +- { "w83783s", w83783s, }, +- { "as99127f", as99127f }, ++ { .name = "w83781d", .driver_data = w83781d }, ++ { .name = "w83782d", .driver_data = w83782d }, ++ { .name = "w83783s", .driver_data = w83783s }, ++ { .name = "as99127f", .driver_data = as99127f }, + { /* LIST END */ } + }; + MODULE_DEVICE_TABLE(i2c, w83781d_ids); +diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c +index 996e36951f9dad..4a777430af5cd4 100644 +--- a/drivers/hwmon/w83791d.c ++++ b/drivers/hwmon/w83791d.c +@@ -333,7 +333,7 @@ static void w83791d_print_debug(struct w83791d_data *data, struct device *dev); + static void w83791d_init_client(struct i2c_client *client); + + static const struct i2c_device_id w83791d_id[] = { +- { "w83791d" }, ++ { .name = "w83791d" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, w83791d_id); +diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c +index b0b5f60eea53bc..f715c79389a565 100644 +--- a/drivers/hwmon/w83792d.c ++++ b/drivers/hwmon/w83792d.c +@@ -296,7 +296,7 @@ static void w83792d_print_debug(struct w83792d_data *data, struct device *dev); + static void w83792d_init_client(struct i2c_client *client); + + static const struct i2c_device_id w83792d_id[] = { +- { "w83792d" }, ++ { .name = "w83792d" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, w83792d_id); +diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c +index 8726c5fe8a952e..a548586369e1db 100644 +--- a/drivers/hwmon/w83793.c ++++ b/drivers/hwmon/w83793.c +@@ -291,7 +291,7 @@ static void w83793_update_nonvolatile(struct device *dev); + static struct w83793_data *w83793_update_device(struct device *dev); + + static const struct i2c_device_id w83793_id[] = { +- { "w83793" }, ++ { .name = "w83793" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, w83793_id); +diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c +index 5174db69db5e1c..c5ce0bf1b08ecf 100644 +--- a/drivers/hwmon/w83795.c ++++ b/drivers/hwmon/w83795.c +@@ -2243,8 +2243,8 @@ static void w83795_remove(struct i2c_client *client) + + + static const struct i2c_device_id w83795_id[] = { +- { "w83795g", w83795g }, +- { "w83795adg", w83795adg }, ++ { .name = "w83795g", .driver_data = w83795g }, ++ { .name = "w83795adg", .driver_data = w83795adg }, + { } + }; + MODULE_DEVICE_TABLE(i2c, w83795_id); +diff --git a/drivers/hwmon/w83l785ts.c b/drivers/hwmon/w83l785ts.c +index df77b53a1b2f9c..e42506a3bcbeca 100644 +--- a/drivers/hwmon/w83l785ts.c ++++ b/drivers/hwmon/w83l785ts.c +@@ -74,7 +74,7 @@ static struct w83l785ts_data *w83l785ts_update_device(struct device *dev); + */ + + static const struct i2c_device_id w83l785ts_id[] = { +- { "w83l785ts" }, ++ { .name = "w83l785ts" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, w83l785ts_id); +diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c +index 1d9109ca1585e7..a72397083cc4fe 100644 +--- a/drivers/hwmon/w83l786ng.c ++++ b/drivers/hwmon/w83l786ng.c +@@ -751,7 +751,7 @@ w83l786ng_probe(struct i2c_client *client) + } + + static const struct i2c_device_id w83l786ng_id[] = { +- { "w83l786ng" }, ++ { .name = "w83l786ng" }, + { } + }; + MODULE_DEVICE_TABLE(i2c, w83l786ng_id); +-- +2.53.0 + diff --git a/queue-7.1/ice-allow-creating-vfs-when-config_ice_switchdev.patch b/queue-7.1/ice-allow-creating-vfs-when-config_ice_switchdev.patch new file mode 100644 index 0000000000..10dc055051 --- /dev/null +++ b/queue-7.1/ice-allow-creating-vfs-when-config_ice_switchdev.patch @@ -0,0 +1,90 @@ +From e0956c3a829adc459b78d7b71a03e79a4783fd55 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:53:23 -0700 +Subject: ice: allow creating VFs when !CONFIG_ICE_SWITCHDEV + +From: Vincent Chen + +[ Upstream commit 99d0f42b0e5c57e4c02070a908aaff082881293a ] + +Currently ice_eswitch_attach_vf() is called unconditionally in +ice_start_vfs(), which causes VF creation to fail when CONFIG_ICE_SWITCHDEV +is not defined. + +Fix this by adding switchdev mode checks at the call sites before +calling ice_eswitch_attach_vf(), consistent with how +ice_eswitch_attach_sf() is already handled in ice_devlink_port_new(). +This is similar to commit aacca7a83b97 ("ice: allow creating VFs for +!CONFIG_NET_SWITCHDEV") which fixed the same issue for the previous +ice_eswitch_configure() API. + +Fixes: 415db8399d06 ("ice: make representor code generic") +Signed-off-by: Vincent Chen +Reviewed-by: Aleksandr Loktionov +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260717185340.3595286-2-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_eswitch.c | 3 --- + drivers/net/ethernet/intel/ice/ice_sriov.c | 14 ++++++++------ + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 3 ++- + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c +index c30e27bbfe6e25..b069e6c514fb12 100644 +--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c ++++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c +@@ -512,9 +512,6 @@ int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf) + struct ice_repr *repr; + int err; + +- if (!ice_is_eswitch_mode_switchdev(pf)) +- return 0; +- + repr = ice_repr_create_vf(vf); + if (IS_ERR(repr)) + return PTR_ERR(repr); +diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c +index 7e00e091756ddc..e04de021559665 100644 +--- a/drivers/net/ethernet/intel/ice/ice_sriov.c ++++ b/drivers/net/ethernet/intel/ice/ice_sriov.c +@@ -484,12 +484,14 @@ static int ice_start_vfs(struct ice_pf *pf) + goto teardown; + } + +- retval = ice_eswitch_attach_vf(pf, vf); +- if (retval) { +- dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d", +- vf->vf_id, retval); +- ice_vf_vsi_release(vf); +- goto teardown; ++ if (ice_is_eswitch_mode_switchdev(pf)) { ++ retval = ice_eswitch_attach_vf(pf, vf); ++ if (retval) { ++ dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d", ++ vf->vf_id, retval); ++ ice_vf_vsi_release(vf); ++ goto teardown; ++ } + } + + set_bit(ICE_VF_STATE_INIT, vf->vf_states); +diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +index 27e4acb1620f0c..9052e71e9c99e3 100644 +--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c +@@ -812,7 +812,8 @@ void ice_reset_all_vfs(struct ice_pf *pf) + } + ice_vf_post_vsi_rebuild(vf); + +- ice_eswitch_attach_vf(pf, vf); ++ if (ice_is_eswitch_mode_switchdev(pf)) ++ ice_eswitch_attach_vf(pf, vf); + + mutex_unlock(&vf->cfg_lock); + } +-- +2.53.0 + diff --git a/queue-7.1/ice-fix-lag-recipe-to-profile-association.patch b/queue-7.1/ice-fix-lag-recipe-to-profile-association.patch new file mode 100644 index 0000000000..2f784ca57c --- /dev/null +++ b/queue-7.1/ice-fix-lag-recipe-to-profile-association.patch @@ -0,0 +1,49 @@ +From 4caedd8ebfbd4d4a15e8a24fa9725d642d59e7cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:53:28 -0700 +Subject: ice: fix LAG recipe to profile association + +From: Marcin Szycik + +[ Upstream commit d6da9b7d48599db078aea6144997a381f8d90d45 ] + +ice_init_lag() associates recipes to profiles, assuming that Link +Aggregation-related profiles will always have profile ID lower than 70 +(ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER). This value seems arbitrary and +might not always be valid for some versions of DDP package, i.e. LAG +profiles may have profile ID greater than 70. This would lead to +misconfigured switch and LAG not working properly. + +Fix it by checking up to maximum profile ID. + +Fixes: 1e0f9881ef79 ("ice: Flesh out implementation of support for SRIOV on bonded interface") +Signed-off-by: Marcin Szycik +Reviewed-by: Michal Swiatkowski +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Dave Ertman +Reviewed-by: Simon Horman +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260717185340.3595286-7-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice_lag.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c +index 310e8fe2925c7d..08a17ded0ad556 100644 +--- a/drivers/net/ethernet/intel/ice/ice_lag.c ++++ b/drivers/net/ethernet/intel/ice/ice_lag.c +@@ -2623,7 +2623,7 @@ int ice_init_lag(struct ice_pf *pf) + goto free_lport_res; + + /* associate recipes to profiles */ +- for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) { ++ for (n = 0; n < ICE_MAX_NUM_PROFILES; n++) { + err = ice_aq_get_recipe_to_profile(&pf->hw, n, + &recipe_bits, NULL); + if (err) +-- +2.53.0 + diff --git a/queue-7.1/ice-prevent-tstamp-ring-allocation-for-non-pf-vsi-ty.patch b/queue-7.1/ice-prevent-tstamp-ring-allocation-for-non-pf-vsi-ty.patch new file mode 100644 index 0000000000..b9ada75b03 --- /dev/null +++ b/queue-7.1/ice-prevent-tstamp-ring-allocation-for-non-pf-vsi-ty.patch @@ -0,0 +1,62 @@ +From aeae3f7f6cd6d19604a55ec7b5b0fe8955365285 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:53:32 -0700 +Subject: ice: prevent tstamp ring allocation for non-PF VSI types + +From: Paul Greenwalt + +[ Upstream commit 144539bbfd3cea1ab0fb6f5216d6004c1f4f029b ] + +The pf->txtime_txqs bitmap tracks which Tx queues have ETF (Earliest +TxTime First) offload enabled. This bitmap is indexed by queue number +and is set by ice_offload_txtime(), which only operates on PF VSI +queues. + +However, ice_is_txtime_ena() does not check the VSI type before +consulting the bitmap. When ETF offload is enabled on PF Tx queue 0, +bit 0 is set in pf->txtime_txqs. During a subsequent PCI reset +rebuild, the CTRL VSI's Tx queue 0 is reconfigured and +ice_is_txtime_ena() is called for that ring. Since it only checks +pf->txtime_txqs by queue index without distinguishing VSI type, it +finds bit 0 set and returns true, matching the PF VSI's ETF queue, +not the CTRL VSI's. This causes ice_vsi_cfg_txq() to spuriously +allocate a tstamp_ring for the CTRL VSI ring. + +Since CTRL VSI rings have no associated netdev, ice_clean_tx_ring() +takes an early return at the !netdev check before reaching +ice_free_tx_tstamp_ring(), leaking the allocation. Each PCI reset +leaks one 64-byte tstamp_ring. + +Fix this by restricting ice_is_txtime_ena() to return true only for +PF VSI rings, since txtime_txqs is only meaningful for PF VSI queues. + +Fixes: ccde82e90946 ("ice: add E830 Earliest TxTime First Offload support") +Signed-off-by: Paul Greenwalt +Reviewed-by: Przemek Kitszel +Reviewed-by: Aleksandr Loktionov +Tested-by: Rinitha S (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260717185340.3595286-11-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ice/ice.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h +index 725b130dd3a2c6..f6671a653f21f2 100644 +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -767,6 +767,9 @@ static inline bool ice_is_txtime_ena(const struct ice_tx_ring *ring) + struct ice_vsi *vsi = ring->vsi; + struct ice_pf *pf = vsi->back; + ++ if (vsi->type != ICE_VSI_PF) ++ return false; ++ + return test_bit(ring->q_index, pf->txtime_txqs); + } + +-- +2.53.0 + diff --git a/queue-7.1/idpf-fix-max_vport-related-crash-on-allocation-error.patch b/queue-7.1/idpf-fix-max_vport-related-crash-on-allocation-error.patch new file mode 100644 index 0000000000..90e30a93f7 --- /dev/null +++ b/queue-7.1/idpf-fix-max_vport-related-crash-on-allocation-error.patch @@ -0,0 +1,91 @@ +From 24e46d29dbccb25ea22018e7ee5f4214b32a513c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:53:34 -0700 +Subject: idpf: fix max_vport related crash on allocation error during init + +From: Emil Tantilov + +[ Upstream commit 237f1f7653b8729169af11fae79f01b90d00b87e ] + +Set adapter->max_vports only after successful allocation of vports, netdevs +and vport_config buffers. This fixes possible crashes on reset or rmmod, +following failed allocation on init + +[ 305.981402] idpf 0000:83:00.0: enabling device (0100 -> 0102) +[ 305.994464] idpf 0000:83:00.0: Device HW Reset initiated +[ 320.416872] BUG: kernel NULL pointer dereference, address: 0000000000000000 +[ 320.416918] #PF: supervisor read access in kernel mode +[ 320.416942] #PF: error_code(0x0000) - not-present page +[ 320.416963] PGD 2099657067 P4D 0 +[ 320.416983] Oops: Oops: 0000 [#1] SMP NOPTI +... +[ 320.417093] RIP: 0010:idpf_remove+0x118/0x200 [idpf] +[ 320.417130] Code: 8b bb 98 09 00 00 e8 17 0f 5b e5 48 8b bb e8 08 00 00 e8 0b 0f 5b e5 66 83 bb 28 06 00 00 00 48 8b bb 20 06 00 00 74 49 31 ed <48> 8b 04 ef 48 85 c0 74 2f 48 8b 78 20 e8 66 58 91 e5 48 8b 83 20 +[ 320.417183] RSP: 0018:ff7322212903fdb8 EFLAGS: 00010246 +[ 320.417205] RAX: 0000000000000000 RBX: ff4463de40300000 RCX: ff7322212903fd4c +[ 320.417228] RDX: 0000000000000001 RSI: ffffffffa7f7d100 RDI: 0000000000000000 +[ 320.417250] RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 +[ 320.417272] R10: 0000000000000001 R11: ff4463de3a638f58 R12: ff4463be89ac7000 +[ 320.417294] R13: ff4463be89ac7198 R14: ff4463be94fc7198 R15: ffffffffc0f10f20 +[ 320.417317] FS: 00007f963c0e6740(0000) GS:ff4463fdd65d8000(0000) knlGS:0000000000000000 +[ 320.417342] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 320.417362] CR2: 0000000000000000 CR3: 00000020ba674002 CR4: 0000000000773ef0 +[ 320.417385] PKRU: 55555554 +[ 320.417398] Call Trace: +[ 320.417412] +[ 320.417429] pci_device_remove+0x42/0xb0 +[ 320.417459] device_release_driver_internal+0x1a9/0x210 +[ 320.417492] driver_detach+0x4b/0x90 +[ 320.417516] bus_remove_driver+0x70/0x100 +[ 320.417539] pci_unregister_driver+0x2e/0xb0 +[ 320.417564] __do_sys_delete_module.constprop.0+0x190/0x2f0 +[ 320.417592] ? kmem_cache_free+0x31e/0x550 +[ 320.417619] ? lockdep_hardirqs_on_prepare+0xde/0x190 +[ 320.417644] ? do_syscall_64+0x38/0x6b0 +[ 320.417665] do_syscall_64+0xc8/0x6b0 +[ 320.417683] ? clear_bhb_loop+0x30/0x80 +[ 320.417706] entry_SYSCALL_64_after_hwframe+0x76/0x7e +[ 320.417727] RIP: 0033:0x7f963bb30beb + +Fixes: 0fe45467a104 ("idpf: add create vport and netdev configuration") +Reviewed-by: Madhu Chittim +Signed-off-by: Emil Tantilov +Reviewed-by: Aleksandr Loktionov +Reviewed-by: Simon Horman +Tested-by: Samuel Salin +Signed-off-by: Tony Nguyen +Link: https://patch.msgid.link/20260717185340.3595286-13-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/idpf/idpf_virtchnl.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c +index be66f9b2e101ca..dc5ad784f456f0 100644 +--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c ++++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c +@@ -3555,7 +3555,6 @@ int idpf_vc_core_init(struct idpf_adapter *adapter) + + pci_sriov_set_totalvfs(adapter->pdev, idpf_get_max_vfs(adapter)); + num_max_vports = idpf_get_max_vports(adapter); +- adapter->max_vports = num_max_vports; + adapter->vports = kzalloc_objs(*adapter->vports, num_max_vports); + if (!adapter->vports) + return -ENOMEM; +@@ -3576,6 +3575,12 @@ int idpf_vc_core_init(struct idpf_adapter *adapter) + goto err_netdev_alloc; + } + ++ /* Set max_vports only after vports, netdevs and vport_config buffers ++ * are allocated to make sure max_vport bound loops don't end up ++ * crashing, following allocation errors on init. ++ */ ++ adapter->max_vports = num_max_vports; ++ + /* Start the mailbox task before requesting vectors. This will ensure + * vector information response from mailbox is handled + */ +-- +2.53.0 + diff --git a/queue-7.1/iomap-correct-the-range-of-a-partial-dirty-clear.patch b/queue-7.1/iomap-correct-the-range-of-a-partial-dirty-clear.patch new file mode 100644 index 0000000000..0243cdfa32 --- /dev/null +++ b/queue-7.1/iomap-correct-the-range-of-a-partial-dirty-clear.patch @@ -0,0 +1,60 @@ +From cb927c6ca8b09695a15bc61884fc9ad36b3849ef Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:23:21 +0800 +Subject: iomap: correct the range of a partial dirty clear + +From: Zhang Yi + +[ Upstream commit 88c26515313169806a412a362b32a1eca53d21bd ] + +The block range calculation in ifs_clear_range_dirty() is incorrect when +partially clearing a range in a folio. We cannot clear the dirty bit of +the first block or the last block if the start or end offset is not +blocksize-aligned. This has not yet caused any issues since we always +clear a whole folio in iomap_writeback_folio(). + +Fix this by rounding up the first block to blocksize alignment, and +calculate the last block by rounding down (using truncation). Correct +the nr_blks calculation accordingly. + +Fixes: 4ce02c679722 ("iomap: Add per-block dirty state tracking to improve performance") +Signed-off-by: Zhang Yi +Link: https://patch.msgid.link/20260714082325.325163-2-yi.zhang@huaweicloud.com +Reviewed-by: Joanne Koong +Reviewed-by: "Darrick J. Wong" +Reviewed-by: Christoph Hellwig +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/iomap/buffered-io.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index 5fa9a2c7e30eb8..116110628994df 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -176,13 +176,17 @@ static void ifs_clear_range_dirty(struct folio *folio, + { + struct inode *inode = folio->mapping->host; + unsigned int blks_per_folio = i_blocks_per_folio(inode, folio); +- unsigned int first_blk = (off >> inode->i_blkbits); +- unsigned int last_blk = (off + len - 1) >> inode->i_blkbits; +- unsigned int nr_blks = last_blk - first_blk + 1; ++ unsigned int first_blk = round_up(off, i_blocksize(inode)) >> ++ inode->i_blkbits; ++ unsigned int last_blk = (off + len) >> inode->i_blkbits; + unsigned long flags; + ++ if (first_blk >= last_blk) ++ return; ++ + spin_lock_irqsave(&ifs->state_lock, flags); +- bitmap_clear(ifs->state, first_blk + blks_per_folio, nr_blks); ++ bitmap_clear(ifs->state, first_blk + blks_per_folio, ++ last_blk - first_blk); + spin_unlock_irqrestore(&ifs->state_lock, flags); + } + +-- +2.53.0 + diff --git a/queue-7.1/iomap-fix-incorrect-did_zero-setting-in-iomap_zero_i.patch b/queue-7.1/iomap-fix-incorrect-did_zero-setting-in-iomap_zero_i.patch new file mode 100644 index 0000000000..577880772d --- /dev/null +++ b/queue-7.1/iomap-fix-incorrect-did_zero-setting-in-iomap_zero_i.patch @@ -0,0 +1,78 @@ +From 9d5d720fb74a15674e32d935f95c25bbe04cfbba Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 16:23:23 +0800 +Subject: iomap: fix incorrect did_zero setting in iomap_zero_iter() + +From: Zhang Yi + +[ Upstream commit 7a6fd6b21d7e1737b40de1a210acf9e6a1e4d59e ] + +The did_zero output parameter was unconditionally set after the loop, +which is incorrect. It should only be set when the zeroing operation +actually completes, not when IOMAP_F_STALE is set or when +IOMAP_F_FOLIO_BATCH is set but !folio causes the loop to break early, +or when iomap_iter_advance() returns an error. + +This causes did_zero to be incorrectly set when zeroing a clean +unwritten extent because the loop exits early without actually zeroing +any data. + +Fix it by using a local variable to track whether any folio was actually +zeroed, and only set did_zero after the loop if zeroing happened. + +Fixes: 98eb8d95025b ("iomap: set did_zero to true when zeroing successfully") +Signed-off-by: Zhang Yi +Link: https://patch.msgid.link/20260714082325.325163-4-yi.zhang@huaweicloud.com +Reviewed-by: "Darrick J. Wong" +Reviewed-by: Christoph Hellwig +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/iomap/buffered-io.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c +index 116110628994df..0edb21bdb2f384 100644 +--- a/fs/iomap/buffered-io.c ++++ b/fs/iomap/buffered-io.c +@@ -1540,6 +1540,7 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + const struct iomap_write_ops *write_ops) + { + u64 bytes = iomap_length(iter); ++ bool zeroed = false; + int status; + + do { +@@ -1558,6 +1559,8 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + /* a NULL folio means we're done with a folio batch */ + if (!folio) { + status = iomap_iter_advance_full(iter); ++ if (status) ++ return status; + break; + } + +@@ -1568,6 +1571,7 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + bytes); + + folio_zero_range(folio, offset, bytes); ++ zeroed = true; + folio_mark_accessed(folio); + + ret = iomap_write_end(iter, bytes, bytes, folio); +@@ -1577,10 +1581,10 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, + + status = iomap_iter_advance(iter, bytes); + if (status) +- break; ++ return status; + } while ((bytes = iomap_length(iter)) > 0); + +- if (did_zero) ++ if (did_zero && zeroed) + *did_zero = true; + return status; + } +-- +2.53.0 + diff --git a/queue-7.1/iommu-amd-bound-the-early-acpi-hid-map.patch b/queue-7.1/iommu-amd-bound-the-early-acpi-hid-map.patch new file mode 100644 index 0000000000..bcc757d5c8 --- /dev/null +++ b/queue-7.1/iommu-amd-bound-the-early-acpi-hid-map.patch @@ -0,0 +1,45 @@ +From a84a36ed06fb8ef0382ab3abc7a8f706bbd0f958 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 19:46:13 +0800 +Subject: iommu/amd: Bound the early ACPI HID map + +From: Pengpeng Hou + +[ Upstream commit fb80117fddb5b477218dc99bb53911b72c3847f8 ] + +The ivrs_acpihid command-line parser appends entries to a fixed +four-element early_acpihid_map array. Unlike the sibling IOAPIC and HPET +parsers, it does not reject a fifth entry before incrementing the map size. + +Check the capacity at the common found label before parsing the HID and +UID or writing the entry. + +Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter") +Signed-off-by: Pengpeng Hou +Reviewed-by: Ankit Soni +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/init.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c +index 9a846dcd030638..0df711c082cb20 100644 +--- a/drivers/iommu/amd/init.c ++++ b/drivers/iommu/amd/init.c +@@ -3872,6 +3872,12 @@ static int __init parse_ivrs_acpihid(char *str) + return 1; + + found: ++ if (early_acpihid_map_size == EARLY_MAP_SIZE) { ++ pr_err("Early ACPI HID map overflow - ignoring ivrs_acpihid%s\n", ++ str); ++ return 1; ++ } ++ + p = acpiid; + hid = strsep(&p, ":"); + uid = p; +-- +2.53.0 + diff --git a/queue-7.1/iommu-amd-fix-irq-unsafe-locking-in-gdom-allocation.patch b/queue-7.1/iommu-amd-fix-irq-unsafe-locking-in-gdom-allocation.patch new file mode 100644 index 0000000000..6cb7e0674b --- /dev/null +++ b/queue-7.1/iommu-amd-fix-irq-unsafe-locking-in-gdom-allocation.patch @@ -0,0 +1,191 @@ +From 7090cbb8fec215835fa426cf2260152e4bd374ce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 13:57:35 -0600 +Subject: iommu/amd: Fix IRQ unsafe locking in gdom allocation + +From: Tycho Andersen (AMD) + +[ Upstream commit 0db3a430d9681fdb29890bef6934cd89cd1745d0 ] + +Lockdep complains: + + [ 259.410489] ===================================================== + [ 259.417287] WARNING: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected + [ 259.424667] 7.0.0-g51db1d8d2113 #54 Not tainted + [ 259.429718] ----------------------------------------------------- + [ 259.436516] qemu-system-x86/10143 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: + [ 259.444670] ff3b2b1c60305170 (&xa->xa_lock#25){+.+.}-{3:3}, at: __domain_flush_pages+0x17c/0x4b0 + [ 259.454485] + and this task is already holding: + [ 259.460991] ff3b2b1c98504cc0 (&domain->lock){-.-.}-{3:3}, at: amd_iommu_iotlb_sync+0x25/0x60 + [ 259.470408] which would create a new lock dependency: + [ 259.476041] (&domain->lock){-.-.}-{3:3} -> (&xa->xa_lock#25){+.+.}-{3:3} + [ 259.483615] + but this new dependency connects a HARDIRQ-irq-safe lock: + [ 259.492447] (&domain->lock){-.-.}-{3:3} + [ 259.492449] + ... which became HARDIRQ-irq-safe at: + [ 259.503705] lock_acquire+0xb6/0x2e0 + [ 259.507790] _raw_spin_lock_irqsave+0x3e/0x60 + [ 259.512748] amd_iommu_flush_iotlb_all+0x20/0x50 + [ 259.517996] iommu_dma_free_iova.isra.0+0x1b8/0x1e0 + [ 259.523534] __iommu_dma_unmap+0xc2/0x140 + [ 259.528100] iommu_dma_unmap_phys+0x55/0xc0 + [ 259.532863] dma_unmap_phys+0x274/0x2e0 + [ 259.537238] dma_unmap_page_attrs+0x17/0x30 + [ 259.542000] nvme_unmap_data+0x13e/0x280 + [ 259.546473] nvme_pci_complete_batch+0x45/0x70 + [ 259.551524] nvme_irq+0x83/0x90 + [ 259.555123] __handle_irq_event_percpu+0x92/0x360 + [ 259.560466] handle_irq_event+0x39/0x80 + [ 259.564841] handle_edge_irq+0xb2/0x1a0 + [ 259.569214] __common_interrupt+0x4e/0x130 + [ 259.573882] common_interrupt+0x88/0xa0 + [ 259.578256] asm_common_interrupt+0x27/0x40 + [ 259.583019] cpuidle_enter_state+0x119/0x5d0 + [ 259.587877] cpuidle_enter+0x2e/0x50 + [ 259.591962] do_idle+0x153/0x2c0 + [ 259.595657] cpu_startup_entry+0x29/0x30 + [ 259.600128] start_secondary+0x118/0x150 + [ 259.604601] common_startup_64+0x13e/0x141 + [ 259.609266] + to a HARDIRQ-irq-unsafe lock: + [ 259.615384] (&xa->xa_lock#25){+.+.}-{3:3} + [ 259.615386] + ... which became HARDIRQ-irq-unsafe at: + [ 259.627039] ... + [ 259.627039] lock_acquire+0xb6/0x2e0 + [ 259.633071] _raw_spin_lock+0x2f/0x50 + [ 259.637250] amd_iommu_alloc_domain_nested+0x140/0x3c0 + [ 259.643078] iommufd_hwpt_alloc+0x272/0x800 [iommufd] + [ 259.648813] iommufd_fops_ioctl+0x14e/0x200 [iommufd] + [ 259.654547] __x64_sys_ioctl+0x9d/0xf0 + ... + +Since amd_iommu_domain_flush_pages() necessarily holds domain->lock to do the +flush, switch the allocation side in gdom_info_load_or_alloc_locked() to +HARDIRQ-safe allocation. The IOMMU_DESTROY->free path has the same issue, +so switch that path to HARDIRQ-safe locking as well. + +Fixes: 757d2b1fdf5b ("iommu/amd: Introduce gDomID-to-hDomID Mapping and handle parent domain invalidation") +Signed-off-by: Tycho Andersen (AMD) +Reviewed-by: Ankit Soni +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/nested.c | 31 ++++++++++++++++++------------- + 1 file changed, 18 insertions(+), 13 deletions(-) + +diff --git a/drivers/iommu/amd/nested.c b/drivers/iommu/amd/nested.c +index 5b902598e68ade..5c9405223f9115 100644 +--- a/drivers/iommu/amd/nested.c ++++ b/drivers/iommu/amd/nested.c +@@ -59,7 +59,9 @@ static int validate_gdte_nested(struct iommu_hwpt_amd_guest *gdte) + return 0; + } + +-static void *gdom_info_load_or_alloc_locked(struct xarray *xa, unsigned long index) ++static void *gdom_info_load_or_alloc_locked(struct xarray *xa, ++ unsigned long index, ++ unsigned long *flags) + { + struct guest_domain_mapping_info *elm, *res; + +@@ -67,13 +69,13 @@ static void *gdom_info_load_or_alloc_locked(struct xarray *xa, unsigned long ind + if (elm) + return elm; + +- xa_unlock(xa); ++ xa_unlock_irqrestore(xa, *flags); + elm = kzalloc_obj(struct guest_domain_mapping_info); +- xa_lock(xa); ++ xa_lock_irqsave(xa, *flags); + if (!elm) + return ERR_PTR(-ENOMEM); + +- res = __xa_cmpxchg(xa, index, NULL, elm, GFP_KERNEL); ++ res = __xa_cmpxchg(xa, index, NULL, elm, GFP_ATOMIC); + if (xa_is_err(res)) + res = ERR_PTR(xa_err(res)); + +@@ -95,6 +97,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags, + const struct iommu_user_data *user_data) + { + int ret; ++ unsigned long irqflags; + struct nested_domain *ndom; + struct guest_domain_mapping_info *gdom_info; + struct amd_iommu_viommu *aviommu = container_of(viommu, struct amd_iommu_viommu, core); +@@ -136,11 +139,12 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags, + * keep track of the gDomID mapping. When the S2 is changed, the INVALIDATE_IOMMU_PAGES + * command must be issued for each hDomID in the xarray. + */ +- xa_lock(&aviommu->gdomid_array); ++ xa_lock_irqsave(&aviommu->gdomid_array, irqflags); + +- gdom_info = gdom_info_load_or_alloc_locked(&aviommu->gdomid_array, ndom->gdom_id); ++ gdom_info = gdom_info_load_or_alloc_locked(&aviommu->gdomid_array, ++ ndom->gdom_id, &irqflags); + if (IS_ERR(gdom_info)) { +- xa_unlock(&aviommu->gdomid_array); ++ xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags); + ret = PTR_ERR(gdom_info); + goto out_err; + } +@@ -148,7 +152,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags, + /* Check if gDomID exist */ + if (refcount_inc_not_zero(&gdom_info->users)) { + ndom->gdom_info = gdom_info; +- xa_unlock(&aviommu->gdomid_array); ++ xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags); + + pr_debug("%s: Found gdom_id=%#x, hdom_id=%#x\n", + __func__, ndom->gdom_id, gdom_info->hdom_id); +@@ -161,7 +165,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags, + if (gdom_info->hdom_id <= 0) { + __xa_cmpxchg(&aviommu->gdomid_array, + ndom->gdom_id, gdom_info, NULL, GFP_ATOMIC); +- xa_unlock(&aviommu->gdomid_array); ++ xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags); + ret = -ENOSPC; + goto out_err_gdom_info; + } +@@ -169,7 +173,7 @@ amd_iommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags, + ndom->gdom_info = gdom_info; + refcount_set(&gdom_info->users, 1); + +- xa_unlock(&aviommu->gdomid_array); ++ xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags); + + pr_debug("%s: Allocate gdom_id=%#x, hdom_id=%#x\n", + __func__, ndom->gdom_id, gdom_info->hdom_id); +@@ -257,14 +261,15 @@ static int nested_attach_device(struct iommu_domain *dom, struct device *dev, + + static void nested_domain_free(struct iommu_domain *dom) + { ++ unsigned long irqflags; + struct guest_domain_mapping_info *curr; + struct nested_domain *ndom = to_ndomain(dom); + struct amd_iommu_viommu *aviommu = ndom->viommu; + +- xa_lock(&aviommu->gdomid_array); ++ xa_lock_irqsave(&aviommu->gdomid_array, irqflags); + + if (!refcount_dec_and_test(&ndom->gdom_info->users)) { +- xa_unlock(&aviommu->gdomid_array); ++ xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags); + return; + } + +@@ -275,7 +280,7 @@ static void nested_domain_free(struct iommu_domain *dom) + curr = __xa_cmpxchg(&aviommu->gdomid_array, ndom->gdom_id, + ndom->gdom_info, NULL, GFP_ATOMIC); + +- xa_unlock(&aviommu->gdomid_array); ++ xa_unlock_irqrestore(&aviommu->gdomid_array, irqflags); + if (WARN_ON(!curr || xa_err(curr))) + return; + +-- +2.53.0 + diff --git a/queue-7.1/iommu-amd-fix-nested-domain-leak.patch b/queue-7.1/iommu-amd-fix-nested-domain-leak.patch new file mode 100644 index 0000000000..d6244a14e4 --- /dev/null +++ b/queue-7.1/iommu-amd-fix-nested-domain-leak.patch @@ -0,0 +1,62 @@ +From a9af171d4f89b92b39e9c1acfbd85054fc9e0c35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 13:57:36 -0600 +Subject: iommu/amd: Fix nested domain leak + +From: Tycho Andersen (AMD) + +[ Upstream commit 283c5c4c34b4c8d1ebd038d8f360c5ba7fcc767b ] + +A couple of runs of different AI tools have generated something like the +following bug report: + + In nested_domain_free(), when refcount_dec_and_test() returns false + (other nested domains still reference the same gdom_info), the function + returns without calling kfree(ndom), leaking the nested_domain + structure. This problem wasn't introduced by this patch, but exists in + the code from commit 757d2b1fdf5b that the patch modifies. Each + nested_domain (ndom) is allocated individually in + amd_iommu_alloc_domain_nested() via kzalloc_obj(*ndom). The .free + callback is the sole point responsible for freeing this domain. When + the refcount is > 0, only the xa_unlock_irqrestore is performed and the + function returns, leaving ndom permanently allocated. This leak occurs + every time a nested domain sharing a gDomID is destroyed while other + domains still use that gDomID. + +There is a similar leak later in this function in the WARN_ON() test when +the mapping is already NULL. Switch to a RAII-based cleanup for ndom, since +it should always be freed in this function. + +Fixes: 757d2b1fdf5b ("iommu/amd: Introduce gDomID-to-hDomID Mapping and handle parent domain invalidation") +Signed-off-by: Tycho Andersen (AMD) +Reviewed-by: Ankit Soni +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/nested.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/iommu/amd/nested.c b/drivers/iommu/amd/nested.c +index 5c9405223f9115..63b53b29e02989 100644 +--- a/drivers/iommu/amd/nested.c ++++ b/drivers/iommu/amd/nested.c +@@ -263,7 +263,7 @@ static void nested_domain_free(struct iommu_domain *dom) + { + unsigned long irqflags; + struct guest_domain_mapping_info *curr; +- struct nested_domain *ndom = to_ndomain(dom); ++ struct nested_domain *ndom __free(kfree) = to_ndomain(dom); + struct amd_iommu_viommu *aviommu = ndom->viommu; + + xa_lock_irqsave(&aviommu->gdomid_array, irqflags); +@@ -290,7 +290,6 @@ static void nested_domain_free(struct iommu_domain *dom) + + amd_iommu_pdom_id_free(ndom->gdom_info->hdom_id); + kfree(curr); +- kfree(ndom); + } + + static const struct iommu_domain_ops nested_domain_ops = { +-- +2.53.0 + diff --git a/queue-7.1/iommu-amd-wait-for-completion-instead-of-returning-e.patch b/queue-7.1/iommu-amd-wait-for-completion-instead-of-returning-e.patch new file mode 100644 index 0000000000..ea73ce4a7d --- /dev/null +++ b/queue-7.1/iommu-amd-wait-for-completion-instead-of-returning-e.patch @@ -0,0 +1,95 @@ +From 598862371fad3f3cd4daca03e6709f581bc7a2bf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 22:16:22 +0800 +Subject: iommu/amd: Wait for completion instead of returning early in + iommu_completion_wait() + +From: Guanghui Feng + +[ Upstream commit 1e75a8255f11c81fb07e81e5029cfd75804350a0 ] + +need_sync is a per-IOMMU flag shared by all domains and devices behind +that IOMMU. It is set whenever a command is queued with sync == true and +cleared when a completion-wait (CWAIT) command is queued. However, a +cleared need_sync only means that a covering CWAIT has been queued, not +that all previously queued commands have actually completed in hardware. + +iommu_completion_wait() read need_sync locklessly and returned early +when it was false. This breaks the "block until all previously queued +commands have completed" contract in a multi-CPU scenario: + + CPU2: queue inv-B => need_sync = true + CPU1: queue CWAIT(N); need_sync = false; then wait_on_sem(N) + CPU2: read need_sync == false => return 0 (no wait!) + +CPU2 returns without waiting for any sequence number even though its +inv-B may not have completed yet (CWAIT(N), queued after inv-B, has not +been signaled). CPU2 then proceeds to, for example, free page-table +pages while the IOMMU can still walk stale translations, opening a +use-after-free window. This is a logical race in the meaning of the +flag, not a memory-visibility issue, so barriers alone do not help. + +Fix it without losing the optimization of avoiding redundant CWAIT +commands: take iommu->lock before testing need_sync, and when it is +false do not return early but wait for the last allocated sequence +number (cmd_sem_val). Since need_sync == false implies no sync command +was queued after the last CWAIT, that CWAIT is FIFO-ordered after every +not-yet-completed command, so waiting for its sequence number guarantees +all prior commands (possibly queued by another CPU) have completed. The +common path with pending work is unchanged and no extra hardware command +is issued. + +Signed-off-by: Guanghui Feng +Fixes: 815b33fdc279 ("x86/amd-iommu: Cleanup completion-wait handling") +Reviewed-by: Vasant Hegde +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/amd/iommu.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c +index 15ffc4742183ea..345178a285c952 100644 +--- a/drivers/iommu/amd/iommu.c ++++ b/drivers/iommu/amd/iommu.c +@@ -1456,11 +1456,23 @@ static int iommu_completion_wait(struct amd_iommu *iommu) + int ret; + u64 data; + +- if (!iommu->need_sync) +- return 0; +- + raw_spin_lock_irqsave(&iommu->lock, flags); + ++ if (!iommu->need_sync) { ++ /* ++ * No command has been queued since the last completion-wait. ++ * A concurrent CPU may have already queued that CWAIT and ++ * cleared need_sync; need_sync == false only means a covering ++ * CWAIT is queued, not that all prior commands have completed. ++ * Wait for the last allocated sequence number so that any ++ * command queued before this call (possibly on another CPU) ++ * is guaranteed to have completed before returning. ++ */ ++ data = iommu->cmd_sem_val; ++ raw_spin_unlock_irqrestore(&iommu->lock, flags); ++ return wait_on_sem(iommu, data); ++ } ++ + data = get_cmdsem_val(iommu); + build_completion_wait(&cmd, iommu, data); + +@@ -1470,9 +1482,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu) + if (ret) + return ret; + +- ret = wait_on_sem(iommu, data); +- +- return ret; ++ return wait_on_sem(iommu, data); + } + + static void domain_flush_complete(struct protection_domain *domain) +-- +2.53.0 + diff --git a/queue-7.1/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch b/queue-7.1/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch new file mode 100644 index 0000000000..4f277f658d --- /dev/null +++ b/queue-7.1/iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch @@ -0,0 +1,43 @@ +From 91e28dd899ede8a4eff509de6c734bfdfba42787 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:34:10 +0800 +Subject: iommu/intel: Fix out-of-bounds memset in dmar_latency_disable() + +From: Li RongQing + +[ Upstream commit 754f8efe45f87e3a9c6871b645b2f9d46d1b407b ] + +dmar_latency_disable() intends to zero out only the single +latency_statistic entry for the given type, but the memset size was +computed as sizeof(*lstat) * DMAR_LATENCY_NUM, which clears the entire +array starting from &lstat[type]. + +When type > 0, this writes beyond the end of the allocated array, +corrupting adjacent memory. + +Fix by using sizeof(*lstat) to clear only the target entry. + +Fixes: 55ee5e67a59a ("iommu/vt-d: Add common code for dmar latency performance monitors") +Signed-off-by: Li RongQing +Signed-off-by: Will Deacon +Signed-off-by: Sasha Levin +--- + drivers/iommu/intel/perf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iommu/intel/perf.c b/drivers/iommu/intel/perf.c +index 02168f2f20a43f..bec98dcbb9ecae 100644 +--- a/drivers/iommu/intel/perf.c ++++ b/drivers/iommu/intel/perf.c +@@ -63,7 +63,7 @@ void dmar_latency_disable(struct intel_iommu *iommu, enum latency_type type) + return; + + spin_lock_irqsave(&latency_lock, flags); +- memset(&lstat[type], 0, sizeof(*lstat) * DMAR_LATENCY_NUM); ++ memset(&lstat[type], 0, sizeof(*lstat)); + spin_unlock_irqrestore(&latency_lock, flags); + } + +-- +2.53.0 + diff --git a/queue-7.1/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch b/queue-7.1/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch new file mode 100644 index 0000000000..c6c5742592 --- /dev/null +++ b/queue-7.1/ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch @@ -0,0 +1,88 @@ +From f9aefb40620bc3a39f8d69ee694d97616f0b5e19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:42:36 +0000 +Subject: ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup + +From: Eric Dumazet + +[ Upstream commit 853e164c2b321f0711361bc23505aaeb7dc432c3 ] + +When Linux forwards a packet and needs to generate an ICMP error, +icmp_route_lookup() performs a reverse-path relookup. For non-local +destinations, it performs a decoy lookup to find the expected egress +interface (rt2->dst.dev) before validating the path with ip_route_input(). + +Currently, the decoy flow structure (fl4_2) only sets .daddr = fl4_dec.saddr, +leaving .saddr, .flowi4_dscp, .flowi4_proto, .flowi4_mark, .flowi4_oif, +.fl4_sport, .fl4_dport, and .flowi4_uid zeroed out. + +When policy routing rules (such as ip rule add from $SRC lookup 100, or +dscp/fwmark/ipproto/port rules, or VRF bindings) are configured: +1. The decoy lookup fails to match the policy rule because saddr and other + key flow selectors are missing in fl4_2. +2. It resolves a route using the default table instead, returning an incorrect + egress netdev. +3. Passing the wrong netdev to ip_route_input() causes strict reverse-path + filtering (rp_filter=1) to fail, logging false-positive "martian source" + warnings and causing the relookup to fail. + +Fix this by initializing fl4_2 from fl4_dec and: +- Swapping source/destination IP addresses. +- Swapping L4 ports for transport protocols with ports (TCP, UDP, SCTP, DCCP) + so port-based policy routing matches correctly. Non-port protocols (such as + ICMP or GRE) leave the flowi_uli union fields intact to prevent corruption. +- Setting .flowi4_oif = l3mdev_master_ifindex(route_lookup_dev) to ensure + VRF routing tables are respected. +- Setting .flowi4_flags |= FLOWI_FLAG_ANYSRC to allow output route lookups + for non-local source IP addresses. +- Using __ip_route_output_key() instead of ip_route_output_key() for fl4_2 + so that raw FIB routing is used without triggering spurious XFRM policy + lookups on the decoy flow (the actual XFRM lookup is performed later using + fl4_dec). + +Fixes: 415b3334a21a ("icmp: Fix regression in nexthop resolution during replies.") +Reported-by: Muhammad Ziad +Closes: https://lore.kernel.org/netdev/CAOAwikA60AYKdFr_UDLyja3oU4hqyAE7uFZWqum5uRdaQsgRYg@mail.gmail.com/ +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Link: https://patch.msgid.link/20260722104236.2938082-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/icmp.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index 23e921d313b36b..0caedfc7ca92f6 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -548,11 +548,23 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4, + if (IS_ERR(rt2)) + err = PTR_ERR(rt2); + } else { +- struct flowi4 fl4_2 = {}; ++ struct flowi4 fl4_2 = fl4_dec; + unsigned long orefdst; + +- fl4_2.daddr = fl4_dec.saddr; +- rt2 = ip_route_output_key(net, &fl4_2); ++ swap(fl4_2.daddr, fl4_2.saddr); ++ switch (fl4_2.flowi4_proto) { ++ case IPPROTO_TCP: ++ case IPPROTO_UDP: ++ case IPPROTO_SCTP: ++ case IPPROTO_DCCP: ++ swap(fl4_2.fl4_sport, fl4_2.fl4_dport); ++ break; ++ } ++ ++ fl4_2.flowi4_oif = l3mdev_master_ifindex(route_lookup_dev); ++ fl4_2.flowi4_flags |= FLOWI_FLAG_ANYSRC; ++ ++ rt2 = __ip_route_output_key(net, &fl4_2); + if (IS_ERR(rt2)) { + err = PTR_ERR(rt2); + goto relookup_failed; +-- +2.53.0 + diff --git a/queue-7.1/ipv6-change-allocation-flags-to-match-rcu_read_lock-.patch b/queue-7.1/ipv6-change-allocation-flags-to-match-rcu_read_lock-.patch new file mode 100644 index 0000000000..5dde42d137 --- /dev/null +++ b/queue-7.1/ipv6-change-allocation-flags-to-match-rcu_read_lock-.patch @@ -0,0 +1,69 @@ +From 6b08d0562847ae55362d5befa1d37222aa5f4065 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Jul 2026 13:57:59 +0300 +Subject: ipv6: Change allocation flags to match rcu_read_lock section + requirements + +From: Nikola Z. Ivanov + +[ Upstream commit 313a123e1fca8827bb463db1f4bb211309764563 ] + +Since the call to __ip6_del_rt_siblings has been converted under +rcu read lock and it only has one call point +we should no longer block or yield. + +Our stack trace from the syzbot reproducer looks as follows: + +__ip6_del_rt_siblings + rtnl_notify (Here we pass gfp_any() -> GFP_KERNEL) + nlmsg_notify + nlmsg_multicast + nlmsg_multicast_filtered + netlink_broadcast_filtered (GFP_KERNEL passed from earlier) + +netlink_broadcast_filtered can yield if GFP_KERNEL +is passed, which we do not want to happen. + +Fix this by changing the allocation flag of rtnl_notify. + +Also change the flag passed to nlmsg_new. Even though it +is not related to the syzbot generated bug it still falls +under the same requirements. + +Reported-by: syzbot+84d4a405ed798b40c96d@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=84d4a405ed798b40c96d +Fixes: bd11ff421d36 ("ipv6: Get rid of RTNL for SIOCDELRT and RTM_DELROUTE.") +Signed-off-by: Nikola Z. Ivanov +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260719105759.558050-1-zlatistiv@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/route.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 88b46967bb67dc..d4edc133c045c4 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -4020,7 +4020,7 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg) + struct fib6_node *fn; + + /* prefer to send a single notification with all hops */ +- skb = nlmsg_new(rt6_nlmsg_size(rt), gfp_any()); ++ skb = nlmsg_new(rt6_nlmsg_size(rt), GFP_ATOMIC); + if (skb) { + u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0; + +@@ -4076,7 +4076,7 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg) + + if (skb) { + rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE, +- info->nlh, gfp_any()); ++ info->nlh, GFP_ATOMIC); + } + return err; + } +-- +2.53.0 + diff --git a/queue-7.1/loongarch-bpf-fix-memory-leak-in-bpf_jit_free.patch b/queue-7.1/loongarch-bpf-fix-memory-leak-in-bpf_jit_free.patch new file mode 100644 index 0000000000..d7d46e9d0d --- /dev/null +++ b/queue-7.1/loongarch-bpf-fix-memory-leak-in-bpf_jit_free.patch @@ -0,0 +1,46 @@ +From 163a62fe04a74d09c927c89bc151e3f029516032 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jul 2026 16:33:08 +0800 +Subject: LoongArch: BPF: Fix memory leak in bpf_jit_free() + +From: Pu Lehui + +[ Upstream commit 47e20d4b3da97ef3881d1e55e43545c22424f3fc ] + +When bpf_int_jit_compile() is called for subprograms, it returns early +during the first pass (!prog->is_func || extra_pass is false), keeping +ctx->offset alive for the subsequent extra pass. + +If JIT compilation fails for a later subprogram, the BPF core aborts and +calls bpf_jit_free() to clean up the first subprogram. However, +bpf_jit_free() fails to free jit_data->ctx.offset, which causes a memory +leak of the JIT context offsets array. + +So fix this by adding the missing kvfree(jit_data->ctx.offset) in +bpf_jit_free(). + +Reported-by: Sashiko +Fixes: 4ab17e762b34 ("LoongArch: BPF: Use BPF prog pack allocator") +Acked-by: Tiezhu Yang +Signed-off-by: Pu Lehui +Signed-off-by: Huacai Chen +Signed-off-by: Sasha Levin +--- + arch/loongarch/net/bpf_jit.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c +index 22c03c02dae6ed..4933869b2c11fb 100644 +--- a/arch/loongarch/net/bpf_jit.c ++++ b/arch/loongarch/net/bpf_jit.c +@@ -2347,6 +2347,7 @@ void bpf_jit_free(struct bpf_prog *prog) + */ + if (jit_data) { + bpf_jit_binary_pack_finalize(jit_data->ro_header, jit_data->header); ++ kvfree(jit_data->ctx.offset); + kfree(jit_data); + } + hdr = bpf_jit_binary_pack_hdr(prog); +-- +2.53.0 + diff --git a/queue-7.1/loongarch-bpf-zero-extend-signed-alu32-div-mod-resul.patch b/queue-7.1/loongarch-bpf-zero-extend-signed-alu32-div-mod-resul.patch new file mode 100644 index 0000000000..ddbfac2ff0 --- /dev/null +++ b/queue-7.1/loongarch-bpf-zero-extend-signed-alu32-div-mod-resul.patch @@ -0,0 +1,75 @@ +From 4cca0b19853fc66f42e43333aa879df4591c268a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jul 2026 22:27:35 +0800 +Subject: LoongArch: BPF: Zero-extend signed ALU32 div/mod results + +From: Nicholas Dudar + +[ Upstream commit dacd348b8a993373576fe2ee2d8b114740ba57a6 ] + +ALU32 operations write a 32-bit result and leave the upper 32 bits of +the BPF register zero. The LoongArch JIT sign-extends the result of +signed ALU32 BPF_DIV and BPF_MOD (off=1), so a negative 32-bit quotient +or remainder leaves bits 63:32 set in JITted code while the verifier +and interpreter model those bits as zero. + +Keep sign-extension on the operands, which signed divide needs, and +zero-extend the ALU32 result after the divide or modulo instruction, +matching the unsigned ALU32 div/mod paths and every other ALU32 +operation in this JIT. + +Fixes: 2425c9e002d2 ("LoongArch: BPF: Support signed div instructions") +Fixes: 7b6b13d32965 ("LoongArch: BPF: Support signed mod instructions") +Assisted-by: Claude:claude-opus-4-8 +Acked-by: Tiezhu Yang +Tested-by: Tiezhu Yang +Signed-off-by: Nicholas Dudar +Signed-off-by: Huacai Chen +Signed-off-by: Sasha Levin +--- + arch/loongarch/net/bpf_jit.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c +index e4966c178abc56..22c03c02dae6ed 100644 +--- a/arch/loongarch/net/bpf_jit.c ++++ b/arch/loongarch/net/bpf_jit.c +@@ -834,7 +834,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext + move_reg(ctx, t1, src); + emit_sext_32(ctx, t1, is32); + emit_insn(ctx, divd, dst, dst, t1); +- emit_sext_32(ctx, dst, is32); ++ emit_zext_32(ctx, dst, is32); + } + break; + +@@ -851,7 +851,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext + emit_sext_32(ctx, t1, is32); + emit_sext_32(ctx, dst, is32); + emit_insn(ctx, divd, dst, dst, t1); +- emit_sext_32(ctx, dst, is32); ++ emit_zext_32(ctx, dst, is32); + } + break; + +@@ -869,7 +869,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext + move_reg(ctx, t1, src); + emit_sext_32(ctx, t1, is32); + emit_insn(ctx, modd, dst, dst, t1); +- emit_sext_32(ctx, dst, is32); ++ emit_zext_32(ctx, dst, is32); + } + break; + +@@ -886,7 +886,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext + emit_sext_32(ctx, t1, is32); + emit_sext_32(ctx, dst, is32); + emit_insn(ctx, modd, dst, dst, t1); +- emit_sext_32(ctx, dst, is32); ++ emit_zext_32(ctx, dst, is32); + } + break; + +-- +2.53.0 + diff --git a/queue-7.1/mctp-check-register_netdevice_notifier-error-in-mctp.patch b/queue-7.1/mctp-check-register_netdevice_notifier-error-in-mctp.patch new file mode 100644 index 0000000000..46e0a7adc6 --- /dev/null +++ b/queue-7.1/mctp-check-register_netdevice_notifier-error-in-mctp.patch @@ -0,0 +1,43 @@ +From 227df1dfdedbbce19996da1ec5803d2f0d4e3d89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 15:25:18 +0800 +Subject: mctp: check register_netdevice_notifier() error in mctp_device_init() + +From: Minhong He + +[ Upstream commit d9a33cadc70a94c1582f65e6042e81027cd200c6 ] + +mctp_device_init() handles errors from rtnl_af_register() and +rtnl_register_many(), but ignores the return value of +register_netdevice_notifier(). If notifier registration fails, init can +still return success while the module is only partially initialized. + +Check the notifier registration error and fail module init early. + +Fixes: 583be982d934 ("mctp: Add device handling and netlink interface") +Signed-off-by: Minhong He +Link: https://patch.msgid.link/20260720072518.112614-1-heminhong@kylinos.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/mctp/device.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/mctp/device.c b/net/mctp/device.c +index 2c84df674669b2..822120e860c82a 100644 +--- a/net/mctp/device.c ++++ b/net/mctp/device.c +@@ -536,7 +536,9 @@ int __init mctp_device_init(void) + { + int err; + +- register_netdevice_notifier(&mctp_dev_nb); ++ err = register_netdevice_notifier(&mctp_dev_nb); ++ if (err) ++ return err; + + err = rtnl_af_register(&mctp_af_ops); + if (err) +-- +2.53.0 + diff --git a/queue-7.1/mpls-set-rt-rt_nhn-just-before-returning-from-mpls_n.patch b/queue-7.1/mpls-set-rt-rt_nhn-just-before-returning-from-mpls_n.patch new file mode 100644 index 0000000000..53a793367c --- /dev/null +++ b/queue-7.1/mpls-set-rt-rt_nhn-just-before-returning-from-mpls_n.patch @@ -0,0 +1,67 @@ +From 51447eeff52e1827557e0034d7d316219448e785 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 17:06:07 +0000 +Subject: mpls: Set rt->rt_nhn just before returning from + mpls_nh_build_multi(). + +From: Kuniyuki Iwashima + +[ Upstream commit 3671f0419d90b98a02f313830595ab958c8b2025 ] + +Commit f0914b8436c5 ("mpls: Hold dev refcnt for mpls_nh.") added +change_nexthops() loop to call netdev_put() for the nexthop devices +before freeing mpls_route. + +Then, mpls_nh_build_multi() was also changed to avoid iterating +uninitialised nexthops in mpls_rt_free_rcu(). + +However, setting rt->rt_nhn to 0 at the entry of mpls_nh_build_multi() +makes the following change_nexthops() no-op. + +Let's set rt->rt_nhn just before returning from mpls_nh_build_multi(). + +Fixes: f0914b8436c5 ("mpls: Hold dev refcnt for mpls_nh.") +Reported-by: Anthony Doeraene +Closes: https://lore.kernel.org/netdev/036a0c95-f5d4-46ab-88e7-1eab567d7a84@uclouvain.be/ +Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260716170609.804629-1-kuniyu@google.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/mpls/af_mpls.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c +index b64a8b1bac0961..35069183f59c3e 100644 +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -922,8 +922,7 @@ static int mpls_nh_build_multi(struct mpls_route_config *cfg, + struct nlattr *nla_via, *nla_newdst; + int remaining = cfg->rc_mp_len; + int err = 0; +- +- rt->rt_nhn = 0; ++ u8 nhs = 0; + + change_nexthops(rt) { + int attrlen; +@@ -959,12 +958,15 @@ static int mpls_nh_build_multi(struct mpls_route_config *cfg, + rt->rt_nhn_alive--; + + rtnh = rtnh_next(rtnh, &remaining); +- rt->rt_nhn++; ++ nhs++; + } endfor_nexthops(rt); + ++ rt->rt_nhn = nhs; ++ + return 0; + + errout: ++ rt->rt_nhn = nhs; + return err; + } + +-- +2.53.0 + diff --git a/queue-7.1/net-airoha-fix-dma-direction-for-npu-mailbox-buffer.patch b/queue-7.1/net-airoha-fix-dma-direction-for-npu-mailbox-buffer.patch new file mode 100644 index 0000000000..488a5862e8 --- /dev/null +++ b/queue-7.1/net-airoha-fix-dma-direction-for-npu-mailbox-buffer.patch @@ -0,0 +1,73 @@ +From bd72c573de40facc8e2bdc7223ad5a547eb34cc4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:35:29 +0800 +Subject: net: airoha: Fix DMA direction for NPU mailbox buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Wayen Yan + +[ Upstream commit 6f884eb87a79e0c482baef2ad96c96b81d024235 ] + +airoha_npu_send_msg() always maps the mailbox buffer with DMA_TO_DEVICE, +but some callers expect the NPU to write response data back into the +same buffer: + +- airoha_npu_wlan_msg_get() (NPU_OP_GET): NPU writes response into + the buffer, then the caller reads it via memcpy() +- airoha_npu_ppe_stats_setup() (NPU_OP_SET): NPU writes back + npu_stats_addr field in the response + +On non-cache-coherent architectures like EN7581 (Cortex-A53 without +hardware cache coherency for NPU DMA), DMA_TO_DEVICE unmap is a no-op +— it does not invalidate the CPU cache. If the NPU-written cache line +is still present in the CPU cache when the caller reads the buffer, +the CPU observes stale data instead of the NPU response. + +This is a timing-sensitive bug: small mailbox buffers (~24 bytes) +typically fit in a single cache line and may survive in the cache +until the caller reads them, producing silent data corruption rather +than a crash. The bug is more likely to trigger when the caller reads +the response immediately after dma_unmap_single() without intervening +cache-evicting operations. + +Fix by using DMA_BIDIRECTIONAL for both map and unmap, which ensures +dma_unmap_single() invalidates the CPU cache on non-coherent systems. +The mailbox buffers are small so there is no performance concern. + +Fixes: c52918744ee1e49cea86622a2633b9782446428f ("net: airoha: npu: Move memory allocation in airoha_npu_send_msg() caller") +Signed-off-by: Wayen Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/178351055214.98729.11403147818632027428@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/airoha/airoha_npu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c +index 17dbdc8325336b..eab3eb4a3ab216 100644 +--- a/drivers/net/ethernet/airoha/airoha_npu.c ++++ b/drivers/net/ethernet/airoha/airoha_npu.c +@@ -168,7 +168,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, + dma_addr_t dma_addr; + int ret; + +- dma_addr = dma_map_single(npu->dev, p, size, DMA_TO_DEVICE); ++ dma_addr = dma_map_single(npu->dev, p, size, DMA_BIDIRECTIONAL); + ret = dma_mapping_error(npu->dev, dma_addr); + if (ret) + return ret; +@@ -191,7 +191,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id, + + spin_unlock_bh(&npu->cores[core].lock); + +- dma_unmap_single(npu->dev, dma_addr, size, DMA_TO_DEVICE); ++ dma_unmap_single(npu->dev, dma_addr, size, DMA_BIDIRECTIONAL); + + return ret; + } +-- +2.53.0 + diff --git a/queue-7.1/net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch b/queue-7.1/net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch new file mode 100644 index 0000000000..50e26e5680 --- /dev/null +++ b/queue-7.1/net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch @@ -0,0 +1,47 @@ +From 09bf97d3aaa7223f72e4426b68073a27e2f3e6b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 13:22:28 +0200 +Subject: net: airoha: fix ETS channel derivation in + airoha_tc_setup_qdisc_ets() + +From: Lorenzo Bianconi + +[ Upstream commit 649ea07fc25a17aa51bff710baac1ab161022a7c ] + +Derive the hardware QoS channel from opt->parent instead of opt->handle +in airoha_tc_setup_qdisc_ets(). The ETS qdisc handle is either +user-specified or auto-allocated by qdisc_alloc_handle() and bears no +relation to the HTB leaf classid that identifies the hardware channel. +HTB derives the channel from TC_H_MIN(opt->classid), and ETS is always +attached as a child of an HTB leaf, so its opt->parent matches that +classid. Using opt->handle instead can cause two ETS qdiscs on different +HTB leaves to collide on the same hardware channel, corrupting scheduler +configuration and stats. + +Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support") +Reviewed-by: Simon Horman +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260720-airoha-ets-handle-fix-v2-1-6f7129ddc06f@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/airoha/airoha_eth.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c +index 1e361a35ebd490..b03d1b2c820a5a 100644 +--- a/drivers/net/ethernet/airoha/airoha_eth.c ++++ b/drivers/net/ethernet/airoha/airoha_eth.c +@@ -2326,8 +2326,7 @@ static int airoha_tc_setup_qdisc_ets(struct net_device *dev, + if (opt->parent == TC_H_ROOT) + return -EINVAL; + +- channel = TC_H_MAJ(opt->handle) >> 16; +- channel = channel % AIROHA_NUM_QOS_CHANNELS; ++ channel = TC_H_MIN(opt->parent) % AIROHA_NUM_QOS_CHANNELS; + + switch (opt->command) { + case TC_ETS_REPLACE: +-- +2.53.0 + diff --git a/queue-7.1/net-airoha-fix-potential-use-after-free-in-airoha_pp.patch b/queue-7.1/net-airoha-fix-potential-use-after-free-in-airoha_pp.patch new file mode 100644 index 0000000000..2528836a57 --- /dev/null +++ b/queue-7.1/net-airoha-fix-potential-use-after-free-in-airoha_pp.patch @@ -0,0 +1,49 @@ +From 97eae05ed109cc267bc76c3f8e341793bbc54377 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 19:16:16 +0800 +Subject: net: airoha: Fix potential use-after-free in airoha_ppe_deinit() + +From: Wayen Yan + +[ Upstream commit 2484568a335cd7bda951c75b3a7d95ea36161ae7 ] + +airoha_ppe_deinit() replaces the NPU pointer with NULL via +rcu_replace_pointer() but does not wait for existing RCU readers +to exit before calling ppe_deinit() and airoha_npu_put(). This can +cause a use-after-free if a reader in an RCU read-side critical +section still holds a reference to the NPU when it is freed. + +The init path (airoha_ppe_init) already calls synchronize_rcu() +after rcu_assign_pointer(), but the deinit path introduced in +commit 6abcf751bc08 ("net: airoha: Fix schedule while atomic in +airoha_ppe_deinit()") omitted the matching barrier when switching +from rcu_read_lock()/rcu_dereference() to rcu_replace_pointer(). + +Add synchronize_rcu() before ppe_deinit() to ensure all existing +RCU readers have completed before the NPU resources are released. + +Fixes: 6abcf751bc084804a9e5b3051442e8a2ce67f48a ("net: airoha: Fix schedule while atomic in airoha_ppe_deinit()") +Signed-off-by: Wayen Yan +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/178351022574.97989.6880403520276841703@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/airoha/airoha_ppe.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c +index a1f9939c21f20a..75b33e5af9b2c5 100644 +--- a/drivers/net/ethernet/airoha/airoha_ppe.c ++++ b/drivers/net/ethernet/airoha/airoha_ppe.c +@@ -1619,6 +1619,7 @@ void airoha_ppe_deinit(struct airoha_eth *eth) + npu = rcu_replace_pointer(eth->npu, NULL, + lockdep_is_held(&flow_offload_mutex)); + if (npu) { ++ synchronize_rcu(); + npu->ops.ppe_deinit(npu); + airoha_npu_put(npu); + } +-- +2.53.0 + diff --git a/queue-7.1/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch b/queue-7.1/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch new file mode 100644 index 0000000000..452ac7f6af --- /dev/null +++ b/queue-7.1/net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch @@ -0,0 +1,149 @@ +From 3d1d3c05264ad098d6e71ea13cfde939e35705d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 17:09:21 +0300 +Subject: net: bridge: vlan: fix vlan range dumps starting with pvid + +From: Nikolay Aleksandrov + +[ Upstream commit 43171c97e4714bf601b468401b37732244639c21 ] + +There is a bug in all range dumps that rely on br_vlan_can_enter_range() +when the PVID is a range starting VLAN, all following VLANs that match +its flags can enter the range, but when the range is filled in only the +PVID VLAN is dumped and the rest of the range is discarded because +br_vlan_fill_vids() checks for the PVID flag. Since the PVID VLAN can +be only one, we need to break ranges around it, the best way to do that +consistently for all is to alter br_vlan_can_enter_range() to take into +account the PVID and return false to break the range when it's matched. + +Before the fix: +$ ip l add br0 type bridge vlan_filtering 1 +$ ip l add dumdum type dummy +$ ip l set dumdum master br0 +$ ip l set br0 up +$ ip l set dumdum up +$ bridge vlan add dev dumdum vid 1 pvid untagged master +$ bridge vlan add dev dumdum vid 2 untagged master +$ bridge vlan show dev dumdum # use legacy dump to show all vlans +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged + +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + +VLAN 2 is missing, and if there are more matching VLANs afterwards +they'd be missing too. + +After the fix: +[ same setup steps ] +$ bridge vlan show dev dumdum +port vlan-id +dumdum 1 PVID Egress Untagged + 2 Egress Untagged +$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN) +port vlan-id +dumdum 1 PVID Egress Untagged + state forwarding mcast_router 1 + 2 Egress Untagged + state forwarding mcast_router 1 + +Fixes: 0ab558795184 ("net: bridge: vlan: add rtm range support") +Signed-off-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260721140922.682265-2-razor@blackwall.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/bridge/br_netlink_tunnel.c | 3 ++- + net/bridge/br_private.h | 6 ++++-- + net/bridge/br_vlan.c | 10 ++++++---- + net/bridge/br_vlan_options.c | 3 +-- + 4 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/net/bridge/br_netlink_tunnel.c b/net/bridge/br_netlink_tunnel.c +index 71a12da30004c7..a713668ea34f0e 100644 +--- a/net/bridge/br_netlink_tunnel.c ++++ b/net/bridge/br_netlink_tunnel.c +@@ -271,7 +271,8 @@ static void __vlan_tunnel_handle_range(const struct net_bridge_port *p, + if (!*v_start) + goto out_init; + +- if (v && curr_change && br_vlan_can_enter_range(v, *v_end)) { ++ if (v && curr_change && ++ br_vlan_can_enter_range(v, *v_end, br_get_pvid(vg))) { + *v_end = v; + return; + } +diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h +index bed1b1d9b28234..6b979a5cc424c8 100644 +--- a/net/bridge/br_private.h ++++ b/net/bridge/br_private.h +@@ -1625,7 +1625,8 @@ void br_vlan_notify(const struct net_bridge *br, + u16 vid, u16 vid_range, + int cmd); + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end); ++ const struct net_bridge_vlan *range_end, ++ u16 pvid); + + void br_vlan_fill_forward_path_pvid(struct net_bridge *br, + struct net_device_path_ctx *ctx, +@@ -1872,7 +1873,8 @@ static inline void br_vlan_notify(const struct net_bridge *br, + } + + static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { + return true; + } +diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c +index 84a180927eb73b..64a4151761d479 100644 +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1982,9 +1982,11 @@ void br_vlan_notify(const struct net_bridge *br, + + /* check if v_curr can enter a range ending in range_end */ + bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, +- const struct net_bridge_vlan *range_end) ++ const struct net_bridge_vlan *range_end, ++ u16 pvid) + { +- return v_curr->vid - range_end->vid == 1 && ++ return v_curr->vid != pvid && range_end->vid != pvid && ++ v_curr->vid - range_end->vid == 1 && + range_end->flags == v_curr->flags && + br_vlan_opts_eq_range(v_curr, range_end); + } +@@ -2066,8 +2068,8 @@ static int br_vlan_dump_dev(const struct net_device *dev, + idx += range_end->vid - range_start->vid + 1; + + range_start = v; +- } else if (dump_stats || v->vid == pvid || +- !br_vlan_can_enter_range(v, range_end)) { ++ } else if (dump_stats || ++ !br_vlan_can_enter_range(v, range_end, pvid)) { + u16 vlan_flags = br_vlan_flags(range_start, pvid); + + if (!br_vlan_fill_vids(skb, range_start->vid, +diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c +index 5514e1fc8d1faf..831e6d3a9c3bd7 100644 +--- a/net/bridge/br_vlan_options.c ++++ b/net/bridge/br_vlan_options.c +@@ -330,8 +330,7 @@ int br_vlan_process_options(const struct net_bridge *br, + continue; + } + +- if (v->vid == pvid || +- !br_vlan_can_enter_range(v, curr_end)) { ++ if (!br_vlan_can_enter_range(v, curr_end, pvid)) { + br_vlan_notify(br, p, curr_start->vid, + curr_end->vid, RTM_NEWVLAN); + curr_start = v; +-- +2.53.0 + diff --git a/queue-7.1/net-call-net_enable_timestamp-before-failure-in-sk_c.patch b/queue-7.1/net-call-net_enable_timestamp-before-failure-in-sk_c.patch new file mode 100644 index 0000000000..cfc9ecf08d --- /dev/null +++ b/queue-7.1/net-call-net_enable_timestamp-before-failure-in-sk_c.patch @@ -0,0 +1,59 @@ +From a5b03962faf16cd9fe748488d519e3beea76364f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 18:31:40 +0000 +Subject: net: Call net_enable_timestamp() before failure in sk_clone(). + +From: Kuniyuki Iwashima + +[ Upstream commit d50557779257a00162411e3048d82971ff1f644c ] + +When sk_clone() fails, sk_destruct() is called for the new socket. + +If the parent socket has SK_FLAGS_TIMESTAMP in sk->sk_flags, +net_disable_timestamp() is called for the child socket even though +net_enable_timestamp() is not called for it. + +Let's call net_enable_timestamp() before any failure path in +sk_clone(). + +Fixes: 704da560c0a0 ("tcp: update the netstamp_needed counter when cloning sockets") +Reported-by: Sashiko +Closes: https://lore.kernel.org/all/20260709032007.9E4D61F000E9@smtp.kernel.org/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Willem de Bruijn +Reviewed-by: Jason Xing +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260709183315.965751-3-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/sock.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/net/core/sock.c b/net/core/sock.c +index d0f518381334ca..5714436b087100 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -2549,6 +2549,9 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority, + + RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL); + ++ if (sock_needs_netstamp(sk) && newsk->sk_flags & SK_FLAGS_TIMESTAMP) ++ net_enable_timestamp(); ++ + rcu_read_lock(); + filter = rcu_dereference(sk->sk_filter); + if (filter != NULL) +@@ -2598,9 +2601,6 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority, + + if (newsk->sk_prot->sockets_allocated) + sk_sockets_allocated_inc(newsk); +- +- if (sock_needs_netstamp(sk) && newsk->sk_flags & SK_FLAGS_TIMESTAMP) +- net_enable_timestamp(); + out: + return newsk; + free: +-- +2.53.0 + diff --git a/queue-7.1/net-dpaa-fix-mode-setting.patch b/queue-7.1/net-dpaa-fix-mode-setting.patch new file mode 100644 index 0000000000..e2601b0c5e --- /dev/null +++ b/queue-7.1/net-dpaa-fix-mode-setting.patch @@ -0,0 +1,81 @@ +From 1ce33d55d1025e9c4d1af22b3d37250c8da29570 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 15:20:29 +0200 +Subject: net: dpaa: fix mode setting + +From: Michael Walle + +[ Upstream commit da2c6bcc5e30b1496ac587785dcacf6e849eb6ef ] + +Before converting to the phylink interface, the init function would have +set a non-reserved I/F mode in the maccfg2 register. After converting to +phylink, 0 is written as mode, which is a reserved value (although it's +the hardware default). Without a valid mode, a SGMII link is never +established between the MAC and the PHY and thus .link_up() is never +called which could set the correct mode according to the actual speed. + +Fix it by setting the maximum speed of the phy_interface_t in use in +.mac_config() - just like the driver did before the phylink conversion. + +Fixes: 5d93cfcf7360 ("net: dpaa: Convert to phylink") +Suggested-by: Sean Anderson +Signed-off-by: Michael Walle +Reviewed-by: Sean Anderson +Reviewed-by: Sean Anderson +Link: https://patch.msgid.link/20260717132401.2653252-1-mwalle@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/freescale/fman/fman_dtsec.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +index fe35703c509e55..b8d70c0ecb6c66 100644 +--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c ++++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c +@@ -900,22 +900,28 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, + { + struct mac_device *mac_dev = fman_config_to_mac(config); + struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs; +- u32 tmp; ++ u32 ecntrl, maccfg2; ++ ++ maccfg2 = ioread32be(®s->maccfg2); ++ maccfg2 &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE); + + switch (state->interface) { + case PHY_INTERFACE_MODE_RMII: +- tmp = DTSEC_ECNTRL_RMM; ++ ecntrl = DTSEC_ECNTRL_RMM; ++ maccfg2 |= MACCFG2_NIBBLE_MODE; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: +- tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; ++ ecntrl = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM; ++ maccfg2 |= MACCFG2_BYTE_MODE; + break; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: +- tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; ++ ecntrl = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM; ++ maccfg2 |= MACCFG2_BYTE_MODE; + break; + default: + dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n", +@@ -923,7 +929,8 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, + return; + } + +- iowrite32be(tmp, ®s->ecntrl); ++ iowrite32be(ecntrl, ®s->ecntrl); ++ iowrite32be(maccfg2, ®s->maccfg2); + } + + static void dtsec_link_up(struct phylink_config *config, struct phy_device *phy, +-- +2.53.0 + diff --git a/queue-7.1/net-drop_monitor-fix-info-leak-in-net_dm_attr_payloa.patch b/queue-7.1/net-drop_monitor-fix-info-leak-in-net_dm_attr_payloa.patch new file mode 100644 index 0000000000..5e0a81f73a --- /dev/null +++ b/queue-7.1/net-drop_monitor-fix-info-leak-in-net_dm_attr_payloa.patch @@ -0,0 +1,77 @@ +From 3631dc74693a18d682d037fead25e01b4ffaad38 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 21:28:17 +0900 +Subject: net: drop_monitor: fix info leak in NET_DM_ATTR_PAYLOAD + +From: Yehyeong Lee + +[ Upstream commit 5e9c8baee0329fbefe7c67aea945e2a07f15e98b ] + +net_dm_packet_report_fill() and net_dm_hw_packet_report_fill() open code +the NET_DM_ATTR_PAYLOAD attribute to avoid zeroing the packet payload +before overwriting it with skb_copy_bits(). + +skb_put() reserves nla_total_size(payload_len), i.e. the header plus the +NLA_ALIGN() padding, but only payload_len bytes are copied in. When +payload_len is not a multiple of 4 the 1-3 padding bytes are never +initialized and are leaked to user space inside the netlink message. + +KMSAN confirms the leak for the software path when the packet payload +length is not 4-byte aligned: + + BUG: KMSAN: kernel-infoleak in _copy_to_iter + _copy_to_iter + __skb_datagram_iter + skb_copy_datagram_iter + netlink_recvmsg + sock_recvmsg + __sys_recvfrom + Uninit was created at: + kmem_cache_alloc_node_noprof + __alloc_skb + net_dm_packet_work + Bytes 173-175 of 176 are uninitialized + +Use __nla_reserve(), which sets up the attribute header and zeroes the +padding, instead of open coding the attribute construction. + +Fixes: ca30707dee2b ("drop_monitor: Add packet alert mode") +Fixes: 5e58109b1ea4 ("drop_monitor: Add support for packet alert mode for hardware drops") +Suggested-by: Eric Dumazet +Signed-off-by: Yehyeong Lee +Link: https://patch.msgid.link/20260722122817.5548-1-yhlee@isslab.korea.ac.kr +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/drop_monitor.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c +index f23cea9e1aafb1..afcd8ba411b6ac 100644 +--- a/net/core/drop_monitor.c ++++ b/net/core/drop_monitor.c +@@ -671,9 +671,7 @@ static int net_dm_packet_report_fill(struct sk_buff *msg, struct sk_buff *skb, + if (nla_put_u16(msg, NET_DM_ATTR_PROTO, be16_to_cpu(skb->protocol))) + goto nla_put_failure; + +- attr = skb_put(msg, nla_total_size(payload_len)); +- attr->nla_type = NET_DM_ATTR_PAYLOAD; +- attr->nla_len = nla_attr_size(payload_len); ++ attr = __nla_reserve(msg, NET_DM_ATTR_PAYLOAD, payload_len); + if (skb_copy_bits(skb, 0, nla_data(attr), payload_len)) + goto nla_put_failure; + +@@ -831,9 +829,7 @@ static int net_dm_hw_packet_report_fill(struct sk_buff *msg, + if (nla_put_u16(msg, NET_DM_ATTR_PROTO, be16_to_cpu(skb->protocol))) + goto nla_put_failure; + +- attr = skb_put(msg, nla_total_size(payload_len)); +- attr->nla_type = NET_DM_ATTR_PAYLOAD; +- attr->nla_len = nla_attr_size(payload_len); ++ attr = __nla_reserve(msg, NET_DM_ATTR_PAYLOAD, payload_len); + if (skb_copy_bits(skb, 0, nla_data(attr), payload_len)) + goto nla_put_failure; + +-- +2.53.0 + diff --git a/queue-7.1/net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch b/queue-7.1/net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch new file mode 100644 index 0000000000..231c627360 --- /dev/null +++ b/queue-7.1/net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch @@ -0,0 +1,92 @@ +From 50973b4e9ae0f28c16f840a812d59de6f5485d12 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 23:09:45 +0800 +Subject: net: gre: fix lltx regression for GRE tunnels with SEQ/CSUM + +From: Yun Zhou + +[ Upstream commit 675ed582c1aa4d919dd535490de08c015005c653 ] + +Before commit 00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to +dev->lltx"), NETIF_F_LLTX was set unconditionally in both +__gre_tunnel_init() and ip6gre_tnl_init_features() alongside +GRE_FEATURES: + + dev->features |= GRE_FEATURES | NETIF_F_LLTX; + +When that commit converted NETIF_F_LLTX to the dev->lltx flag, it +placed 'dev->lltx = true' after the SEQ/CSUM early returns instead +of before them. This causes GRE/GRETAP/ip6gre tunnels with SEQ or +CSUM+encap to lose lockless TX, reintroducing _xmit_lock acquisition +around their ndo_start_xmit. Since GRE xmit re-enters the stack via +ip_tunnel_xmit(), holding _xmit_lock risks ABBA deadlock with the +underlay device. + + CPU0 CPU1 + ---- ---- + lock(&qdisc_xmit_lock_key#6); + lock(&qdisc_xmit_lock_key#3); + lock(&qdisc_xmit_lock_key#6); + lock(&qdisc_xmit_lock_key#3); + +Fix by moving dev->lltx = true before the early returns in both +functions, restoring the original unconditional behavior. + +Fixes: 00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to dev->lltx") +Signed-off-by: Yun Zhou +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260713150945.1779628-1-yun.zhou@windriver.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_gre.c | 4 ++-- + net/ipv6/ip6_gre.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index 0ebed1438f6c51..739b7fae8d3da2 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -1018,6 +1018,8 @@ static void __gre_tunnel_init(struct net_device *dev) + dev->features |= GRE_FEATURES; + dev->hw_features |= GRE_FEATURES; + ++ dev->lltx = true; ++ + /* TCP offload with GRE SEQ is not supported, nor can we support 2 + * levels of outer headers requiring an update. + */ +@@ -1029,8 +1031,6 @@ static void __gre_tunnel_init(struct net_device *dev) + + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; +- +- dev->lltx = true; + } + + static int ipgre_tunnel_init(struct net_device *dev) +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 8ebc99a299c954..1a81e80a124aac 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -1455,6 +1455,8 @@ static void ip6gre_tnl_init_features(struct net_device *dev) + dev->features |= GRE6_FEATURES; + dev->hw_features |= GRE6_FEATURES; + ++ dev->lltx = true; ++ + /* TCP offload with GRE SEQ is not supported, nor can we support 2 + * levels of outer headers requiring an update. + */ +@@ -1466,8 +1468,6 @@ static void ip6gre_tnl_init_features(struct net_device *dev) + + dev->features |= NETIF_F_GSO_SOFTWARE; + dev->hw_features |= NETIF_F_GSO_SOFTWARE; +- +- dev->lltx = true; + } + + static int ip6gre_tunnel_init_common(struct net_device *dev) +-- +2.53.0 + diff --git a/queue-7.1/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch b/queue-7.1/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch new file mode 100644 index 0000000000..147dc52d77 --- /dev/null +++ b/queue-7.1/net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch @@ -0,0 +1,56 @@ +From 088875f4213668d393e719b0b7cd5016219cf269 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 10:12:40 +0000 +Subject: net: hsr: fix memory leak on slave unregistration by removing synced + VLANs + +From: Eric Dumazet + +[ Upstream commit dcf15eaf5641812f1cfc5e96537380132a7da89d ] + +When an HSR master device is brought UP, it auto-adds VLAN 0 via +vlan_vid0_add(), which propagates VID 0 to its slave devices (slave A and B). + +If a slave device is later unregistered while HSR is active (e.g., during +netns cleanup or interface destruction), hsr_del_port() is called to +detach the slave port from the HSR master. However, hsr_del_port() currently +does not delete the VLAN IDs that were synced to the slave device by HSR. + +As a result, the slave device retains a refcount on VID 0 (and any other +synced VLANs). When the slave device is destroyed, its vlan_info / +vlan_vid_info structure remains allocated, leading to a memory leak. + +Fix this by calling vlan_vids_del_by_dev(port->dev, master->dev) in +hsr_del_port() before unlinking slave A or slave B ports, matching the +propagation logic in hsr_ndo_vlan_rx_add_vid() / hsr_ndo_vlan_rx_kill_vid() +and the cleanup behavior in bonding and team drivers. + +Fixes: 1a8a63a5305e ("net: hsr: Add VLAN CTAG filter support") +Reported-by: syzbot+456957213f32970c0762@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/netdev/6a4cb6ca.57639fcc.86d58.000b.GAE@google.com/T/#u +Signed-off-by: Eric Dumazet +Reviewed-by: Fernando Fernandez Mancera +Reviewed-by: Felix Maurer +Link: https://patch.msgid.link/20260721101240.995597-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/hsr/hsr_slave.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c +index d9af9e65f72f07..01c73b4b50ddd8 100644 +--- a/net/hsr/hsr_slave.c ++++ b/net/hsr/hsr_slave.c +@@ -242,6 +242,8 @@ void hsr_del_port(struct hsr_port *port) + netdev_rx_handler_unregister(port->dev); + if (!port->hsr->fwd_offloaded) + dev_set_promiscuity(port->dev, -1); ++ if (port->type == HSR_PT_SLAVE_A || port->type == HSR_PT_SLAVE_B) ++ vlan_vids_del_by_dev(port->dev, master->dev); + netdev_upper_dev_unlink(port->dev, master->dev); + if (hsr->prot_version == PRP_V1 && + port->type == HSR_PT_SLAVE_B) { +-- +2.53.0 + diff --git a/queue-7.1/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch b/queue-7.1/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch new file mode 100644 index 0000000000..d2ea7a1085 --- /dev/null +++ b/queue-7.1/net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch @@ -0,0 +1,48 @@ +From e0a7bb9d0ba934b3edd12d9879e5f81842aca5b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 22:32:30 +0800 +Subject: net: ipv6: fix dif and sdif mismatch in raw6_icmp_error + +From: Li RongQing + +[ Upstream commit 440e274da4d1b93c7df2cb0ce893c3009dd4db55 ] + +In raw6_icmp_error(), raw_v6_match() is called with inet6_iif(skb) passed +to both the 'dif' and 'sdif' arguments. This is a copy-paste or typo error, +as the last argument should represent the secondary interface index (sdif). + +This mismatch breaks ICMPv6 error handling for IPv6 raw sockets in VRF +(Virtual Routing and Forwarding) environments. When a raw socket is bound +to a VRF master device, raw_v6_match() fails to find a match because it is +not given the correct sdif value, causing the socket to miss relevant +ICMPv6 error notifications. + +Fix this by properly passing inet6_sdif(skb) as the last argument to +raw_v6_match(). + +Fixes: 5108ab4bf446fa ("net: ipv6: add second dif to raw socket lookups") +Signed-off-by: Li RongQing +Reviewed-by: Joe Damato +Link: https://patch.msgid.link/20260717143230.1836-1-lirongqing@baidu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/raw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c +index 3cc58698cbbd3a..b88d364e78aae9 100644 +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -349,7 +349,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, + const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data; + + if (!raw_v6_match(net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr, +- inet6_iif(skb), inet6_iif(skb))) ++ inet6_iif(skb), inet6_sdif(skb))) + continue; + rawv6_err(sk, skb, type, code, inner_offset, info); + } +-- +2.53.0 + diff --git a/queue-7.1/net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch b/queue-7.1/net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch new file mode 100644 index 0000000000..0882e3b5a6 --- /dev/null +++ b/queue-7.1/net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch @@ -0,0 +1,68 @@ +From 8ebb33cc9f0446f0c6f2a60cd218d096554b639b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 16:25:17 +0900 +Subject: net: mctp i3c: clean up notifier and buses if driver register fails + +From: Myeonghun Pak + +[ Upstream commit 03d1057305ef17ac3f5936ac1580bc9a1a826e14 ] + +mctp_i3c_mod_init() registers the I3C bus notifier and then walks the +existing buses with i3c_for_each_bus_locked(mctp_i3c_bus_add_new, NULL) +before registering the I3C device driver. If i3c_driver_register() +fails, the function returns the error directly, leaving the notifier +registered and every mctp_i3c_bus object created for the existing buses +allocated. The notifier is left pointing into the module that failed to +load and the bus list is leaked. + +Mirror the module exit path on this failure: unregister the notifier and +tear down the buses that were added before returning the error. + +This issue was identified during our ongoing static-analysis research while +reviewing kernel code. + +Fixes: c8755b29b58e ("mctp i3c: MCTP I3C driver") +Co-developed-by: Ijae Kim +Signed-off-by: Ijae Kim +Signed-off-by: Myeonghun Pak +Acked-by: Jeremy Kerr +Link: https://patch.msgid.link/20260715072517.13216-1-mhun512@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/mctp/mctp-i3c.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c +index 6d2bbae7477b39..88d9e36cd4a2bc 100644 +--- a/drivers/net/mctp/mctp-i3c.c ++++ b/drivers/net/mctp/mctp-i3c.c +@@ -731,18 +731,21 @@ static __init int mctp_i3c_mod_init(void) + int rc; + + rc = i3c_register_notifier(&mctp_i3c_notifier); +- if (rc < 0) { +- i3c_driver_unregister(&mctp_i3c_driver); ++ if (rc < 0) + return rc; +- } + + i3c_for_each_bus_locked(mctp_i3c_bus_add_new, NULL); + + rc = i3c_driver_register(&mctp_i3c_driver); + if (rc < 0) +- return rc; ++ goto err_unregister_notifier; + + return 0; ++ ++err_unregister_notifier: ++ i3c_unregister_notifier(&mctp_i3c_notifier); ++ mctp_i3c_bus_remove_all(); ++ return rc; + } + + static __exit void mctp_i3c_mod_exit(void) +-- +2.53.0 + diff --git a/queue-7.1/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch b/queue-7.1/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch new file mode 100644 index 0000000000..8965d94b3e --- /dev/null +++ b/queue-7.1/net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch @@ -0,0 +1,51 @@ +From abeb9acf6fb2014a552bf60b0f503041836cd596 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:33:06 +0300 +Subject: net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule + +From: Yael Chemla + +[ Upstream commit d12956d083eb70f2c6d72711aebaf8c2ce21e170 ] + +esw_egress_acl_vlan_create() hardcodes num_dest=0 in its +mlx5_add_flow_rules() call. When invoked from the non-bond path +fwd_dest is NULL and num_dest=0 is correct. When invoked from +esw_acl_egress_ofld_rules_create() during a bond event, fwd_dest is +non-NULL and flow_act.action carries MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, +but _mlx5_add_flow_rules() rejects a non-NULL dest pointer paired with +dest_num<=0 and returns -EINVAL. The error propagates as +"configure slave vport egress fwd, err(-22)". The passive vport's egress +ACL table ends up with its flow groups allocated but no FTEs, so +prio-tagged packets are not popped and bond failover is broken on +prio_tag_required devices. + +Fix by passing fwd_dest ? 1 : 0 as num_dest to match the actual number +of destinations supplied. + +Fixes: bf773dc0e6d5 ("net/mlx5: E-Switch, Introduce APIs to enable egress acl forward-to-vport rule") +Signed-off-by: Yael Chemla +Reviewed-by: Cosmin Ratiu +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20260717073306.1242399-1-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +index ba5cce706ea269..9693c74e9b16a4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +@@ -71,7 +71,7 @@ int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw, + flow_act.action = flow_action; + vport->egress.allowed_vlan = + mlx5_add_flow_rules(vport->egress.acl, spec, +- &flow_act, fwd_dest, 0); ++ &flow_act, fwd_dest, fwd_dest ? 1 : 0); + if (IS_ERR(vport->egress.allowed_vlan)) { + err = PTR_ERR(vport->egress.allowed_vlan); + esw_warn(esw->dev, +-- +2.53.0 + diff --git a/queue-7.1/net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch b/queue-7.1/net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch new file mode 100644 index 0000000000..edd6532c1f --- /dev/null +++ b/queue-7.1/net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch @@ -0,0 +1,93 @@ +From c2211cef9167a1269998bce817219a2e8c067ee8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:23:38 +0300 +Subject: net/mlx5: Fix MCIA register buffer overflow on 32 dword reads + +From: Gal Pressman + +[ Upstream commit 11c057d23465c7a5817a7284c896d19d54c0b616 ] + +The MCIA register can return up to 32 dwords (128 bytes) when the device +advertises the mcia_32dwords capability, but struct +mlx5_ifc_mcia_reg_bits only defines dword_0..11, leaving room for just +12 dwords (48 bytes) of data. + +mlx5_query_mcia() clamps the read size to mlx5_mcia_max_bytes() and then +memcpy()s that many bytes out of the register, potentially reading past +the end of the 'out' buffer. On kernels built with FORTIFY_SOURCE this +is caught as a buffer overflow while reading the module EEPROM via +ethtool: + + detected buffer overflow in memcpy + kernel BUG at lib/string_helpers.c:1048! + RIP: 0010:fortify_panic+0x13/0x20 + Call Trace: + mlx5_query_mcia.isra.0+0x200/0x210 [mlx5_core] + mlx5_query_module_eeprom_by_page+0x4a/0xa0 [mlx5_core] + mlx5e_get_module_eeprom_by_page+0xbb/0x120 [mlx5_core] + eeprom_prepare_data+0xf3/0x170 + ethnl_default_doit+0xf1/0x3b0 + +Extend the mcia_reg layout to 32 dwords. + +Fixes: 271907ee2f29 ("net/mlx5: Query the maximum MCIA register read size from firmware") +Signed-off-by: Gal Pressman +Reviewed-by: Alex Lazar +Signed-off-by: Tariq Toukan +Link: https://patch.msgid.link/20260717072338.1240582-1-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/port.c | 4 ++-- + include/linux/mlx5/mlx5_ifc.h | 13 +------------ + 2 files changed, 3 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c +index ee8b9765c5bafd..2cba370a01d468 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c +@@ -314,7 +314,7 @@ static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num, + return -EIO; + } + +- ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); ++ ptr = MLX5_ADDR_OF(mcia_reg, out, dwords); + + *module_id = ptr[0]; + +@@ -399,7 +399,7 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev, + return -EIO; + } + +- ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0); ++ ptr = MLX5_ADDR_OF(mcia_reg, out, dwords); + memcpy(data, ptr, size); + + return size; +diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h +index 49f3ad4b1a7c54..dfd98e17fe688d 100644 +--- a/include/linux/mlx5/mlx5_ifc.h ++++ b/include/linux/mlx5/mlx5_ifc.h +@@ -12203,18 +12203,7 @@ struct mlx5_ifc_mcia_reg_bits { + + u8 reserved_at_60[0x20]; + +- u8 dword_0[0x20]; +- u8 dword_1[0x20]; +- u8 dword_2[0x20]; +- u8 dword_3[0x20]; +- u8 dword_4[0x20]; +- u8 dword_5[0x20]; +- u8 dword_6[0x20]; +- u8 dword_7[0x20]; +- u8 dword_8[0x20]; +- u8 dword_9[0x20]; +- u8 dword_10[0x20]; +- u8 dword_11[0x20]; ++ u8 dwords[0x400]; + }; + + struct mlx5_ifc_dcbx_param_bits { +-- +2.53.0 + diff --git a/queue-7.1/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch b/queue-7.1/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch new file mode 100644 index 0000000000..d631c8aa62 --- /dev/null +++ b/queue-7.1/net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch @@ -0,0 +1,46 @@ +From 70d3d086333a2663a6f9b429ed2359f4a2a7fdb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:25 +0300 +Subject: net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation + +From: Alexei Lazar + +[ Upstream commit 9173e1d3c7c7d49a71eee813091f9e834ec7cee5 ] + +Credit Based (CB) TSA is not supported by the mlx5 driver, so reject +any configurations that specify it. + +Fixes: 08fb1dacdd76 ("net/mlx5e: Support DCBNL IEEE ETS") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-3-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 762f0a46c12097..00e706e1ede111 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -324,6 +324,14 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev, + } + } + ++ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { ++ if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_CB_SHAPER) { ++ netdev_err(netdev, ++ "Failed to validate ETS: CB Shaper is not supported\n"); ++ return -EOPNOTSUPP; ++ } ++ } ++ + /* Validate Bandwidth Sum */ + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { +-- +2.53.0 + diff --git a/queue-7.1/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch b/queue-7.1/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch new file mode 100644 index 0000000000..be0a6104ba --- /dev/null +++ b/queue-7.1/net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch @@ -0,0 +1,53 @@ +From cf481cdb0af54c5324d8d9d079a34963054f7a09 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 10:51:24 +0300 +Subject: net/mlx5e: Report zero bandwidth for non-ETS traffic classes + +From: Alexei Lazar + +[ Upstream commit ffb1873b2df11945b8c395e859169248675c91c5 ] + +The IEEE 802.1Qaz standard defines that bandwidth allocation percentages +only apply to Enhanced Transmission Selection (ETS) traffic classes. +For STRICT and VENDOR transmission selection algorithms, bandwidth +percentage values are not applicable. + +Currently for non-ETS 100 bandwidth is being reported for all traffic +classes in the get operation due to hardware limitation, regardless of +their TSA type. + +Fix this by reporting 0 for non-ETS traffic classes. + +Fixes: 820c2c5e773d ("net/mlx5e: Read ETS settings directly from firmware") +Signed-off-by: Alexei Lazar +Reviewed-by: Carolina Jubran +Signed-off-by: Tariq Toukan +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260717075125.1244877-2-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +index 4b86df6d5b9eaa..762f0a46c12097 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +@@ -173,6 +173,13 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, + } + memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa)); + ++ /* Report 0 for non ETS TSA */ ++ for (i = 0; i < ets->ets_cap; i++) { ++ if (ets->tc_tx_bw[i] == MLX5E_MAX_BW_ALLOC && ++ priv->dcbx.tc_tsa[i] != IEEE_8021QAZ_TSA_ETS) ++ ets->tc_tx_bw[i] = 0; ++ } ++ + return err; + } + +-- +2.53.0 + diff --git a/queue-7.1/net-packet-avoid-fanout-hook-re-registration-after-u.patch b/queue-7.1/net-packet-avoid-fanout-hook-re-registration-after-u.patch new file mode 100644 index 0000000000..8e8a0db161 --- /dev/null +++ b/queue-7.1/net-packet-avoid-fanout-hook-re-registration-after-u.patch @@ -0,0 +1,61 @@ +From 8c1bba094067f7a05f9861a73a3bd70806538c27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:44:37 +0000 +Subject: net/packet: avoid fanout hook re-registration after unregister + +From: David Lee + +[ Upstream commit 50aff80475abd3533eef4320477037e6fcc6b56e ] + +packet_set_ring() temporarily detaches a socket from packet delivery while +reconfiguring its ring. It records the previous running state, clears +po->num, unregisters the protocol hook when needed, drops po->bind_lock, +and later restores po->num and re-registers the hook from the saved +was_running value. + +That unlocked window can race with NETDEV_UNREGISTER. The notifier can +observe the socket as not running, skip __unregister_prot_hook(), and +invalidate the per-socket binding by setting po->ifindex to -1 and clearing +po->prot_hook.dev. A one-member fanout group can still retain its shared +fanout hook device pointer. When packet_set_ring() resumes, re-registering +solely from the stale was_running state can re-add the fanout hook after +the device has been unregistered. + +Treat po->ifindex == -1 as an invalidated binding after reacquiring +po->bind_lock. This is distinct from ifindex 0, the normal +unbound/wildcard state: ifindex -1 marks an existing device binding that +was invalidated when the device was unregistered. Restore po->num as +before, but do not re-register the hook if device unregister already +detached the socket. + +Fixes: dc99f600698d ("packet: Add fanout support.") +Link: https://lore.kernel.org/netdev/20260701113947.23180-1-david.lee@trailofbits.com/ +Signed-off-by: David Lee +Reviewed-by: Willem de Bruijn +Link: https://patch.msgid.link/20260707104440.833129-1-david.lee@trailofbits.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/packet/af_packet.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c +index 8e6f3a734ba0bd..e75d2932475ac0 100644 +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -4561,7 +4561,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, + + spin_lock(&po->bind_lock); + WRITE_ONCE(po->num, num); +- if (was_running) ++ /* ++ * NETDEV_UNREGISTER may have invalidated the binding while bind_lock ++ * was dropped above. Do not re-add a fanout hook to a dead device. ++ */ ++ if (was_running && READ_ONCE(po->ifindex) != -1) + register_prot_hook(sk); + + spin_unlock(&po->bind_lock); +-- +2.53.0 + diff --git a/queue-7.1/net-phy-marvell-fix-return-code.patch b/queue-7.1/net-phy-marvell-fix-return-code.patch new file mode 100644 index 0000000000..390b5ca1ef --- /dev/null +++ b/queue-7.1/net-phy-marvell-fix-return-code.patch @@ -0,0 +1,37 @@ +From 692f034669b528cca2cfe12f85aa188a11c78e1b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 14:06:27 +0200 +Subject: net: phy: marvell: fix return code + +From: Michael Walle + +[ Upstream commit 7d8ca62d6a9ef593780161586b4efc811ac094fe ] + +Return the correct error code, not the value written to the register. + +Fixes: a219912e0fec ("net: phy: marvell: implement config_inband() method") +Signed-off-by: Michael Walle +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260706120637.1947685-1-mwalle@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/phy/marvell.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c +index 7a578b5aa2ed60..f71cffa8840628 100644 +--- a/drivers/net/phy/marvell.c ++++ b/drivers/net/phy/marvell.c +@@ -753,7 +753,7 @@ static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes) + err = phy_modify(phydev, MII_M1111_PHY_EXT_SR, + MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr); + if (err < 0) +- return extsr; ++ return err; + + return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR, + BMCR_ANENABLE, bmcr); +-- +2.53.0 + diff --git a/queue-7.1/net-qrtr-restrict-socket-creation-to-the-initial-net.patch b/queue-7.1/net-qrtr-restrict-socket-creation-to-the-initial-net.patch new file mode 100644 index 0000000000..191b1d9a33 --- /dev/null +++ b/queue-7.1/net-qrtr-restrict-socket-creation-to-the-initial-net.patch @@ -0,0 +1,63 @@ +From c0019d7c4d921507c5c7a3f3cbea7a02fcce960e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 12:43:19 -0300 +Subject: net: qrtr: restrict socket creation to the initial network namespace + +From: Aldo Ariel Panzardo + +[ Upstream commit 3b536db8fb32da9e9c62f2bb45e2e319331f0426 ] + +QRTR keeps its entire port and node state in module-global variables +that are not partitioned per network namespace: qrtr_local_nid is a +single global node id (always 1) and qrtr_ports is a single global +xarray. qrtr_port_lookup() and qrtr_local_enqueue() operate on that +global state with no network-namespace check, and qrtr_create() places +no restriction on the namespace a socket is created in. + +As a result an unprivileged process that creates an AF_QIPCRTR socket +in a separate network namespace, e.g. via +unshare(CLONE_NEWUSER | CLONE_NEWNET), can send QRTR datagrams - +including control-plane messages such as QRTR_TYPE_NEW_SERVER - to QRTR +sockets owned by another namespace, and vice versa. The receiving +socket sees such a message as coming from node id 1, indistinguishable +from a legitimate local client, breaking the isolation that network +namespaces are expected to provide. + +QRTR is a transport to global hardware endpoints (the modem and other +remote processors) and has no per-namespace semantics; its in-kernel +name service already creates its socket in init_net only. Confine the +socket family to the initial network namespace, as other +non-namespace-aware socket families do (see llc_ui_create() and the +ieee802154 socket code). + +Fixes: bdabad3e363d ("net: Add Qualcomm IPC router") +Signed-off-by: Aldo Ariel Panzardo +Link: https://patch.msgid.link/20260716154319.3297699-1-qwe.aldo@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/qrtr/af_qrtr.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c +index 2288159f5b1bba..7482a09adb54f9 100644 +--- a/net/qrtr/af_qrtr.c ++++ b/net/qrtr/af_qrtr.c +@@ -1261,6 +1261,14 @@ static int qrtr_create(struct net *net, struct socket *sock, + if (sock->type != SOCK_DGRAM) + return -EPROTOTYPE; + ++ /* QRTR keeps its port and node state in module-global variables that ++ * are not partitioned per network namespace, and the in-kernel name ++ * service only operates in init_net. Confine the family to init_net so ++ * a socket in another namespace cannot reach the global control plane. ++ */ ++ if (!net_eq(net, &init_net)) ++ return -EAFNOSUPPORT; ++ + sk = sk_alloc(net, AF_QIPCRTR, GFP_KERNEL, &qrtr_proto, kern); + if (!sk) + return -ENOMEM; +-- +2.53.0 + diff --git a/queue-7.1/net-sched-handle-tc_act_redirect-from-qdisc-filter-c.patch b/queue-7.1/net-sched-handle-tc_act_redirect-from-qdisc-filter-c.patch new file mode 100644 index 0000000000..a51ef505e8 --- /dev/null +++ b/queue-7.1/net-sched-handle-tc_act_redirect-from-qdisc-filter-c.patch @@ -0,0 +1,283 @@ +From 95a3d4aceb8d23867a1ecd0b691db98e83905e9d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 20:56:08 +0200 +Subject: net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains + +From: Jamal Hadi Salim + +[ Upstream commit ec48b3be2c8595dd290be883dbd4fb8b2f9f5d5e ] + +When a TC filter attached to a qdisc filter chain returns +TC_ACT_REDIRECT (ex: via an eBPF program calling bpf_redirect() or an +act_bpf action), the redirect was silently lost i.e no qdisc classify +function handled TC_ACT_REDIRECT, so the packet fell through the +switch and was enqueued normally instead of being redirected. + +This has been broken since bpf_redirect() was introduced for TC in +commit 27b29f63058d ("bpf: add bpf_redirect() helper"). We got lucky +for a long time because bpf_net_context was a per-CPU variable that +was always available. + +commit 401cb7dae813 ("net: Reference bpf_redirect_info via task_struct +on PREEMPT_RT.") turned bpf_net_context into a task_struct member that +is only set up by explicit callers. Without a caller setting it up, +bpf_redirect() itself crashes with a NULL pointer dereference in +bpf_net_ctx_get_ri(). However, even with bpf_net_context available, +TC_ACT_REDIRECT from qdisc filter chains cannot be honored without +adding skb_do_redirect() calls to every qdisc classify function, which +would require changes across net/sched/. Isolate it to ebpf core where +it belongs. + +Instead, add a tcf_classify_qdisc() inline helper in pkt_cls.h, as a +wrapper around tcf_classify() for use by qdisc classify functions and +tcf_qevent_handle(). When the classify verdict is TC_ACT_REDIRECT, +the wrapper converts it to TC_ACT_SHOT, dropping the packet rather +than letting it continue silently. Dropping is preferred over +letting the packet through because the user immediately sees packet +loss. Silently passing the packet through would hide the problem and +leave the user wondering why their redirect is not working. + +The clsact fast path, tc_run() continues to call tcf_classify() directly +and is unaffected: TC_ACT_REDIRECT is returned as-is and handled by +sch_handle_egress/ingress() calling skb_do_redirect() as before. + +Fixes: 27b29f63058d ("bpf: add bpf_redirect() helper") +Fixes: 401cb7dae813 ("net: Reference bpf_redirect_info via task_struct on PREEMPT_RT.") +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Signed-off-by: Daniel Borkmann +Reviewed-by: Sebastian Andrzej Siewior +Link: https://patch.msgid.link/20260706185609.330006-3-daniel@iogearbox.net +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/pkt_cls.h | 14 +++++++++++++- + net/sched/cls_api.c | 4 +--- + net/sched/sch_cake.c | 2 +- + net/sched/sch_drr.c | 2 +- + net/sched/sch_dualpi2.c | 2 +- + net/sched/sch_ets.c | 2 +- + net/sched/sch_fq_codel.c | 2 +- + net/sched/sch_fq_pie.c | 2 +- + net/sched/sch_hfsc.c | 2 +- + net/sched/sch_htb.c | 2 +- + net/sched/sch_multiq.c | 2 +- + net/sched/sch_prio.c | 2 +- + net/sched/sch_qfq.c | 2 +- + net/sched/sch_sfb.c | 2 +- + net/sched/sch_sfq.c | 2 +- + 15 files changed, 27 insertions(+), 17 deletions(-) + +diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h +index 99ac747b790607..7f0c422307f455 100644 +--- a/include/net/pkt_cls.h ++++ b/include/net/pkt_cls.h +@@ -156,8 +156,20 @@ static inline int tcf_classify(struct sk_buff *skb, + { + return TC_ACT_UNSPEC; + } +- + #endif ++static inline int tcf_classify_qdisc(struct sk_buff *skb, ++ const struct tcf_proto *tp, ++ struct tcf_result *res, bool compat_mode) ++{ ++ int ret = tcf_classify(skb, NULL, tp, res, compat_mode); ++ ++ /* TC_ACT_REDIRECT from qdisc filter chains is not supported. ++ * Use BPF via tcx or mirred redirect instead. ++ */ ++ if (unlikely(ret == TC_ACT_REDIRECT)) ++ ret = TC_ACT_SHOT; ++ return ret; ++} + + static inline unsigned long + __cls_set_class(unsigned long *clp, unsigned long cl) +diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c +index 523cf2a8bd1d6d..fee4524adc98ef 100644 +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -4045,9 +4045,7 @@ struct sk_buff *tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, stru + + fl = rcu_dereference_bh(qe->filter_chain); + +- switch (tcf_classify(skb, NULL, fl, &cl_res, false)) { +- case TC_ACT_REDIRECT: +- fallthrough; ++ switch (tcf_classify_qdisc(skb, fl, &cl_res, false)) { + case TC_ACT_SHOT: + qdisc_qstats_drop(sch); + __qdisc_drop(skb, to_free); +diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c +index 07ea175657bb8e..b967b7153ad34e 100644 +--- a/net/sched/sch_cake.c ++++ b/net/sched/sch_cake.c +@@ -1727,7 +1727,7 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t, + goto hash; + + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; +- result = tcf_classify(skb, NULL, filter, &res, false); ++ result = tcf_classify_qdisc(skb, filter, &res, false); + + if (result >= 0) { + #ifdef CONFIG_NET_CLS_ACT +diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c +index 2eedd3a4322ad5..c7d489feec614a 100644 +--- a/net/sched/sch_drr.c ++++ b/net/sched/sch_drr.c +@@ -314,7 +314,7 @@ static struct drr_class *drr_classify(struct sk_buff *skb, struct Qdisc *sch, + + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; + fl = rcu_dereference_bh(q->filter_list); +- result = tcf_classify(skb, NULL, fl, &res, false); ++ result = tcf_classify_qdisc(skb, fl, &res, false); + if (result >= 0) { + #ifdef CONFIG_NET_CLS_ACT + switch (result) { +diff --git a/net/sched/sch_dualpi2.c b/net/sched/sch_dualpi2.c +index 27088760eff443..4f678d4ff10ec7 100644 +--- a/net/sched/sch_dualpi2.c ++++ b/net/sched/sch_dualpi2.c +@@ -364,7 +364,7 @@ static int dualpi2_skb_classify(struct dualpi2_sched_data *q, + if (!fl) + return NET_XMIT_SUCCESS; + +- result = tcf_classify(skb, NULL, fl, &res, false); ++ result = tcf_classify_qdisc(skb, fl, &res, false); + if (result >= 0) { + #ifdef CONFIG_NET_CLS_ACT + switch (result) { +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index c817e0a6c14653..dc72a7a44813ad 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -393,7 +393,7 @@ static struct ets_class *ets_classify(struct sk_buff *skb, struct Qdisc *sch, + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; + if (TC_H_MAJ(skb->priority) != sch->handle) { + fl = rcu_dereference_bh(q->filter_list); +- err = tcf_classify(skb, NULL, fl, &res, false); ++ err = tcf_classify_qdisc(skb, fl, &res, false); + #ifdef CONFIG_NET_CLS_ACT + switch (err) { + case TC_ACT_STOLEN: +diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c +index 09ab84580160ae..ac4eeb5fe51cc0 100644 +--- a/net/sched/sch_fq_codel.c ++++ b/net/sched/sch_fq_codel.c +@@ -91,7 +91,7 @@ static unsigned int fq_codel_classify(struct sk_buff *skb, struct Qdisc *sch, + return fq_codel_hash(q, skb) + 1; + + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; +- result = tcf_classify(skb, NULL, filter, &res, false); ++ result = tcf_classify_qdisc(skb, filter, &res, false); + if (result >= 0) { + #ifdef CONFIG_NET_CLS_ACT + switch (result) { +diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c +index 0a4eca4ab086eb..1815f93abb1359 100644 +--- a/net/sched/sch_fq_pie.c ++++ b/net/sched/sch_fq_pie.c +@@ -96,7 +96,7 @@ static unsigned int fq_pie_classify(struct sk_buff *skb, struct Qdisc *sch, + return fq_pie_hash(q, skb) + 1; + + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; +- result = tcf_classify(skb, NULL, filter, &res, false); ++ result = tcf_classify_qdisc(skb, filter, &res, false); + if (result >= 0) { + #ifdef CONFIG_NET_CLS_ACT + switch (result) { +diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c +index 50112c8a71e033..33801faf16209c 100644 +--- a/net/sched/sch_hfsc.c ++++ b/net/sched/sch_hfsc.c +@@ -1143,7 +1143,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; + head = &q->root; + tcf = rcu_dereference_bh(q->root.filter_list); +- while (tcf && (result = tcf_classify(skb, NULL, tcf, &res, false)) >= 0) { ++ while (tcf && (result = tcf_classify_qdisc(skb, tcf, &res, false)) >= 0) { + #ifdef CONFIG_NET_CLS_ACT + switch (result) { + case TC_ACT_QUEUED: +diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c +index ccabafed3fe44a..75b9e534a8063b 100644 +--- a/net/sched/sch_htb.c ++++ b/net/sched/sch_htb.c +@@ -242,7 +242,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, + } + + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; +- while (tcf && (result = tcf_classify(skb, NULL, tcf, &res, false)) >= 0) { ++ while (tcf && (result = tcf_classify_qdisc(skb, tcf, &res, false)) >= 0) { + #ifdef CONFIG_NET_CLS_ACT + switch (result) { + case TC_ACT_QUEUED: +diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c +index a467dd12236970..66df30939aa5c1 100644 +--- a/net/sched/sch_multiq.c ++++ b/net/sched/sch_multiq.c +@@ -36,7 +36,7 @@ multiq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) + int err; + + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; +- err = tcf_classify(skb, NULL, fl, &res, false); ++ err = tcf_classify_qdisc(skb, fl, &res, false); + #ifdef CONFIG_NET_CLS_ACT + switch (err) { + case TC_ACT_STOLEN: +diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c +index fe42ae3d6b696b..9da76296177aef 100644 +--- a/net/sched/sch_prio.c ++++ b/net/sched/sch_prio.c +@@ -39,7 +39,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; + if (TC_H_MAJ(skb->priority) != sch->handle) { + fl = rcu_dereference_bh(q->filter_list); +- err = tcf_classify(skb, NULL, fl, &res, false); ++ err = tcf_classify_qdisc(skb, fl, &res, false); + #ifdef CONFIG_NET_CLS_ACT + switch (err) { + case TC_ACT_STOLEN: +diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c +index 195c434aae5f7e..413fa89673e7df 100644 +--- a/net/sched/sch_qfq.c ++++ b/net/sched/sch_qfq.c +@@ -709,7 +709,7 @@ static struct qfq_class *qfq_classify(struct sk_buff *skb, struct Qdisc *sch, + + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; + fl = rcu_dereference_bh(q->filter_list); +- result = tcf_classify(skb, NULL, fl, &res, false); ++ result = tcf_classify_qdisc(skb, fl, &res, false); + if (result >= 0) { + #ifdef CONFIG_NET_CLS_ACT + switch (result) { +diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c +index efd9251c3add31..ea1998a21d3b2b 100644 +--- a/net/sched/sch_sfb.c ++++ b/net/sched/sch_sfb.c +@@ -260,7 +260,7 @@ static bool sfb_classify(struct sk_buff *skb, struct tcf_proto *fl, + struct tcf_result res; + int result; + +- result = tcf_classify(skb, NULL, fl, &res, false); ++ result = tcf_classify_qdisc(skb, fl, &res, false); + if (result >= 0) { + #ifdef CONFIG_NET_CLS_ACT + switch (result) { +diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c +index f9807ee2cf6c72..04c8c2cae26bc5 100644 +--- a/net/sched/sch_sfq.c ++++ b/net/sched/sch_sfq.c +@@ -171,7 +171,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch, + return sfq_hash(q, skb) + 1; + + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; +- result = tcf_classify(skb, NULL, fl, &res, false); ++ result = tcf_classify_qdisc(skb, fl, &res, false); + if (result >= 0) { + #ifdef CONFIG_NET_CLS_ACT + switch (result) { +-- +2.53.0 + diff --git a/queue-7.1/net-stmmac-dwmac4-mask-interrupts-when-stopping-dma-.patch b/queue-7.1/net-stmmac-dwmac4-mask-interrupts-when-stopping-dma-.patch new file mode 100644 index 0000000000..cf9774e7d7 --- /dev/null +++ b/queue-7.1/net-stmmac-dwmac4-mask-interrupts-when-stopping-dma-.patch @@ -0,0 +1,135 @@ +From fb4625914b65912dc2c5488453ca93ada3659932 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 13:15:29 +0200 +Subject: net: stmmac: dwmac4: mask interrupts when stopping DMA in suspend + +From: Luis Lang + +[ Upstream commit 59a57128ae5231f9aa9d544fa9d3e38986f0efaa ] + +Since commit 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU +interrupts"), suspending causes an interrupt storm from the RPS +interrupt. +Fix this by adding a deinit_chan() op to stmmac_dma_ops, which +masks all default dma channel interrupts. This is called from +stmmac_stop_all_dma(), so interrupts don't trigger while suspending. + +Fixes: 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts") +Suggested-by: Andrew Lunn +Suggested-by: Maxime Chevallier +Signed-off-by: Luis Lang +Reviewed-by: Andrew Lunn +Tested-by: Maxime Chevallier +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260720111534.163416-1-luis.la@mail.de +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 24 +++++++++++++++++++ + drivers/net/ethernet/stmicro/stmmac/hwif.h | 4 ++++ + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++++ + 3 files changed, 32 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +index 28728271fbc9ef..55c170b930106c 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +@@ -106,6 +106,17 @@ static void dwmac4_dma_init_channel(struct stmmac_priv *priv, + ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); + } + ++static void dwmac4_dma_deinit_channel(struct stmmac_priv *priv, ++ void __iomem *ioaddr, u32 chan) ++{ ++ const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; ++ u32 value; ++ ++ value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); ++ value &= ~DMA_CHAN_INTR_DEFAULT_MASK; ++ writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); ++} ++ + static void dwmac410_dma_init_channel(struct stmmac_priv *priv, + void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, u32 chan) +@@ -125,6 +136,17 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv, + ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); + } + ++static void dwmac410_dma_deinit_channel(struct stmmac_priv *priv, ++ void __iomem *ioaddr, u32 chan) ++{ ++ const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; ++ u32 value; ++ ++ value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); ++ value &= ~DMA_CHAN_INTR_DEFAULT_MASK_4_10; ++ writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); ++} ++ + static void dwmac4_dma_init(void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg) + { +@@ -547,6 +569,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = { + .reset = dwmac4_dma_reset, + .init = dwmac4_dma_init, + .init_chan = dwmac4_dma_init_channel, ++ .deinit_chan = dwmac4_dma_deinit_channel, + .init_rx_chan = dwmac4_dma_init_rx_chan, + .init_tx_chan = dwmac4_dma_init_tx_chan, + .axi = dwmac4_dma_axi, +@@ -576,6 +599,7 @@ const struct stmmac_dma_ops dwmac410_dma_ops = { + .reset = dwmac4_dma_reset, + .init = dwmac4_dma_init, + .init_chan = dwmac410_dma_init_channel, ++ .deinit_chan = dwmac410_dma_deinit_channel, + .init_rx_chan = dwmac4_dma_init_rx_chan, + .init_tx_chan = dwmac4_dma_init_tx_chan, + .axi = dwmac4_dma_axi, +diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h +index e6317b94fff7d4..04dafec021b4f9 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h ++++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h +@@ -170,6 +170,8 @@ struct stmmac_dma_ops { + void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg); + void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, u32 chan); ++ void (*deinit_chan)(struct stmmac_priv *priv, void __iomem *ioaddr, ++ u32 chan); + void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr, + struct stmmac_dma_cfg *dma_cfg, + dma_addr_t phy, u32 chan); +@@ -235,6 +237,8 @@ struct stmmac_dma_ops { + stmmac_do_void_callback(__priv, dma, init, __args) + #define stmmac_init_chan(__priv, __args...) \ + stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args) ++#define stmmac_deinit_chan(__priv, __args...) \ ++ stmmac_do_void_callback(__priv, dma, deinit_chan, __priv, __args) + #define stmmac_init_rx_chan(__priv, __args...) \ + stmmac_do_void_callback(__priv, dma, init_rx_chan, __priv, __args) + #define stmmac_init_tx_chan(__priv, __args...) \ +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 3591755ea30be5..50dfdf5bd3eb02 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -2560,6 +2560,7 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv) + { + u8 rx_channels_count = priv->plat->rx_queues_to_use; + u8 tx_channels_count = priv->plat->tx_queues_to_use; ++ u8 dma_csr_ch = max(rx_channels_count, tx_channels_count); + u8 chan; + + for (chan = 0; chan < rx_channels_count; chan++) +@@ -2567,6 +2568,9 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv) + + for (chan = 0; chan < tx_channels_count; chan++) + stmmac_stop_tx_dma(priv, chan); ++ ++ for (chan = 0; chan < dma_csr_ch; chan++) ++ stmmac_deinit_chan(priv, priv->ioaddr, chan); + } + + /** +-- +2.53.0 + diff --git a/queue-7.1/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch b/queue-7.1/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch new file mode 100644 index 0000000000..16028aa9f1 --- /dev/null +++ b/queue-7.1/net-stmmac-enable-the-mac-on-link-up-for-all-support.patch @@ -0,0 +1,186 @@ +From 2fd529f66cf310a087fe1660fb48171da63d5de2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 10:49:11 +0300 +Subject: net: stmmac: enable the MAC on link up for all supported speeds + +From: vadik likholetov + +[ Upstream commit 9c99db3a2080b8c2cbbb1100369586a9bea43321 ] + +stmmac_mac_link_down() clears the MAC's transmit and receive enable bits. +stmmac_mac_link_up() is expected to set them again through +stmmac_mac_set(..., true), but it first switches on the negotiated speed +and returns early for a speed the switch does not list. The MAC is then +left gated off. + +The speed selection is split into three switches, keyed on the interface. +The generic branch -- taken for everything that is neither USXGMII nor +XLGMII, so including PHY_INTERFACE_MODE_10GBASER -- lists only SPEED_2500, +SPEED_1000, SPEED_100 and SPEED_10. + +MGBE on Tegra234 runs 10GBASE-R into an Aquantia AQR113C. That PHY does +rate matching, so phylink_link_up() replaces the media speed with the +MAC-side interface speed before calling into the MAC: + + case RATE_MATCH_PAUSE: + speed = phylink_interface_max_speed(link_state.interface); + duplex = DUPLEX_FULL; + +The driver is therefore called as + + stmmac_mac_link_up(interface=10GBASER, speed=10000, duplex=1) + +which falls through to "default: return;". The interface stops passing +traffic after the first link flap. + +The failure is easy to misread. The link still comes up, because the PHY +is polled over MDIO and needs no MAC, so the interface reports carrier 1 +at the media speed. The DMA is untouched, so its start bits stay set and +descriptors are still consumed. Only the MAC itself is gated off: the +receiver counts nothing (mmc_rx_framecount_gb stops advancing, RE is 0) +and nothing reaches the wire (TE is 0). The interface survives boot only +because stmmac_hw_setup(), called from ndo_open, enables the MAC +unconditionally -- so the problem appears only once the cable has been +unplugged and plugged back in, and "ip link set dev down && ip +link set dev up" appears to fix it. + +The interface is not what the speed bits depend on: with the single +exception of 2.5G, which is selected through the XGMII block on USXGMII +and through the regular speed bits otherwise, each speed maps to one +field of struct mac_link. The per-interface switches are speed +validation, and phylink already validates the speed against +priv->hw->link.caps. So collapse the three switches into one keyed on the +speed alone, keeping the interface test only for the 2.5G case. This +covers 10G on 10GBASE-R, and equally 5G, and 1G/100/10 on USXGMII, all of +which hit "default: return;" today. + +A core that does not support a speed leaves the corresponding mac_link +field at 0, and phylink will not offer it that speed in the first place. +For dwxgmac2 at 10G, link.xgmii.speed10000 is XGMAC_CONFIG_SS_10000, +which is 0 and is the correct speed selection for a 10GBASE-R MAC: ctrl +then equals old_ctrl, the register write is skipped, and execution +reaches stmmac_mac_set(..., true). + +Log an error in the default case, since a speed with no entry here leaves +the MAC disabled and the symptom does not point at the cause. + +Fixes: d8ca113724e7 ("net: stmmac: tegra: Add MGBE support") +Suggested-by: Maxime Chevallier +Signed-off-by: vadik likholetov +Reviewed-by: Jacob Keller +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260713074911.30090-1-vadikas@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 92 ++++++++----------- + 1 file changed, 37 insertions(+), 55 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +index 50dfdf5bd3eb02..755f48a34314b1 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +@@ -1083,63 +1083,45 @@ static void stmmac_mac_link_up(struct phylink_config *config, + old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG); + ctrl = old_ctrl & ~priv->hw->link.speed_mask; + +- if (interface == PHY_INTERFACE_MODE_USXGMII) { +- switch (speed) { +- case SPEED_10000: +- ctrl |= priv->hw->link.xgmii.speed10000; +- break; +- case SPEED_5000: +- ctrl |= priv->hw->link.xgmii.speed5000; +- break; +- case SPEED_2500: ++ switch (speed) { ++ case SPEED_100000: ++ ctrl |= priv->hw->link.xlgmii.speed100000; ++ break; ++ case SPEED_50000: ++ ctrl |= priv->hw->link.xlgmii.speed50000; ++ break; ++ case SPEED_40000: ++ ctrl |= priv->hw->link.xlgmii.speed40000; ++ break; ++ case SPEED_25000: ++ ctrl |= priv->hw->link.xlgmii.speed25000; ++ break; ++ case SPEED_10000: ++ ctrl |= priv->hw->link.xgmii.speed10000; ++ break; ++ case SPEED_5000: ++ ctrl |= priv->hw->link.xgmii.speed5000; ++ break; ++ case SPEED_2500: ++ if (interface == PHY_INTERFACE_MODE_USXGMII) + ctrl |= priv->hw->link.xgmii.speed2500; +- break; +- default: +- return; +- } +- } else if (interface == PHY_INTERFACE_MODE_XLGMII) { +- switch (speed) { +- case SPEED_100000: +- ctrl |= priv->hw->link.xlgmii.speed100000; +- break; +- case SPEED_50000: +- ctrl |= priv->hw->link.xlgmii.speed50000; +- break; +- case SPEED_40000: +- ctrl |= priv->hw->link.xlgmii.speed40000; +- break; +- case SPEED_25000: +- ctrl |= priv->hw->link.xlgmii.speed25000; +- break; +- case SPEED_10000: +- ctrl |= priv->hw->link.xgmii.speed10000; +- break; +- case SPEED_2500: +- ctrl |= priv->hw->link.speed2500; +- break; +- case SPEED_1000: +- ctrl |= priv->hw->link.speed1000; +- break; +- default: +- return; +- } +- } else { +- switch (speed) { +- case SPEED_2500: ++ else + ctrl |= priv->hw->link.speed2500; +- break; +- case SPEED_1000: +- ctrl |= priv->hw->link.speed1000; +- break; +- case SPEED_100: +- ctrl |= priv->hw->link.speed100; +- break; +- case SPEED_10: +- ctrl |= priv->hw->link.speed10; +- break; +- default: +- return; +- } ++ break; ++ case SPEED_1000: ++ ctrl |= priv->hw->link.speed1000; ++ break; ++ case SPEED_100: ++ ctrl |= priv->hw->link.speed100; ++ break; ++ case SPEED_10: ++ ctrl |= priv->hw->link.speed10; ++ break; ++ default: ++ netdev_err(priv->dev, ++ "unsupported speed %s on %s, leaving the MAC disabled\n", ++ phy_speed_to_str(speed), phy_modes(interface)); ++ return; + } + + if (priv->plat->fix_mac_speed) +-- +2.53.0 + diff --git a/queue-7.1/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch b/queue-7.1/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch new file mode 100644 index 0000000000..30d4e940dc --- /dev/null +++ b/queue-7.1/net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch @@ -0,0 +1,103 @@ +From fdb458e833969a47f83403c6a9501e4fd4c0e0d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:15 -0700 +Subject: net: stmmac: fix l3l4 filter rejecting unsupported offload requests + +From: Nazim Amirul + +[ Upstream commit 5536d7c843637e9430279b94935fcf7df98babb3 ] + +The basic flow parser in tc_add_basic_flow() does not validate match +keys before proceeding. Unsupported offload configurations such as +partial protocol masks, non-IPv4 network proto, or non-TCP/UDP transport +proto are silently accepted instead of returning -EOPNOTSUPP. + +Add validation to return -EOPNOTSUPP early for: +- No network or transport proto present in the key +- Partial protocol mask (only full mask supported) +- Network proto is not IPv4 +- Transport proto is not TCP or UDP + +Each rejection includes an extack message so the user knows which part +of the match is unsupported. + +Also propagate -EOPNOTSUPP from tc_add_basic_flow() in tc_add_flow() +by returning it directly rather than using break. The break was silently +discarding the error for FLOW_CLS_REPLACE operations where entry->in_use +is already true, causing tc_add_flow() to return 0 (success) for +unsupported replace requests. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-4-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 34 +++++++++++++++++++ + 1 file changed, 34 insertions(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index d786527185999d..1f8c9f47306b97 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -446,6 +446,7 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv, + } + + #define ETHER_TYPE_FULL_MASK cpu_to_be16(~0) ++#define IP_PROTO_FULL_MASK 0xFF + + static int tc_add_basic_flow(struct stmmac_priv *priv, + struct flow_cls_offload *cls, +@@ -461,6 +462,37 @@ static int tc_add_basic_flow(struct stmmac_priv *priv, + + flow_rule_match_basic(rule, &match); + ++ /* Both network proto and transport proto not present in the key */ ++ if (!match.mask || !(match.mask->n_proto || match.mask->ip_proto)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "filter must specify network or transport protocol"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* If the proto is present in the key and is not full mask */ ++ if ((match.mask->n_proto && match.mask->n_proto != ETHER_TYPE_FULL_MASK) || ++ (match.mask->ip_proto && match.mask->ip_proto != IP_PROTO_FULL_MASK)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only full protocol mask is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Network proto is present in the key and is not IPv4 */ ++ if (match.mask->n_proto && match.key->n_proto != cpu_to_be16(ETH_P_IP)) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only IPv4 network protocol is supported"); ++ return -EOPNOTSUPP; ++ } ++ ++ /* Transport proto is present in the key and is not TCP or UDP */ ++ if (match.mask->ip_proto && ++ match.key->ip_proto != IPPROTO_TCP && ++ match.key->ip_proto != IPPROTO_UDP) { ++ NL_SET_ERR_MSG_MOD(cls->common.extack, ++ "only TCP and UDP transport protocols are supported"); ++ return -EOPNOTSUPP; ++ } ++ + entry->ip_proto = match.key->ip_proto; + return 0; + } +@@ -598,6 +630,8 @@ static int tc_add_flow(struct stmmac_priv *priv, + ret = tc_flow_parsers[i].fn(priv, cls, entry); + if (!ret) + entry->in_use = true; ++ else if (ret == -EOPNOTSUPP) ++ return ret; + } + + if (!entry->in_use) +-- +2.53.0 + diff --git a/queue-7.1/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch b/queue-7.1/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch new file mode 100644 index 0000000000..5225e56cae --- /dev/null +++ b/queue-7.1/net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch @@ -0,0 +1,43 @@ +From f2ca52214a09ef2fddbcdf8287dd314259e18e89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:16 -0700 +Subject: net: stmmac: reset residual action in L3L4 filters on delete + +From: Nazim Amirul + +[ Upstream commit a448f821289934b961dd9d8d0beb006cc8937ba2 ] + +When deleting an L3/L4 flower filter entry, the action field is not +reset. If a filter was previously configured with a drop action, that +action may persist and affect subsequent filter configurations +unintentionally. + +Clear the action field when the filter entry is deleted. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-5-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +index 1f8c9f47306b97..14cabe76e53ec8 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c ++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +@@ -661,6 +661,7 @@ static int tc_del_flow(struct stmmac_priv *priv, + entry->in_use = false; + entry->cookie = 0; + entry->is_l4 = false; ++ entry->action = 0; + return ret; + } + +-- +2.53.0 + diff --git a/queue-7.1/net-stmmac-xgmac-fix-l4-filter-port-overwrite-on-reg.patch b/queue-7.1/net-stmmac-xgmac-fix-l4-filter-port-overwrite-on-reg.patch new file mode 100644 index 0000000000..77963cc785 --- /dev/null +++ b/queue-7.1/net-stmmac-xgmac-fix-l4-filter-port-overwrite-on-reg.patch @@ -0,0 +1,88 @@ +From 59fd78d15876236ee6bd6c84171db0059020872a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 19:37:14 -0700 +Subject: net: stmmac: xgmac: fix l4 filter port overwrite on register update + +From: Nazim Amirul + +[ Upstream commit 9fcf274d93af17396f20cccb63f1d4c17492a000 ] + +The XGMAC_L4_ADDR register holds both source and destination port +match values. The current implementation overwrites the entire register +when configuring either port, so setting one silently erases the other. + +Fix this by reading the register first, then masking and updating only +the relevant field before writing back. + +Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower") +Signed-off-by: Rohan G Thomas +Signed-off-by: Nazim Amirul +Reviewed-by: Maxime Chevallier +Link: https://patch.msgid.link/20260714023716.29865-3-muhammad.nazim.amirul.nazle.asmade@altera.com +Reviewed-by: Jakub Raczynski +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 28 +++++++++++-------- + 1 file changed, 16 insertions(+), 12 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +index f02b434bbd505b..52054f31376d50 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +@@ -1370,36 +1370,40 @@ static int dwxgmac2_config_l4_filter(struct mac_device_info *hw, u32 filter_no, + value &= ~XGMAC_L4PEN0; + } + +- value &= ~(XGMAC_L4SPM0 | XGMAC_L4SPIM0); +- value &= ~(XGMAC_L4DPM0 | XGMAC_L4DPIM0); + if (sa) { + value |= XGMAC_L4SPM0; + if (inv) + value |= XGMAC_L4SPIM0; ++ else ++ value &= ~XGMAC_L4SPIM0; + } else { + value |= XGMAC_L4DPM0; + if (inv) + value |= XGMAC_L4DPIM0; ++ else ++ value &= ~XGMAC_L4DPIM0; + } + + ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L3L4_CTRL, value); + if (ret) + return ret; + +- if (sa) { +- value = FIELD_PREP(XGMAC_L4SP0, match); ++ ret = dwxgmac2_filter_read(hw, filter_no, XGMAC_L4_ADDR, &value); ++ if (ret) ++ return ret; + +- ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value); +- if (ret) +- return ret; ++ if (sa) { ++ value &= ~XGMAC_L4SP0; ++ value |= FIELD_PREP(XGMAC_L4SP0, match); + } else { +- value = FIELD_PREP(XGMAC_L4DP0, match); +- +- ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value); +- if (ret) +- return ret; ++ value &= ~XGMAC_L4DP0; ++ value |= FIELD_PREP(XGMAC_L4DP0, match); + } + ++ ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value); ++ if (ret) ++ return ret; ++ + if (!en) + return dwxgmac2_filter_write(hw, filter_no, XGMAC_L3L4_CTRL, 0); + +-- +2.53.0 + diff --git a/queue-7.1/net-txgbe-fix-fdir-filter-leak-on-remove.patch b/queue-7.1/net-txgbe-fix-fdir-filter-leak-on-remove.patch new file mode 100644 index 0000000000..b4744b4b69 --- /dev/null +++ b/queue-7.1/net-txgbe-fix-fdir-filter-leak-on-remove.patch @@ -0,0 +1,40 @@ +From 0f15630106b4ba252fa3e70605de0dd11bd9f952 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:19:11 +0800 +Subject: net: txgbe: fix FDIR filter leak on remove + +From: Chenguang Zhao + +[ Upstream commit ecaa37826340520664a4e5522f803ff48fc3f564 ] + +Perfect FDIR filters can be added while the interface is down and are +kept on the software list for later restore. unregister_netdev() only +calls ndo_stop when the device is up, so txgbe_fdir_filter_exit() in +txgbe_close() is skipped in that case and the filters are leaked on +driver remove. Free the filter list from txgbe_remove() as well. + +Fixes: 4bdb441105dc ("net: txgbe: support Flow Director perfect filters") +Signed-off-by: Chenguang Zhao +Reviewed-by: Jacob Keller +Link: https://patch.msgid.link/20260713091911.1614795-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +index 8b7c3753bb6acc..1f633bdf1972f6 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +@@ -951,6 +951,7 @@ static void txgbe_remove(struct pci_dev *pdev) + netdev = wx->netdev; + wx_disable_sriov(wx); + unregister_netdev(netdev); ++ txgbe_fdir_filter_exit(wx); + + timer_shutdown_sync(&wx->service_timer); + cancel_work_sync(&wx->service_task); +-- +2.53.0 + diff --git a/queue-7.1/net-txgbe-fix-heap-overflow-when-reading-module-eepr.patch b/queue-7.1/net-txgbe-fix-heap-overflow-when-reading-module-eepr.patch new file mode 100644 index 0000000000..3972ec7706 --- /dev/null +++ b/queue-7.1/net-txgbe-fix-heap-overflow-when-reading-module-eepr.patch @@ -0,0 +1,48 @@ +From 8eee8ec574d40c6a17c0a8067028e7011d411d9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 16:51:11 +0800 +Subject: net: txgbe: fix heap overflow when reading module EEPROM + +From: Chenguang Zhao + +[ Upstream commit 6a905a71fd43ce8b45f05044b11491337f232c9d ] + +txgbe_read_eeprom_hostif() always copies round_up(length, 4) bytes +into the caller buffer, which ethtool allocates with exactly 'length' +bytes. A non-4-aligned length therefore causes an out-of-bounds write. +Copy only the remaining bytes on the final dword instead. + +Signed-off-by: Chenguang Zhao +Reviewed-by: Jiawen Wu +Reviewed-by: Jacob Keller +Fixes: 9b97b6b5635b ("net: txgbe: support getting module EEPROM by page") +Link: https://patch.msgid.link/20260713085111.1481884-1-chenguang.zhao@linux.dev +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c +index 8fc32df8e49a44..479c83f5d6454c 100644 +--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c ++++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c +@@ -96,11 +96,13 @@ int txgbe_read_eeprom_hostif(struct wx *wx, + dword_len = round_up(length, 4) >> 2; + + for (i = 0; i < dword_len; i++) { ++ u32 copy_len = min_t(u32, 4, length - i * 4); ++ + value = rd32a(wx, WX_FW2SW_MBOX, i + offset); + le32_to_cpus(&value); + +- memcpy(data, &value, 4); +- data += 4; ++ memcpy(data, &value, copy_len); ++ data += copy_len; + } + + return 0; +-- +2.53.0 + diff --git a/queue-7.1/netlink-specs-rt-link-convert-bridge-port-flag-attri.patch b/queue-7.1/netlink-specs-rt-link-convert-bridge-port-flag-attri.patch new file mode 100644 index 0000000000..a0027df4bf --- /dev/null +++ b/queue-7.1/netlink-specs-rt-link-convert-bridge-port-flag-attri.patch @@ -0,0 +1,144 @@ +From d6bbd6b877ce1175d8ed5cafddc6209459e3b221 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 11:03:04 +0300 +Subject: netlink: specs: rt-link: convert bridge port flag attributes to u8 + +From: Danielle Ratson + +[ Upstream commit f6e3b21608e974c4aaa4cfd73a239dacf1d8a9a3 ] + +A number of IFLA_BRPORT_* attributes are documented in the rt-link spec +as having the "flag" type, i.e. a payload-less NLA_FLAG attribute whose +meaning is presence-only. This does not match the kernel, which emits +these attributes with nla_put_u8() and validates them as NLA_U8 in +br_port_policy[]. The values are not mere presence flags but carry a u8 +payload (0/1). + +Convert these bridge port attributes from "flag" to "u8" so the spec +reflects the actual wire format. + +Fixes: 077b6022d24b ("doc/netlink/specs: Add sub-message type to rt_link family") +Reviewed-by: Petr Machata +Acked-by: Nikolay Aleksandrov +Reviewed-by: Ido Schimmel +Signed-off-by: Danielle Ratson +Link: https://patch.msgid.link/a57cdfcfc4a6dcb92106c25b4dde5059fde2bd44.1783236731.git.danieller@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + Documentation/netlink/specs/rt-link.yaml | 40 ++++++++++++------------ + 1 file changed, 20 insertions(+), 20 deletions(-) + +diff --git a/Documentation/netlink/specs/rt-link.yaml b/Documentation/netlink/specs/rt-link.yaml +index 644a8bd7b93c34..e656f05268ed26 100644 +--- a/Documentation/netlink/specs/rt-link.yaml ++++ b/Documentation/netlink/specs/rt-link.yaml +@@ -1583,31 +1583,31 @@ attribute-sets: + type: u32 + - + name: mode +- type: flag ++ type: u8 + - + name: guard +- type: flag ++ type: u8 + - + name: protect +- type: flag ++ type: u8 + - + name: fast-leave +- type: flag ++ type: u8 + - + name: learning +- type: flag ++ type: u8 + - + name: unicast-flood +- type: flag ++ type: u8 + - + name: proxyarp +- type: flag ++ type: u8 + - + name: learning-sync +- type: flag ++ type: u8 + - + name: proxyarp-wifi +- type: flag ++ type: u8 + - + name: root-id + type: binary +@@ -1654,34 +1654,34 @@ attribute-sets: + type: pad + - + name: mcast-flood +- type: flag ++ type: u8 + - + name: mcast-to-ucast +- type: flag ++ type: u8 + - + name: vlan-tunnel +- type: flag ++ type: u8 + - + name: bcast-flood +- type: flag ++ type: u8 + - + name: group-fwd-mask + type: u16 + - + name: neigh-suppress +- type: flag ++ type: u8 + - + name: isolated +- type: flag ++ type: u8 + - + name: backup-port + type: u32 + - + name: mrp-ring-open +- type: flag ++ type: u8 + - + name: mrp-in-open +- type: flag ++ type: u8 + - + name: mcast-eht-hosts-limit + type: u32 +@@ -1690,10 +1690,10 @@ attribute-sets: + type: u32 + - + name: locked +- type: flag ++ type: u8 + - + name: mab +- type: flag ++ type: u8 + - + name: mcast-n-groups + type: u32 +@@ -1702,7 +1702,7 @@ attribute-sets: + type: u32 + - + name: neigh-vlan-suppress +- type: flag ++ type: u8 + - + name: backup-nhid + type: u32 +-- +2.53.0 + diff --git a/queue-7.1/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch b/queue-7.1/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch new file mode 100644 index 0000000000..607c305e3d --- /dev/null +++ b/queue-7.1/nexthop-initialize-extack-in-nh_res_bucket_migrate.patch @@ -0,0 +1,59 @@ +From c0b74a9101d5423b91905adfbbe79d38bc2a9877 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 22:15:51 +0000 +Subject: nexthop: initialize extack in nh_res_bucket_migrate() + +From: Xiang Mei (Microsoft) + +[ Upstream commit 6347c5314cee49f364aaf2e40ff15415a57a116e ] + +nh_res_bucket_migrate() passes an uninitialized netlink_ext_ack to +call_nexthop_res_bucket_notifiers(). When +nh_notifier_res_bucket_info_init() fails (e.g. the kzalloc returns +-ENOMEM), the error is propagated back before any notifier sets +extack._msg, and the error path formats the stale pointer with +pr_err_ratelimited("%s\n", extack._msg). With CONFIG_INIT_STACK_NONE +this dereferences uninitialized stack memory: + + Oops: general protection fault, probably for non-canonical address ... + KASAN: maybe wild-memory-access in range [...] + RIP: 0010:string (lib/vsprintf.c:730) + vsnprintf (lib/vsprintf.c:2945) + _printk (kernel/printk/printk.c:2504) + nh_res_bucket_migrate (net/ipv4/nexthop.c:1816) + nh_res_table_upkeep (net/ipv4/nexthop.c:1866) + rtm_new_nexthop (net/ipv4/nexthop.c:3323) + rtnetlink_rcv_msg (net/core/rtnetlink.c:7076) + netlink_sendmsg (net/netlink/af_netlink.c:1900) + Kernel panic - not syncing: Fatal exception + +Zero-initialize extack so _msg is NULL on error paths that never set it. + +Fixes: 7c37c7e00411 ("nexthop: Implement notifiers for resilient nexthop groups") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Xiang Mei (Microsoft) +Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260713221551.3344650-1-xmei5@asu.edu +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/nexthop.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c +index f92fcc39fc4c80..dc95a3d6e899e0 100644 +--- a/net/ipv4/nexthop.c ++++ b/net/ipv4/nexthop.c +@@ -1788,8 +1788,8 @@ static bool nh_res_bucket_migrate(struct nh_res_table *res_table, + bool notify_nl, bool force) + { + struct nh_res_bucket *bucket = &res_table->nh_buckets[bucket_index]; ++ struct netlink_ext_ack extack = {}; + struct nh_grp_entry *new_nhge; +- struct netlink_ext_ack extack; + int err; + + new_nhge = list_first_entry_or_null(&res_table->uw_nh_entries, +-- +2.53.0 + diff --git a/queue-7.1/nfp-check-resource-mutex-allocation.patch b/queue-7.1/nfp-check-resource-mutex-allocation.patch new file mode 100644 index 0000000000..ec41fc49c9 --- /dev/null +++ b/queue-7.1/nfp-check-resource-mutex-allocation.patch @@ -0,0 +1,52 @@ +From 0dffb82771d9eca563a8c3237af6f48d38c849f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:08 +0800 +Subject: nfp: Check resource mutex allocation + +From: Ruoyu Wang + +[ Upstream commit a61b4db34a753bdf5c9e77a7f3d3dddd41dcfacc ] + +nfp_cpp_resource_find() allocates a CPP mutex handle for the matching +resource-table entry and then reports success. nfp_resource_try_acquire() +immediately passes that handle to nfp_cpp_mutex_trylock(). + +However, nfp_cpp_mutex_alloc() returns NULL on failure. If that happens +for a matching table entry, the resource lookup still returns success and +the following trylock dereferences a NULL mutex pointer while opening the +resource. + +nfp_resource_acquire() already treats failure to allocate the table mutex +as -ENOMEM. Do the same for the resource mutex and fail the lookup before +publishing the rest of the resource handle. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: f01a2161577d ("nfp: add support for resources") +Signed-off-by: Ruoyu Wang +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708143408.3168425-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +index 6d5833479d123f..237300b82b9132 100644 +--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c ++++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +@@ -96,6 +96,9 @@ static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res) + res->mutex = + nfp_cpp_mutex_alloc(cpp, + NFP_RESOURCE_TBL_TARGET, addr, key); ++ if (!res->mutex) ++ return -ENOMEM; ++ + res->cpp_id = NFP_CPP_ID(entry.region.cpp_target, + entry.region.cpp_action, + entry.region.cpp_token); +-- +2.53.0 + diff --git a/queue-7.1/octeontx2-pf-tc-fix-egress-ratelimiting.patch b/queue-7.1/octeontx2-pf-tc-fix-egress-ratelimiting.patch new file mode 100644 index 0000000000..93089a2e1b --- /dev/null +++ b/queue-7.1/octeontx2-pf-tc-fix-egress-ratelimiting.patch @@ -0,0 +1,89 @@ +From c7ac313716df9545cf6907c626970c6751eeaad4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 14:13:49 +0530 +Subject: octeontx2-pf: tc: fix egress ratelimiting + +From: Hariprasad Kelam + +[ Upstream commit bb0d96ebe5f4d1acccf4dc36ca7f01f9a8fa1ba1 ] + +The egress rate calculation computes an incorrect mantissa and exponent, +causing up to ~50% deviation from the configured rate at lower speeds. + +Rework the computation to follow the hardware rate formula: + + rate = 2 * (1 + mantissa/256) * 2^exp / (1 << div_exp) + +Keep div_exp = 0 and derive exp and mantissa from half of the requested +rate. Rates below 2 Mbps are floored to the smallest encodable step +(exp = 0, mantissa = 0). + +Fixes: e638a83f167e ("octeontx2-pf: TC_MATCHALL egress ratelimiting offload") +Signed-off-by: Hariprasad Kelam +Signed-off-by: Nitin Shetty J +Link: https://patch.msgid.link/20260717084349.2227796-1-nshettyj@marvell.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 29 ++++++++++--------- + 1 file changed, 16 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +index 40162b08014dd6..0b46ec29e64eaa 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +@@ -30,6 +30,7 @@ + #define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4) + + #define MCAST_INVALID_GRP (-1U) ++#define RATE_MANTISSA_BITS 8 + + static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, + u32 *burst_exp, u32 *burst_mantissa) +@@ -66,28 +67,30 @@ static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst, + static void otx2_get_egress_rate_cfg(u64 maxrate, u32 *exp, + u32 *mantissa, u32 *div_exp) + { +- u64 tmp; +- + /* Rate calculation by hardware + * + * PIR_ADD = ((256 + mantissa) << exp) / 256 + * rate = (2 * PIR_ADD) / ( 1 << div_exp) + * The resultant rate is in Mbps. ++ * ++ * Use div_exp = 0 and compute exp/mantissa for maxrate / 2; the ++ * leading factor of two yields the full rate. Rates below 2 Mbps ++ * are floored to the smallest step (exp = 0, mantissa = 0). + */ + +- /* 2Mbps to 100Gbps can be expressed with div_exp = 0. +- * Setting this to '0' will ease the calculation of +- * exponent and mantissa. +- */ + *div_exp = 0; +- + if (maxrate) { +- *exp = ilog2(maxrate) ? ilog2(maxrate) - 1 : 0; +- tmp = maxrate - rounddown_pow_of_two(maxrate); +- if (maxrate < MAX_RATE_MANTISSA) +- *mantissa = tmp * 2; +- else +- *mantissa = tmp / (1ULL << (*exp - 7)); ++ maxrate = maxrate / 2; ++ if (!maxrate) { ++ /* Rates below 2 Mbps map to the smallest step */ ++ *exp = 0; ++ *mantissa = 0; ++ } else { ++ *exp = ilog2(maxrate); ++ /* Clear MSB and derive fractional bits */ ++ maxrate &= ~BIT(*exp); ++ *mantissa = (maxrate << RATE_MANTISSA_BITS) >> *exp; ++ } + } else { + /* Instead of disabling rate limiting, set all values to max */ + *exp = MAX_RATE_EXPONENT; +-- +2.53.0 + diff --git a/queue-7.1/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch b/queue-7.1/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch new file mode 100644 index 0000000000..127f678967 --- /dev/null +++ b/queue-7.1/octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch @@ -0,0 +1,40 @@ +From 66d615418287c763035297ccebe8ada42e28277b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 10:50:07 +0530 +Subject: octeontx2-vf: set TC flower flag on MCAM entry allocation + +From: Suman Ghosh + +[ Upstream commit 0d4d31e3cc5dd6204fa1495c4107f5075acce5ed ] + +When MCAM entries are allocated for a VF netdev via the devlink +mcam_count parameter, only OTX2_FLAG_NTUPLE_SUPPORT was set. That +enabled ethtool ntuple filters but not tc flower offload. Also set +OTX2_FLAG_TC_FLOWER_SUPPORT when entries are successfully allocated. + +Fixes: 2da489432747 ("octeontx2-pf: devlink params support to set mcam entry count") +Signed-off-by: Suman Ghosh +Signed-off-by: Ratheesh Kannoth +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260715052007.2099851-1-rkannoth@marvell.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +index 38cc539d724d84..3b3eee15715f75 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +@@ -270,6 +270,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count) + if (allocated) { + pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC; + pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT; ++ pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT; + } + + if (allocated != count) +-- +2.53.0 + diff --git a/queue-7.1/ovl-check-access-to-copy_file_range-source-with-src-.patch b/queue-7.1/ovl-check-access-to-copy_file_range-source-with-src-.patch new file mode 100644 index 0000000000..ede7919410 --- /dev/null +++ b/queue-7.1/ovl-check-access-to-copy_file_range-source-with-src-.patch @@ -0,0 +1,82 @@ +From 091ee54c425d39a99cd4e603141ba281cbc6a45a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 12 Jul 2026 14:24:21 +0200 +Subject: ovl: check access to copy_file_range source with src mounter creds + +From: Amir Goldstein + +[ Upstream commit a1e0eb8f55cfe09bb31a202a388babc411292656 ] + +Commit 5dae222a5ff0c ("vfs: allow copy_file_range to copy across devices") +allowed filesystems that implement the copy_file_range() f_op to decide +if they want to access cross-sb copy from/to the same fs type. + +The same commit added checks to verify same sb copy for filesystems that +implement ->copy_file_range() and do not support cross-sb copy at the +time, namely, to ceph, fuse and nfs. + +The two remaining fs which implement ->copy_file_range(), cifs and +overlayfs started to support cross-sb copy from this time. + +While overlayfs does support cross-sb copy when the two underlying files +are on the same base fs, the copy operation on the two real files from +two different overalyfs filesystems is performed with the mounter +creds of the destination overlayfs and the read permission access hook +for the source file was called with the wrong creds. + +This could cause either deny of access to copy which would otherwise be +allowed (e.g. with splice) or allow read access to file which would +otherwise be denied. + +Fix the latter case by explicitly verifying read access to source file +with the source overlayfs mounter creds. + +The former case remains a quirk of cross-sb overlayfs copy, but +userspace could fall back to regular copy so no harm done. + +Fixes: 5dae222a5ff0c ("vfs: allow copy_file_range to copy across devices") +Signed-off-by: Amir Goldstein +Link: https://patch.msgid.link/20260712122421.203113-1-amir73il@gmail.com +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/overlayfs/file.c | 16 +++++++++++++++- + 1 file changed, 15 insertions(+), 1 deletion(-) + +diff --git a/fs/overlayfs/file.c b/fs/overlayfs/file.c +index 27cc07738f33bf..f3d97eb146e85b 100644 +--- a/fs/overlayfs/file.c ++++ b/fs/overlayfs/file.c +@@ -528,6 +528,7 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + struct file *file_out, loff_t pos_out, + loff_t len, unsigned int flags, enum ovl_copyop op) + { ++ struct inode *inode_in = file_inode(file_in); + struct inode *inode_out = file_inode(file_out); + struct file *realfile_in, *realfile_out; + loff_t ret; +@@ -551,7 +552,20 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, + if (IS_ERR(realfile_in)) + goto out_unlock; + +- with_ovl_creds(file_inode(file_out)->i_sb) { ++ /* ++ * For cross-sb copy, vfs_copy_file_range() will verify read access with ++ * the mounter creds of the dest fs mounter, so we need to explicitly ++ * verify read access with the source mounter creds. ++ */ ++ if (unlikely(inode_in->i_sb != inode_out->i_sb)) { ++ with_ovl_creds(inode_in->i_sb) { ++ ret = rw_verify_area(READ, realfile_in, &pos_in, len); ++ if (unlikely(ret)) ++ goto out_unlock; ++ } ++ } ++ ++ with_ovl_creds(inode_out->i_sb) { + switch (op) { + case OVL_COPY: + ret = vfs_copy_file_range(realfile_in, pos_in, +-- +2.53.0 + diff --git a/queue-7.1/ovl-fix-trusted-xattr-escape-prefix-matching.patch b/queue-7.1/ovl-fix-trusted-xattr-escape-prefix-matching.patch new file mode 100644 index 0000000000..2cc5b8ec2b --- /dev/null +++ b/queue-7.1/ovl-fix-trusted-xattr-escape-prefix-matching.patch @@ -0,0 +1,49 @@ +From f6660f5e7a826d6f6259c35d39844a45428ef0dd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:22:21 +0800 +Subject: ovl: fix trusted xattr escape prefix matching + +From: Yichong Chen + +[ Upstream commit a8e72879cd0d8422c0b47d6d3c1802274fe73b98 ] + +In the trusted.* xattr namespace, ovl_is_escaped_xattr() compares +one byte less than the escaped overlay xattr prefix length. This makes +it match "trusted.overlay.overlay" without requiring the trailing dot. + +As a result, an xattr such as "trusted.overlay.overlayfoo" is +incorrectly treated as an escaped overlay xattr. This can be reproduced +by setting "trusted.overlay.overlayfoo" on a lower file and listing xattrs +through an overlay mount. listxattr() then exposes it as +"trusted.overlay.oo", and a following getxattr() on that listed name fails +with ENODATA. + +Compare the full escaped prefix, including the trailing dot, so +similarly-prefixed private xattrs are not misclassified. + +Fixes: dad02fad84cbc ("ovl: Support escaped overlay.* xattrs") +Signed-off-by: Yichong Chen +Link: https://patch.msgid.link/20260708082221.633602-1-chenyichong@uniontech.com +Reviewed-by: Amir Goldstein +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/overlayfs/xattrs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/overlayfs/xattrs.c b/fs/overlayfs/xattrs.c +index aa95855c70237b..859e80ae6f4057 100644 +--- a/fs/overlayfs/xattrs.c ++++ b/fs/overlayfs/xattrs.c +@@ -13,7 +13,7 @@ static bool ovl_is_escaped_xattr(struct super_block *sb, const char *name) + OVL_XATTR_ESCAPE_USER_PREFIX_LEN) == 0; + else + return strncmp(name, OVL_XATTR_ESCAPE_TRUSTED_PREFIX, +- OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN - 1) == 0; ++ OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN) == 0; + } + + static bool ovl_is_own_xattr(struct super_block *sb, const char *name) +-- +2.53.0 + diff --git a/queue-7.1/ovpn-avoid-putting-unrelated-p2p-peer-on-socket-rele.patch b/queue-7.1/ovpn-avoid-putting-unrelated-p2p-peer-on-socket-rele.patch new file mode 100644 index 0000000000..9aacdeb7a2 --- /dev/null +++ b/queue-7.1/ovpn-avoid-putting-unrelated-p2p-peer-on-socket-rele.patch @@ -0,0 +1,58 @@ +From cf161c2340caa78f293263c8f9561f6ede3c6ee2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 May 2026 16:15:43 +0800 +Subject: ovpn: avoid putting unrelated P2P peer on socket release + +From: Qing Ming + +[ Upstream commit b52c5103f64ee825996ca1ab8df7283cde8c5f86 ] + +ovpn_peer_release_p2p() is called when an OVPN UDP socket is being +destroyed. It checks the currently published P2P peer and releases it only +if that peer still uses the socket being destroyed. + +A peer replacement can publish a new peer before the old UDP socket is +destroyed. When the old socket destruction path runs afterwards, +ovpn_peer_release_p2p() observes the new peer through ovpn->peer. Since the +new peer uses a different socket, the function takes the socket mismatch +branch. + +That branch still calls ovpn_peer_put(peer). At this point, however, peer +is the currently published replacement peer, not the peer associated with +the socket being destroyed. Dropping its reference can free it while +ovpn->peer still points to it, leading to later use-after-free accesses +from the peer and socket cleanup paths. + +KASAN reports this as a slab-use-after-free on the kmalloc-1k ovpn_peer +object. In the reproducer, the object is allocated from ovpn_peer_new() via +ovpn_nl_peer_new_doit(), and freed through ovpn_peer_release_rcu() from RCU +callback processing. Observed access sites include ovpn_peer_remove(), +ovpn_socket_release(), ovpn_nl_peer_del_notify(), and unlock_ovpn(). + +Fix this by returning from the socket mismatch branch without putting the +peer. + +Fixes: f6226ae7a0cd ("ovpn: introduce the ovpn_socket object") +Signed-off-by: Qing Ming +Reviewed-by: Simon Horman +Signed-off-by: Antonio Quartulli +Signed-off-by: Sasha Levin +--- + drivers/net/ovpn/peer.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c +index a09d61296425aa..1844d97154cea7 100644 +--- a/drivers/net/ovpn/peer.c ++++ b/drivers/net/ovpn/peer.c +@@ -1167,7 +1167,6 @@ static void ovpn_peer_release_p2p(struct ovpn_priv *ovpn, struct sock *sk, + ovpn_sock = rcu_access_pointer(peer->sock); + if (!ovpn_sock || ovpn_sock->sk != sk) { + spin_unlock_bh(&ovpn->lock); +- ovpn_peer_put(peer); + return; + } + } +-- +2.53.0 + diff --git a/queue-7.1/ovpn-fix-use-after-free-in-unlock_ovpn.patch b/queue-7.1/ovpn-fix-use-after-free-in-unlock_ovpn.patch new file mode 100644 index 0000000000..879214a848 --- /dev/null +++ b/queue-7.1/ovpn-fix-use-after-free-in-unlock_ovpn.patch @@ -0,0 +1,51 @@ +From f1a150aed122e9d23f8288ca28ffb150ea3c485b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Jun 2026 16:04:46 +0200 +Subject: ovpn: fix use after free in unlock_ovpn() + +From: Marco Baffo + +[ Upstream commit e1ad6fe5db719874efa45b2caf9934552e09fc43 ] + +unlock_ovpn() iterates over the release_list using llist_for_each_entry() +and drops the peer reference inside the loop body via ovpn_peer_put(). + +If this drops the last reference, the peer is eventually freed. However, +llist_for_each_entry() reads peer->release_entry.next in the loop advance +expression, which runs after the body. By that time the peer may have +already been freed, resulting in a use after free when advancing to the +next list entry. + +Fix this by using llist_for_each_entry_safe(), which caches the next +pointer before executing the loop body. + +Fixes: 80747caef33d ("ovpn: introduce the ovpn_peer object") +Signed-off-by: Marco Baffo +Signed-off-by: Antonio Quartulli +Signed-off-by: Sasha Levin +--- + drivers/net/ovpn/peer.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c +index 1844d97154cea7..7dedbe54a37cfb 100644 +--- a/drivers/net/ovpn/peer.c ++++ b/drivers/net/ovpn/peer.c +@@ -26,11 +26,12 @@ static void unlock_ovpn(struct ovpn_priv *ovpn, + struct llist_head *release_list) + __releases(&ovpn->lock) + { +- struct ovpn_peer *peer; ++ struct ovpn_peer *peer, *next; + + spin_unlock_bh(&ovpn->lock); + +- llist_for_each_entry(peer, release_list->first, release_entry) { ++ llist_for_each_entry_safe(peer, next, release_list->first, ++ release_entry) { + ovpn_socket_release(peer); + ovpn_peer_put(peer); + } +-- +2.53.0 + diff --git a/queue-7.1/ovpn-use-monotonic-clock-for-peer-keepalive-timeouts.patch b/queue-7.1/ovpn-use-monotonic-clock-for-peer-keepalive-timeouts.patch new file mode 100644 index 0000000000..f16b7db87f --- /dev/null +++ b/queue-7.1/ovpn-use-monotonic-clock-for-peer-keepalive-timeouts.patch @@ -0,0 +1,80 @@ +From c627e768ef8fab19efa8b6013ee4abdb3ff98a14 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Jun 2026 16:06:42 +0200 +Subject: ovpn: use monotonic clock for peer keepalive timeouts + +From: Marco Baffo + +[ Upstream commit f7e6287ccd3abeed9e638b581dc3fdf742106ba3 ] + +Replace ktime_get_real_seconds() with the monotonic +ktime_get_boottime_seconds() to ensure the keepalive mechanism is robust +against system clock modifications. + +Right now, the driver uses ktime_get_real_seconds() to track peer +timeouts, relying on the system wall-clock. + +An administrative time adjustment or an NTP sync that steps the clock +forward can cause `now' to instantly exceed `last_recv + timeout'. + +When this occurs, the driver artificially expires healthy peers. +Depending on the OpenVPN user-space configuration, this triggers a +premature tunnel restart (if --keepalive or --ping-restart is used) or +a complete disconnection of the client (if --ping-exit is used). + +Fixes: 3ecfd9349f40 ("ovpn: implement keepalive mechanism") +Signed-off-by: Marco Baffo +Signed-off-by: Antonio Quartulli +Signed-off-by: Sasha Levin +--- + drivers/net/ovpn/io.c | 4 ++-- + drivers/net/ovpn/peer.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ovpn/io.c b/drivers/net/ovpn/io.c +index a6b777a9c2d9a2..9a66d693039a3c 100644 +--- a/drivers/net/ovpn/io.c ++++ b/drivers/net/ovpn/io.c +@@ -142,7 +142,7 @@ void ovpn_decrypt_post(void *data, int ret) + } + + /* keep track of last received authenticated packet for keepalive */ +- WRITE_ONCE(peer->last_recv, ktime_get_real_seconds()); ++ WRITE_ONCE(peer->last_recv, ktime_get_boottime_seconds()); + + rcu_read_lock(); + sock = rcu_dereference(peer->sock); +@@ -294,7 +294,7 @@ void ovpn_encrypt_post(void *data, int ret) + + ovpn_peer_stats_increment_tx(&peer->link_stats, orig_len); + /* keep track of last sent packet for keepalive */ +- WRITE_ONCE(peer->last_sent, ktime_get_real_seconds()); ++ WRITE_ONCE(peer->last_sent, ktime_get_boottime_seconds()); + /* skb passed down the stack - don't free it */ + skb = NULL; + err_unlock: +diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c +index 7dedbe54a37cfb..9c82078146bbaf 100644 +--- a/drivers/net/ovpn/peer.c ++++ b/drivers/net/ovpn/peer.c +@@ -45,7 +45,7 @@ static void unlock_ovpn(struct ovpn_priv *ovpn, + */ + void ovpn_peer_keepalive_set(struct ovpn_peer *peer, u32 interval, u32 timeout) + { +- time64_t now = ktime_get_real_seconds(); ++ time64_t now = ktime_get_boottime_seconds(); + + netdev_dbg(peer->ovpn->dev, + "scheduling keepalive for peer %u: interval=%u timeout=%u\n", +@@ -1357,7 +1357,7 @@ void ovpn_peer_keepalive_work(struct work_struct *work) + { + struct ovpn_priv *ovpn = container_of(work, struct ovpn_priv, + keepalive_work.work); +- time64_t next_run = 0, now = ktime_get_real_seconds(); ++ time64_t next_run = 0, now = ktime_get_boottime_seconds(); + LLIST_HEAD(release_list); + + spin_lock_bh(&ovpn->lock); +-- +2.53.0 + diff --git a/queue-7.1/pds_core-check-for-workqueue-allocation-failure.patch b/queue-7.1/pds_core-check-for-workqueue-allocation-failure.patch new file mode 100644 index 0000000000..9ebac0fc2f --- /dev/null +++ b/queue-7.1/pds_core-check-for-workqueue-allocation-failure.patch @@ -0,0 +1,71 @@ +From 5f3436b1a48d2f9ce4b41813ef2ca9bc0a367c0e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:27:13 +0000 +Subject: pds_core: check for workqueue allocation failure + +From: Nikhil P. Rao + +[ Upstream commit 3a660ca49e2c3807bffe0519db3cff677a5906e0 ] + +pdsc_init_pf() does not check whether create_singlethread_workqueue() +succeeded. + +Fail probe on failure. The workqueue is set up before the timer and +mutexes, so its failure path must unwind only the earlier setup. + +Fixes: c2dbb0904310 ("pds_core: health timer and workqueue") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Brett Creeley +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714212713.1788438-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/main.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c +index 638b9c7a509d9d..8d94a4d70395ed 100644 +--- a/drivers/net/ethernet/amd/pds_core/main.c ++++ b/drivers/net/ethernet/amd/pds_core/main.c +@@ -238,6 +238,10 @@ static int pdsc_init_pf(struct pdsc *pdsc) + /* General workqueue and timer, but don't start timer yet */ + snprintf(wq_name, sizeof(wq_name), "%s.%d", PDS_CORE_DRV_NAME, pdsc->uid); + pdsc->wq = create_singlethread_workqueue(wq_name); ++ if (!pdsc->wq) { ++ err = -ENOMEM; ++ goto err_out_unmap_bars; ++ } + INIT_WORK(&pdsc->health_work, pdsc_health_thread); + INIT_WORK(&pdsc->pci_reset_work, pdsc_pci_reset_thread); + timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0); +@@ -253,7 +257,7 @@ static int pdsc_init_pf(struct pdsc *pdsc) + err = pdsc_setup(pdsc, PDSC_SETUP_INIT); + if (err) { + mutex_unlock(&pdsc->config_lock); +- goto err_out_unmap_bars; ++ goto err_out_shutdown_timer; + } + + err = pdsc_start(pdsc); +@@ -305,13 +309,14 @@ static int pdsc_init_pf(struct pdsc *pdsc) + pdsc_stop(pdsc); + err_out_teardown: + pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING); +-err_out_unmap_bars: ++err_out_shutdown_timer: + timer_shutdown_sync(&pdsc->wdtimer); + if (pdsc->wq) + destroy_workqueue(pdsc->wq); + mutex_destroy(&pdsc->config_lock); + mutex_destroy(&pdsc->devcmd_lock); + pci_free_irq_vectors(pdsc->pdev); ++err_out_unmap_bars: + pdsc_unmap_bars(pdsc); + err_out_release_regions: + pci_release_regions(pdsc->pdev); +-- +2.53.0 + diff --git a/queue-7.1/pds_core-fix-auxiliary-device-add-del-races.patch b/queue-7.1/pds_core-fix-auxiliary-device-add-del-races.patch new file mode 100644 index 0000000000..571c2e6b21 --- /dev/null +++ b/queue-7.1/pds_core-fix-auxiliary-device-add-del-races.patch @@ -0,0 +1,80 @@ +From 7bbff99603ec6c9b66ac1c21bb179b54d08cdd44 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 21:07:45 +0000 +Subject: pds_core: fix auxiliary device add/del races + +From: Nikhil P. Rao + +[ Upstream commit bfa33cd513c7ceb93c5a4c30e5662acd73c0a916 ] + +Two paths add or delete the same slot (pf->vfs[vf_id].padev): a VF's +pdsc_reset_done() and the PF's devlink enable_vnet/disable_vnet handler. +They serialize on config_lock, but neither guards the slot under it +correctly. + +add() registers and stores a new auxiliary device without first checking +the slot, so a second add of an already-populated slot leaks the first +device. del() makes that check outside config_lock, so two concurrent +dels can both pass it; the first clears the slot, and the second +dereferences a NULL pointer. + +Check and update the slot under config_lock in both paths. + +Fixes: b699bdc720c0 ("pds_core: specify auxiliary_device to be created") +Reported-by: sashiko-bot@kernel.org # Running on a local machine +Signed-off-by: Nikhil P. Rao +Reviewed-by: Brett Creeley +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714210745.1785625-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/auxbus.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c +index 73b3481220b1ac..3acafe10a6d5ba 100644 +--- a/drivers/net/ethernet/amd/pds_core/auxbus.c ++++ b/drivers/net/ethernet/amd/pds_core/auxbus.c +@@ -177,17 +177,21 @@ void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf, + { + struct pds_auxiliary_dev *padev; + +- if (!*pd_ptr) +- return; +- + mutex_lock(&pf->config_lock); + ++ /* A concurrent del may have already torn this device down and ++ * cleared it. ++ */ + padev = *pd_ptr; ++ if (!padev) ++ goto out_unlock; ++ + pds_client_unregister(pf, padev->client_id); + auxiliary_device_delete(&padev->aux_dev); + auxiliary_device_uninit(&padev->aux_dev); + *pd_ptr = NULL; + ++out_unlock: + mutex_unlock(&pf->config_lock); + } + +@@ -210,6 +214,13 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf, + + mutex_lock(&pf->config_lock); + ++ /* Nothing to do if the aux device is already present. This also ++ * guards against a second add overwriting *pd_ptr and leaking the ++ * first, symmetric with the check in pdsc_auxbus_dev_del(). ++ */ ++ if (*pd_ptr) ++ goto out_unlock; ++ + mask = BIT_ULL(PDSC_S_FW_DEAD) | + BIT_ULL(PDSC_S_STOPPING_DRIVER); + if (cf->state & mask) { +-- +2.53.0 + diff --git a/queue-7.1/pds_core-fix-deadlock-between-reset-thread-and-remov.patch b/queue-7.1/pds_core-fix-deadlock-between-reset-thread-and-remov.patch new file mode 100644 index 0000000000..0b88199732 --- /dev/null +++ b/queue-7.1/pds_core-fix-deadlock-between-reset-thread-and-remov.patch @@ -0,0 +1,59 @@ +From bd90863ad163f4118257cd8e689a0b741dc2e38c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:02:22 +0000 +Subject: pds_core: fix deadlock between reset thread and remove + +From: Nikhil P. Rao + +[ Upstream commit ab0eec0ff0a421737a37f510ceab5c6ea59cd05a ] + +pci_reset_function() acquires device_lock before performing the reset. +pdsc_remove() is called by the PCI core with device_lock already held. +If pdsc_pci_reset_thread() is running when pdsc_remove() is called, +destroy_workqueue() will block waiting for the work to complete, while +the work is blocked waiting for device_lock - deadlock. + +Use pci_try_reset_function() which uses pci_dev_trylock() internally. +This acquires both the device lock and the PCI config access lock +without blocking - if either lock is contended, it returns -EAGAIN +immediately. This avoids the deadlock while also ensuring proper +config space access serialization during the reset. + +The pci_dev_get/put calls are also removed as they were unnecessary - +the driver-owned workqueue is destroyed in pdsc_remove(), guaranteeing +the work completes before remove returns. The PCI core holds its +reference to pci_dev throughout the entire unbind sequence. + +Fixes: 81665adf25d2 ("pds_core: Fix pdsc_check_pci_health function to use work thread") +Reported-by: sashiko-bot +Closes: https://patchwork.kernel.org/comment/27002369/ +Signed-off-by: Nikhil P. Rao +Reviewed-by: Harshitha Ramamurthy +Link: https://patch.msgid.link/20260714180223.1642792-2-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/core.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c +index 705cab7b07273d..b6d4b30147232a 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.c ++++ b/drivers/net/ethernet/amd/pds_core/core.c +@@ -602,9 +602,10 @@ void pdsc_pci_reset_thread(struct work_struct *work) + struct pdsc *pdsc = container_of(work, struct pdsc, pci_reset_work); + struct pci_dev *pdev = pdsc->pdev; + +- pci_dev_get(pdev); +- pci_reset_function(pdev); +- pci_dev_put(pdev); ++ /* Use try variant to avoid deadlock with pdsc_remove(). ++ * If lock is contended, the watchdog timer will retry. ++ */ ++ pci_try_reset_function(pdev); + } + + static void pdsc_check_pci_health(struct pdsc *pdsc) +-- +2.53.0 + diff --git a/queue-7.1/pds_core-fix-use-after-free-on-workqueue-during-remo.patch b/queue-7.1/pds_core-fix-use-after-free-on-workqueue-during-remo.patch new file mode 100644 index 0000000000..a76739c99f --- /dev/null +++ b/queue-7.1/pds_core-fix-use-after-free-on-workqueue-during-remo.patch @@ -0,0 +1,120 @@ +From 3a89f02ed1bc959b642a524039807dfb3c12b355 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 18:02:23 +0000 +Subject: pds_core: fix use-after-free on workqueue during remove + +From: Nikhil P. Rao + +[ Upstream commit 0ad134881508c36b65c1a8864f8bec53adbd3327 ] + +In pdsc_remove(), the workqueue is destroyed before pdsc_teardown() +is called. This ordering allows two paths to queue work on the +destroyed workqueue: + +1. If pdsc_teardown() -> pdsc_devcmd_reset() times out, the error + path in pdsc_devcmd_locked() queues health_work. + +2. A NotifyQ event can trigger the ISR and queue work before free_irq() + is called in pdsc_teardown(). + +Fix by moving destroy_workqueue() after pdsc_teardown() so the +workqueue outlives every queuer; destroy_workqueue() then flushes any +work still pending. + +Draining the queued work also requires ordering the teardown so the +resources that work touches are freed last: + + - In pdsc_qcq_free(), after freeing the interrupt, cancel_work_sync() + the queue's work and only then clear qcq->intx, so + pdsc_process_adminq()'s read of qcq->intx for interrupt-credit + return cannot race with the clear. + + - Free adminqcq before notifyqcq: the shared adminq ISR is released + when adminqcq is freed, and the adminq work accesses notifyqcq, so + both must be stopped before notifyqcq is freed. + +Fixes: 01ba61b55b20 ("pds_core: Add adminq processing and commands") +Reported-by: sashiko-bot +Closes: https://patchwork.kernel.org/comment/27002369/ +Signed-off-by: Nikhil P. Rao +Link: https://patch.msgid.link/20260714180223.1642792-3-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/core.c | 14 ++++++++++---- + drivers/net/ethernet/amd/pds_core/main.c | 5 +++-- + 2 files changed, 13 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c +index b6d4b30147232a..a73a2ab9060e62 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.c ++++ b/drivers/net/ethernet/amd/pds_core/core.c +@@ -110,7 +110,6 @@ static void pdsc_qcq_intr_free(struct pdsc *pdsc, struct pdsc_qcq *qcq) + return; + + pdsc_intr_free(pdsc, qcq->intx); +- qcq->intx = PDS_CORE_INTR_INDEX_NOT_ASSIGNED; + } + + static int pdsc_qcq_intr_alloc(struct pdsc *pdsc, struct pdsc_qcq *qcq) +@@ -145,6 +144,12 @@ void pdsc_qcq_free(struct pdsc *pdsc, struct pdsc_qcq *qcq) + + pdsc_qcq_intr_free(pdsc, qcq); + ++ /* Drain any work queued by ISR before it was freed above */ ++ if (qcq->work.func) ++ cancel_work_sync(&qcq->work); ++ ++ qcq->intx = PDS_CORE_INTR_INDEX_NOT_ASSIGNED; ++ + if (qcq->q_base) + dma_free_coherent(dev, qcq->q_size, + qcq->q_base, qcq->q_base_pa); +@@ -304,8 +309,11 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index, + + static void pdsc_core_uninit(struct pdsc *pdsc) + { +- pdsc_qcq_free(pdsc, &pdsc->notifyqcq); ++ /* Free adminqcq first: its work accesses notifyqcq, so we must ++ * disable its IRQ and drain its work before freeing notifyqcq. ++ */ + pdsc_qcq_free(pdsc, &pdsc->adminqcq); ++ pdsc_qcq_free(pdsc, &pdsc->notifyqcq); + + if (pdsc->kern_dbpage) { + iounmap(pdsc->kern_dbpage); +@@ -477,8 +485,6 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing) + { + if (!pdsc->pdev->is_virtfn) + pdsc_devcmd_reset(pdsc); +- if (pdsc->adminqcq.work.func) +- cancel_work_sync(&pdsc->adminqcq.work); + + pdsc_core_uninit(pdsc); + +diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c +index 22db78343eb075..638b9c7a509d9d 100644 +--- a/drivers/net/ethernet/amd/pds_core/main.c ++++ b/drivers/net/ethernet/amd/pds_core/main.c +@@ -435,8 +435,6 @@ static void pdsc_remove(struct pci_dev *pdev) + pdsc_auxbus_dev_del(pdsc, pdsc, &pdsc->padev); + + timer_shutdown_sync(&pdsc->wdtimer); +- if (pdsc->wq) +- destroy_workqueue(pdsc->wq); + + mutex_lock(&pdsc->config_lock); + set_bit(PDSC_S_STOPPING_DRIVER, &pdsc->state); +@@ -444,6 +442,9 @@ static void pdsc_remove(struct pci_dev *pdev) + pdsc_stop(pdsc); + pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING); + mutex_unlock(&pdsc->config_lock); ++ ++ if (pdsc->wq) ++ destroy_workqueue(pdsc->wq); + mutex_destroy(&pdsc->config_lock); + mutex_destroy(&pdsc->devcmd_lock); + +-- +2.53.0 + diff --git a/queue-7.1/pds_core-order-completion-reads-after-the-ownership-.patch b/queue-7.1/pds_core-order-completion-reads-after-the-ownership-.patch new file mode 100644 index 0000000000..3b0a13761e --- /dev/null +++ b/queue-7.1/pds_core-order-completion-reads-after-the-ownership-.patch @@ -0,0 +1,62 @@ +From ec058a689711d764eb7223202ac70dfd62a47ca7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 20:41:45 +0000 +Subject: pds_core: order completion reads after the ownership check + +From: Nikhil P. Rao + +[ Upstream commit dd6b1cc748cd28147c113f9daa76393916ad9494 ] + +pdsc_process_adminq() and pdsc_process_notifyq() decide a completion is +valid from its ownership field - the color bit for the adminq, the event +id for the notifyq - then read the rest of the descriptor, with no +barrier in between. + +On a weakly ordered architecture the CPU may read the payload first. Add +dma_rmb() between the ownership read and the payload reads. + +Fixes: 7e82a8745b95 ("pds_core: Prevent race issues involving the adminq") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Eric Joyner +Link: https://patch.msgid.link/20260714204145.1782390-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/adminq.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/amd/pds_core/adminq.c b/drivers/net/ethernet/amd/pds_core/adminq.c +index 097bb092bdb8cd..eadb4b604fbe3c 100644 +--- a/drivers/net/ethernet/amd/pds_core/adminq.c ++++ b/drivers/net/ethernet/amd/pds_core/adminq.c +@@ -18,7 +18,13 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq) + comp = cq_info->comp; + eid = le64_to_cpu(comp->event.eid); + while (eid > pdsc->last_eid) { +- u16 ecode = le16_to_cpu(comp->event.ecode); ++ u16 ecode; ++ ++ /* Order the payload read after the event id, the field the ++ * driver uses to detect a new completion. ++ */ ++ dma_rmb(); ++ ecode = le16_to_cpu(comp->event.ecode); + + switch (ecode) { + case PDS_EVENT_LINK_CHANGE: +@@ -101,6 +107,10 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq) + spin_lock_irqsave(&pdsc->adminq_lock, irqflags); + comp = cq->info[cq->tail_idx].comp; + while (pdsc_color_match(comp->color, cq->done_color)) { ++ /* Order the payload reads after the color bit, the field the ++ * driver uses to detect a new completion. ++ */ ++ dma_rmb(); + q_info = &q->info[q->tail_idx]; + q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1); + +-- +2.53.0 + diff --git a/queue-7.1/pds_core-reject-component-parameter-in-legacy-firmwa.patch b/queue-7.1/pds_core-reject-component-parameter-in-legacy-firmwa.patch new file mode 100644 index 0000000000..a5ced844c6 --- /dev/null +++ b/queue-7.1/pds_core-reject-component-parameter-in-legacy-firmwa.patch @@ -0,0 +1,44 @@ +From 0b3bfc99b5559c4ecbf98b9f30648bffe2726e25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:36:49 +0000 +Subject: pds_core: reject component parameter in legacy firmware update + +From: Nikhil P. Rao + +[ Upstream commit 7be2552e601c247a328a5aba6fc06ac844b94a16 ] + +The legacy firmware update path does not support per-component updates. +If a user specifies a component parameter with devlink flash, reject +the request with -EOPNOTSUPP rather than silently ignoring the component +parameter and flashing the entire firmware image. + +Fixes: 49ce92fbee0b ("pds_core: add FW update feature to devlink") +Signed-off-by: Nikhil P. Rao +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708163649.128620-1-nikhil.rao@amd.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/devlink.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c +index 3f0e56b951bf0b..d6fccd89476a0a 100644 +--- a/drivers/net/ethernet/amd/pds_core/devlink.c ++++ b/drivers/net/ethernet/amd/pds_core/devlink.c +@@ -90,6 +90,12 @@ int pdsc_dl_flash_update(struct devlink *dl, + { + struct pdsc *pdsc = devlink_priv(dl); + ++ if (params->component) { ++ NL_SET_ERR_MSG_MOD(extack, ++ "Component update not supported by this device"); ++ return -EOPNOTSUPP; ++ } ++ + return pdsc_firmware_update(pdsc, params->fw, extack); + } + +-- +2.53.0 + diff --git a/queue-7.1/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch b/queue-7.1/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch new file mode 100644 index 0000000000..06cdcae10e --- /dev/null +++ b/queue-7.1/pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch @@ -0,0 +1,53 @@ +From 9e922cc746f6d192e81278646e9cb0fc24b40cf7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 20:14:56 +0000 +Subject: pds_core: yield the CPU while waiting for the adminq to drain + +From: Nikhil P. Rao + +[ Upstream commit a11f0b8a204296fe7db9eaec53441012222cb004 ] + +pdsc_adminq_wait_and_dec_once_unused() busy-waits for adminq_refcnt to +drop to one: + + while (!refcount_dec_if_one(&pdsc->adminq_refcnt)) + cpu_relax(); + +The refcount is held by pdsc_adminq_post() for the duration of an +in-flight command, which can wait up to devcmd_timeout seconds +(PDS_CORE_DEVCMD_TIMEOUT is 5) for the hardware to complete. cpu_relax() +is not a reschedule point, so on a non-preemptible kernel this loop can +spin on the CPU for several seconds, starving other tasks on that core. + +Add cond_resched() to the loop so the waiter yields to other runnable +tasks while it polls, keeping cpu_relax() as the busy-wait hint between +checks. + +Fixes: 7e82a8745b95 ("pds_core: Prevent race issues involving the adminq") +Reported-by: sashiko-bot +Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2 +Signed-off-by: Nikhil P. Rao +Reviewed-by: Eric Joyner +Reviewed-by: Pavan Chebbi +Link: https://patch.msgid.link/20260714201456.1776153-1-nikhil.rao@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/amd/pds_core/core.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c +index a73a2ab9060e62..34181ac8479919 100644 +--- a/drivers/net/ethernet/amd/pds_core/core.c ++++ b/drivers/net/ethernet/amd/pds_core/core.c +@@ -535,6 +535,7 @@ static void pdsc_adminq_wait_and_dec_once_unused(struct pdsc *pdsc) + dev_dbg_ratelimited(pdsc->dev, "%s: adminq in use\n", + __func__); + cpu_relax(); ++ cond_resched(); + } + } + +-- +2.53.0 + diff --git a/queue-7.1/pidfs-make-pidfs_ino_lock-static.patch b/queue-7.1/pidfs-make-pidfs_ino_lock-static.patch new file mode 100644 index 0000000000..a28199af5d --- /dev/null +++ b/queue-7.1/pidfs-make-pidfs_ino_lock-static.patch @@ -0,0 +1,37 @@ +From b24b1f82aae542192cd126ed03f88c05188ae85f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Jul 2026 18:01:13 +0200 +Subject: pidfs: make pidfs_ino_lock static + +From: Mateusz Guzik + +[ Upstream commit c1d04c1bce98f9dd984a9c6657278a7761854c9c ] + +Fixes: 87caaeef7995 ("pidfs: implement ino allocation without the pidmap lock") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202607231547.ehCQxi0L-lkp@intel.com/ + +Signed-off-by: Mateusz Guzik +Link: https://patch.msgid.link/20260723160114.291515-1-mjguzik@gmail.com +Signed-off-by: Christian Brauner (Amutable) +Signed-off-by: Sasha Levin +--- + fs/pidfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/pidfs.c b/fs/pidfs.c +index 143d0aec16af10..33874c891d285e 100644 +--- a/fs/pidfs.c ++++ b/fs/pidfs.c +@@ -107,7 +107,7 @@ struct pidfs_attr { + + #if BITS_PER_LONG == 32 + +-DEFINE_SPINLOCK(pidfs_ino_lock); ++static DEFINE_SPINLOCK(pidfs_ino_lock); + static u64 pidfs_ino_nr = 1; + + static inline unsigned long pidfs_ino(u64 ino) +-- +2.53.0 + diff --git a/queue-7.1/platform-x86-asus-wmi-temporarily-revert-to-setting-.patch b/queue-7.1/platform-x86-asus-wmi-temporarily-revert-to-setting-.patch new file mode 100644 index 0000000000..c2edf86706 --- /dev/null +++ b/queue-7.1/platform-x86-asus-wmi-temporarily-revert-to-setting-.patch @@ -0,0 +1,81 @@ +From 12cc02fd9a407d59893798846fdb6f13097a549f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 16:58:41 +0000 +Subject: platform/x86: asus-wmi: temporarily revert to setting a charge limit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Denis Benato + +[ Upstream commit 78bf392ba77dd8b2a25656e489449d2f91cfd1eb ] + +A userspace regression has been observed leaving the battery charging +threshold unconfigured, so while the fix is being shipped revert +the change keeping the infrastructure in place to return to the +preferred behaviour as soon as it's appropriate to do. + +Link: https://lore.kernel.org/all/5db117b7-aad1-437f-a3d4-ba7b29fc68b3@redhat.com/ +Link: https://gitlab.freedesktop.org/upower/upower/-/work_items/347 +Closes: https://lore.kernel.org/all/CABsFS_g+V_Owum6knLhenhM15EXJRrsF0FcLiw30WZxarsTpUA@mail.gmail.com/ +Fixes: 186bf9031666 ("platform/x86: asus-wmi: do not enforce a battery charge threshold") +Reported-by: Travers Biddle +Signed-off-by: Denis Benato +Link: https://patch.msgid.link/20260710165841.59957-1-denis.benato@linux.dev +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-wmi.c | 26 +++++++++++++++++++++++--- + 1 file changed, 23 insertions(+), 3 deletions(-) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 80144c412b902f..a459b7ad18ba0f 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -1566,6 +1566,8 @@ static DEVICE_ATTR_RW(charge_control_end_threshold); + + static int asus_wmi_battery_add(struct power_supply *battery, struct acpi_battery_hook *hook) + { ++ int ret, rv; ++ + /* The WMI method does not provide a way to specific a battery, so we + * just assume it is the first battery. + * Note: On some newer ASUS laptops (Zenbook UM431DA), the primary/first +@@ -1583,12 +1585,30 @@ static int asus_wmi_battery_add(struct power_supply *battery, struct acpi_batter + + /* The charge threshold is only reset when the system is power cycled, + * and we can't read the current threshold, however the majority of +- * platforms retains it, therefore signal the threshold as unknown +- * until user explicitly sets it to a new value. ++ * platforms retains it. ++ * ++ * Setting a negative value would signal the threshold as unknown ++ * until user explicitly sets it to a new value, however to avoid ++ * regressing userspace, we initialize it to a value of 100. + */ +- charge_end_threshold = -1; ++ charge_end_threshold = 100; ++ ret = asus_wmi_set_devstate(ASUS_WMI_DEVID_RSOC, charge_end_threshold, &rv); ++ if (ret) { ++ pr_err("Failed to reset battery charge threshold\n"); ++ goto asus_wmi_battery_add_err; ++ } ++ ++ if (rv != 1) { ++ pr_err("Error in battery charge threshold reset\n"); ++ ret = -EIO; ++ goto asus_wmi_battery_add_err; ++ } + + return 0; ++asus_wmi_battery_add_err: ++ device_remove_file(&battery->dev, ++ &dev_attr_charge_control_end_threshold); ++ return ret; + } + + static int asus_wmi_battery_remove(struct power_supply *battery, struct acpi_battery_hook *hook) +-- +2.53.0 + diff --git a/queue-7.1/platform-x86-intel-vsec-allocate-res-with-intel_vsec.patch b/queue-7.1/platform-x86-intel-vsec-allocate-res-with-intel_vsec.patch new file mode 100644 index 0000000000..a7c8f4c263 --- /dev/null +++ b/queue-7.1/platform-x86-intel-vsec-allocate-res-with-intel_vsec.patch @@ -0,0 +1,168 @@ +From 6d2070854909bac8565114c21c29c291e27df4e1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Apr 2026 15:43:07 -0700 +Subject: platform/x86/intel/vsec: allocate res with intel_vsec_dev +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Rosen Penev + +[ Upstream commit 8ef6b01cee44803691c0a0c95b36f8ec710e2afb ] + +Use a flexible array member to combine allocations. Avoids having to +free separately. + +Add __counted_by for extra runtime analysis. + +Move counting variable assignment to after allocations as is already +done by kzalloc_flex for GCC 15 and above. + +Signed-off-by: Rosen Penev +Tested-by: David E. Box +Reviewed-by: David E. Box +Link: https://patch.msgid.link/20260430224307.109311-1-rosenp@gmail.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Stable-dep-of: 09b2ae290a24 ("platform/x86/intel/vsec: free ACPI discovery data on early errors") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/vsec.c | 14 ++++---------- + drivers/platform/x86/intel/vsec_tpmi.c | 13 ++++--------- + include/linux/intel_vsec.h | 6 +++--- + 3 files changed, 11 insertions(+), 22 deletions(-) + +diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c +index 439c0c8ac896c7..3ae4557b32b478 100644 +--- a/drivers/platform/x86/intel/vsec.c ++++ b/drivers/platform/x86/intel/vsec.c +@@ -112,7 +112,6 @@ static void intel_vsec_dev_release(struct device *dev) + ida_free(intel_vsec_dev->ida, intel_vsec_dev->auxdev.id); + + kfree(intel_vsec_dev->acpi_disc); +- kfree(intel_vsec_dev->resource); + kfree(intel_vsec_dev); + } + +@@ -225,7 +224,6 @@ int intel_vsec_add_aux(struct device *parent, + ret = xa_alloc(&auxdev_array, &intel_vsec_dev->id, intel_vsec_dev, + PMT_XA_LIMIT, GFP_KERNEL); + if (ret < 0) { +- kfree(intel_vsec_dev->resource); + kfree(intel_vsec_dev); + return ret; + } +@@ -233,7 +231,6 @@ int intel_vsec_add_aux(struct device *parent, + id = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL); + if (id < 0) { + xa_erase(&auxdev_array, intel_vsec_dev->id); +- kfree(intel_vsec_dev->resource); + kfree(intel_vsec_dev); + return id; + } +@@ -282,7 +279,7 @@ static int intel_vsec_add_dev(struct device *dev, struct intel_vsec_header *head + unsigned long cap_id, u64 base_addr) + { + struct intel_vsec_device __free(kfree) *intel_vsec_dev = NULL; +- struct resource __free(kfree) *res = NULL; ++ struct resource *res; + struct resource *tmp; + struct device *parent; + unsigned long quirks = info->quirks; +@@ -306,13 +303,12 @@ static int intel_vsec_add_dev(struct device *dev, struct intel_vsec_header *head + return -EINVAL; + } + +- intel_vsec_dev = kzalloc_obj(*intel_vsec_dev); ++ intel_vsec_dev = kzalloc_flex(*intel_vsec_dev, resource, header->num_entries); + if (!intel_vsec_dev) + return -ENOMEM; + +- res = kzalloc_objs(*res, header->num_entries); +- if (!res) +- return -ENOMEM; ++ intel_vsec_dev->num_resources = header->num_entries; ++ res = intel_vsec_dev->resource; + + if (quirks & VSEC_QUIRK_TABLE_SHIFT) + header->offset >>= TABLE_OFFSET_SHIFT; +@@ -342,8 +338,6 @@ static int intel_vsec_add_dev(struct device *dev, struct intel_vsec_header *head + } + + intel_vsec_dev->dev = dev; +- intel_vsec_dev->resource = no_free_ptr(res); +- intel_vsec_dev->num_resources = header->num_entries; + intel_vsec_dev->quirks = info->quirks; + intel_vsec_dev->base_addr = info->base_addr; + intel_vsec_dev->priv_data = info->priv_data; +diff --git a/drivers/platform/x86/intel/vsec_tpmi.c b/drivers/platform/x86/intel/vsec_tpmi.c +index 88f14d0ad4102f..3b76cccb975f6b 100644 +--- a/drivers/platform/x86/intel/vsec_tpmi.c ++++ b/drivers/platform/x86/intel/vsec_tpmi.c +@@ -634,15 +634,12 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info, + if (!name) + return -EOPNOTSUPP; + +- res = kzalloc_objs(*res, pfs->pfs_header.num_entries); +- if (!res) ++ feature_vsec_dev = kzalloc_flex(*feature_vsec_dev, resource, pfs->pfs_header.num_entries); ++ if (!feature_vsec_dev) + return -ENOMEM; + +- feature_vsec_dev = kzalloc_obj(*feature_vsec_dev); +- if (!feature_vsec_dev) { +- kfree(res); +- return -ENOMEM; +- } ++ feature_vsec_dev->num_resources = pfs->pfs_header.num_entries; ++ res = feature_vsec_dev->resource; + + snprintf(feature_id_name, sizeof(feature_id_name), "tpmi-%s", name); + +@@ -655,8 +652,6 @@ static int tpmi_create_device(struct intel_tpmi_info *tpmi_info, + } + + feature_vsec_dev->dev = vsec_dev->dev; +- feature_vsec_dev->resource = res; +- feature_vsec_dev->num_resources = pfs->pfs_header.num_entries; + feature_vsec_dev->priv_data = &tpmi_info->plat_info; + feature_vsec_dev->priv_data_size = sizeof(tpmi_info->plat_info); + feature_vsec_dev->ida = &intel_vsec_tpmi_ida; +diff --git a/include/linux/intel_vsec.h b/include/linux/intel_vsec.h +index 1fe5665a9d02a8..07ea563f524ee2 100644 +--- a/include/linux/intel_vsec.h ++++ b/include/linux/intel_vsec.h +@@ -135,8 +135,6 @@ struct intel_vsec_platform_info { + * struct intel_vsec_device - Auxbus specific device information + * @auxdev: auxbus device struct for auxbus access + * @dev: struct device associated with the device +- * @resource: PCI discovery resources (BAR windows), one per discovery +- * instance. Valid only when @src == INTEL_VSEC_DISC_PCI + * @acpi_disc: ACPI discovery tables, each entry is two QWORDs + * in little-endian format as defined by the PMT ACPI spec. + * Valid only when @src == INTEL_VSEC_DISC_ACPI. +@@ -149,11 +147,12 @@ struct intel_vsec_platform_info { + * @quirks: specified quirks + * @base_addr: base address of entries (if specified) + * @cap_id: the enumerated id of the vsec feature ++ * @resource: PCI discovery resources (BAR windows), one per discovery ++ * instance. Valid only when @src == INTEL_VSEC_DISC_PCI + */ + struct intel_vsec_device { + struct auxiliary_device auxdev; + struct device *dev; +- struct resource *resource; + u32 (*acpi_disc)[4]; + enum intel_vsec_disc_source src; + struct ida *ida; +@@ -164,6 +163,7 @@ struct intel_vsec_device { + unsigned long quirks; + u64 base_addr; + unsigned long cap_id; ++ struct resource resource[] __counted_by(num_resources); + }; + + /** +-- +2.53.0 + diff --git a/queue-7.1/platform-x86-intel-vsec-free-acpi-discovery-data-on-.patch b/queue-7.1/platform-x86-intel-vsec-free-acpi-discovery-data-on-.patch new file mode 100644 index 0000000000..99ae208697 --- /dev/null +++ b/queue-7.1/platform-x86-intel-vsec-free-acpi-discovery-data-on-.patch @@ -0,0 +1,88 @@ +From 3ec121b3a612ec849a5f934984e4cf090c66ae11 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 09:13:39 -0400 +Subject: platform/x86/intel/vsec: free ACPI discovery data on early errors +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Yousef Alhouseen + +[ Upstream commit 09b2ae290a241ce1f5f738fb65c35f449dcf663d ] + +intel_vsec_add_dev() may attach an ACPI discovery table copy to the +intel_vsec_device before passing ownership to intel_vsec_add_aux(). The +normal auxiliary-device release path frees that copy, but the earliest +intel_vsec_add_aux() failures free only the outer structure directly. + +Route those direct frees through a common helper so acpi_disc is +released consistently on the parent, xarray, and ID allocation failure +paths. + +Fixes: 22fa2ebc11a1 ("platform/x86/intel/vsec: Plumb ACPI PMT discovery tables through vsec") +Signed-off-by: Yousef Alhouseen +Reviewed-by: David E. Box +Link: https://patch.msgid.link/CAMuQ4bUtJtYNTguKoiXngROJw0QQQcrvW3=3_B0-hpMQOFqvCQ@mail.gmail.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/vsec.c | 17 ++++++++++++----- + 1 file changed, 12 insertions(+), 5 deletions(-) + +diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c +index 3ae4557b32b478..5ab2215fdd7fa8 100644 +--- a/drivers/platform/x86/intel/vsec.c ++++ b/drivers/platform/x86/intel/vsec.c +@@ -103,6 +103,12 @@ static void intel_vsec_remove_aux(void *data) + auxiliary_device_uninit(data); + } + ++static void intel_vsec_dev_free(struct intel_vsec_device *intel_vsec_dev) ++{ ++ kfree(intel_vsec_dev->acpi_disc); ++ kfree(intel_vsec_dev); ++} ++ + static void intel_vsec_dev_release(struct device *dev) + { + struct intel_vsec_device *intel_vsec_dev = dev_to_ivdev(dev); +@@ -111,8 +117,7 @@ static void intel_vsec_dev_release(struct device *dev) + + ida_free(intel_vsec_dev->ida, intel_vsec_dev->auxdev.id); + +- kfree(intel_vsec_dev->acpi_disc); +- kfree(intel_vsec_dev); ++ intel_vsec_dev_free(intel_vsec_dev); + } + + static const struct vsec_feature_dependency * +@@ -218,20 +223,22 @@ int intel_vsec_add_aux(struct device *parent, + struct auxiliary_device *auxdev = &intel_vsec_dev->auxdev; + int ret, id; + +- if (!parent) ++ if (!parent) { ++ intel_vsec_dev_free(intel_vsec_dev); + return -EINVAL; ++ } + + ret = xa_alloc(&auxdev_array, &intel_vsec_dev->id, intel_vsec_dev, + PMT_XA_LIMIT, GFP_KERNEL); + if (ret < 0) { +- kfree(intel_vsec_dev); ++ intel_vsec_dev_free(intel_vsec_dev); + return ret; + } + + id = ida_alloc(intel_vsec_dev->ida, GFP_KERNEL); + if (id < 0) { + xa_erase(&auxdev_array, intel_vsec_dev->id); +- kfree(intel_vsec_dev); ++ intel_vsec_dev_free(intel_vsec_dev); + return id; + } + +-- +2.53.0 + diff --git a/queue-7.1/ppp-annotate-concurrent-dev-stats-accesses.patch b/queue-7.1/ppp-annotate-concurrent-dev-stats-accesses.patch new file mode 100644 index 0000000000..1a7c1c54f1 --- /dev/null +++ b/queue-7.1/ppp-annotate-concurrent-dev-stats-accesses.patch @@ -0,0 +1,142 @@ +From 05fb95e634ef641bc8529e8219dcca0a7a246d2a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 05:55:41 +0000 +Subject: ppp: annotate concurrent dev->stats accesses + +From: Eric Dumazet + +[ Upstream commit ba712ecfd942b68b21a4b0a5daaf72f6616cc66d ] + +dev->stats fields can be updated concurrently from multiple CPUs +without synchronization. + +Use DEV_STATS_INC() for stats increments and DEV_STATS_READ() +when reading dev->stats in ppp_get_stats64() and ppp_get_stats() +to avoid data races. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/20260715055541.1147542-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 32 ++++++++++++++++---------------- + 1 file changed, 16 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 717c1d3aa95380..ef54e0a0462a17 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1482,7 +1482,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) + + outf: + kfree_skb(skb); +- ++dev->stats.tx_dropped; ++ DEV_STATS_INC(dev, tx_dropped); + return NETDEV_TX_OK; + } + +@@ -1532,11 +1532,11 @@ ppp_net_siocdevprivate(struct net_device *dev, struct ifreq *ifr, + static void + ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) + { +- stats64->rx_errors = dev->stats.rx_errors; +- stats64->tx_errors = dev->stats.tx_errors; +- stats64->rx_dropped = dev->stats.rx_dropped; +- stats64->tx_dropped = dev->stats.tx_dropped; +- stats64->rx_length_errors = dev->stats.rx_length_errors; ++ stats64->rx_errors = DEV_STATS_READ(dev, rx_errors); ++ stats64->tx_errors = DEV_STATS_READ(dev, tx_errors); ++ stats64->rx_dropped = DEV_STATS_READ(dev, rx_dropped); ++ stats64->tx_dropped = DEV_STATS_READ(dev, tx_dropped); ++ stats64->rx_length_errors = DEV_STATS_READ(dev, rx_length_errors); + dev_fetch_sw_netstats(stats64, dev->tstats); + } + +@@ -1889,7 +1889,7 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb) + + drop: + kfree_skb(skb); +- ++ppp->dev->stats.tx_errors; ++ DEV_STATS_INC(ppp->dev, tx_errors); + return 1; + } + +@@ -2156,7 +2156,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + err_linearize: + if (ppp->debug & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); +- ++ppp->dev->stats.tx_errors; ++ DEV_STATS_INC(ppp->dev, tx_errors); + ++ppp->nxseq; + return 1; /* abandon the frame */ + } +@@ -2329,7 +2329,7 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) + if (!ppp_decompress_proto(skb)) { + kfree_skb(skb); + if (ppp) { +- ++ppp->dev->stats.rx_length_errors; ++ DEV_STATS_INC(ppp->dev, rx_length_errors); + ppp_receive_error(ppp); + } + goto done; +@@ -2391,7 +2391,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) + static void + ppp_receive_error(struct ppp *ppp) + { +- ++ppp->dev->stats.rx_errors; ++ DEV_STATS_INC(ppp->dev, rx_errors); + if (ppp->vj) + slhc_toss(ppp->vj); + } +@@ -2658,7 +2658,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) + */ + if (seq_before(seq, ppp->nextseq)) { + kfree_skb(skb); +- ++ppp->dev->stats.rx_dropped; ++ DEV_STATS_INC(ppp->dev, rx_dropped); + ppp_receive_error(ppp); + return; + } +@@ -2694,7 +2694,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) + if (pskb_may_pull(skb, 2)) + ppp_receive_nonmp_frame(ppp, skb); + else { +- ++ppp->dev->stats.rx_length_errors; ++ DEV_STATS_INC(ppp->dev, rx_length_errors); + kfree_skb(skb); + ppp_receive_error(ppp); + } +@@ -2800,7 +2800,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + if (lost == 0 && (PPP_MP_CB(p)->BEbits & E) && + (PPP_MP_CB(head)->BEbits & B)) { + if (len > ppp->mrru + 2) { +- ++ppp->dev->stats.rx_length_errors; ++ DEV_STATS_INC(ppp->dev, rx_length_errors); + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: reconstructed packet" + " is too long (%d)\n", len); +@@ -2855,7 +2855,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + " missed pkts %u..%u\n", + ppp->nextseq, + PPP_MP_CB(head)->sequence-1); +- ++ppp->dev->stats.rx_dropped; ++ DEV_STATS_INC(ppp->dev, rx_dropped); + ppp_receive_error(ppp); + } + +@@ -3322,8 +3322,8 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) + st->p.ppp_opackets += tx_packets; + st->p.ppp_obytes += tx_bytes; + } +- st->p.ppp_ierrors = ppp->dev->stats.rx_errors; +- st->p.ppp_oerrors = ppp->dev->stats.tx_errors; ++ st->p.ppp_ierrors = DEV_STATS_READ(ppp->dev, rx_errors); ++ st->p.ppp_oerrors = DEV_STATS_READ(ppp->dev, tx_errors); + if (!vj) + return; + st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed; +-- +2.53.0 + diff --git a/queue-7.1/ppp-annotate-data-races-in-ppp_generic.patch b/queue-7.1/ppp-annotate-data-races-in-ppp_generic.patch new file mode 100644 index 0000000000..9457362fef --- /dev/null +++ b/queue-7.1/ppp-annotate-data-races-in-ppp_generic.patch @@ -0,0 +1,233 @@ +From 89eafa88ed8229f26e41040a538afa4fd52e2d6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Jul 2026 10:16:05 +0000 +Subject: ppp: annotate data races in ppp_generic + +From: Eric Dumazet + +[ Upstream commit 543adf072165aaf2e3b635c0476204f9658ed3bf ] + +Several fields in struct ppp can be read or updated concurrently +from multiple CPUs without synchronization, causing data races: + +1. ppp->mru is read concurrently in ppp_receive_nonmp_frame() while + being updated via PPPIOCSMRU ioctl. Protect ppp->mru updates in + PPPIOCSMRU with ppp_recv_lock(ppp). + +2. PPPIOCGFLAGS reads ppp->flags, ppp->xstate, and ppp->rstate + unlocked. Wrap the read in ppp_lock(ppp) to get a consistent + snapshot. + +3. ppp->debug is updated via PPPIOCSDEBUG and read concurrently on + fast paths. Annotate reads with READ_ONCE() and writes with + WRITE_ONCE(). + +4. ppp->last_xmit and ppp->last_recv are updated on TX/RX data paths + and read via PPPIOCGIDLE32 / PPPIOCGIDLE64 ioctls. Annotate with + WRITE_ONCE() / READ_ONCE() and use max() to handle jiffies + subtraction. + +5. ppp->npmode[] is updated via PPPIOCSNPMODE and read on TX/RX + paths. Annotate with WRITE_ONCE() / READ_ONCE(). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reviewed-by: Qingfang Deng +Link: https://patch.msgid.link/20260722101605.2868548-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ppp/ppp_generic.c | 50 ++++++++++++++++++++--------------- + 1 file changed, 28 insertions(+), 22 deletions(-) + +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index ef54e0a0462a17..cacc4c3a37d2cd 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -810,7 +810,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case PPPIOCSMRU: + if (get_user(val, p)) + break; ++ ppp_recv_lock(ppp); + ppp->mru = val; ++ ppp_recv_unlock(ppp); + err = 0; + break; + +@@ -831,7 +833,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + + case PPPIOCGFLAGS: ++ ppp_lock(ppp); + val = ppp->flags | ppp->xstate | ppp->rstate; ++ ppp_unlock(ppp); + if (put_user(val, p)) + break; + err = 0; +@@ -855,7 +859,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + case PPPIOCSDEBUG: + if (get_user(val, p)) + break; +- ppp->debug = val; ++ WRITE_ONCE(ppp->debug, val); + err = 0; + break; + +@@ -866,16 +870,16 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + break; + + case PPPIOCGIDLE32: +- idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ; +- idle32.recv_idle = (jiffies - ppp->last_recv) / HZ; +- if (copy_to_user(argp, &idle32, sizeof(idle32))) ++ idle32.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ; ++ idle32.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ; ++ if (copy_to_user(argp, &idle32, sizeof(idle32))) + break; + err = 0; + break; + + case PPPIOCGIDLE64: +- idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ; +- idle64.recv_idle = (jiffies - ppp->last_recv) / HZ; ++ idle64.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ; ++ idle64.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ; + if (copy_to_user(argp, &idle64, sizeof(idle64))) + break; + err = 0; +@@ -916,7 +920,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + if (copy_to_user(argp, &npi, sizeof(npi))) + break; + } else { +- ppp->npmode[i] = npi.mode; ++ WRITE_ONCE(ppp->npmode[i], npi.mode); + /* we may be able to transmit more packets now (??) */ + netif_wake_queue(ppp->dev); + } +@@ -1454,7 +1458,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) + goto outf; + + /* Drop, accept or reject the packet */ +- switch (ppp->npmode[npi]) { ++ switch (READ_ONCE(ppp->npmode[npi])) { + case NPMODE_PASS: + break; + case NPMODE_QUEUE: +@@ -1790,7 +1794,7 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb) + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_OUTBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: outbound frame " + "not passed\n"); +@@ -1800,11 +1804,11 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb) + /* if this packet passes the active filter, record the time */ + if (!(ppp->active_filter && + bpf_prog_run(ppp->active_filter, skb) == 0)) +- ppp->last_xmit = jiffies; ++ WRITE_ONCE(ppp->last_xmit, jiffies); + skb_pull(skb, 2); + #else + /* for data packets, record the time */ +- ppp->last_xmit = jiffies; ++ WRITE_ONCE(ppp->last_xmit, jiffies); + #endif /* CONFIG_PPP_FILTER */ + } + +@@ -2154,7 +2158,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) + noskb: + spin_unlock(&pch->downl); + err_linearize: +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); + DEV_STATS_INC(ppp->dev, tx_errors); + ++ppp->nxseq; +@@ -2502,7 +2506,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + *(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG); + if (ppp->pass_filter && + bpf_prog_run(ppp->pass_filter, skb) == 0) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "PPP: inbound frame " + "not passed\n"); +@@ -2511,14 +2515,14 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) + } + if (!(ppp->active_filter && + bpf_prog_run(ppp->active_filter, skb) == 0)) +- ppp->last_recv = jiffies; ++ WRITE_ONCE(ppp->last_recv, jiffies); + __skb_pull(skb, 2); + } else + #endif /* CONFIG_PPP_FILTER */ +- ppp->last_recv = jiffies; ++ WRITE_ONCE(ppp->last_recv, jiffies); + + if ((ppp->dev->flags & IFF_UP) == 0 || +- ppp->npmode[npi] != NPMODE_PASS) { ++ READ_ONCE(ppp->npmode[npi]) != NPMODE_PASS) { + kfree_skb(skb); + } else { + /* chop off protocol */ +@@ -2771,7 +2775,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + seq = seq_before(minseq, PPP_MP_CB(p)->sequence)? + minseq + 1: PPP_MP_CB(p)->sequence; + +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "lost frag %u..%u\n", + oldseq, seq-1); +@@ -2820,7 +2824,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + struct sk_buff *tmp2; + + skb_queue_reverse_walk_from_safe(list, p, tmp2) { +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "discarding frag %u\n", + PPP_MP_CB(p)->sequence); +@@ -2842,7 +2846,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + skb_queue_walk_safe(list, p, tmp) { + if (p == head) + break; +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + "discarding frag %u\n", + PPP_MP_CB(p)->sequence); +@@ -2850,7 +2854,7 @@ ppp_mp_reconstruct(struct ppp *ppp) + kfree_skb(p); + } + +- if (ppp->debug & 1) ++ if (READ_ONCE(ppp->debug) & 1) + netdev_printk(KERN_DEBUG, ppp->dev, + " missed pkts %u..%u\n", + ppp->nextseq, +@@ -3161,7 +3165,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) + if (!ppp->rc_state) + break; + if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len, +- ppp->file.index, 0, ppp->mru, ppp->debug)) { ++ ppp->file.index, 0, ppp->mru, ++ READ_ONCE(ppp->debug))) { + ppp->rstate |= SC_DECOMP_RUN; + ppp->rstate &= ~(SC_DC_ERROR | SC_DC_FERROR); + } +@@ -3170,7 +3175,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) + if (!ppp->xc_state) + break; + if (ppp->xcomp->comp_init(ppp->xc_state, dp, len, +- ppp->file.index, 0, ppp->debug)) ++ ppp->file.index, 0, ++ READ_ONCE(ppp->debug))) + ppp->xstate |= SC_COMP_RUN; + } + break; +-- +2.53.0 + diff --git a/queue-7.1/ptp-netc-explicitly-clear-tmr_off-during-initializat.patch b/queue-7.1/ptp-netc-explicitly-clear-tmr_off-during-initializat.patch new file mode 100644 index 0000000000..eb98438fba --- /dev/null +++ b/queue-7.1/ptp-netc-explicitly-clear-tmr_off-during-initializat.patch @@ -0,0 +1,52 @@ +From c042186772825191336a9099b0e0cd82f36c1773 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 09:25:08 +0800 +Subject: ptp: netc: explicitly clear TMR_OFF during initialization + +From: Clark Wang + +[ Upstream commit c3f2fc231a39e29fe9f0adc14a3ecc3c1260d3c5 ] + +The NETC timer does not support function level reset, so TMR_OFF_L/H +registers are not cleared by pcie_flr(). If TMR_OFF was set to a +non-zero value in a previous binding, it will persist across driver +rebind and cause inaccurate PTP time. + +There is also a hardware issue: after a warm reset or soft reset, +TMR_OFF_L/H registers appear to be cleared to zero, but the timer clock +domain internally retains the stale value. When the timer is re-enabled, +TMR_CUR_TIME continues to track the old offset until TMR_OFF is written +explicitly. This can cause incorrect PTP timestamps and even PTP clock +synchronization failures. + +Per the recommendation from the IP team, explicitly write 0 to TMR_OFF +in netc_timer_init() to flush the internally cached value and ensure +TMR_CUR_TIME follows the freshly initialized counter. + +Fixes: 87a201d59963 ("ptp: netc: add NETC V4 Timer PTP driver support") +Signed-off-by: Clark Wang +Signed-off-by: Wei Fang +Reviewed-by: Vadim Fedorenko +Reviewed-by: Breno Leitao +Link: https://patch.msgid.link/20260720012508.23227-1-wei.fang@oss.nxp.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/ptp/ptp_netc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/ptp/ptp_netc.c b/drivers/ptp/ptp_netc.c +index 94e952ee69902e..5e381c354d746a 100644 +--- a/drivers/ptp/ptp_netc.c ++++ b/drivers/ptp/ptp_netc.c +@@ -779,6 +779,7 @@ static void netc_timer_init(struct netc_timer *priv) + netc_timer_wr(priv, NETC_TMR_FIPER_CTRL, fiper_ctrl); + netc_timer_wr(priv, NETC_TMR_ECTRL, NETC_TMR_DEFAULT_ETTF_THR); + ++ netc_timer_offset_write(priv, 0); + ktime_get_real_ts64(&now); + ns = timespec64_to_ns(&now); + netc_timer_cnt_write(priv, ns); +-- +2.53.0 + diff --git a/queue-7.1/raw-annotate-lockless-match-fields-in-raw_v4_match.patch b/queue-7.1/raw-annotate-lockless-match-fields-in-raw_v4_match.patch new file mode 100644 index 0000000000..69d9808d64 --- /dev/null +++ b/queue-7.1/raw-annotate-lockless-match-fields-in-raw_v4_match.patch @@ -0,0 +1,101 @@ +From e530b08fb98510156a623e8fed382675d8608433 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 22:29:58 +0800 +Subject: raw: annotate lockless match fields in raw_v4_match() + +From: Runyu Xiao + +[ Upstream commit 18f116931f52e3c3303ad4b15ff41eb89b0e4239 ] + +raw_v4_match() is a lockless match helper under sk_for_each_rcu(). It +still reads inet->inet_daddr, inet->inet_rcv_saddr and +sk->sk_bound_dev_if with plain loads while bind, connect and +bind-to-device paths can update the same match fields concurrently. + +Annotate only those mutable match fields in raw_v4_match(), and do so +at the point of use instead of hoisting the bound-device read before +the earlier short-circuit tests. + +Also annotate the raw bind writer and the shared IPv4 datagram connect +writer used by raw sockets, so the address fields updated on bind and +connect match explicit WRITE_ONCE() updates. + +This version intentionally leaves the shared disconnect-side IPv4 +writers to follow-up cleanup and limits the writer changes here to the +raw bind path and the datagram connect path directly exercised by raw +sockets. + +Fixes: 0daf07e52709 ("raw: convert raw sockets to RCU") +Signed-off-by: Runyu Xiao +Link: https://patch.msgid.link/20260716142958.3064224-1-runyu.xiao@seu.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/datagram.c | 4 ++-- + net/ipv4/raw.c | 23 ++++++++++++++++------- + 2 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c +index 1614593b6d7270..7d25519a6cdd3f 100644 +--- a/net/ipv4/datagram.c ++++ b/net/ipv4/datagram.c +@@ -63,12 +63,12 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr_unsized *uaddr, int + } + + /* Update addresses before rehashing */ +- inet->inet_daddr = fl4->daddr; ++ WRITE_ONCE(inet->inet_daddr, fl4->daddr); + inet->inet_dport = usin->sin_port; + if (!inet->inet_saddr) + inet->inet_saddr = fl4->saddr; + if (!inet->inet_rcv_saddr) { +- inet->inet_rcv_saddr = fl4->saddr; ++ WRITE_ONCE(inet->inet_rcv_saddr, fl4->saddr); + if (sk->sk_prot->rehash) + sk->sk_prot->rehash(sk); + } +diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c +index 68e88cb3e55cbd..f47b8b49da3d12 100644 +--- a/net/ipv4/raw.c ++++ b/net/ipv4/raw.c +@@ -120,13 +120,21 @@ bool raw_v4_match(struct net *net, const struct sock *sk, unsigned short num, + __be32 raddr, __be32 laddr, int dif, int sdif) + { + const struct inet_sock *inet = inet_sk(sk); ++ __be32 daddr, rcv_saddr; + +- if (net_eq(sock_net(sk), net) && inet->inet_num == num && +- !(inet->inet_daddr && inet->inet_daddr != raddr) && +- !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && +- raw_sk_bound_dev_eq(net, sk->sk_bound_dev_if, dif, sdif)) +- return true; +- return false; ++ if (!net_eq(sock_net(sk), net) || inet->inet_num != num) ++ return false; ++ ++ daddr = READ_ONCE(inet->inet_daddr); ++ if (daddr && daddr != raddr) ++ return false; ++ ++ rcv_saddr = READ_ONCE(inet->inet_rcv_saddr); ++ if (rcv_saddr && rcv_saddr != laddr) ++ return false; ++ ++ return raw_sk_bound_dev_eq(net, READ_ONCE(sk->sk_bound_dev_if), ++ dif, sdif); + } + EXPORT_SYMBOL_GPL(raw_v4_match); + +@@ -724,7 +732,8 @@ static int raw_bind(struct sock *sk, struct sockaddr_unsized *uaddr, + chk_addr_ret)) + goto out; + +- inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr; ++ inet->inet_saddr = addr->sin_addr.s_addr; ++ WRITE_ONCE(inet->inet_rcv_saddr, addr->sin_addr.s_addr); + if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) + inet->inet_saddr = 0; /* Use device */ + sk_dst_reset(sk); +-- +2.53.0 + diff --git a/queue-7.1/rds-drop-incoming-messages-that-cross-network-namesp.patch b/queue-7.1/rds-drop-incoming-messages-that-cross-network-namesp.patch new file mode 100644 index 0000000000..8091747d33 --- /dev/null +++ b/queue-7.1/rds-drop-incoming-messages-that-cross-network-namesp.patch @@ -0,0 +1,78 @@ +From d8e9bde05461770e779ef31fd7bcab71dbab2f58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 19:43:14 -0700 +Subject: rds: drop incoming messages that cross network namespace boundaries + +From: Aldo Ariel Panzardo + +[ Upstream commit 5521ae71e32a8069ed4ca6e792179dc57bc43ab2 ] + +rds_find_bound() looks up the destination socket using a global +rhashtable keyed solely on (addr, port, scope_id). Network namespaces +are not part of the key, so a sender in netns A can deliver an incoming +message (inc) to a socket that lives in a different netns B. + +When this happens, inc->i_conn points to an rds_connection whose c_net +is netns A, but the receiving rs lives in netns B. Once the child +process that created netns A exits, cleanup_net() calls +rds_loop_exit_net() -> rds_loop_kill_conns() -> rds_conn_destroy(), +freeing that connection. If the survivor socket in netns B still holds +the inc, any subsequent dereference of inc->i_conn is a use-after-free. + +There are two dangerous sites in rds_clear_recv_queue(): + 1. inc->i_conn->c_lcong (offset 88 of freed rds_connection, size 200) + read via rds_recv_rcvbuf_delta() -- confirmed by KASAN. + 2. inc->i_conn->c_trans->inc_free(inc) (function pointer at offset 80) + called via rds_inc_put() when the inc refcount reaches zero -- same + race window, potential call-through-freed-object primitive. + +The bug is reachable from unprivileged user namespaces +(CLONE_NEWUSER + CLONE_NEWNET), available since Linux 3.8. + +Fix this by rejecting the delivery in rds_recv_incoming() when the +socket returned by rds_find_bound() belongs to a different network +namespace than the connection that carried the message. Use the +existing rds_conn_net() / sock_net() helpers and net_eq() for the +comparison. + +Fixes: c809195f5523 ("rds: clean up loopback rds_connections on netns deletion") +Signed-off-by: Aldo Ariel Panzardo +Reviewed-by: Allison Henderson +Tested-by: Allison Henderson +Signed-off-by: Allison Henderson +Link: https://patch.msgid.link/20260708024314.601139-1-achender@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/rds/recv.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/net/rds/recv.c b/net/rds/recv.c +index 4b3f9e4a8bfda5..cf3884d8793195 100644 +--- a/net/rds/recv.c ++++ b/net/rds/recv.c +@@ -399,6 +399,21 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr, + goto out; + } + ++ /* ++ * rds_find_bound() uses a global (netns-agnostic) hash table. ++ * An RDS connection created in netns A can match a socket bound ++ * in the init netns, delivering inc cross-netns with inc->i_conn ++ * pointing into netns A. When cleanup_net() then frees that conn, ++ * any subsequent dereference of inc->i_conn is a use-after-free. ++ * Drop the inc if the receiving socket lives in a different netns. ++ */ ++ if (!net_eq(sock_net(rds_rs_to_sk(rs)), rds_conn_net(conn))) { ++ rds_stats_inc(s_recv_drop_no_sock); ++ rds_sock_put(rs); ++ rs = NULL; ++ goto out; ++ } ++ + /* Process extension headers */ + rds_recv_incoming_exthdrs(inc, rs); + +-- +2.53.0 + diff --git a/queue-7.1/rds-fix-inet6_addr_lst-null-dereference-when-ipv6-is.patch b/queue-7.1/rds-fix-inet6_addr_lst-null-dereference-when-ipv6-is.patch new file mode 100644 index 0000000000..067ca77f6a --- /dev/null +++ b/queue-7.1/rds-fix-inet6_addr_lst-null-dereference-when-ipv6-is.patch @@ -0,0 +1,117 @@ +From 48847a2313a16d4195332a696e696a6e03d7750e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 16:27:54 +0000 +Subject: rds: Fix inet6_addr_lst NULL dereference when IPv6 is disabled + +From: Ilia Gavrilov + +[ Upstream commit 9c805e592a29be9e4e61ff1bd567da04aa8fd6f9 ] + +When booting with the 'ipv6.disable=1' parameter, inet6_addr_lst +is never initialized because inet6_init() exits before addrconf_init() +is called to initialize it. An attempt to bind an RDS socket to +an ipv6 address results in a crash in __ipv6_chk_addr_and_flags() + +KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] +RIP: 0010:__ipv6_chk_addr_and_flags+0x1df/0x7e0 +Call Trace: + + ipv6_chk_addr+0x3b/0x50 + rds_tcp_laddr_check+0x155/0x3b0 [rds_tcp] + rds_trans_get_preferred+0x15d/0x2d0 [rds] + ? trace_hardirqs_on+0x2d/0x110 + rds_bind+0x1433/0x1d60 [rds] + ? rds_remove_bound+0xd50/0xd50 [rds] + ? aa_af_perm+0x250/0x250 + ? __might_fault+0xde/0x190 + ? __sys_bind+0x1dc/0x210 + __sys_bind+0x1dc/0x210 + ? __ia32_sys_socketpair+0x100/0x100 + ? restore_fpregs_from_fpstate+0x53/0x100 + __x64_sys_bind+0x73/0xb0 + ? syscall_enter_from_user_mode+0x1c/0x50 + do_syscall_64+0x34/0x80 + entry_SYSCALL_64_after_hwframe+0x6e/0xd8 +RIP: 0033:0x7f47f8269ea9 + + +The following code reproduces the issue: + +struct sockaddr_in6 addr; +s = socket(PF_RDS, SOCK_SEQPACKET, 0); + +memset(&addr, 0, sizeof(addr)); +inet_pton(AF_INET6, ADDRESS, &addr.sin6_addr); +addr.sin6_family = AF_INET6; +addr.sin6_port = htons(PORT); + +bind(s, &addr, sizeof(addr)); + +Found by InfoTeCS on behalf of Linux Verification Center +(linuxtesting.org) with Syzkaller. + +Fixes: eee2fa6ab322 ("rds: Changing IP address internal representation to struct in6_addr") +Fixes: 1e2b44e78eea ("rds: Enable RDS IPv6 support") +Signed-off-by: Ilia Gavrilov +Reviewed-by: Allison Henderson +Link: https://patch.msgid.link/20260709162723.367523-1-Ilia.Gavrilov@infotecs.ru +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/rds/ib.c | 4 ++++ + net/rds/ib_cm.c | 4 ++++ + net/rds/tcp.c | 8 +++++--- + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/net/rds/ib.c b/net/rds/ib.c +index 39f87272e071bf..8f9cf491984f12 100644 +--- a/net/rds/ib.c ++++ b/net/rds/ib.c +@@ -429,6 +429,10 @@ static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr, + sa = (struct sockaddr *)&sin; + } else { + #if IS_ENABLED(CONFIG_IPV6) ++ if (!ipv6_mod_enabled()) { ++ ret = -EADDRNOTAVAIL; ++ goto out; ++ } + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_addr = *addr; +diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c +index 4001de0c495938..9b25486fde81c8 100644 +--- a/net/rds/ib_cm.c ++++ b/net/rds/ib_cm.c +@@ -810,6 +810,10 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id, + dp = event->param.conn.private_data; + if (isv6) { + #if IS_ENABLED(CONFIG_IPV6) ++ if (!ipv6_mod_enabled()) { ++ err = -EOPNOTSUPP; ++ goto out; ++ } + dp_cmn = &dp->ricp_v6.dp_cmn; + saddr6 = &dp->ricp_v6.dp_saddr; + daddr6 = &dp->ricp_v6.dp_daddr; +diff --git a/net/rds/tcp.c b/net/rds/tcp.c +index 5830b31a1f37b3..d3acad60315ab0 100644 +--- a/net/rds/tcp.c ++++ b/net/rds/tcp.c +@@ -347,9 +347,11 @@ int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr, + rcu_read_unlock(); + } + #if IS_ENABLED(CONFIG_IPV6) +- ret = ipv6_chk_addr(net, addr, dev, 0); +- if (ret) +- return 0; ++ if (ipv6_mod_enabled()) { ++ ret = ipv6_chk_addr(net, addr, dev, 0); ++ if (ret) ++ return 0; ++ } + #endif + return -EADDRNOTAVAIL; + } +-- +2.53.0 + diff --git a/queue-7.1/rds-tcp-unregister-sysctl-before-tearing-down-listen.patch b/queue-7.1/rds-tcp-unregister-sysctl-before-tearing-down-listen.patch new file mode 100644 index 0000000000..a29c48024f --- /dev/null +++ b/queue-7.1/rds-tcp-unregister-sysctl-before-tearing-down-listen.patch @@ -0,0 +1,64 @@ +From d9c3fe321dd8e50761d5e52b3878f76452fd8fc0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 19 Jul 2026 17:03:57 -0400 +Subject: rds: tcp: unregister sysctl before tearing down listen socket + +From: Cen Zhang (Microsoft) + +[ Upstream commit 167e54c703ccd4fa028feb568b0d1002020cff86 ] + +rds_tcp_exit_net() frees the per-netns RDS TCP listen socket via +rds_tcp_kill_sock() before unregistering the per-netns sysctl table. Since +rds_tcp_skbuf_handler() derives the netns from +rtn->rds_tcp_listen_sock->sk, a concurrent sysctl write can race with +netns teardown and dereference the freed socket/sk. + +KASAN reports the race as: + + BUG: KASAN: slab-use-after-free in rds_tcp_skbuf_handler+0x2aa/0x2e0 + rds_tcp_skbuf_handler net/rds/tcp.c:721 + proc_sys_call_handler fs/proc/proc_sysctl.c + vfs_write fs/read_write.c + __x64_sys_pwrite64 fs/read_write.c + +Fix this by unregistering the RDS TCP sysctl table before calling +rds_tcp_kill_sock(). unregister_net_sysctl_table() prevents new sysctl +handlers from starting and waits for in-flight handlers to finish, so +the listen socket can then be released safely. The fix was tested +against the linked reproducer. + +Fixes: 7f5611cbc487 ("rds: sysctl: rds_tcp_{rcv,snd}buf: avoid using current->nsproxy") +Reported-by: AutonomousCodeSecurity@microsoft.com +Link: https://lore.kernel.org/all/20260719203718.9680-1-blbllhy@gmail.com +Reviewed-by: Allison Henderson +Signed-off-by: Cen Zhang (Microsoft) +Link: https://patch.msgid.link/20260719210357.10179-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/rds/tcp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/rds/tcp.c b/net/rds/tcp.c +index d3acad60315ab0..76f441cbf50e64 100644 +--- a/net/rds/tcp.c ++++ b/net/rds/tcp.c +@@ -638,13 +638,13 @@ static void __net_exit rds_tcp_exit_net(struct net *net) + { + struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid); + +- rds_tcp_kill_sock(net); +- + if (rtn->rds_tcp_sysctl) + unregister_net_sysctl_table(rtn->rds_tcp_sysctl); + + if (net != &init_net) + kfree(rtn->ctl_table); ++ ++ rds_tcp_kill_sock(net); + } + + static struct pernet_operations rds_tcp_net_ops = { +-- +2.53.0 + diff --git a/queue-7.1/regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch b/queue-7.1/regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch new file mode 100644 index 0000000000..e294136639 --- /dev/null +++ b/queue-7.1/regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch @@ -0,0 +1,60 @@ +From b279a30d9962c328ce0dfe8c93b7aeeda788fb99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Jul 2026 02:05:59 +0100 +Subject: regulator: mt6358: use regmap helper to read fixed LDO calibration + +From: Daniel Golle + +[ Upstream commit 1d26f125501f3fbe6c259ab75bf6516299a0bf0e ] + +The "fixed" LDOs with output voltage calibration use +mt6358_get_buck_voltage_sel as their get_voltage_sel op, but the +MT6358_REG_FIXED and MT6366_REG_FIXED entries do not populate +da_vsel_reg/da_vsel_mask. The op therefore reads register 0x0 with a +zero mask and shifts the result by ffs(0) - 1 = -1, which is undefined +behaviour and gets flagged by UBSAN on every boot on MT6366 boards: + + UBSAN: shift-out-of-bounds in drivers/regulator/mt6358-regulator.c:384:38 + shift exponent -1 is negative + Call trace: + mt6358_get_buck_voltage_sel+0xc8/0x120 + regulator_get_voltage_rdev+0x70/0x170 + set_machine_constraints+0x504/0xc38 + regulator_register+0x324/0xc68 + +Besides the undefined shift, the returned selector is always 0, so the +actual calibration offset programmed in _ANA_CON0 is never +reported. + +The descriptor already carries the correct vsel_reg/vsel_mask (the +ANA_CON0 calibration field), matching the regulator_set_voltage_sel_regmap +op already in use. Read the selector back through +regulator_get_voltage_sel_regmap instead. + +Fixes: cf08fa74c716 ("regulator: mt6358: Add output voltage fine tuning to fixed regulators") +Signed-off-by: Daniel Golle +Reviewed-by: Chen-Yu Tsai +Tested-by: Chen-Yu Tsai +Link: https://patch.msgid.link/dcd98d81dede338c9bbb9700a9613c848b702e49.1784336005.git.daniel@makrotopia.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/mt6358-regulator.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c +index 2604f674be493b..d483f85936f81f 100644 +--- a/drivers/regulator/mt6358-regulator.c ++++ b/drivers/regulator/mt6358-regulator.c +@@ -492,7 +492,7 @@ static const struct regulator_ops mt6358_volt_fixed_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +- .get_voltage_sel = mt6358_get_buck_voltage_sel, ++ .get_voltage_sel = regulator_get_voltage_sel_regmap, + .set_voltage_time_sel = regulator_set_voltage_time_sel, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, +-- +2.53.0 + diff --git a/queue-7.1/rxrpc-fix-io_thread-race-in-rxrpc_wake_up_io_thread.patch b/queue-7.1/rxrpc-fix-io_thread-race-in-rxrpc_wake_up_io_thread.patch new file mode 100644 index 0000000000..4252747154 --- /dev/null +++ b/queue-7.1/rxrpc-fix-io_thread-race-in-rxrpc_wake_up_io_thread.patch @@ -0,0 +1,49 @@ +From d4227f714c8018519686922a8c49f41b25f4c370 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 17:35:34 +0800 +Subject: rxrpc: fix io_thread race in rxrpc_wake_up_io_thread() + +From: Xuanqiang Luo + +[ Upstream commit 745fb794c3e933c023af9dbb5876a5e16ad2dc71 ] + +rxrpc_wake_up_io_thread() checks local->io_thread before waking it, but +then reloads the pointer for wake_up_process(). + +local->io_thread is cleared with WRITE_ONCE() when the I/O thread exits, so +the second load can see NULL even if the first load did not. + +Take a READ_ONCE() snapshot and use it for both the NULL check and the +wake_up_process() call, as rxrpc_encap_rcv() already does. + +Fixes: 5800b1cf3fd8 ("rxrpc: Allow CHALLENGEs to the passed to the app for a RESPONSE") +Signed-off-by: Xuanqiang Luo +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260708093534.53486-1-xuanqiang.luo@linux.dev +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/rxrpc/ar-internal.h | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h +index d2b31d15851b96..38b0997ce0cb3a 100644 +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -1266,9 +1266,11 @@ int rxrpc_io_thread(void *data); + void rxrpc_post_response(struct rxrpc_connection *conn, struct sk_buff *skb); + static inline void rxrpc_wake_up_io_thread(struct rxrpc_local *local) + { +- if (!local->io_thread) ++ struct task_struct *io_thread = READ_ONCE(local->io_thread); ++ ++ if (!io_thread) + return; +- wake_up_process(READ_ONCE(local->io_thread)); ++ wake_up_process(io_thread); + } + + static inline bool rxrpc_protocol_error(struct sk_buff *skb, enum rxrpc_abort_reason why) +-- +2.53.0 + diff --git a/queue-7.1/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch b/queue-7.1/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch new file mode 100644 index 0000000000..508a7c0c9e --- /dev/null +++ b/queue-7.1/sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch @@ -0,0 +1,51 @@ +From 46e692abd02666b26219ac065fcb177cde4ab807 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Jul 2026 09:55:32 +0800 +Subject: sctp: auth: verify auth requirement when auth_chunk is NULL + +From: Qing Luo + +[ Upstream commit 8e04823c120b376ef7dab14b60ebf6823aa16c14 ] + +sctp_auth_chunk_verify() returns true unconditionally when +chunk->auth_chunk is NULL, silently skipping authentication. +This is incorrect when: + +1. skb_clone() failed in the BH receive path, leaving auth_chunk + NULL. In sctp_endpoint_bh_rcv() asoc is NULL for new + connections, so the early sctp_auth_recv_cid() check cannot + catch this. + +2. No AUTH chunk precedes COOKIE-ECHO, so skb_clone() is never + called and auth_chunk remains NULL. + +Fix by checking sctp_auth_recv_cid() when auth_chunk is NULL: +if authentication is required, return false to drop the chunk; +otherwise continue normally. + +Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk") +Signed-off-by: Qing Luo +Acked-by: Xin Long +Link: https://patch.msgid.link/20260721015532.120157-2-l1138897701@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/sm_statefuns.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 3893b44448b381..708fa07d5fffc7 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -643,7 +643,7 @@ static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk, + struct sctp_chunk auth; + + if (!chunk->auth_chunk) +- return true; ++ return !sctp_auth_recv_cid(chunk->chunk_hdr->type, asoc); + + /* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo + * is supposed to be authenticated and we have to do delayed +-- +2.53.0 + diff --git a/queue-7.1/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch b/queue-7.1/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch new file mode 100644 index 0000000000..efba639deb --- /dev/null +++ b/queue-7.1/sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch @@ -0,0 +1,46 @@ +From c2bbd0b0ab79cf04464ae972e78936a4fa91dad3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 03:20:21 +0000 +Subject: sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid + +From: HanQuan + +[ Upstream commit ff04b26794a16a8a879eb4fd2c02c2d6b03850e9 ] + +sctp_auth_ep_add_chunkid() uses SCTP_NUM_CHUNK_TYPES (20) as the +capacity limit for ep->auth_chunk_list, allowing it to hold up to +20 chunk entries (param_hdr.length up to 24). However, the copy +destination asoc->c.auth_chunks in struct sctp_cookie is only +SCTP_AUTH_MAX_CHUNKS (16) entries (20 bytes). When more than 16 +chunks are added, sctp_association_init() memcpy overflows the +destination by up to 4 bytes. + +Fix by using SCTP_AUTH_MAX_CHUNKS as the capacity limit, matching +the destination capacity. + +Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals") +Signed-off-by: HanQuan +Acked-by: Xin Long +Link: https://patch.msgid.link/20260713032021.3491702-1-zhoujian.zja@antgroup.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/auth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/sctp/auth.c b/net/sctp/auth.c +index be9782760f5093..c901d373af803c 100644 +--- a/net/sctp/auth.c ++++ b/net/sctp/auth.c +@@ -672,7 +672,7 @@ int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id) + /* Check if we can add this chunk to the array */ + param_len = ntohs(p->param_hdr.length); + nchunks = param_len - sizeof(struct sctp_paramhdr); +- if (nchunks == SCTP_NUM_CHUNK_TYPES) ++ if (nchunks == SCTP_AUTH_MAX_CHUNKS) + return -EINVAL; + + p->chunks[nchunks] = chunk_id; +-- +2.53.0 + diff --git a/queue-7.1/sctp-validate-stream-count-in-sctp_process_strreset_.patch b/queue-7.1/sctp-validate-stream-count-in-sctp_process_strreset_.patch new file mode 100644 index 0000000000..2d74f5c6a9 --- /dev/null +++ b/queue-7.1/sctp-validate-stream-count-in-sctp_process_strreset_.patch @@ -0,0 +1,80 @@ +From d86d61f446914304ab8ea504d36fc907eec571ac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 21:07:18 -0400 +Subject: sctp: validate stream count in sctp_process_strreset_inreq() + +From: Cen Zhang (Microsoft) + +[ Upstream commit 18ae07691d43183d270de8be9dc8e027906015d9 ] + +When processing a RESET_IN_REQUEST from a peer, +sctp_process_strreset_inreq() derives the stream count from the +parameter length but does not check whether the resulting +RESET_OUT_REQUEST would exceed SCTP_MAX_CHUNK_LEN. + +The OUT request header (sctp_strreset_outreq, 16 bytes) is 8 bytes +larger than the IN request header (sctp_strreset_inreq, 8 bytes). +Generally, the IP payload is bounded to 65535 bytes, so the stream +list cannot be large enough to trigger the overflow. However, on +interfaces with MTU > 65535 (e.g., loopback with IPv6 jumbograms), a +stream list that fits within the incoming IN parameter can cause a +__u16 overflow in sctp_make_strreset_req() when computing the OUT +request size, leading to an undersized skb allocation and a kernel +BUG: + + net/core/skbuff.c:207 skb_panic + net/core/skbuff.c:2625 skb_put + net/sctp/sm_make_chunk.c:1535 sctp_addto_chunk + net/sctp/sm_make_chunk.c:3695 sctp_make_strreset_req + net/sctp/stream.c:655 sctp_process_strreset_inreq + +The local setsockopt path validates the generated reset request size. +However, for an incoming-only reset, it accounts for the smaller IN +request even though the peer must generate an OUT request with the same +stream list. Such a request cannot be completed successfully by the +peer. + +Reject peer IN requests whose corresponding OUT request would exceed +SCTP_MAX_CHUNK_LEN. Also tighten the local check so it does not send an +IN request that would require an oversized OUT request from the peer. + +Fixes: 7f9d68ac944e ("sctp: implement sender-side procedures for SSN Reset Request Parameter") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/20260707203215.2752-1-blbllhy@gmail.com/ +Suggested-by: Xin Long +Signed-off-by: Cen Zhang (Microsoft) +Acked-by: Xin Long +Link: https://patch.msgid.link/20260710010718.20318-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/stream.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/sctp/stream.c b/net/sctp/stream.c +index 5c2fdedea088ff..34ffe6c945a4bb 100644 +--- a/net/sctp/stream.c ++++ b/net/sctp/stream.c +@@ -308,7 +308,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc, + goto out; + + param_len += str_nums * sizeof(__u16) + +- sizeof(struct sctp_strreset_inreq); ++ (out ? sizeof(struct sctp_strreset_inreq) ++ : sizeof(struct sctp_strreset_outreq)); + } + + if (param_len > SCTP_MAX_CHUNK_LEN - +@@ -639,6 +640,9 @@ struct sctp_chunk *sctp_process_strreset_inreq( + + nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16); + str_p = inreq->list_of_streams; ++ if (nums * sizeof(__u16) + sizeof(struct sctp_strreset_outreq) > ++ SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_reconf_chunk)) ++ goto out; + for (i = 0; i < nums; i++) { + if (ntohs(str_p[i]) >= stream->outcnt) { + result = SCTP_STRRESET_ERR_WRONG_SSN; +-- +2.53.0 + diff --git a/queue-7.1/selftests-af_unix-add-user_ns-config.patch b/queue-7.1/selftests-af_unix-add-user_ns-config.patch new file mode 100644 index 0000000000..728dcdc5a0 --- /dev/null +++ b/queue-7.1/selftests-af_unix-add-user_ns-config.patch @@ -0,0 +1,40 @@ +From 4ee9ec65f4c8c5997c8b1aa474d6c51196558e67 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:41 +0200 +Subject: selftests: af_unix: add USER_NS config + +From: Matthieu Baerts (NGI0) + +[ Upstream commit f8b1abed736111f914b2c567d9a3db1f71e788e8 ] + +This is required to use unshare(CLONE_NEWUSER). + +This has not been seen on NIPA before, because the 'af_unix' tests are +executed with the 'net' ones, merging their config files. USER_NS is +present in tools/testing/selftests/net/config. + +This issue is visible when only the af_unix config is used on top of the +default one. This is the recommended way to execute selftest targets. + +Fixes: ac011361bd4f ("af_unix: Add test for sock_diag and UDIAG_SHOW_UID.") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-1-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/af_unix/config | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tools/testing/selftests/net/af_unix/config b/tools/testing/selftests/net/af_unix/config +index b5429c15a53c75..41dbb03c747eb7 100644 +--- a/tools/testing/selftests/net/af_unix/config ++++ b/tools/testing/selftests/net/af_unix/config +@@ -1,3 +1,4 @@ + CONFIG_AF_UNIX_OOB=y + CONFIG_UNIX=y + CONFIG_UNIX_DIAG=m ++CONFIG_USER_NS=y +-- +2.53.0 + diff --git a/queue-7.1/selftests-drv-net-add-missing-kconfig-for-psp.py.patch b/queue-7.1/selftests-drv-net-add-missing-kconfig-for-psp.py.patch new file mode 100644 index 0000000000..b26dda05b5 --- /dev/null +++ b/queue-7.1/selftests-drv-net-add-missing-kconfig-for-psp.py.patch @@ -0,0 +1,53 @@ +From bb99fccf64f1018c04bc17e260cf85e0d40741a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:46 +0200 +Subject: selftests: drv-net: add missing kconfig for psp.py + +From: Matthieu Baerts (NGI0) + +[ Upstream commit c25dd7439f84cf607e13d6de8cc1c79cd51f56ff ] + +This psp.py selftest was failing on my side when only using the +drivers/net config file on top of the default one -- the recommended way +to execute selftest targets. + +It looks like some kernel config are needed to execute the new tc +commands. + +Note that this was not visible on NIPA, because these tests are executed +with the drivers/net/hw ones, combining the two config files, and the hw +one contains the missing ones. + +Fixes: 3f74d5bb807e ("selftests/net: Add env for container based tests") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Wei Wang +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-6-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/drivers/net/config | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tools/testing/selftests/drivers/net/config b/tools/testing/selftests/drivers/net/config +index 617de8aaf55100..d08955b133b3ee 100644 +--- a/tools/testing/selftests/drivers/net/config ++++ b/tools/testing/selftests/drivers/net/config +@@ -4,12 +4,15 @@ CONFIG_DEBUG_INFO_BTF_MODULES=n + CONFIG_INET_PSP=y + CONFIG_IPV6=y + CONFIG_MACSEC=m ++CONFIG_NET_CLS_ACT=y ++CONFIG_NET_CLS_BPF=y + CONFIG_NETCONSOLE=m + CONFIG_NETCONSOLE_DYNAMIC=y + CONFIG_NETCONSOLE_EXTENDED_LOG=y + CONFIG_NETDEVSIM=m + CONFIG_NET_SCH_ETF=m + CONFIG_NET_SCH_FQ=m ++CONFIG_NET_SCH_INGRESS=y + CONFIG_PPP=y + CONFIG_PPPOE=y + CONFIG_VLAN_8021Q=m +-- +2.53.0 + diff --git a/queue-7.1/selftests-drv-net-convert-so_txtime-to-drv-net.patch b/queue-7.1/selftests-drv-net-convert-so_txtime-to-drv-net.patch new file mode 100644 index 0000000000..4f15d81000 --- /dev/null +++ b/queue-7.1/selftests-drv-net-convert-so_txtime-to-drv-net.patch @@ -0,0 +1,451 @@ +From c13ba1159300d76b10c14007e62f07bf0de62bdd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 May 2026 13:38:34 -0400 +Subject: selftests: drv-net: convert so_txtime to drv-net + +From: Willem de Bruijn + +[ Upstream commit 5c6baef3885c0e16e63d432fe31aa6f7e98e18dc ] + +In preparation for extending to pacing hardware offload, convert the +so_txtime.sh test to a drv-net test that can be run against netdevsim +and real hardware. + +Also update so_txtime.c to not exit on first failure, but run to +completion and report exit code there. This helps with debugging +unexpected results, especially when processing multiple packets, +as happens in the "reverse_order" testcase. + +Signed-off-by: Willem de Bruijn + +---- + +v6 -> v7 + +- update test to use new argument expect_fail +- v6 received Reviewed-by, but dropped due to above (minor) change + +v5 -> v6 + +- fix order in tools/testing/selftests/drivers/net/config + +v4 -> v5 + +- move qdisc setup/restore into each test +- add tc to utils.py (separate patch) +- test expected failure (separate patch) +- fix pylint +- convert fail to pass for timing errors if KSFT_MACHINE_SLOW + (cmd does not special case KSFT_SKIP process returncode yet) + +Responses to sashiko review + +- The test converts per packet failure to errors, to continue + testing other packets, but other error() cases are not in scope. +- The test starts sender and receiver at an absolute future time, + like the original test. This assumes ~msec scale sync'ed clocks. +- The tc qdisc replace command works fine with noqueue. Tested + manually. + +v3 -> v4 + +- restore original qdisc after test +- drop unnecessary underscore in tap test names + +v2 -> v3 + +- Makefile: so_txtime from YNL_GEN_FILES to TEST_GEN_FILES (Sashiko, NIPA) + +v1 -> v2 +- move so_txtime.c for net/lib to drivers/net (Jakub) +- fix drivers/net/config order (Jakub) +- detect passing when failure is expected (Jakub, Sashiko) +- pass pylint --disable=R (Jakub) +- only call ksft_run once (Jakub) +- do not sleep if waiting time is negative (Sashiko) +- add \n when converting error() to fprintf() (Sashiko) +- 4 space indentation, instead of 2 space +- increase sync delay from 100 to 200ms, to fix rare vng flakes + +Link: https://patch.msgid.link/20260504174056.565319-4-willemdebruijn.kernel@gmail.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: c25dd7439f84 ("selftests: drv-net: add missing kconfig for psp.py") +Signed-off-by: Sasha Levin +--- + .../testing/selftests/drivers/net/.gitignore | 1 + + tools/testing/selftests/drivers/net/Makefile | 2 + + tools/testing/selftests/drivers/net/config | 2 + + .../selftests/{ => drivers}/net/so_txtime.c | 25 +++- + .../selftests/drivers/net/so_txtime.py | 96 +++++++++++++++ + tools/testing/selftests/net/.gitignore | 1 - + tools/testing/selftests/net/Makefile | 2 - + tools/testing/selftests/net/so_txtime.sh | 110 ------------------ + 8 files changed, 121 insertions(+), 118 deletions(-) + rename tools/testing/selftests/{ => drivers}/net/so_txtime.c (96%) + create mode 100755 tools/testing/selftests/drivers/net/so_txtime.py + delete mode 100755 tools/testing/selftests/net/so_txtime.sh + +diff --git a/tools/testing/selftests/drivers/net/.gitignore b/tools/testing/selftests/drivers/net/.gitignore +index 585ecb4d5dc42e..e5314ce4bb2dea 100644 +--- a/tools/testing/selftests/drivers/net/.gitignore ++++ b/tools/testing/selftests/drivers/net/.gitignore +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only + napi_id_helper + psp_responder ++so_txtime +diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile +index b72080c6d06b01..d5bf4cb638a8c4 100644 +--- a/tools/testing/selftests/drivers/net/Makefile ++++ b/tools/testing/selftests/drivers/net/Makefile +@@ -7,6 +7,7 @@ TEST_INCLUDES := $(wildcard lib/py/*.py) \ + + TEST_GEN_FILES := \ + napi_id_helper \ ++ so_txtime \ + # end of TEST_GEN_FILES + + TEST_PROGS := \ +@@ -21,6 +22,7 @@ TEST_PROGS := \ + queues.py \ + ring_reconfig.py \ + shaper.py \ ++ so_txtime.py \ + stats.py \ + xdp.py \ + # end of TEST_PROGS +diff --git a/tools/testing/selftests/drivers/net/config b/tools/testing/selftests/drivers/net/config +index fd16994366f4ba..2309109a94ecea 100644 +--- a/tools/testing/selftests/drivers/net/config ++++ b/tools/testing/selftests/drivers/net/config +@@ -8,5 +8,7 @@ CONFIG_NETCONSOLE=m + CONFIG_NETCONSOLE_DYNAMIC=y + CONFIG_NETCONSOLE_EXTENDED_LOG=y + CONFIG_NETDEVSIM=m ++CONFIG_NET_SCH_ETF=m ++CONFIG_NET_SCH_FQ=m + CONFIG_VLAN_8021Q=m + CONFIG_XDP_SOCKETS=y +diff --git a/tools/testing/selftests/net/so_txtime.c b/tools/testing/selftests/drivers/net/so_txtime.c +similarity index 96% +rename from tools/testing/selftests/net/so_txtime.c +rename to tools/testing/selftests/drivers/net/so_txtime.c +index b76df1efc2efc0..b6930883569b0a 100644 +--- a/tools/testing/selftests/net/so_txtime.c ++++ b/tools/testing/selftests/drivers/net/so_txtime.c +@@ -33,6 +33,8 @@ + #include + #include + ++#include "kselftest.h" ++ + static int cfg_clockid = CLOCK_TAI; + static uint16_t cfg_port = 8000; + static int cfg_variance_us = 4000; +@@ -43,6 +45,8 @@ static bool cfg_rx; + static uint64_t glob_tstart; + static uint64_t tdeliver_max; + ++static int errors; ++ + /* encode one timed transmission (of a 1B payload) */ + struct timed_send { + char data; +@@ -131,13 +135,15 @@ static void do_recv_one(int fdr, struct timed_send *ts) + fprintf(stderr, "payload:%c delay:%lld expected:%lld (us)\n", + rbuf[0], (long long)tstop, (long long)texpect); + +- if (rbuf[0] != ts->data) +- error(1, 0, "payload mismatch. expected %c", ts->data); ++ if (rbuf[0] != ts->data) { ++ fprintf(stderr, "payload mismatch. expected %c\n", ts->data); ++ errors++; ++ } + + if (llabs(tstop - texpect) > cfg_variance_us) { + fprintf(stderr, "exceeds variance (%d us)\n", cfg_variance_us); + if (!getenv("KSFT_MACHINE_SLOW")) +- exit(1); ++ errors++; + } + } + +@@ -255,8 +261,12 @@ static void start_time_wait(void) + return; + + now = gettime_ns(CLOCK_REALTIME); +- if (cfg_start_time_ns < now) ++ if (cfg_start_time_ns < now) { ++ fprintf(stderr, "FAIL: start time already passed\n"); ++ if (!getenv("KSFT_MACHINE_SLOW")) ++ errors++; + return; ++ } + + err = usleep((cfg_start_time_ns - now) / 1000); + if (err) +@@ -513,5 +523,10 @@ int main(int argc, char **argv) + else + do_test_tx((void *)&cfg_src_addr, cfg_alen); + +- return 0; ++ if (errors) { ++ fprintf(stderr, "FAIL: %d errors\n", errors); ++ return KSFT_FAIL; ++ } ++ ++ return KSFT_PASS; + } +diff --git a/tools/testing/selftests/drivers/net/so_txtime.py b/tools/testing/selftests/drivers/net/so_txtime.py +new file mode 100755 +index 00000000000000..5b54ce76dff40d +--- /dev/null ++++ b/tools/testing/selftests/drivers/net/so_txtime.py +@@ -0,0 +1,96 @@ ++#!/usr/bin/env python3 ++# SPDX-License-Identifier: GPL-2.0 ++ ++"""Regression tests for the SO_TXTIME interface. ++ ++Test delivery time in FQ and ETF qdiscs. ++""" ++ ++import time ++ ++from lib.py import ksft_exit, ksft_run, ksft_variants ++from lib.py import KsftNamedVariant, KsftSkipEx ++from lib.py import NetDrvEpEnv, bkg, cmd, defer, tc ++ ++ ++def test_so_txtime(cfg, clockid, ipver, args_tx, args_rx, expect_success): ++ """Main function. Run so_txtime as sender and receiver.""" ++ bin_path = cfg.test_dir / "so_txtime" ++ ++ tstart = time.time_ns() + 200_000_000 ++ ++ cmd_addr = f"-S {cfg.addr_v[ipver]} -D {cfg.remote_addr_v[ipver]}" ++ cmd_base = f"{bin_path} -{ipver} -c {clockid} -t {tstart} {cmd_addr}" ++ cmd_rx = f"{cmd_base} {args_rx} -r" ++ cmd_tx = f"{cmd_base} {args_tx}" ++ ++ with bkg(cmd_rx, host=cfg.remote, fail=expect_success, ++ expect_fail=(not expect_success), exit_wait=True): ++ cmd(cmd_tx) ++ ++ ++def _qdisc_setup(ifname, qdisc, optargs=""): ++ """Replace root qdisc. Restore the original after the test. ++ ++ If the original is mq, children will be of type default_qdisc. ++ """ ++ orig = tc(f"qdisc show dev {ifname} root", json=True)[0].get("kind", None) ++ defer(tc, f"qdisc replace dev {ifname} root {orig}") ++ tc(f"qdisc replace dev {ifname} root {qdisc} {optargs}") ++ ++ ++def _test_variants_mono(): ++ for ipver in ["4", "6"]: ++ for testcase in [ ++ ["no_delay", "a,-1", "a,-1"], ++ ["zero_delay", "a,0", "a,0"], ++ ["one_pkt", "a,10", "a,10"], ++ ["in_order", "a,10,b,20", "a,10,b,20"], ++ ["reverse_order", "a,20,b,10", "b,20,a,20"], ++ ]: ++ name = f"v{ipver}_{testcase[0]}" ++ yield KsftNamedVariant(name, ipver, testcase[1], testcase[2]) ++ ++ ++@ksft_variants(_test_variants_mono()) ++def test_so_txtime_mono(cfg, ipver, args_tx, args_rx): ++ """Run all variants of monotonic (fq) tests.""" ++ _qdisc_setup(cfg.ifname, "fq") ++ test_so_txtime(cfg, "mono", ipver, args_tx, args_rx, True) ++ ++ ++def _test_variants_etf(): ++ for ipver in ["4", "6"]: ++ for testcase in [ ++ ["no_delay", "a,-1", "a,-1", False], ++ ["zero_delay", "a,0", "a,0", False], ++ ["one_pkt", "a,10", "a,10", True], ++ ["in_order", "a,10,b,20", "a,10,b,20", True], ++ ["reverse_order", "a,20,b,10", "b,10,a,20", True], ++ ]: ++ name = f"v{ipver}_{testcase[0]}" ++ yield KsftNamedVariant( ++ name, ipver, testcase[1], testcase[2], testcase[3] ++ ) ++ ++ ++@ksft_variants(_test_variants_etf()) ++def test_so_txtime_etf(cfg, ipver, args_tx, args_rx, expect_fail): ++ """Run all variants of etf tests.""" ++ try: ++ _qdisc_setup(cfg.ifname, "etf", "clockid CLOCK_TAI delta 400000") ++ except Exception as e: ++ raise KsftSkipEx("tc does not support qdisc etf. skipping") from e ++ ++ test_so_txtime(cfg, "tai", ipver, args_tx, args_rx, expect_fail) ++ ++ ++def main() -> None: ++ """Boilerplate ksft main.""" ++ with NetDrvEpEnv(__file__) as cfg: ++ ksft_run([test_so_txtime_mono, test_so_txtime_etf], args=(cfg,)) ++ ksft_exit() ++ ++ ++if __name__ == "__main__": ++ main() +diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore +index 97ad4d551d44d0..02ad4c99a2b49f 100644 +--- a/tools/testing/selftests/net/.gitignore ++++ b/tools/testing/selftests/net/.gitignore +@@ -40,7 +40,6 @@ skf_net_off + socket + so_incoming_cpu + so_netns_cookie +-so_txtime + so_rcv_listener + stress_reuseport_listen + tap +diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile +index 2ed7d803eb5484..2e4ff5b34f4cb4 100644 +--- a/tools/testing/selftests/net/Makefile ++++ b/tools/testing/selftests/net/Makefile +@@ -83,7 +83,6 @@ TEST_PROGS := \ + rxtimestamp.sh \ + sctp_vrf.sh \ + skf_net_off.sh \ +- so_txtime.sh \ + srv6_end_dt46_l3vpn_test.sh \ + srv6_end_dt4_l3vpn_test.sh \ + srv6_end_dt6_l3vpn_test.sh \ +@@ -159,7 +158,6 @@ TEST_GEN_FILES := \ + skf_net_off \ + so_netns_cookie \ + so_rcv_listener \ +- so_txtime \ + socket \ + stress_reuseport_listen \ + tcp_fastopen_backup_key \ +diff --git a/tools/testing/selftests/net/so_txtime.sh b/tools/testing/selftests/net/so_txtime.sh +deleted file mode 100755 +index 5e861ad32a42e1..00000000000000 +--- a/tools/testing/selftests/net/so_txtime.sh ++++ /dev/null +@@ -1,110 +0,0 @@ +-#!/bin/bash +-# SPDX-License-Identifier: GPL-2.0 +-# +-# Regression tests for the SO_TXTIME interface +- +-set -e +- +-readonly ksft_skip=4 +-readonly DEV="veth0" +-readonly BIN="./so_txtime" +- +-readonly RAND="$(mktemp -u XXXXXX)" +-readonly NSPREFIX="ns-${RAND}" +-readonly NS1="${NSPREFIX}1" +-readonly NS2="${NSPREFIX}2" +- +-readonly SADDR4='192.168.1.1' +-readonly DADDR4='192.168.1.2' +-readonly SADDR6='fd::1' +-readonly DADDR6='fd::2' +- +-cleanup() { +- ip netns del "${NS2}" +- ip netns del "${NS1}" +-} +- +-trap cleanup EXIT +- +-# Create virtual ethernet pair between network namespaces +-ip netns add "${NS1}" +-ip netns add "${NS2}" +- +-ip link add "${DEV}" netns "${NS1}" type veth \ +- peer name "${DEV}" netns "${NS2}" +- +-# Bring the devices up +-ip -netns "${NS1}" link set "${DEV}" up +-ip -netns "${NS2}" link set "${DEV}" up +- +-# Set fixed MAC addresses on the devices +-ip -netns "${NS1}" link set dev "${DEV}" address 02:02:02:02:02:02 +-ip -netns "${NS2}" link set dev "${DEV}" address 06:06:06:06:06:06 +- +-# Add fixed IP addresses to the devices +-ip -netns "${NS1}" addr add 192.168.1.1/24 dev "${DEV}" +-ip -netns "${NS2}" addr add 192.168.1.2/24 dev "${DEV}" +-ip -netns "${NS1}" addr add fd::1/64 dev "${DEV}" nodad +-ip -netns "${NS2}" addr add fd::2/64 dev "${DEV}" nodad +- +-run_test() { +- local readonly IP="$1" +- local readonly CLOCK="$2" +- local readonly TXARGS="$3" +- local readonly RXARGS="$4" +- +- if [[ "${IP}" == "4" ]]; then +- local readonly SADDR="${SADDR4}" +- local readonly DADDR="${DADDR4}" +- elif [[ "${IP}" == "6" ]]; then +- local readonly SADDR="${SADDR6}" +- local readonly DADDR="${DADDR6}" +- else +- echo "Invalid IP version ${IP}" +- exit 1 +- fi +- +- local readonly START="$(date +%s%N --date="+ 0.1 seconds")" +- +- ip netns exec "${NS2}" "${BIN}" -"${IP}" -c "${CLOCK}" -t "${START}" -S "${SADDR}" -D "${DADDR}" "${RXARGS}" -r & +- ip netns exec "${NS1}" "${BIN}" -"${IP}" -c "${CLOCK}" -t "${START}" -S "${SADDR}" -D "${DADDR}" "${TXARGS}" +- wait "$!" +-} +- +-do_test() { +- run_test $@ +- [ $? -ne 0 ] && ret=1 +-} +- +-do_fail_test() { +- run_test $@ +- [ $? -eq 0 ] && ret=1 +-} +- +-ip netns exec "${NS1}" tc qdisc add dev "${DEV}" root fq +-set +e +-ret=0 +-do_test 4 mono a,-1 a,-1 +-do_test 6 mono a,0 a,0 +-do_test 6 mono a,10 a,10 +-do_test 4 mono a,10,b,20 a,10,b,20 +-do_test 6 mono a,20,b,10 b,20,a,20 +- +-if ip netns exec "${NS1}" tc qdisc replace dev "${DEV}" root etf clockid CLOCK_TAI delta 400000; then +- do_fail_test 4 tai a,-1 a,-1 +- do_fail_test 6 tai a,0 a,0 +- do_test 6 tai a,10 a,10 +- do_test 4 tai a,10,b,20 a,10,b,20 +- do_test 6 tai a,20,b,10 b,10,a,20 +-else +- echo "tc ($(tc -V)) does not support qdisc etf. skipping" +- [ $ret -eq 0 ] && ret=$ksft_skip +-fi +- +-if [ $ret -eq 0 ]; then +- echo OK. All tests passed +-elif [[ $ret -ne $ksft_skip && -n "$KSFT_MACHINE_SLOW" ]]; then +- echo "Ignoring errors due to slow environment" 1>&2 +- ret=0 +-fi +-exit $ret +-- +2.53.0 + diff --git a/queue-7.1/selftests-drv-net-increase-timeout.patch b/queue-7.1/selftests-drv-net-increase-timeout.patch new file mode 100644 index 0000000000..9795873923 --- /dev/null +++ b/queue-7.1/selftests-drv-net-increase-timeout.patch @@ -0,0 +1,38 @@ +From f3b067074c6c52f42356bf65f4d9172bed397acb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:45 +0200 +Subject: selftests: drv-net: increase timeout + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 3529d75d67411497341cd804a045185d6035dff2 ] + +The default timeout is 45 seconds, that's too low for the xdp.py test. + +Indeed, this test can take up to 3 minutes with some debug kernel config +on NIPA. Set a timeout to 6 minutes, just to be on the safe side. + +Note that the Fixes tag here points to the introduction of the xdp.py +test because I don't know when this test started to take more than 45 +seconds. That's OK because a timeout of 6 minutes is not exaggerated. + +Fixes: 1cbcb1b28b26 ("selftests: drv-net: Test XDP_PASS/DROP support") +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-5-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/drivers/net/settings | 1 + + 1 file changed, 1 insertion(+) + create mode 100644 tools/testing/selftests/drivers/net/settings + +diff --git a/tools/testing/selftests/drivers/net/settings b/tools/testing/selftests/drivers/net/settings +new file mode 100644 +index 00000000000000..eef533824a3c19 +--- /dev/null ++++ b/tools/testing/selftests/drivers/net/settings +@@ -0,0 +1 @@ ++timeout=360 +-- +2.53.0 + diff --git a/queue-7.1/selftests-net-fix-tun-ipv6-test-addresses-to-avoid-6.patch b/queue-7.1/selftests-net-fix-tun-ipv6-test-addresses-to-avoid-6.patch new file mode 100644 index 0000000000..dab2e4e5b2 --- /dev/null +++ b/queue-7.1/selftests-net-fix-tun-ipv6-test-addresses-to-avoid-6.patch @@ -0,0 +1,68 @@ +From e8ca8f8c1bfa0ffcfe75c7a75f7b97151b0a7f40 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Jul 2026 13:24:04 -0300 +Subject: selftests/net: Fix tun IPv6 test addresses to avoid 6to4 range +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ricardo B. Marlière + +[ Upstream commit ef01724fa235a228e3d3e8b117e89403cd8feb25 ] + +The IPv6 addresses used for the tun_vnet_udptnl fixture currently fall in +the 2002::/16 prefix, which is reserved for the 6to4 transition mechanism +(RFC 3056). + +On systems where the sit module is loaded, the kernel automatically claims +2002::/16 as a 6to4 tunnel prefix. When the test assigns a 2002:: address +to a TUN interface, sit registers a competing local route for the same +address. This ambiguity breaks the GENEVE decapsulation path: packets +injected via the TUN fd are not delivered to the test socket, causing the +IPv6-outer gtgso send_gso_packet variants to fail. + +Replace all four IPv6 test addresses with addresses from the fd00:db8::/32 +range, which is part of the ULA space (fc00::/7, RFC 4193) and carries no +special kernel semantics. + +Fixes: 24e59f26eef2 ("selftest: tun: Add helpers for GSO over UDP tunnel") +Signed-off-by: Ricardo B. Marlière +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260706-b4-net_tun_addr-v1-1-3d3cb2473560@suse.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/tun.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/net/tun.c +index cf106a49b55e38..abe488bac50bb3 100644 +--- a/tools/testing/selftests/net/tun.c ++++ b/tools/testing/selftests/net/tun.c +@@ -42,19 +42,19 @@ static struct in_addr param_ipaddr4_inner_src = { + }; + + static struct in6_addr param_ipaddr6_outer_dst = { +- { { 0x20, 0x02, 0x0d, 0xb8, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } }, ++ { { 0xfd, 0x00, 0x0d, 0xb8, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } }, + }; + + static struct in6_addr param_ipaddr6_outer_src = { +- { { 0x20, 0x02, 0x0d, 0xb8, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } }, ++ { { 0xfd, 0x00, 0x0d, 0xb8, 0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } }, + }; + + static struct in6_addr param_ipaddr6_inner_dst = { +- { { 0x20, 0x02, 0x0d, 0xb8, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } }, ++ { { 0xfd, 0x00, 0x0d, 0xb8, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 } }, + }; + + static struct in6_addr param_ipaddr6_inner_src = { +- { { 0x20, 0x02, 0x0d, 0xb8, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } }, ++ { { 0xfd, 0x00, 0x0d, 0xb8, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 } }, + }; + + #ifndef BIT +-- +2.53.0 + diff --git a/queue-7.1/selftests-net-ovpn-fix-getaddrinfo-memory-leak-in-ov.patch b/queue-7.1/selftests-net-ovpn-fix-getaddrinfo-memory-leak-in-ov.patch new file mode 100644 index 0000000000..d8cff62099 --- /dev/null +++ b/queue-7.1/selftests-net-ovpn-fix-getaddrinfo-memory-leak-in-ov.patch @@ -0,0 +1,55 @@ +From 37624da2f0e93a38c94a06737cc84d1a212ae7e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jun 2026 15:27:41 +0800 +Subject: selftests/net: ovpn: fix getaddrinfo memory leak in + ovpn_parse_remote() + +From: longlong yan + +[ Upstream commit 0bd9cfebc1c91e1066e56d6261b99691b9df6008 ] + +The ovpn_parse_remote() function has two memory management issues: + +1. When both 'host' and 'vpnip' are non-NULL, the first getaddrinfo() + allocation is leaked because 'result' is overwritten by the second + getaddrinfo() call without freeing the first allocation. + +2. When both 'host' and 'vpnip' are NULL, 'result' is an uninitialized + stack variable passed to freeaddrinfo(), which is undefined behavior. + +Fix by initializing 'result' to NULL and calling freeaddrinfo() after +the first getaddrinfo() result is consumed. + +Fixes: 959bc330a439 ("testing/selftests: add test tool and scripts for ovpn module") +Signed-off-by: longlong yan +Signed-off-by: Antonio Quartulli +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/ovpn/ovpn-cli.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/net/ovpn/ovpn-cli.c b/tools/testing/selftests/net/ovpn/ovpn-cli.c +index d40953375c86fa..f4effa7580c0f9 100644 +--- a/tools/testing/selftests/net/ovpn/ovpn-cli.c ++++ b/tools/testing/selftests/net/ovpn/ovpn-cli.c +@@ -1785,7 +1785,7 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host, + const char *service, const char *vpnip) + { + int ret; +- struct addrinfo *result; ++ struct addrinfo *result = NULL; + struct addrinfo hints = { + .ai_family = ovpn->sa_family, + .ai_socktype = SOCK_DGRAM, +@@ -1809,6 +1809,8 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host, + } + + memcpy(&ovpn->remote, result->ai_addr, result->ai_addrlen); ++ freeaddrinfo(result); ++ result = NULL; + } + + if (vpnip) { +-- +2.53.0 + diff --git a/queue-7.1/selftests-net-test-pppoe-packets-in-gro.sh.patch b/queue-7.1/selftests-net-test-pppoe-packets-in-gro.sh.patch new file mode 100644 index 0000000000..98c03123eb --- /dev/null +++ b/queue-7.1/selftests-net-test-pppoe-packets-in-gro.sh.patch @@ -0,0 +1,298 @@ +From f9d9bd13a591537a14c39d0221818180960fc0a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 May 2026 09:33:49 +0800 +Subject: selftests: net: test PPPoE packets in gro.sh + +From: Qingfang Deng + +[ Upstream commit 6160ec9d03d7af5aa345b8b994de80fa8454274b ] + +Add PPPoE test-cases to the GRO selftest. Only run a subset of +common_tests to avoid changing the hardcoded L3 offsets everywhere. +Add a new "pppoe_sid" test case to verify that packets with different +PPPoE session IDs are correctly identified as separate flows and not +coalesced. + +Signed-off-by: Qingfang Deng +Link: https://patch.msgid.link/20260513013400.7467-2-qingfang.deng@linux.dev +Signed-off-by: Paolo Abeni +Stable-dep-of: c25dd7439f84 ("selftests: drv-net: add missing kconfig for psp.py") +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/drivers/net/config | 2 + + tools/testing/selftests/drivers/net/gro.py | 11 +++ + tools/testing/selftests/net/lib/gro.c | 100 +++++++++++++++++---- + 3 files changed, 97 insertions(+), 16 deletions(-) + +diff --git a/tools/testing/selftests/drivers/net/config b/tools/testing/selftests/drivers/net/config +index 2309109a94ecea..617de8aaf55100 100644 +--- a/tools/testing/selftests/drivers/net/config ++++ b/tools/testing/selftests/drivers/net/config +@@ -10,5 +10,7 @@ CONFIG_NETCONSOLE_EXTENDED_LOG=y + CONFIG_NETDEVSIM=m + CONFIG_NET_SCH_ETF=m + CONFIG_NET_SCH_FQ=m ++CONFIG_PPP=y ++CONFIG_PPPOE=y + CONFIG_VLAN_8021Q=m + CONFIG_XDP_SOCKETS=y +diff --git a/tools/testing/selftests/drivers/net/gro.py b/tools/testing/selftests/drivers/net/gro.py +index 221f27e571476c..ad7c80f7ba96c5 100755 +--- a/tools/testing/selftests/drivers/net/gro.py ++++ b/tools/testing/selftests/drivers/net/gro.py +@@ -313,6 +313,12 @@ def _gro_variants(): + "ip_frag6", "ip_v6ext_same", "ip_v6ext_diff", + ] + ++ # Tests specific to PPPoE ++ pppoe_tests = [ ++ "data_same", "data_lrg_sml", "data_sml_lrg", "data_lrg_1byte", ++ "data_burst", "pppoe_sid", ++ ] ++ + for mode in ["sw", "hw", "lro"]: + for protocol in ["ipv4", "ipv6", "ipip", "ip6ip6"]: + for test_name in common_tests: +@@ -325,6 +331,11 @@ def _gro_variants(): + for test_name in ipv6_tests: + yield mode, protocol, test_name + ++ for mode in ["sw"]: ++ for protocol in ["pppoev4", "pppoev6"]: ++ for test_name in pppoe_tests: ++ yield mode, protocol, test_name ++ + + @ksft_variants(_gro_variants()) + def test(cfg, mode, protocol, test_name): +diff --git a/tools/testing/selftests/net/lib/gro.c b/tools/testing/selftests/net/lib/gro.c +index 11b16ae5f0e83d..fa35dfc8e790f6 100644 +--- a/tools/testing/selftests/net/lib/gro.c ++++ b/tools/testing/selftests/net/lib/gro.c +@@ -67,12 +67,14 @@ + #include + #include + #include ++#include ++#include + #include + #include ++#include + #include + #include +-#include +-#include ++#include + #include + #include + #include +@@ -102,6 +104,7 @@ + #define MAX_LARGE_PKT_CNT ((IP_MAXPACKET - (MAX_HDR_LEN - ETH_HLEN)) / \ + (ASSUMED_MTU - (MAX_HDR_LEN - ETH_HLEN))) + #define MIN_EXTHDR_SIZE 8 ++#define L2_HLEN_MAX (ETH_HLEN + PPPOE_SES_HLEN) + #define EXT_PAYLOAD_1 "\x00\x00\x00\x00\x00\x00" + #define EXT_PAYLOAD_2 "\x11\x11\x11\x11\x11\x11" + +@@ -134,6 +137,7 @@ static int total_hdr_len = -1; + static int ethhdr_proto = -1; + static bool ipip; + static bool ip6ip6; ++static bool pppoe; + static uint64_t txtime_ns; + static int num_flows = 4; + static bool order_check; +@@ -171,6 +175,22 @@ static void vlog(const char *fmt, ...) + } + } + ++static void fill_pppoelayer(void *buf, int payload_len, uint16_t sid) ++{ ++ struct pppoe_ppp_hdr { ++ struct pppoe_hdr eh; ++ __be16 proto; ++ } *ph = buf; ++ ++ payload_len += sizeof(struct tcphdr); ++ ph->eh.type = 1; ++ ph->eh.ver = 1; ++ ph->eh.code = 0; ++ ph->eh.sid = htons(sid); ++ ph->eh.length = htons(payload_len + sizeof(ph->proto)); ++ ph->proto = htons(proto == PF_INET ? PPP_IP : PPP_IPV6); ++} ++ + static void setup_sock_filter(int fd) + { + const int dport_off = tcp_offset + offsetof(struct tcphdr, dest); +@@ -412,11 +432,15 @@ static void create_packet(void *buf, int seq_offset, int ack_offset, + + fill_networklayer(buf + inner_ip_off, payload_len, IPPROTO_TCP); + if (inner_ip_off > ETH_HLEN) { +- int encap_proto = (proto == PF_INET) ? +- IPPROTO_IPIP : IPPROTO_IPV6; ++ if (pppoe) { ++ fill_pppoelayer(buf + ETH_HLEN, payload_len + ip_hdr_len, 0x1234); ++ } else { ++ int encap_proto = (proto == PF_INET) ? ++ IPPROTO_IPIP : IPPROTO_IPV6; + +- fill_networklayer(buf + ETH_HLEN, +- payload_len + ip_hdr_len, encap_proto); ++ fill_networklayer(buf + ETH_HLEN, ++ payload_len + ip_hdr_len, encap_proto); ++ } + } + + fill_datalinklayer(buf); +@@ -526,7 +550,7 @@ static void send_flags(int fd, struct sockaddr_ll *daddr, int psh, int syn, + static void send_data_pkts(int fd, struct sockaddr_ll *daddr, + int payload_len1, int payload_len2) + { +- static char buf[ETH_HLEN + IP_MAXPACKET]; ++ static char buf[L2_HLEN_MAX + IP_MAXPACKET]; + + create_packet(buf, 0, 0, payload_len1, 0); + write_packet(fd, buf, total_hdr_len + payload_len1, daddr); +@@ -1071,6 +1095,20 @@ static void send_fragment6(int fd, struct sockaddr_ll *daddr) + write_packet(fd, buf, bufpkt_len, daddr); + } + ++static void send_changed_pppoe_sid(int fd, struct sockaddr_ll *daddr) ++{ ++ static char buf[MAX_HDR_LEN + PAYLOAD_LEN]; ++ int pkt_size = total_hdr_len + PAYLOAD_LEN; ++ struct pppoe_hdr *hdr = (struct pppoe_hdr *)(buf + ETH_HLEN); ++ ++ create_packet(buf, 0, 0, PAYLOAD_LEN, 0); ++ write_packet(fd, buf, pkt_size, daddr); ++ ++ create_packet(buf, PAYLOAD_LEN, 0, PAYLOAD_LEN, 0); ++ hdr->sid = htons(0x4321); ++ write_packet(fd, buf, pkt_size, daddr); ++} ++ + static void bind_packetsocket(int fd) + { + struct sockaddr_ll daddr = {}; +@@ -1121,9 +1159,10 @@ static void recv_error(int fd, int rcv_errno) + static void check_recv_pkts(int fd, int *correct_payload, + int correct_num_pkts) + { +- static char buffer[IP_MAXPACKET + ETH_HLEN + 1]; +- struct iphdr *iph = (struct iphdr *)(buffer + ETH_HLEN); +- struct ipv6hdr *ip6h = (struct ipv6hdr *)(buffer + ETH_HLEN); ++ static char buffer[IP_MAXPACKET + L2_HLEN_MAX + 1]; ++ int nhoff = ETH_HLEN + (pppoe ? PPPOE_SES_HLEN : 0); ++ struct iphdr *iph = (struct iphdr *)(buffer + nhoff); ++ struct ipv6hdr *ip6h = (struct ipv6hdr *)(buffer + nhoff); + struct tcphdr *tcph; + bool bad_packet = false; + int tcp_ext_len = 0; +@@ -1140,7 +1179,7 @@ static void check_recv_pkts(int fd, int *correct_payload, + + while (1) { + ip_ext_len = 0; +- pkt_size = recv(fd, buffer, IP_MAXPACKET + ETH_HLEN + 1, 0); ++ pkt_size = recv(fd, buffer, sizeof(buffer), 0); + if (pkt_size < 0) + recv_error(fd, errno); + +@@ -1183,9 +1222,10 @@ static void check_recv_pkts(int fd, int *correct_payload, + + static void check_capacity_pkts(int fd) + { +- static char buffer[IP_MAXPACKET + ETH_HLEN + 1]; +- struct iphdr *iph = (struct iphdr *)(buffer + ETH_HLEN); +- struct ipv6hdr *ip6h = (struct ipv6hdr *)(buffer + ETH_HLEN); ++ static char buffer[IP_MAXPACKET + L2_HLEN_MAX + 1]; ++ int nhoff = ETH_HLEN + (pppoe ? PPPOE_SES_HLEN : 0); ++ struct iphdr *iph = (struct iphdr *)(buffer + nhoff); ++ struct ipv6hdr *ip6h = (struct ipv6hdr *)(buffer + nhoff); + int num_pkt = 0, num_coal = 0, pkt_idx; + const char *fail_reason = NULL; + int flow_order[num_flows * 2]; +@@ -1203,7 +1243,7 @@ static void check_capacity_pkts(int fd) + + while (1) { + ip_ext_len = 0; +- pkt_size = recv(fd, buffer, IP_MAXPACKET + ETH_HLEN + 1, 0); ++ pkt_size = recv(fd, buffer, sizeof(buffer), 0); + if (pkt_size < 0) + recv_error(fd, errno); + +@@ -1499,6 +1539,12 @@ static void gro_sender(void) + usleep(fin_delay_us); + write_packet(txfd, fin_pkt, total_hdr_len, &daddr); + ++ /* PPPoE sub-tests */ ++ } else if (strcmp(testname, "pppoe_sid") == 0) { ++ send_changed_pppoe_sid(txfd, &daddr); ++ usleep(fin_delay_us); ++ write_packet(txfd, fin_pkt, total_hdr_len, &daddr); ++ + } else { + error(1, 0, "Unknown testcase: %s", testname); + } +@@ -1716,6 +1762,12 @@ static void gro_receiver(void) + } else if (strcmp(testname, "capacity") == 0) { + check_capacity_pkts(rxfd); + ++ } else if (strcmp(testname, "pppoe_sid") == 0) { ++ correct_payload[0] = PAYLOAD_LEN; ++ correct_payload[1] = PAYLOAD_LEN; ++ printf("different PPPoE session ID doesn't coalesce: "); ++ check_recv_pkts(rxfd, correct_payload, 2); ++ + } else { + error(1, 0, "Test case error: unknown testname %s", testname); + } +@@ -1734,6 +1786,8 @@ static void parse_args(int argc, char **argv) + { "ipv6", no_argument, NULL, '6' }, + { "ipip", no_argument, NULL, 'e' }, + { "ip6ip6", no_argument, NULL, 'E' }, ++ { "pppoev4", no_argument, NULL, 'p' }, ++ { "pppoev6", no_argument, NULL, 'P' }, + { "num-flows", required_argument, NULL, 'n' }, + { "rx", no_argument, NULL, 'r' }, + { "saddr", required_argument, NULL, 's' }, +@@ -1745,7 +1799,7 @@ static void parse_args(int argc, char **argv) + }; + int c; + +- while ((c = getopt_long(argc, argv, "46d:D:eEi:n:rs:S:t:ov", opts, NULL)) != -1) { ++ while ((c = getopt_long(argc, argv, "46d:D:eEi:n:pPrs:S:t:ov", opts, NULL)) != -1) { + switch (c) { + case '4': + proto = PF_INET; +@@ -1765,6 +1819,16 @@ static void parse_args(int argc, char **argv) + proto = PF_INET6; + ethhdr_proto = htons(ETH_P_IPV6); + break; ++ case 'p': ++ pppoe = true; ++ proto = PF_INET; ++ ethhdr_proto = htons(ETH_P_PPP_SES); ++ break; ++ case 'P': ++ pppoe = true; ++ proto = PF_INET6; ++ ethhdr_proto = htons(ETH_P_PPP_SES); ++ break; + case 'd': + addr4_dst = addr6_dst = optarg; + break; +@@ -1812,6 +1876,10 @@ int main(int argc, char **argv) + } else if (ip6ip6) { + tcp_offset = ETH_HLEN + sizeof(struct ipv6hdr) * 2; + total_hdr_len = tcp_offset + sizeof(struct tcphdr); ++ } else if (pppoe) { ++ tcp_offset = ETH_HLEN + PPPOE_SES_HLEN + ++ (proto == PF_INET ? sizeof(struct iphdr) : sizeof(struct ipv6hdr)); ++ total_hdr_len = tcp_offset + sizeof(struct tcphdr); + } else if (proto == PF_INET) { + tcp_offset = ETH_HLEN + sizeof(struct iphdr); + total_hdr_len = tcp_offset + sizeof(struct tcphdr); +-- +2.53.0 + diff --git a/queue-7.1/selftests-openvswitch-add-config-file.patch b/queue-7.1/selftests-openvswitch-add-config-file.patch new file mode 100644 index 0000000000..b37047892b --- /dev/null +++ b/queue-7.1/selftests-openvswitch-add-config-file.patch @@ -0,0 +1,59 @@ +From 907897387892ac45b5443169c08430e7ab02e523 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:42 +0200 +Subject: selftests: openvswitch: add config file + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 441a820ccef9af80a9ac5a4c85b9c396e595967c ] + +The kselftests doc mentions that a config file should be present "if a +test needs specific kernel config options enabled". This selftest +requires some kernel config, but no config file was provided. + +We could say that a sub-target could use the parent's config file, but +the kselftests doc doesn't mention anything about that. Plus the +net/openvswitch target is the only net target without a config file. + +Here is a new config file, which is a trimmed version of the net one, +with hopefully the minimal required kconfig on top of 'make defconfig'. + +The Fixes tag points to the introduction of the net/openvswitch target, +just to help validating this target on stable kernels. + +Fixes: 25f16c873fb1 ("selftests: add openvswitch selftest suite") +Signed-off-by: Matthieu Baerts (NGI0) +Reviewed-by: Eelco Chaudron +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-2-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/openvswitch/config | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + create mode 100644 tools/testing/selftests/net/openvswitch/config + +diff --git a/tools/testing/selftests/net/openvswitch/config b/tools/testing/selftests/net/openvswitch/config +new file mode 100644 +index 00000000000000..c659749cd086c7 +--- /dev/null ++++ b/tools/testing/selftests/net/openvswitch/config +@@ -0,0 +1,16 @@ ++CONFIG_GENEVE=m ++CONFIG_INET_DIAG=y ++CONFIG_IPV6=y ++CONFIG_NETFILTER=y ++CONFIG_NET_IPGRE=m ++CONFIG_NET_IPGRE_DEMUX=m ++CONFIG_NF_CONNTRACK=m ++CONFIG_NF_CONNTRACK_OVS=y ++CONFIG_OPENVSWITCH=m ++CONFIG_OPENVSWITCH_GENEVE=m ++CONFIG_OPENVSWITCH_GRE=m ++CONFIG_OPENVSWITCH_VXLAN=m ++CONFIG_PSAMPLE=m ++CONFIG_VETH=y ++CONFIG_VLAN_8021Q=y ++CONFIG_VXLAN=m +-- +2.53.0 + diff --git a/queue-7.1/selftests-ovpn-add-ipv6-and-veth-configs.patch b/queue-7.1/selftests-ovpn-add-ipv6-and-veth-configs.patch new file mode 100644 index 0000000000..34fbaf44b4 --- /dev/null +++ b/queue-7.1/selftests-ovpn-add-ipv6-and-veth-configs.patch @@ -0,0 +1,52 @@ +From ba8766719ff76cdb67ec66c510fda57482179865 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:43 +0200 +Subject: selftests: ovpn: add IPV6 and VETH configs + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 90c792681a3732caaf7bf5bc435877736baf591a ] + +They are required to run the selftests: + + - Tests are executed in v4 and v6. + + - Virtual Ethernet are used between the different netns. + +This has not been seen on NIPA before, because the 'ovpn' tests are +executed with the 'tcp_ao' ones, merging their config files. These two +kernel config are present in tools/testing/selftests/net/tcp_ao/config. + +This issue is visible when only the ovpn config is used on top of the +default one. This is the recommended way to execute selftest targets. + +Fixes: 959bc330a439 ("testing/selftests: add test tool and scripts for ovpn module") +Signed-off-by: Matthieu Baerts (NGI0) +Acked-by: Antonio Quartulli +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-3-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/ovpn/config | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/tools/testing/selftests/net/ovpn/config b/tools/testing/selftests/net/ovpn/config +index d6cf033d555e70..6b424762e46ee3 100644 +--- a/tools/testing/selftests/net/ovpn/config ++++ b/tools/testing/selftests/net/ovpn/config +@@ -4,6 +4,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=y + CONFIG_CRYPTO_GCM=y + CONFIG_DST_CACHE=y + CONFIG_INET=y ++CONFIG_IPV6=y + CONFIG_NET=y + CONFIG_NETFILTER=y + CONFIG_NET_UDP_TUNNEL=y +@@ -11,3 +12,4 @@ CONFIG_NF_TABLES=m + CONFIG_NF_TABLES_INET=y + CONFIG_OVPN=m + CONFIG_STREAM_PARSER=y ++CONFIG_VETH=y +-- +2.53.0 + diff --git a/queue-7.1/selftests-ovpn-increase-timeout.patch b/queue-7.1/selftests-ovpn-increase-timeout.patch new file mode 100644 index 0000000000..01a014af53 --- /dev/null +++ b/queue-7.1/selftests-ovpn-increase-timeout.patch @@ -0,0 +1,40 @@ +From 77f211d4bbfd93d1d02de3a4f32b95f504c86fcd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Jul 2026 20:04:44 +0200 +Subject: selftests: ovpn: increase timeout + +From: Matthieu Baerts (NGI0) + +[ Upstream commit 61ac7049aaa86ae044e8a5b94d852218163d5bf8 ] + +The default timeout is 45 seconds, that's too low for a few ovpn tests. + +Indeed, these tests can take up to 50 seconds with some debug kernel +config on NIPA. Set a timeout to 90 seconds, just to be on the safe +side. + +Note that the Fixes tag here points to the introduction of the ovpn +tests because I don't know when they started to take more than 45 +seconds. That's OK because a timeout of 1.5 minutes is not exaggerated. + +Fixes: 959bc330a439 ("testing/selftests: add test tool and scripts for ovpn module") +Signed-off-by: Matthieu Baerts (NGI0) +Acked-by: Antonio Quartulli +Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-4-a2915c294ef5@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/ovpn/settings | 1 + + 1 file changed, 1 insertion(+) + create mode 100644 tools/testing/selftests/net/ovpn/settings + +diff --git a/tools/testing/selftests/net/ovpn/settings b/tools/testing/selftests/net/ovpn/settings +new file mode 100644 +index 00000000000000..ba4d85f74cd6b9 +--- /dev/null ++++ b/tools/testing/selftests/net/ovpn/settings +@@ -0,0 +1 @@ ++timeout=90 +-- +2.53.0 + diff --git a/queue-7.1/series b/queue-7.1/series index bca54f6338..8f349c52d5 100644 --- a/queue-7.1/series +++ b/queue-7.1/series @@ -165,3 +165,197 @@ revert-drm-amd-display-add-missing-kdoc-for-allm-par.patch usb-xhci-pci-limit-via-vl805-dma-addressing-to-36-bi.patch selftests-bpf-adjust-verifier_map_ptr-for-the-map-s-.patch selftests-bpf-keep-verifier_map_ptr-exercising-ops-p.patch +watchdog-ni903x_wdt-check-acpi_companion-against-nul.patch +wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch +wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch +hwmon-corsair-psu-stop-device-io-before-calling-hid_.patch +hwmon-corsair-cpro-stop-device-io-before-calling-hid.patch +hwmon-gigabyte_waterforce-stop-device-io-before-call.patch +hwmon-nzxt-smart2-stop-device-io-before-calling-hid_.patch +hwmon-nzxt-kraken3-stop-device-io-before-calling-hid.patch +watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch +watchdog-airoha-prevent-division-by-zero-when-clock-.patch +wifi-ath10k-fix-skb-leak-on-incomplete-msdu-during-r.patch +wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch +wifi-ath11k-flush-the-posted-write-after-writing-to-.patch +wifi-ath12k-flush-the-posted-write-after-writing-to-.patch +platform-x86-intel-vsec-allocate-res-with-intel_vsec.patch +platform-x86-intel-vsec-free-acpi-discovery-data-on-.patch +platform-x86-asus-wmi-temporarily-revert-to-setting-.patch +firewire-net-fix-fragmented-datagram-reassembly.patch +wifi-ath12k-fix-low-mlo-rx-throughput-on-wcn7850.patch +wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch +wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch +wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch +wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch +wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch +btrfs-declare-btrfs_ioctl_search_args_v2-buf-as-__u8.patch +btrfs-fix-u32-to-s64-type-conversion-in-dirty_metada.patch +btrfs-don-t-propagate-extent_flag_logging-to-split-e.patch +btrfs-free-mapping-node-on-duplicate-reloc-root-inse.patch +asoc-tas2781-bound-firmware-description-string-parsi.patch +asoc-sun4i-codec-set-quirks.playback_only-for-h616-c.patch +iommu-amd-fix-irq-unsafe-locking-in-gdom-allocation.patch +iommu-amd-fix-nested-domain-leak.patch +alsa-hda-cs35l41-validate-and-free-acpi-mute-object.patch +asoc-bt-sco-fix-duplicate-dapm-widget-names-for-wide.patch +arm_mpam-fix-software-reset-values-of-mpamcfg_pri.patch +arm_mpam-fix-mpamcfg_mbw_pbm-register-setting.patch +arm_mpam-guard-mbwu-state-before-adding-it-to-garbag.patch +asoc-cs35l56-fix-potential-probe-deadlock.patch +asoc-cs35l56-use-complete_all-to-signal-init_complet.patch +wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch +wifi-iwlwifi-fix-pointer-arithmetic-in-iwl_add_mcc_t.patch +wifi-iwlwifi-validate-payload-length-in-iwl_pnvm_com.patch +wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch +usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch +drivers-virt-pkvm-fix-end-calculation-in-mmio_guard_.patch +hwmon-drop-unused-i2c-driver_data.patch +hwmon-use-named-initializers-for-arrays-of-i2c_devic.patch +hwmon-pmbus-max34440-add-support-adpm12250.patch +hwmon-pmbus-max34440-block-unsupported-vin-and-iin-l.patch +hwmon-asus-ec-sensors-fix-looping-over-banks-while-r.patch +hwmon-asus-ec-sensors-fix-ec-read-intervals.patch +hwmon-asus-ec-sensors-add-missed-handle-for-enomem.patch +smb-client-validate-dfs-referral-pathconsumed.patch +drm-i915-backlight-remove-dp_edp_backlight_aux_enabl.patch +ovpn-avoid-putting-unrelated-p2p-peer-on-socket-rele.patch +selftests-net-ovpn-fix-getaddrinfo-memory-leak-in-ov.patch +ovpn-fix-use-after-free-in-unlock_ovpn.patch +ovpn-use-monotonic-clock-for-peer-keepalive-timeouts.patch +hwmon-occ-validate-poll-response-sensor-blocks.patch +regulator-mt6358-use-regmap-helper-to-read-fixed-ldo.patch +bluetooth-btusb-validate-realtek-vendor-event-length.patch +net-phy-marvell-fix-return-code.patch +selftests-net-fix-tun-ipv6-test-addresses-to-avoid-6.patch +netlink-specs-rt-link-convert-bridge-port-flag-attri.patch +net-packet-avoid-fanout-hook-re-registration-after-u.patch +bpf-reject-redirect-helpers-without-a-bpf_net_contex.patch +net-sched-handle-tc_act_redirect-from-qdisc-filter-c.patch +bonding-fix-devconf_all-null-dereference-when-ipv6-i.patch +rds-drop-incoming-messages-that-cross-network-namesp.patch +gtp-parse-extension-headers-before-reading-inner-pro.patch +rxrpc-fix-io_thread-race-in-rxrpc_wake_up_io_thread.patch +dpaa2-switch-put-mac-endpoint-device-on-disconnect.patch +net-airoha-fix-potential-use-after-free-in-airoha_pp.patch +dpaa2-eth-put-mac-endpoint-device-on-disconnect.patch +net-airoha-fix-dma-direction-for-npu-mailbox-buffer.patch +iommu-amd-wait-for-completion-instead-of-returning-e.patch +wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch +nfp-check-resource-mutex-allocation.patch +wan-wanxl-only-reset-hardware-after-bar-mapping.patch +vhost-net-fix-tx-stall-when-vhost-owns-virtio-net-he.patch +wifi-mac80211-copy-aggregation-information.patch +wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch +iommu-amd-bound-the-early-acpi-hid-map.patch +iommu-intel-fix-out-of-bounds-memset-in-dmar_latency.patch +wifi-mac80211-recalculate-tim-when-a-station-enters-.patch +pds_core-reject-component-parameter-in-legacy-firmwa.patch +arm64-correct-value-returned-by-esr_elx_fsc_addrsz_n.patch +arm64-mm-check-the-requested-pfn-range-during-memory.patch +amd-xgbe-fix-mac_auto_sw-handling-in-cl37-an.patch +soreuseport-clear-sk_reuseport_cb-before-failure-in-.patch +net-call-net_enable_timestamp-before-failure-in-sk_c.patch +geneve-fix-hint-header-definition-wrt-endianness.patch +geneve-ensure-the-skb-is-writable-before-fixing-its-.patch +tipc-serialize-udp-bearer-replicast-list-updates.patch +net-txgbe-fix-heap-overflow-when-reading-module-eepr.patch +rds-fix-inet6_addr_lst-null-dereference-when-ipv6-is.patch +net-txgbe-fix-fdir-filter-leak-on-remove.patch +sctp-fix-auth_chunk_list-capacity-check-in-sctp_auth.patch +pds_core-fix-deadlock-between-reset-thread-and-remov.patch +pds_core-fix-use-after-free-on-workqueue-during-remo.patch +pds_core-yield-the-cpu-while-waiting-for-the-adminq-.patch +pds_core-order-completion-reads-after-the-ownership-.patch +pds_core-fix-auxiliary-device-add-del-races.patch +pds_core-check-for-workqueue-allocation-failure.patch +accel-ethosu-fix-element-size-accounting-for-cmd-str.patch +accel-ethosu-handle-u85-internal-chaining-buffer.patch +sctp-validate-stream-count-in-sctp_process_strreset_.patch +net-mctp-i3c-clean-up-notifier-and-buses-if-driver-r.patch +tls-device-push-pending-open-record-on-splice-eof.patch +selftests-af_unix-add-user_ns-config.patch +selftests-openvswitch-add-config-file.patch +selftests-ovpn-add-ipv6-and-veth-configs.patch +selftests-ovpn-increase-timeout.patch +selftests-drv-net-increase-timeout.patch +selftests-drv-net-convert-so_txtime-to-drv-net.patch +selftests-net-test-pppoe-packets-in-gro.sh.patch +selftests-drv-net-add-missing-kconfig-for-psp.py.patch +gtp-check-skb_pull_data-return-in-gtp1u_send_echo_re.patch +nexthop-initialize-extack-in-nh_res_bucket_migrate.patch +tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch +cifs-prevent-readdir-from-changing-file-size-due-to-.patch +cifs-fix-cifsfileinfo-leak-on-kmalloc-failure-in-def.patch +ppp-annotate-concurrent-dev-stats-accesses.patch +wifi-mt76-disable-napi-when-removing-device.patch +wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch +wifi-mt76-mt7915-guard-he-capability-lookups.patch +wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch +wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch +wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch +wifi-mt76-fix-airoha_npu-dependency-tracking.patch +wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch +wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch +drm-xe-vf-add-drm_dev-guards-when-detaching-ccs-read.patch +wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch +ovl-fix-trusted-xattr-escape-prefix-matching.patch +drm-panel-ilitek-ili9882t-fix-unmet-dependency-for-d.patch +drm-panel-s6e3ha8-fix-unmet-dependency-on-drm_displa.patch +drm-panel-fix-unmet-dependency-bug-for-drm_panel_him.patch +drm-vc4-hvs-v3d-fix-null-dereference-in-unbind.patch +ovl-check-access-to-copy_file_range-source-with-src-.patch +amt-re-read-skb-header-pointers-after-every-pull.patch +amt-make-the-head-writable-before-rewriting-the-l2-h.patch +net-bridge-vlan-fix-vlan-range-dumps-starting-with-p.patch +net-hsr-fix-memory-leak-on-slave-unregistration-by-r.patch +smp-avoid-invalid-per-cpu-csd-lookup-with-csd-lock-d.patch +smp-make-csd-lock-acquisition-atomic-for-debug-mode.patch +net-dpaa-fix-mode-setting.patch +net-stmmac-dwmac4-mask-interrupts-when-stopping-dma-.patch +sctp-auth-verify-auth-requirement-when-auth_chunk-is.patch +vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch +drm-xe-i2c-allow-per-domain-unique-id.patch +drm-xe-vm-fix-svm-leak-on-resv-obj-alloc-failure-in-.patch +iomap-correct-the-range-of-a-partial-dirty-clear.patch +iomap-fix-incorrect-did_zero-setting-in-iomap_zero_i.patch +tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch +drm-tests-shmem-set-dma-mask-to-64-bit-in-drm_gem_sh.patch +bpf-tcp-fix-double-sock-release-on-batch-realloc.patch +net-stmmac-xgmac-fix-l4-filter-port-overwrite-on-reg.patch +net-stmmac-fix-l3l4-filter-rejecting-unsupported-off.patch +net-stmmac-reset-residual-action-in-l3l4-filters-on-.patch +net-stmmac-enable-the-mac-on-link-up-for-all-support.patch +net-gre-fix-lltx-regression-for-gre-tunnels-with-seq.patch +mpls-set-rt-rt_nhn-just-before-returning-from-mpls_n.patch +octeontx2-vf-set-tc-flower-flag-on-mcam-entry-alloca.patch +ipv4-icmp-fill-flow-parameters-in-icmp_route_lookup-.patch +ppp-annotate-data-races-in-ppp_generic.patch +hinic-remove-unused-ethtool-rss-user-configuration-b.patch +loongarch-bpf-zero-extend-signed-alu32-div-mod-resul.patch +net-qrtr-restrict-socket-creation-to-the-initial-net.patch +raw-annotate-lockless-match-fields-in-raw_v4_match.patch +net-mlx5-fix-mcia-register-buffer-overflow-on-32-dwo.patch +net-mlx5-e-switch-fix-zero-num_dest-in-prio_tag-egre.patch +net-mlx5e-report-zero-bandwidth-for-non-ets-traffic-.patch +net-mlx5e-reject-unsupported-cb-shaper-tsa-in-ets-va.patch +octeontx2-pf-tc-fix-egress-ratelimiting.patch +net-ipv6-fix-dif-and-sdif-mismatch-in-raw6_icmp_erro.patch +ice-allow-creating-vfs-when-config_ice_switchdev.patch +ice-fix-lag-recipe-to-profile-association.patch +ice-prevent-tstamp-ring-allocation-for-non-pf-vsi-ty.patch +idpf-fix-max_vport-related-crash-on-allocation-error.patch +ipv6-change-allocation-flags-to-match-rcu_read_lock-.patch +rds-tcp-unregister-sysctl-before-tearing-down-listen.patch +ptp-netc-explicitly-clear-tmr_off-during-initializat.patch +mctp-check-register_netdevice_notifier-error-in-mctp.patch +net-airoha-fix-ets-channel-derivation-in-airoha_tc_s.patch +tipc-fix-integer-overflow-in-tipc_recvmsg-and-tipc_r.patch +bnge-bng_re-fix-ring-id-widths.patch +net-drop_monitor-fix-info-leak-in-net_dm_attr_payloa.patch +drop_monitor-fix-size-calculations-for-64-bit-attrib.patch +drop_monitor-perform-u64_stats-updates-under-irq-dis.patch +pidfs-make-pidfs_ino_lock-static.patch +loongarch-bpf-fix-memory-leak-in-bpf_jit_free.patch +bpf-sockmap-fix-cork-use-after-free-in-tcp_bpf_sendm.patch +tracing-fix-use-after-free-freeing-trigger-private-d.patch diff --git a/queue-7.1/smb-client-validate-dfs-referral-pathconsumed.patch b/queue-7.1/smb-client-validate-dfs-referral-pathconsumed.patch new file mode 100644 index 0000000000..5468bd06ef --- /dev/null +++ b/queue-7.1/smb-client-validate-dfs-referral-pathconsumed.patch @@ -0,0 +1,97 @@ +From 20683953c028e4faacac752e690910078e19a6d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Jul 2026 13:25:23 +0800 +Subject: smb: client: validate DFS referral PathConsumed + +From: Yichong Chen + +[ Upstream commit f6f5ee2aa33b350c671721b965251c42cebb962e ] + +parse_dfs_referrals() validates that the response contains the fixed +referral entry array and, on for-next, the per-referral string offsets. +However, the response also contains a PathConsumed value that is later +used for DFS path parsing. + +If a malformed response provides a PathConsumed value larger than the +search name, later DFS parsing can advance beyond the end of the path. + +Validate PathConsumed against the search name length before storing it in +the parsed referral. + +Fixes: 4ecce920e13a ("CIFS: move DFS response parsing out of SMB1 code") +Reviewed-by: Paulo Alcantara (Red Hat) +Signed-off-by: Yichong Chen +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/misc.c | 34 +++++++++++++++++++++++++--------- + 1 file changed, 25 insertions(+), 9 deletions(-) + +diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c +index ee1728eec8aa0a..f8bc1b8d3fdeae 100644 +--- a/fs/smb/client/misc.c ++++ b/fs/smb/client/misc.c +@@ -678,6 +678,8 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + int i, rc = 0; + char *data_end; + struct dfs_referral_level_3 *ref; ++ unsigned int path_consumed; ++ size_t search_name_len; + + if (rsp_size < sizeof(*rsp)) { + cifs_dbg(VFS | ONCE, +@@ -724,6 +726,7 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + rc = -ENOMEM; + goto parse_DFS_referrals_exit; + } ++ search_name_len = strlen(searchName); + + /* collect necessary data from referrals */ + for (i = 0; i < *num_of_nodes; i++) { +@@ -732,21 +735,34 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size, + struct dfs_info3_param *node = (*target_nodes)+i; + + node->flags = le32_to_cpu(rsp->DFSFlags); ++ path_consumed = le16_to_cpu(rsp->PathConsumed); + if (is_unicode) { +- __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, +- GFP_KERNEL); +- if (tmp == NULL) { ++ size_t search_name_utf16_len = search_name_len * 2 + 2; ++ __le16 *tmp; ++ ++ if (path_consumed > search_name_utf16_len) { ++ rc = -EINVAL; ++ goto parse_DFS_referrals_exit; ++ } ++ ++ tmp = kmalloc(search_name_utf16_len, GFP_KERNEL); ++ if (!tmp) { + rc = -ENOMEM; + goto parse_DFS_referrals_exit; + } +- cifsConvertToUTF16((__le16 *) tmp, searchName, ++ cifsConvertToUTF16((__le16 *)tmp, searchName, + PATH_MAX, nls_codepage, remap); +- node->path_consumed = cifs_utf16_bytes(tmp, +- le16_to_cpu(rsp->PathConsumed), +- nls_codepage); ++ node->path_consumed = cifs_utf16_bytes(tmp, path_consumed, ++ nls_codepage); + kfree(tmp); +- } else +- node->path_consumed = le16_to_cpu(rsp->PathConsumed); ++ } else { ++ if (path_consumed > search_name_len) { ++ rc = -EINVAL; ++ goto parse_DFS_referrals_exit; ++ } ++ ++ node->path_consumed = path_consumed; ++ } + + node->server_type = le16_to_cpu(ref->ServerType); + node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags); +-- +2.53.0 + diff --git a/queue-7.1/smp-avoid-invalid-per-cpu-csd-lookup-with-csd-lock-d.patch b/queue-7.1/smp-avoid-invalid-per-cpu-csd-lookup-with-csd-lock-d.patch new file mode 100644 index 0000000000..151ea9c910 --- /dev/null +++ b/queue-7.1/smp-avoid-invalid-per-cpu-csd-lookup-with-csd-lock-d.patch @@ -0,0 +1,56 @@ +From a63f01205fa89d4f266326b5fd4654b8fc8a05a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 17:45:38 -0700 +Subject: smp: Avoid invalid per-CPU CSD lookup with CSD lock debug + +From: Chuyi Zhou + +[ Upstream commit c58ea9adf7342508c6ac0b7ad79ef10d589f9c6e ] + +Commit b0473dcd4b1d ("smp: Improve smp_call_function_single() +CSD-lock diagnostics") made smp_call_function_single() use the destination +CPU's csd_data when CSD lock debugging is enabled. That lets the debug code +associate a stuck CSD lock with the target CPU, but it also means the CPU +argument is used in per_cpu_ptr() before generic_exec_single() has a chance +to validate it. + +This becomes unsafe when smp_call_function_any() cannot find an online CPU +in the supplied mask. In that case the selected CPU can be nr_cpu_ids, and +the !wait path calls get_single_csd_data(cpu) before generic_exec_single() +returns -ENXIO. With csdlock_debug_enabled set, that indexes the per-CPU +offset array with an invalid CPU number. + +Use the destination CPU's csd_data only when the CPU number is within +nr_cpu_ids. For invalid CPU numbers, fall back to the local CPU's csd_data +and let generic_exec_single() perform the existing validation and return +-ENXIO. + +Fixes: b0473dcd4b1d ("smp: Improve smp_call_function_single() CSD-lock diagnostics") +Signed-off-by: Chuyi Zhou +Signed-off-by: Paul E. McKenney +Signed-off-by: Thomas Gleixner +Reviewed-by: Paul E. McKenney +Acked-by: Muchun Song +Link: https://patch.msgid.link/20260716004539.13983-1-paulmck@kernel.org +Signed-off-by: Sasha Levin +--- + kernel/smp.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/smp.c b/kernel/smp.c +index a0bb56bd8ddadb..dc6582bb35d084 100644 +--- a/kernel/smp.c ++++ b/kernel/smp.c +@@ -380,7 +380,8 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(call_single_data_t, csd_data); + #ifdef CONFIG_CSD_LOCK_WAIT_DEBUG + static call_single_data_t *get_single_csd_data(int cpu) + { +- if (static_branch_unlikely(&csdlock_debug_enabled)) ++ if (static_branch_unlikely(&csdlock_debug_enabled) && ++ (unsigned int)cpu < nr_cpu_ids) + return per_cpu_ptr(&csd_data, cpu); + return this_cpu_ptr(&csd_data); + } +-- +2.53.0 + diff --git a/queue-7.1/smp-make-csd-lock-acquisition-atomic-for-debug-mode.patch b/queue-7.1/smp-make-csd-lock-acquisition-atomic-for-debug-mode.patch new file mode 100644 index 0000000000..6793e9082b --- /dev/null +++ b/queue-7.1/smp-make-csd-lock-acquisition-atomic-for-debug-mode.patch @@ -0,0 +1,97 @@ +From 4f5a4cfeb69a75d959c5a3dedfaa0a82fd683302 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 17:45:39 -0700 +Subject: smp: Make CSD lock acquisition atomic for debug mode + +From: Chuyi Zhou + +[ Upstream commit 35551efb155e3b83445a6c3f66cb498d5efc182c ] + +Commit b0473dcd4b1d ("smp: Improve smp_call_function_single() +CSD-lock diagnostics") changed smp_call_function_single() so that, +when CSD lock debugging is enabled, async !wait calls use the +destination CPU csd_data. That improves diagnostics, but it also removes +the single-writer property that made the old csd_lock() safe: multiple +CPUs can now prepare the same destination CPU CSD concurrently. + +csd_lock() currently waits for CSD_FLAG_LOCK to clear and then sets the +bit with a non-atomic read-modify-write. Two senders can both see an +unlocked CSD, set the bit, overwrite the callback fields, and enqueue +the same llist node. Re-adding a node that is already the queue head can +make node->next point to itself, leaving the target CPU stuck walking +call_single_queue. Later synchronous work, such as a TLB shootdown, can +then remain queued and trigger soft-lockup warnings or panics. + +Keep the single csd_lock() implementation, but when CSD lock debugging is +enabled, acquire CSD_FLAG_LOCK with try_cmpxchg_acquire(). This makes the +destination CPU CSD a real atomic lock in the only configuration where it +can be shared by multiple remote senders, while preserving the existing +non-debug fast path. + +Fixes: b0473dcd4b1d ("smp: Improve smp_call_function_single() CSD-lock diagnostics") +Signed-off-by: Chuyi Zhou +Signed-off-by: Paul E. McKenney +Signed-off-by: Thomas Gleixner +Link: https://patch.msgid.link/20260716004539.13983-2-paulmck@kernel.org +Signed-off-by: Sasha Levin +--- + kernel/smp.c | 27 +++++++++++++++++++++++---- + 1 file changed, 23 insertions(+), 4 deletions(-) + +diff --git a/kernel/smp.c b/kernel/smp.c +index dc6582bb35d084..52dffc86555cd2 100644 +--- a/kernel/smp.c ++++ b/kernel/smp.c +@@ -137,10 +137,10 @@ csd_do_func(smp_call_func_t func, void *info, call_single_data_t *csd) + trace_csd_function_exit(func, csd); + } + +-#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG +- + static DEFINE_STATIC_KEY_MAYBE(CONFIG_CSD_LOCK_WAIT_DEBUG_DEFAULT, csdlock_debug_enabled); + ++#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG ++ + /* + * Parse the csdlock_debug= kernel boot parameter. + * +@@ -342,6 +342,10 @@ static __always_inline void csd_lock_wait(call_single_data_t *csd) + smp_cond_load_acquire(&csd->node.u_flags, !(VAL & CSD_FLAG_LOCK)); + } + #else ++static __always_inline void __csd_lock_wait(call_single_data_t *csd) ++{ ++} ++ + static void csd_lock_record(call_single_data_t *csd) + { + } +@@ -354,8 +358,23 @@ static __always_inline void csd_lock_wait(call_single_data_t *csd) + + static __always_inline void csd_lock(call_single_data_t *csd) + { +- csd_lock_wait(csd); +- csd->node.u_flags |= CSD_FLAG_LOCK; ++ if (IS_ENABLED(CONFIG_CSD_LOCK_WAIT_DEBUG) && ++ static_branch_unlikely(&csdlock_debug_enabled)) { ++ ++ for (;;) { ++ unsigned int flags; ++ ++ __csd_lock_wait(csd); ++ flags = READ_ONCE(csd->node.u_flags); ++ ++ if (!(flags & CSD_FLAG_LOCK) && ++ try_cmpxchg_acquire(&csd->node.u_flags, &flags, flags | CSD_FLAG_LOCK)) ++ break; ++ } ++ } else { ++ csd_lock_wait(csd); ++ csd->node.u_flags |= CSD_FLAG_LOCK; ++ } + + /* + * prevent CPU from reordering the above assignment +-- +2.53.0 + diff --git a/queue-7.1/soreuseport-clear-sk_reuseport_cb-before-failure-in-.patch b/queue-7.1/soreuseport-clear-sk_reuseport_cb-before-failure-in-.patch new file mode 100644 index 0000000000..2f73d77be2 --- /dev/null +++ b/queue-7.1/soreuseport-clear-sk_reuseport_cb-before-failure-in-.patch @@ -0,0 +1,59 @@ +From 60e2f24d71020539e508582410b8605ffecdd353 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 18:31:39 +0000 +Subject: soreuseport: Clear sk_reuseport_cb before failure in sk_clone(). + +From: Kuniyuki Iwashima + +[ Upstream commit 98da8ce87dd561f08fbe44f75865edc5d9b2ba5f ] + +When sk_clone() fails, sk_destruct() is called for the new socket. + +If the parent socket has sk->sk_reuseport_cb, the child will call +reuseport_detach_sock() for the reuseport group. + +Let's clear sk->sk_reuseport_cb before any failure path in sk_clone(). + +Note that this was not a problem before the cited commit because +reuseport_detach_sock() did nothing if the socket was not found in +the reuseport array. + +Fixes: 5dc4c4b7d4e8 ("bpf: Introduce BPF_MAP_TYPE_REUSEPORT_SOCKARRAY") +Reported-by: Sashiko +Closes: https://lore.kernel.org/all/20260709032007.9E4D61F000E9@smtp.kernel.org/ +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Willem de Bruijn +Reviewed-by: Jason Xing +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260709183315.965751-2-kuniyu@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/sock.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/core/sock.c b/net/core/sock.c +index 1c73b6841d0ae9..d0f518381334ca 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -2547,6 +2547,8 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority, + + cgroup_sk_clone(&newsk->sk_cgrp_data); + ++ RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL); ++ + rcu_read_lock(); + filter = rcu_dereference(sk->sk_filter); + if (filter != NULL) +@@ -2569,8 +2571,6 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority, + goto free; + } + +- RCU_INIT_POINTER(newsk->sk_reuseport_cb, NULL); +- + if (bpf_sk_storage_clone(sk, newsk)) + goto free; + +-- +2.53.0 + diff --git a/queue-7.1/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch b/queue-7.1/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch new file mode 100644 index 0000000000..d5a988d858 --- /dev/null +++ b/queue-7.1/tipc-fix-infinite-loop-in-__tipc_nl_compat_dumpit.patch @@ -0,0 +1,47 @@ +From 61f9793fd5abea351209b7b832d2cf5835421555 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 17:49:35 -0300 +Subject: tipc: fix infinite loop in __tipc_nl_compat_dumpit + +From: Helen Koike + +[ Upstream commit 22f8aa35964e8f2ab026578f45befc9605fd1b28 ] + +cmd->dumpit callback can return a negative errno, causing an infinite +loop due to the while(len) condition. As the loop never terminates, +genl_mutex is never released, and other tasks waiting on it starve in D +state. + +Check dumpit's return value, propagate it and jump to err_out on error. + +Reported-by: syzbot+85d0bec020d805014a3a@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=85d0bec020d805014a3a +Fixes: d0796d1ef63d ("tipc: convert legacy nl bearer dump to nl compat") +Signed-off-by: Helen Koike +Reviewed-by: Tung Nguyen +Link: https://patch.msgid.link/20260713204940.647668-1-koike@igalia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/netlink_compat.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c +index 2a786c56c8c59e..d9a4f94ea2d43d 100644 +--- a/net/tipc/netlink_compat.c ++++ b/net/tipc/netlink_compat.c +@@ -221,6 +221,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, + int rem; + + len = (*cmd->dumpit)(buf, &cb); ++ if (len < 0) { ++ err = len; ++ goto err_out; ++ } + + nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) { + err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN, +-- +2.53.0 + diff --git a/queue-7.1/tipc-fix-integer-overflow-in-tipc_recvmsg-and-tipc_r.patch b/queue-7.1/tipc-fix-integer-overflow-in-tipc_recvmsg-and-tipc_r.patch new file mode 100644 index 0000000000..28a7502514 --- /dev/null +++ b/queue-7.1/tipc-fix-integer-overflow-in-tipc_recvmsg-and-tipc_r.patch @@ -0,0 +1,70 @@ +From 099a4a6dd1edbaeaf22ed1ca605b56b1a10cdec8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Jul 2026 17:41:03 -0400 +Subject: tipc: fix integer overflow in tipc_recvmsg() and tipc_recvstream() + +From: Cen Zhang (Microsoft) + +[ Upstream commit 47f42ff521b4eeb46e82f9a46a4783a99f7570d7 ] + +In tipc_recvmsg(), the copy length is computed as: + + copy = min_t(int, dlen - offset, buflen); + +buflen is size_t but min_t(int, ...) casts it to int. When buflen +exceeds INT_MAX (e.g. 0xFFFFFFFF via io_uring provided buffers), it +wraps negative, wins the comparison, and the negative copy length +propagates to simple_copy_to_iter() where int-to-size_t promotion +makes it SIZE_MAX, triggering a WARN_ON. tipc_recvstream() has the +same pattern. + + Kernel panic - not syncing: kernel: panic_on_warn set ... + RIP: 0010:simple_copy_to_iter+0x9e/0xd0 (net/core/datagram.c:521) + Call Trace: + __skb_datagram_iter+0x123/0x8b0 (net/core/datagram.c:402) + skb_copy_datagram_iter+0x77/0x1a0 (net/core/datagram.c:534) + tipc_recvmsg+0x3d7/0xe80 (net/tipc/socket.c:1934) + io_recvmsg+0x47e/0xda0 + +Fix by changing min_t(int, ...) to min_t(size_t, ...) in both +functions. The result is always <= (dlen - offset), which is bounded +by TIPC maximum message size (0x1ffff bytes), so the implicit +narrowing on assignment to int copy is always safe. + +Fixes: e9f8b10101c6 ("tipc: refactor function tipc_sk_recvmsg()") +Fixes: ec8a09fbbeff ("tipc: refactor function tipc_sk_recv_stream()") +Reported-by: AutonomousCodeSecurity@microsoft.com +Signed-off-by: Cen Zhang (Microsoft) +Reviewed-by: Tung Nguyen +Link: https://patch.msgid.link/20260720214103.47732-1-blbllhy@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/socket.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/tipc/socket.c b/net/tipc/socket.c +index 490f30899b5a9a..14f3f2e5dba092 100644 +--- a/net/tipc/socket.c ++++ b/net/tipc/socket.c +@@ -1934,7 +1934,7 @@ static int tipc_recvmsg(struct socket *sock, struct msghdr *m, + if (likely(!err)) { + int offset = skb_cb->bytes_read; + +- copy = min_t(int, dlen - offset, buflen); ++ copy = min_t(size_t, dlen - offset, buflen); + rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy); + if (unlikely(rc)) + goto exit; +@@ -2066,7 +2066,7 @@ static int tipc_recvstream(struct socket *sock, struct msghdr *m, + /* Copy data if msg ok, otherwise return error/partial data */ + if (likely(!err)) { + offset = skb_cb->bytes_read; +- copy = min_t(int, dlen - offset, buflen - copied); ++ copy = min_t(size_t, dlen - offset, buflen - copied); + rc = skb_copy_datagram_msg(skb, hlen + offset, m, copy); + if (unlikely(rc)) + break; +-- +2.53.0 + diff --git a/queue-7.1/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch b/queue-7.1/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch new file mode 100644 index 0000000000..731caa1052 --- /dev/null +++ b/queue-7.1/tipc-fix-u16-mtu-truncation-in-media-and-bearer-mtu-.patch @@ -0,0 +1,72 @@ +From 884de0bf7571d9d6eec66ef8e936a229a2bda9a4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 00:15:41 -0400 +Subject: tipc: fix u16 MTU truncation in media and bearer MTU validation + +From: Cen Zhang (Microsoft) + +[ Upstream commit 9f29cd8a8e7901a2617c8064ce9f50fc67b97cb8 ] + +Both TIPC_NL_MEDIA_SET and TIPC_NL_BEARER_SET accept user-supplied +MTU values but only enforce a minimum bound, not a maximum. When a user +sets the MTU to a value exceeding U16_MAX (65535), it passes validation +but is silently truncated when assigned to u16 fields l->mtu and +l->advertised_mtu in tipc_link_create(). Values like 65536 (0x10000) +truncate to 0, causing a division by zero in tipc_link_set_queue_limits() +which computes TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE). Other overflowing +values (e.g. 65537-131071) produce small incorrect MTU values, resulting +in link malfunction behaviors. + +Crash stack (triggered as unprivileged user via user namespace): + + tipc_link_set_queue_limits net/tipc/link.c:2531 + tipc_link_create net/tipc/link.c:520 + tipc_node_check_dest net/tipc/node.c:1279 + tipc_disc_rcv net/tipc/discover.c:252 + tipc_rcv net/tipc/node.c:2129 + tipc_udp_recv net/tipc/udp_media.c:392 + +Two independent paths lack the upper bound check: +1. tipc_udp_mtu_bad() -- called from __tipc_nl_media_set() (MEDIA_SET) +2. inline check in __tipc_nl_bearer_set() at bearer.c:1160 (BEARER_SET) + +Fix both by rejecting MTU values above U16_MAX. + +Fixes: 901271e0403a ("tipc: implement configuration of UDP media MTU") +Reported-by: AutonomousCodeSecurity@microsoft.com +Closes: https://lore.kernel.org/all/CAB8m9WgETt0AjmFwE=F-CKjGXsK6_WDv0=kbYRcC8-noo+amnA@mail.gmail.com +Reviewed-by: Vadim Fedorenko +Signed-off-by: Cen Zhang (Microsoft) +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260714041541.307702-1-blbllhy@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/tipc/netlink.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c +index 8336a9664703fe..1307dd1a961341 100644 +--- a/net/tipc/netlink.c ++++ b/net/tipc/netlink.c +@@ -113,12 +113,16 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { + }; + + /* Properties valid for media, bearer and link */ ++static const struct netlink_range_validation tipc_nl_mtu_range = { ++ .max = U16_MAX, ++}; ++ + const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = { + [TIPC_NLA_PROP_UNSPEC] = { .type = NLA_UNSPEC }, + [TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_TOL] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_WIN] = { .type = NLA_U32 }, +- [TIPC_NLA_PROP_MTU] = { .type = NLA_U32 }, ++ [TIPC_NLA_PROP_MTU] = NLA_POLICY_FULL_RANGE(NLA_U32, &tipc_nl_mtu_range), + [TIPC_NLA_PROP_BROADCAST] = { .type = NLA_U32 }, + [TIPC_NLA_PROP_BROADCAST_RATIO] = { .type = NLA_U32 } + }; +-- +2.53.0 + diff --git a/queue-7.1/tipc-serialize-udp-bearer-replicast-list-updates.patch b/queue-7.1/tipc-serialize-udp-bearer-replicast-list-updates.patch new file mode 100644 index 0000000000..6c5a4f8800 --- /dev/null +++ b/queue-7.1/tipc-serialize-udp-bearer-replicast-list-updates.patch @@ -0,0 +1,193 @@ +From 5cb9e83c4133b9bbf3028db5a01a58d97f192025 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 19:52:04 -0700 +Subject: tipc: serialize udp bearer replicast list updates + +From: Weiming Shi + +[ Upstream commit 350e592ff4e30e48ffb55e142d11a73e63f4869c ] + +tipc_udp_rcast_add() and cleanup_bearer() both update ub->rcast.list with +list_add_rcu() / list_del_rcu(), but nothing serializes them. The add runs +from the encap receive softirq (via tipc_udp_rcast_disc()) without +rtnl_lock(), so it can race the cleanup delete and corrupt the list: + + list_del corruption. prev->next should be ffff8880298d7ab8, + but was ffff88802449ad38. (prev=ffff888027e3ec98) + kernel BUG at lib/list_debug.c:62! + RIP: __list_del_entry_valid_or_report+0x17a/0x200 + Workqueue: events cleanup_bearer + Call Trace: + cleanup_bearer (net/tipc/udp_media.c:811) + process_one_work (kernel/workqueue.c:3302) + worker_thread (kernel/workqueue.c:3466) + +The bearer can be enabled from an unprivileged user namespace, as the +TIPCv2 generic-netlink ops carry no GENL_ADMIN_PERM. + +Add a spinlock to struct udp_bearer and take it around the list_add_rcu() +in tipc_udp_rcast_add() and the list_del_rcu() loop in cleanup_bearer() so +the two writers can no longer corrupt the list. + +Reject a duplicate peer under the same lock before allocating, and remove +tipc_udp_is_known_peer(). The old lockless pre-check in +tipc_udp_rcast_disc() was racy: two softirqs discovering the same peer +could both find it absent and add it twice. + +cleanup_bearer() runs from a workqueue after tipc_udp_disable() clears the +bearer's up bit, so an encap softirq can still reach tipc_udp_rcast_add() +and add a peer after cleanup_bearer() has already emptied the list, leaking +that entry when the bearer is freed. Mark the bearer disabled under +rcast_lock once the list is emptied and refuse further additions. + +Fixes: ef20cd4dd163 ("tipc: introduce UDP replicast") +Reported-by: Xiang Mei +Suggested-by: Tung Nguyen +Signed-off-by: Weiming Shi +Reviewed-by: Tung Nguyen +Link: https://patch.msgid.link/20260716025203.9332-2-bestswngs@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/udp_media.c | 56 +++++++++++++++++++++----------------------- + 1 file changed, 27 insertions(+), 29 deletions(-) + +diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c +index 62ae7f5b58409c..230645cc01c921 100644 +--- a/net/tipc/udp_media.c ++++ b/net/tipc/udp_media.c +@@ -94,6 +94,8 @@ struct udp_replicast { + * @ifindex: local address scope + * @work: used to schedule deferred work on a bearer + * @rcast: associated udp_replicast container ++ * @rcast_lock: serialize updates to @rcast.list against concurrent updaters ++ * @disabled: bearer is being torn down; reject further @rcast.list additions + */ + struct udp_bearer { + struct tipc_bearer __rcu *bearer; +@@ -101,6 +103,8 @@ struct udp_bearer { + u32 ifindex; + struct work_struct work; + struct udp_replicast rcast; ++ spinlock_t rcast_lock; ++ bool disabled; + }; + + static int tipc_udp_is_mcast_addr(struct udp_media_addr *addr) +@@ -278,26 +282,6 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb, + return err; + } + +-static bool tipc_udp_is_known_peer(struct tipc_bearer *b, +- struct udp_media_addr *addr) +-{ +- struct udp_replicast *rcast, *tmp; +- struct udp_bearer *ub; +- +- ub = rcu_dereference_rtnl(b->media_ptr); +- if (!ub) { +- pr_err_ratelimited("UDP bearer instance not found\n"); +- return false; +- } +- +- list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) { +- if (!memcmp(&rcast->addr, addr, sizeof(struct udp_media_addr))) +- return true; +- } +- +- return false; +-} +- + static int tipc_udp_rcast_add(struct tipc_bearer *b, + struct udp_media_addr *addr) + { +@@ -308,16 +292,34 @@ static int tipc_udp_rcast_add(struct tipc_bearer *b, + if (!ub) + return -ENODEV; + ++ spin_lock_bh(&ub->rcast_lock); ++ if (ub->disabled) { ++ spin_unlock_bh(&ub->rcast_lock); ++ return 0; ++ } ++ list_for_each_entry(rcast, &ub->rcast.list, list) { ++ if (!memcmp(&rcast->addr, addr, sizeof(*addr))) { ++ spin_unlock_bh(&ub->rcast_lock); ++ return 0; ++ } ++ } ++ + rcast = kmalloc_obj(*rcast, GFP_ATOMIC); +- if (!rcast) ++ if (!rcast) { ++ spin_unlock_bh(&ub->rcast_lock); + return -ENOMEM; ++ } + + if (dst_cache_init(&rcast->dst_cache, GFP_ATOMIC)) { ++ spin_unlock_bh(&ub->rcast_lock); + kfree(rcast); + return -ENOMEM; + } + + memcpy(&rcast->addr, addr, sizeof(struct udp_media_addr)); ++ list_add_rcu(&rcast->list, &ub->rcast.list); ++ b->bcast_addr.broadcast = TIPC_REPLICAST_SUPPORT; ++ spin_unlock_bh(&ub->rcast_lock); + + if (ntohs(addr->proto) == ETH_P_IP) + pr_info("New replicast peer: %pI4\n", &rcast->addr.ipv4); +@@ -325,8 +327,6 @@ static int tipc_udp_rcast_add(struct tipc_bearer *b, + else if (ntohs(addr->proto) == ETH_P_IPV6) + pr_info("New replicast peer: %pI6\n", &rcast->addr.ipv6); + #endif +- b->bcast_addr.broadcast = TIPC_REPLICAST_SUPPORT; +- list_add_rcu(&rcast->list, &ub->rcast.list); + return 0; + } + +@@ -361,9 +361,6 @@ static int tipc_udp_rcast_disc(struct tipc_bearer *b, struct sk_buff *skb) + return 0; + } + +- if (likely(tipc_udp_is_known_peer(b, &src))) +- return 0; +- + return tipc_udp_rcast_add(b, &src); + } + +@@ -644,9 +641,6 @@ int tipc_udp_nl_bearer_add(struct tipc_bearer *b, struct nlattr *attr) + return -EINVAL; + } + +- if (tipc_udp_is_known_peer(b, &addr)) +- return 0; +- + return tipc_udp_rcast_add(b, &addr); + } + +@@ -679,6 +673,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b, + return -ENOMEM; + + INIT_LIST_HEAD(&ub->rcast.list); ++ spin_lock_init(&ub->rcast_lock); + + if (!attrs[TIPC_NLA_BEARER_UDP_OPTS]) + goto err; +@@ -819,10 +814,13 @@ static void cleanup_bearer(struct work_struct *work) + struct udp_replicast *rcast, *tmp; + struct tipc_net *tn; + ++ spin_lock_bh(&ub->rcast_lock); + list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) { + list_del_rcu(&rcast->list); + call_rcu_hurry(&rcast->rcu, rcast_free_rcu); + } ++ ub->disabled = true; ++ spin_unlock_bh(&ub->rcast_lock); + + tn = tipc_net(sock_net(ub->sk)); + +-- +2.53.0 + diff --git a/queue-7.1/tls-device-push-pending-open-record-on-splice-eof.patch b/queue-7.1/tls-device-push-pending-open-record-on-splice-eof.patch new file mode 100644 index 0000000000..cc00063a1a --- /dev/null +++ b/queue-7.1/tls-device-push-pending-open-record-on-splice-eof.patch @@ -0,0 +1,56 @@ +From d7e6a756c9ecdb12de4f556160c03f39a61ddd5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 Jul 2026 16:44:36 -0600 +Subject: tls: device: push pending open record on splice EOF + +From: Rishikesh Jethwani + +[ Upstream commit eaa39f9f8ac8c1d032cd26b9cd572804e9d7683f ] + +On kTLS device-offload sockets, sendfile() with count > EOF can reach +->splice_eof() with a fully assembled but still-open TLS record left +pending. tls_device_splice_eof() only flushes partially sent records, +so an abrupt close() can drop the final record and the peer receives +a short file. + +Fix tls_device_splice_eof() to also push pending open records. +This matches the software path, where splice EOF already flushes +pending open records. + +Fixes: d4c1e80b0d1b ("tls/device: Use splice_eof() to flush") +Link: https://lore.kernel.org/netdev/CAMPsyauZ+jzG9AysO0FWv6ZY0kvCUpjX_U7o=oOjCuOQ87BCgg@mail.gmail.com/ +Reported-by: Nils Juenemann +Signed-off-by: Rishikesh Jethwani +Tested-by: Nils Juenemann +Link: https://patch.msgid.link/20260709224436.1608993-2-rjethwani@purestorage.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tls/tls_device.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c +index 99c8eff9783e68..33c42f65364a22 100644 +--- a/net/tls/tls_device.c ++++ b/net/tls/tls_device.c +@@ -595,13 +595,15 @@ void tls_device_splice_eof(struct socket *sock) + struct tls_context *tls_ctx = tls_get_ctx(sk); + struct iov_iter iter = {}; + +- if (!tls_is_partially_sent_record(tls_ctx)) ++ if (!tls_is_partially_sent_record(tls_ctx) && ++ !tls_is_pending_open_record(tls_ctx)) + return; + + mutex_lock(&tls_ctx->tx_lock); + lock_sock(sk); + +- if (tls_is_partially_sent_record(tls_ctx)) { ++ if (tls_is_partially_sent_record(tls_ctx) || ++ tls_is_pending_open_record(tls_ctx)) { + iov_iter_bvec(&iter, ITER_SOURCE, NULL, 0, 0); + tls_push_data(sk, &iter, 0, 0, TLS_RECORD_TYPE_DATA); + } +-- +2.53.0 + diff --git a/queue-7.1/tracing-fix-use-after-free-freeing-trigger-private-d.patch b/queue-7.1/tracing-fix-use-after-free-freeing-trigger-private-d.patch new file mode 100644 index 0000000000..92a967c031 --- /dev/null +++ b/queue-7.1/tracing-fix-use-after-free-freeing-trigger-private-d.patch @@ -0,0 +1,142 @@ +From 544e94409d79b5b10a5c733ec313447900c593d3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 24 Jul 2026 04:05:17 +0100 +Subject: tracing: Fix use-after-free freeing trigger private data + +From: David Carlier + +[ Upstream commit 79097812153b826fc156a2930ec8a90ed9edf4a2 ] + +Commit 61d445af0a7c ("tracing: Add bulk garbage collection of freeing +event_trigger_data") moved the kfree() of event_trigger_data to a kthread +that runs tracepoint_synchronize_unregister() before freeing. That removed +the synchronization the trigger .free callbacks used to get implicitly and +inline from trigger_data_free(). + +event_hist_trigger_free(), event_hist_trigger_named_free() and +event_enable_trigger_free() free their satellite data (hist_data, cmd_ops, +enable_data) right after trigger_data_free() returns. With the +synchronization now deferred to the kthread, a concurrent tracepoint +handler can still reach that data through the list_del_rcu()'d trigger, +causing a use-after-free. + +The histogram teardown must stay synchronous: remove_hist_vars() and +unregister_field_var_hists() have to detach a synthetic event from the +histogram before the trigger-removal write returns, otherwise a following +command races in and the synthetic-event removal fails with -EBUSY, as the +trigger-synthetic-eprobe.tc selftest catches. Make those callbacks wait +with the correct barrier - tracepoint_synchronize_unregister(), matching +the free kthread - before freeing. + +The enable trigger has no such synchronous requirement, and a blocking +synchronize there would re-serialize the path that commit deliberately +deferred. Give it an optional private_data_free() callback that the free +kthread runs after its grace period, and free enable_data from there. + +Link: https://patch.msgid.link/20260724030523.19081-1-devnexen@gmail.com +Suggested-by: Masami Hiramatsu (Google) +Suggested-by: Steven Rostedt +Fixes: 61d445af0a7c ("tracing: Add bulk garbage collection of freeing event_trigger_data") +Signed-off-by: David Carlier +Signed-off-by: Steven Rostedt +Signed-off-by: Sasha Levin +--- + kernel/trace/trace.h | 1 + + kernel/trace/trace_events_hist.c | 2 ++ + kernel/trace/trace_events_trigger.c | 18 +++++++++++++++--- + 3 files changed, 18 insertions(+), 3 deletions(-) + +diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h +index 80fe152af1dd84..bf77331f56a4dd 100644 +--- a/kernel/trace/trace.h ++++ b/kernel/trace/trace.h +@@ -1941,6 +1941,7 @@ struct event_trigger_data { + struct list_head named_list; + struct event_trigger_data *named_data; + struct llist_node llist; ++ void (*private_data_free)(struct event_trigger_data *data); + }; + + /* Avoid typos */ +diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c +index 9701650c89b2f2..e287dad25fc39f 100644 +--- a/kernel/trace/trace_events_hist.c ++++ b/kernel/trace/trace_events_hist.c +@@ -6358,6 +6358,7 @@ static void event_hist_trigger_free(struct event_trigger_data *data) + + trigger_data_free(data); + ++ tracepoint_synchronize_unregister(); + remove_hist_vars(hist_data); + + unregister_field_var_hists(hist_data); +@@ -6397,6 +6398,7 @@ static void event_hist_trigger_named_free(struct event_trigger_data *data) + + del_named_trigger(data); + trigger_data_free(data); ++ tracepoint_synchronize_unregister(); + kfree(cmd_ops); + } + } +diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c +index 655db2e8251349..46e60b70a4bbc4 100644 +--- a/kernel/trace/trace_events_trigger.c ++++ b/kernel/trace/trace_events_trigger.c +@@ -38,6 +38,13 @@ static void trigger_create_kthread_locked(void) + } + } + ++static void trigger_data_free_one(struct event_trigger_data *data) ++{ ++ if (data->private_data_free) ++ data->private_data_free(data); ++ kfree(data); ++} ++ + static void trigger_data_free_queued_locked(void) + { + struct event_trigger_data *data, *tmp; +@@ -52,7 +59,7 @@ static void trigger_data_free_queued_locked(void) + tracepoint_synchronize_unregister(); + + llist_for_each_entry_safe(data, tmp, llnodes, llist) +- kfree(data); ++ trigger_data_free_one(data); + } + + /* Bulk garbage collection of event_trigger_data elements */ +@@ -75,7 +82,7 @@ static int trigger_kthread_fn(void *ignore) + tracepoint_synchronize_unregister(); + + llist_for_each_entry_safe(data, tmp, llnodes, llist) +- kfree(data); ++ trigger_data_free_one(data); + } + + return 0; +@@ -1717,6 +1724,11 @@ int event_enable_trigger_print(struct seq_file *m, + return 0; + } + ++static void enable_trigger_private_data_free(struct event_trigger_data *data) ++{ ++ kfree(data->private_data); ++} ++ + void event_enable_trigger_free(struct event_trigger_data *data) + { + struct enable_trigger_data *enable_data = data->private_data; +@@ -1728,9 +1740,9 @@ void event_enable_trigger_free(struct event_trigger_data *data) + if (!data->ref) { + /* Remove the SOFT_MODE flag */ + trace_event_enable_disable(enable_data->file, 0, 1); ++ data->private_data_free = enable_trigger_private_data_free; + trace_event_put_ref(enable_data->file->event_call); + trigger_data_free(data); +- kfree(enable_data); + } + } + +-- +2.53.0 + diff --git a/queue-7.1/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch b/queue-7.1/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch new file mode 100644 index 0000000000..a5576d88e0 --- /dev/null +++ b/queue-7.1/usb-atm-ueagle-atm-reject-descriptors-that-confuse-p.patch @@ -0,0 +1,93 @@ +From 177a0bb8d50241fae0756f2e8db52da7c700bf64 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 02:07:04 -0600 +Subject: usb: atm: ueagle-atm: reject descriptors that confuse probe and + disconnect + +From: Diego Fernando Mancera Gomez + +[ Upstream commit 71132cedd1ecbc4032d76e9928c18a10f7e39b80 ] + +uea_probe() distinguishes a pre-firmware device from a post-firmware one +using the USB id (UEA_IS_PREFIRM()), and stores a different object as the +interface data in each case: a 'struct completion' for a pre-firmware +device (to be waited on in .disconnect()), or a 'struct usbatm_data' for a +post-firmware one. + +uea_disconnect() instead tells the two apart by the number of interfaces +of the active configuration (a pre-firmware device exposes a single +interface, ADI930 has 2 and eagle has 3), and casts the interface data +accordingly. + +Because the two handlers use different criteria, a crafted device that +advertises a pre-firmware id together with a multi-interface descriptor +(or a post-firmware id with a single interface) makes them disagree: the +small 'struct completion' stored by uea_probe() is then passed to +usbatm_usb_disconnect(), which casts it to 'struct usbatm_data' and takes +instance->serialize, reading past the end of the allocation: + + BUG: KASAN: slab-out-of-bounds in __mutex_lock+0x152a/0x1b80 + Read of size 8 at addr ffff8880470e2c60 by task kworker/1:2/982 + ... + __mutex_lock+0x152a/0x1b80 + usbatm_usb_disconnect+0x70/0x820 + uea_disconnect+0x133/0x2c0 + usb_unbind_interface+0x1dd/0x9e0 + ... + which belongs to the cache kmalloc-96 of size 96 + The buggy address is located 0 bytes to the right of + allocated 96-byte region [ffff8880470e2c00, ffff8880470e2c60) + +Reject such inconsistent descriptors in uea_probe() so that both handlers +always make the same pre/post-firmware decision. + +Reported-by: syzbot+e62a973f8322b3bbe3ac@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=e62a973f8322b3bbe3ac +Fixes: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()") +Signed-off-by: Diego Fernando Mancera Gomez +Acked-by: Stanislaw Gruszka +Link: https://patch.msgid.link/20260717080704.1264-1-diegomancera.dev@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/atm/ueagle-atm.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c +index 1e12fc19f8726d..ee77c38f4ed145 100644 +--- a/drivers/usb/atm/ueagle-atm.c ++++ b/drivers/usb/atm/ueagle-atm.c +@@ -2551,6 +2551,7 @@ static struct usbatm_driver uea_usbatm_driver = { + static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + { + struct usb_device *usb = interface_to_usbdev(intf); ++ bool single_iface = usb->config->desc.bNumInterfaces == 1; + int ret; + + uea_dbg(usb, "ADSL device found with vid (%#X) pid (%#X) Rev (%#X): %s\n", +@@ -2559,6 +2560,22 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) + le16_to_cpu(usb->descriptor.bcdDevice), + chip_name[UEA_CHIP_VERSION(id)]); + ++ /* ++ * uea_probe() decides between the pre-firmware and post-firmware case ++ * from the USB id and stores a different object as interface data in ++ * each case: a struct completion for a pre-firmware device, a struct ++ * usbatm_data for a post-firmware one. uea_disconnect() instead tells ++ * the two apart by the number of interfaces (a pre-firmware device ++ * exposes a single interface, ADI930 has 2 and eagle has 3). A crafted ++ * device advertising a pre-firmware id together with a multi-interface ++ * descriptor (or the other way around) makes the two disagree, so that ++ * usbatm_usb_disconnect() treats the small completion object as a ++ * struct usbatm_data and reads out of bounds. Reject such inconsistent ++ * descriptors so both paths make the same decision. ++ */ ++ if (UEA_IS_PREFIRM(id) != single_iface) ++ return -ENODEV; ++ + usb_reset_device(usb); + + if (UEA_IS_PREFIRM(id)) { +-- +2.53.0 + diff --git a/queue-7.1/vhost-net-fix-tx-stall-when-vhost-owns-virtio-net-he.patch b/queue-7.1/vhost-net-fix-tx-stall-when-vhost-owns-virtio-net-he.patch new file mode 100644 index 0000000000..cb8be53166 --- /dev/null +++ b/queue-7.1/vhost-net-fix-tx-stall-when-vhost-owns-virtio-net-he.patch @@ -0,0 +1,58 @@ +From cb8db9e64d2f3adba605ffe9465fcffb4642912d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:22:42 +0100 +Subject: vhost-net: fix TX stall when vhost owns virtio-net header + +From: Enrico Zanda + +[ Upstream commit 3c0d10f233f19153f81fef685b5c6716776a5af3 ] + +When vhost owns the virtio-net header, i.e. when +VHOST_NET_F_VIRTIO_NET_HDR is negotiated, sock_hlen is 0, +meaning that no header will be forwarded to the TAP device. + +In the current vhost_net_build_xdp() implementation, +when sock_hlen == 0, the gso pointer can point at the start of the +Ethernet frame instead of a virtio-net header. +This results in a wrong interpretation of the destination MAC address +bytes as struct virtio_net_hdr fields. + +This can, for some MAC addresses, trigger -EINVAL and return early +before the TX descriptor is completed, which can stall vhost-net TX. + +Before 97b2409f28e0, the gso pointer was set to the zeroed padding area, +using it as a synthetic virtio-net header. Restore that behavior. + +Fixes: 97b2409f28e0 ("vhost-net: reduce one userspace copy when building XDP buff") +Signed-off-by: Enrico Zanda +Acked-by: Michael S. Tsirkin +Link: https://patch.msgid.link/20260708152242.2268848-1-enrico.zanda@arm.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/vhost/net.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c +index b9af63fb630602..6949b704166d58 100644 +--- a/drivers/vhost/net.c ++++ b/drivers/vhost/net.c +@@ -722,10 +722,12 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, + goto err; + } + +- gso = buf + pad - sock_hlen; +- +- if (!sock_hlen) ++ if (!sock_hlen) { + memset(buf, 0, pad); ++ gso = buf; ++ } else { ++ gso = buf + pad - sock_hlen; ++ } + + if ((gso->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && + vhost16_to_cpu(vq, gso->csum_start) + +-- +2.53.0 + diff --git a/queue-7.1/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch b/queue-7.1/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch new file mode 100644 index 0000000000..3e32ec0a70 --- /dev/null +++ b/queue-7.1/vmxnet3-fix-bug_on-in-vmxnet3_get_hdr_len-for-geneve.patch @@ -0,0 +1,84 @@ +From 846f420f6cdfb9c237ca5f349cd7464428f42c0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jul 2026 07:09:15 -0700 +Subject: vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets + +From: Harshaka Narayana + +[ Upstream commit 34a71f5361fc3adb5b7138da78750b0d535a8252 ] + +vmxnet3_get_hdr_len() assumes gdesc->rcd.v4/v6/tcp always describe the +outer header, but for a Geneve-encapsulated packet the device can set +them based on the inner header instead, signalled by the +VMXNET3_RCD_HDR_INNER_SHIFT bit in the completion descriptor. Since the +function never skips the outer encapsulation, this mismatch triggers: + +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP), because the outer + protocol is UDP (Geneve), not TCP. +- BUG_ON(hdr.eth->h_proto != ...), when the tunnel's outer and inner + IP versions differ (e.g. outer IPv6/inner IPv4 or vice versa). + +Check VMXNET3_RCD_HDR_INNER_SHIFT up front and bail out, since the +function cannot locate the inner header it would need to parse. Also +convert the remaining BUG_ON()s in this function to return 0 +defensively. + +Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)") +Signed-off-by: Harshaka Narayana +Reviewed-by: Ronak Doshi +Reviewed-by: Sankararaman Jayaraman +Reviewed-by: Simon Horman +Link: https://patch.msgid.link/20260713140915.3381715-1-harshaka.narayana@broadcom.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c +index 40522afc053203..f8df83f9965db5 100644 +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -1530,7 +1530,11 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + struct ipv6hdr *ipv6; + struct tcphdr *tcp; + } hdr; +- BUG_ON(gdesc->rcd.tcp == 0); ++ ++ /* v4/v6/tcp then describe the inner header, which we can't locate. */ ++ if ((le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT)) || ++ gdesc->rcd.tcp == 0) ++ return 0; + + maplen = skb_headlen(skb); + if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen)) +@@ -1544,15 +1548,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, + + hdr.eth = eth_hdr(skb); + if (gdesc->rcd.v4) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)); ++ if (hdr.eth->h_proto != htons(ETH_P_IP) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP)) ++ return 0; ++ + hdr.ptr += hlen; +- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP); ++ if (hdr.ipv4->protocol != IPPROTO_TCP) ++ return 0; ++ + hlen = hdr.ipv4->ihl << 2; + hdr.ptr += hdr.ipv4->ihl << 2; + } else if (gdesc->rcd.v6) { +- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) && +- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)); ++ if (hdr.eth->h_proto != htons(ETH_P_IPV6) && ++ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6)) ++ return 0; ++ + hdr.ptr += hlen; + /* Use an estimated value, since we also need to handle + * TSO case. +-- +2.53.0 + diff --git a/queue-7.1/wan-wanxl-only-reset-hardware-after-bar-mapping.patch b/queue-7.1/wan-wanxl-only-reset-hardware-after-bar-mapping.patch new file mode 100644 index 0000000000..6f4603f0c1 --- /dev/null +++ b/queue-7.1/wan-wanxl-only-reset-hardware-after-bar-mapping.patch @@ -0,0 +1,51 @@ +From a62b3491c73a0def3a3081065b3e46426bb1ffce Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 22:34:15 +0800 +Subject: wan: wanxl: Only reset hardware after BAR mapping + +From: Ruoyu Wang + +[ Upstream commit 91957b89da995607cb654b1f9a3c126ddbaee10f ] + +wanxl_pci_init_one() stores the freshly allocated card in driver data +before the PLX BAR is mapped. Several early probe failures then unwind +through wanxl_pci_remove_one(), including failure to allocate the coherent +status area or to restore the DMA mask. + +wanxl_pci_remove_one() unconditionally calls wanxl_reset(), and +wanxl_reset() dereferences card->plx. On those early failures card->plx +is still NULL, so the error path can dereference a NULL MMIO pointer. + +Only issue the hardware reset once the BAR mapping exists. The remaining +cleanup in wanxl_pci_remove_one() already checks whether later resources +were allocated. + +This issue was found by a static analysis checker and confirmed by +manual source review. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Ruoyu Wang +Link: https://patch.msgid.link/20260708143415.3169358-1-ruoyuw560@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/wan/wanxl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c +index 3f770711845053..8790251feb7d6d 100644 +--- a/drivers/net/wan/wanxl.c ++++ b/drivers/net/wan/wanxl.c +@@ -514,7 +514,8 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev) + if (card->irq) + free_irq(card->irq, card); + +- wanxl_reset(card); ++ if (card->plx) ++ wanxl_reset(card); + + for (i = 0; i < RX_QUEUE_LENGTH; i++) + if (card->rx_skbs[i]) { +-- +2.53.0 + diff --git a/queue-7.1/watchdog-airoha-prevent-division-by-zero-when-clock-.patch b/queue-7.1/watchdog-airoha-prevent-division-by-zero-when-clock-.patch new file mode 100644 index 0000000000..27a3aad406 --- /dev/null +++ b/queue-7.1/watchdog-airoha-prevent-division-by-zero-when-clock-.patch @@ -0,0 +1,46 @@ +From fcb69c6684cd24409f6e46e3534309125f947c56 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 10:41:54 +0800 +Subject: watchdog: airoha: Prevent division by zero when clock frequency is + zero + +From: Wayen Yan + +[ Upstream commit bcfcd7619f277842430d197556463b401b839ee9 ] + +clk_get_rate() can return 0 when the clock provider is not properly +configured or the clock is unmanaged. The driver uses wdt_freq as a +divisor directly in airoha_wdt_probe() to compute max_timeout and in +airoha_wdt_get_timeleft() to compute the remaining time, which results +in a division by zero. + +Add a check for wdt_freq == 0 in probe and return -EINVAL with +dev_err_probe() to prevent the division by zero and provide a +diagnostic message. + +Fixes: 3cf67f3769b8 ("watchdog: Add support for Airoha EN7851 watchdog") +Signed-off-by: Wayen Yan +Link: https://lore.kernel.org/r/178347932594.81327.4834644880399144119@gmail.com +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/airoha_wdt.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/watchdog/airoha_wdt.c b/drivers/watchdog/airoha_wdt.c +index dc8ca11c14d81a..4bd333189b87ec 100644 +--- a/drivers/watchdog/airoha_wdt.c ++++ b/drivers/watchdog/airoha_wdt.c +@@ -147,6 +147,9 @@ static int airoha_wdt_probe(struct platform_device *pdev) + + /* Watchdog ticks at half the bus rate */ + airoha_wdt->wdt_freq = clk_get_rate(bus_clk) / 2; ++ if (!airoha_wdt->wdt_freq) ++ return dev_err_probe(dev, -EINVAL, ++ "invalid clock frequency\n"); + + /* Initialize struct watchdog device */ + wdog_dev = &airoha_wdt->wdog_dev; +-- +2.53.0 + diff --git a/queue-7.1/watchdog-ni903x_wdt-check-acpi_companion-against-nul.patch b/queue-7.1/watchdog-ni903x_wdt-check-acpi_companion-against-nul.patch new file mode 100644 index 0000000000..bcfcbc8fc8 --- /dev/null +++ b/queue-7.1/watchdog-ni903x_wdt-check-acpi_companion-against-nul.patch @@ -0,0 +1,58 @@ +From bfa2e556c786840c40334d74ad4dac39017a7aab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 May 2026 18:22:57 +0200 +Subject: watchdog: ni903x_wdt: Check ACPI_COMPANION() against NULL + +From: Rafael J. Wysocki + +[ Upstream commit 36e05e134ee44f9fbfcebcbcdadb5f765fccd9f0 ] + +Every platform driver can be forced to match a device that doesn't match +its list of device IDs because of device_match_driver_override(), so +platform drivers that rely on the existence of a device's ACPI companion +object need to verify its presence. + +Accordingly, add a requisite ACPI_COMPANION() check against NULL to the +ni903x_wdt watchdog driver. + +Fixes: d37ec2fbab55 ("watchdog: ni903x_wdt: Convert to a platform driver") +Signed-off-by: Rafael J. Wysocki +Reviewed-by: Andy Shevchenko +Link: https://lore.kernel.org/r/2280455.irdbgypaU6@rafael.j.wysocki +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/ni903x_wdt.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/drivers/watchdog/ni903x_wdt.c b/drivers/watchdog/ni903x_wdt.c +index 8b1b9baa914e5f..c72a9ee9cb8e19 100644 +--- a/drivers/watchdog/ni903x_wdt.c ++++ b/drivers/watchdog/ni903x_wdt.c +@@ -183,9 +183,14 @@ static int ni903x_acpi_probe(struct platform_device *pdev) + struct device *dev = &pdev->dev; + struct watchdog_device *wdd; + struct ni903x_wdt *wdt; ++ acpi_handle handle; + acpi_status status; + int ret; + ++ handle = ACPI_HANDLE(dev); ++ if (!handle) ++ return -ENODEV; ++ + wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL); + if (!wdt) + return -ENOMEM; +@@ -193,7 +198,7 @@ static int ni903x_acpi_probe(struct platform_device *pdev) + platform_set_drvdata(pdev, wdt); + wdt->dev = dev; + +- status = acpi_walk_resources(ACPI_HANDLE(dev), METHOD_NAME__CRS, ++ status = acpi_walk_resources(handle, METHOD_NAME__CRS, + ni903x_resources, wdt); + if (ACPI_FAILURE(status) || wdt->io_base == 0) { + dev_err(dev, "failed to get resources\n"); +-- +2.53.0 + diff --git a/queue-7.1/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch b/queue-7.1/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch new file mode 100644 index 0000000000..710b85966b --- /dev/null +++ b/queue-7.1/watchdog-pretimeout-fix-uaf-in-watchdog_unregister_g.patch @@ -0,0 +1,48 @@ +From de5c86638504a2f365c1dca4bf9f3eac9e521da6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Jul 2026 10:18:03 +0000 +Subject: watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() + +From: Tzung-Bi Shih + +[ Upstream commit 7362ba0f9c96ac3ad6a2ca3995bd9fc9a28a8661 ] + +When a watchdog governor is unregistered, it updates existing watchdog +devices that were using this governor by falling back to `default_gov`. + +If the governor being unregistered is currently set as `default_gov`, +the `default_gov` is never cleared. This leads to 2 use-after-free +issues: +1. New watchdog devices registered after this point will inherit the + dangling `default_gov`. +2. Existing watchdog devices using the unregistered governor will have + their `wdd->gov` reassigned to the dangling `default_gov`. + +Fix the UAF by clearing `default_gov` if it matches the governor being +unregistered. + +Fixes: da0d12ff2b82 ("watchdog: pretimeout: add panic pretimeout governor") +Signed-off-by: Tzung-Bi Shih +Link: https://lore.kernel.org/r/20260707101803.3598173-1-tzungbi@kernel.org +Signed-off-by: Guenter Roeck +Signed-off-by: Sasha Levin +--- + drivers/watchdog/watchdog_pretimeout.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c +index 19eb2ed2c7cb0e..02e09b9e396dab 100644 +--- a/drivers/watchdog/watchdog_pretimeout.c ++++ b/drivers/watchdog/watchdog_pretimeout.c +@@ -167,6 +167,8 @@ void watchdog_unregister_governor(struct watchdog_governor *gov) + } + + spin_lock_irq(&pretimeout_lock); ++ if (default_gov == gov) ++ default_gov = NULL; + list_for_each_entry(p, &pretimeout_list, entry) + if (p->wdd->gov == gov) + p->wdd->gov = default_gov; +-- +2.53.0 + diff --git a/queue-7.1/wifi-ath10k-fix-skb-leak-on-incomplete-msdu-during-r.patch b/queue-7.1/wifi-ath10k-fix-skb-leak-on-incomplete-msdu-during-r.patch new file mode 100644 index 0000000000..209f6a8e1f --- /dev/null +++ b/queue-7.1/wifi-ath10k-fix-skb-leak-on-incomplete-msdu-during-r.patch @@ -0,0 +1,56 @@ +From 1dc006a4cbccf93cb8000bc02439cbe8b08ae80e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 12:13:55 +0530 +Subject: wifi: ath10k: fix skb leak on incomplete msdu during rx pop + +From: Manikanta Pubbisetty + +[ Upstream commit 7393878255e492515858f751ba4c260f248fb108 ] + +When ath10k_htt_rx_pop_paddr32_list() or +ath10k_htt_rx_pop_paddr64_list() encounters an incomplete frame +(RX_ATTENTION_FLAGS_MSDU_DONE not set), it returns -EIO without +purging the skb list built up so far, leaking any skbs already +queued in the list. + +Other early-exit paths within these same functions already call +__skb_queue_purge() before returning an error. Add it before the +-EIO return as well to be consistent and prevent the leak. + +Tested-on: WCN3990 hw1.0 WLAN.HL.3.2.2.c10-00754-QCAHLSWMTPL-1 + +Fixes: c545070e404b ("ath10k: implement rx reorder support") +Fixes: 3b0b55b19d1d ("ath10k: Add support for 64 bit HTT in-order indication msg") +Signed-off-by: Manikanta Pubbisetty +Reviewed-by: Rameshkumar Sundaram +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20260623064355.1876743-1-manikanta.pubbisetty@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath10k/htt_rx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c +index 25ab945fecef2c..8f88ea116a32c7 100644 +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -707,6 +707,7 @@ static int ath10k_htt_rx_pop_paddr32_list(struct ath10k_htt *htt, + if (!(__le32_to_cpu(rxd_attention->flags) & + RX_ATTENTION_FLAGS_MSDU_DONE)) { + ath10k_warn(htt->ar, "tried to pop an incomplete frame, oops!\n"); ++ __skb_queue_purge(list); + return -EIO; + } + } +@@ -771,6 +772,7 @@ static int ath10k_htt_rx_pop_paddr64_list(struct ath10k_htt *htt, + if (!(__le32_to_cpu(rxd_attention->flags) & + RX_ATTENTION_FLAGS_MSDU_DONE)) { + ath10k_warn(htt->ar, "tried to pop an incomplete frame, oops!\n"); ++ __skb_queue_purge(list); + return -EIO; + } + } +-- +2.53.0 + diff --git a/queue-7.1/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch b/queue-7.1/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch new file mode 100644 index 0000000000..10f1c78069 --- /dev/null +++ b/queue-7.1/wifi-ath11k-fix-null-pointer-dereference-in-ath11k_h.patch @@ -0,0 +1,68 @@ +From 711e92cd4aa00a224de3b46efc936e33f67df642 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jun 2026 17:06:09 +0800 +Subject: wifi: ath11k: fix NULL pointer dereference in + ath11k_hal_srng_access_begin + +From: Gaole Zhang + +[ Upstream commit e8d85672dd7e2523f774caafba8f858384e18df7 ] + +In ATH11K_QMI_EVENT_FW_READY, ATH11K_FLAG_REGISTERED is set +unconditionally even when ath11k_core_qmi_firmware_ready() fails. +This leaves the driver in an inconsistent state where +initialization is considered complete although the firmware ready +handling did not finish successfully. During the subsequent SSR, +the driver enters the restart path based on this incorrect state +and dereferences uninitialized srng members, resulting in a NULL +pointer dereference. + +Call trace: + ath11k_hal_srng_access_begin+0xc/0x60 [ath11k] (P) + ath11k_ce_cleanup_pipes+0x17c/0x180 [ath11k] + ath11k_core_restart+0x40/0x168 [ath11k] + +Fix this by: +- skipping firmware_ready if ATH11K_FLAG_REGISTERED is already set +- setting ATH11K_FLAG_REGISTERED only when firmware_ready succeeds +- setting ATH11K_FLAG_QMI_FAIL and aborting the FW_READY handling +on error + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.2.0.c2-00204-QCAMSLSWPLZ-1 + +Fixes: 6fe62a8cec51c ("wifi: ath11k: Add cold boot calibration support on WCN6750") +Signed-off-by: Gaole Zhang +Reviewed-by: Baochen Qiang +Reviewed-by: Rameshkumar Sundaram +Link: https://patch.msgid.link/20260609090609.4041009-1-gaole.zhang@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/qmi.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c +index feebbc30f3df32..a304feca70423e 100644 +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -3295,9 +3295,14 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work) + clear_bit(ATH11K_FLAG_CRASH_FLUSH, + &ab->dev_flags); + clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); +- ath11k_core_qmi_firmware_ready(ab); +- set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); +- ++ if (!test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) { ++ ret = ath11k_core_qmi_firmware_ready(ab); ++ if (ret) { ++ set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags); ++ break; ++ } ++ set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags); ++ } + break; + case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE: + break; +-- +2.53.0 + diff --git a/queue-7.1/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch b/queue-7.1/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch new file mode 100644 index 0000000000..cf99a5a278 --- /dev/null +++ b/queue-7.1/wifi-ath11k-fix-potential-buffer-underflow-in-ath11k.patch @@ -0,0 +1,48 @@ +From 2a0a6db63226535e7fb6ab477032a39c7dcbd66c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 May 2026 11:42:52 +0000 +Subject: wifi: ath11k: fix potential buffer underflow in + ath11k_hal_rx_msdu_list_get() + +From: Dmitry Morgun + +[ Upstream commit 7f11e70629650ff6ea140984e5ce188b775b2683 ] + +When the first entry in msdu_details has a zero buffer address, +the code accesses msdu_details[i - 1] with i == 0, causing a +buffer underflow. + +Fix similarly to ath12k_wifi7_hal_rx_msdu_list_get() by adding +a separate check for i == 0 before the main condition to prevent +the out-of-bounds access. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices") +Signed-off-by: Dmitry Morgun +Reviewed-by: Rameshkumar Sundaram +Reviewed-by: Baochen Qiang +Link: https://patch.msgid.link/20260530114252.42615-1-d.morgun@ispras.ru +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c +index 2a413e3a07a78c..c9f520c2a93583 100644 +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -4565,6 +4565,9 @@ static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar, + msdu_details = &msdu_link->msdu_link[0]; + + for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) { ++ if (!i && FIELD_GET(BUFFER_ADDR_INFO0_ADDR, ++ msdu_details[i].buf_addr_info.info0) == 0) ++ break; + if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR, + msdu_details[i].buf_addr_info.info0) == 0) { + msdu_desc_info = &msdu_details[i - 1].rx_msdu_info; +-- +2.53.0 + diff --git a/queue-7.1/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch b/queue-7.1/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch new file mode 100644 index 0000000000..6d38a23c76 --- /dev/null +++ b/queue-7.1/wifi-ath11k-flush-the-posted-write-after-writing-to-.patch @@ -0,0 +1,60 @@ +From d0e0f8dccd63f9d1311119475e3eb48a13efa1c8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 16:16:48 +0200 +Subject: wifi: ath11k: Flush the posted write after writing to + PCIE_SOC_GLOBAL_RESET + +From: Manivannan Sadhasivam + +[ Upstream commit 0fe8010fc5b147607fc19ba010ba469afc95f35f ] + +ath11k_pci_soc_global_reset() tries to reset the device by writing to the +PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure +that the write gets flushed to the device before the delay. + +This may lead to the delay on the host to be insufficient, if the posted +write doesn't reach the device before the delay. + +So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and +before the delay. + +Compile tested only. + +Fixes: f3c603d412b3 ("ath11k: reset MHI during power down and power up") +Reported-by: Alex Williamson +Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Reviewed-by: Raj Kumar Bhagat +Link: https://patch.msgid.link/20260623141649.41087-1-manivannan.sadhasivam@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath11k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c +index 35bb9e7a63a207..a163168f361764 100644 +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -199,6 +199,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) + val |= PCIE_SOC_GLOBAL_RESET_V; + + ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); + + /* TODO: exact time to sleep is uncertain */ + delay = 10; +@@ -208,6 +210,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab) + val &= ~PCIE_SOC_GLOBAL_RESET_V; + + ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET); + + mdelay(delay); + +-- +2.53.0 + diff --git a/queue-7.1/wifi-ath12k-fix-low-mlo-rx-throughput-on-wcn7850.patch b/queue-7.1/wifi-ath12k-fix-low-mlo-rx-throughput-on-wcn7850.patch new file mode 100644 index 0000000000..05ff8e4fdf --- /dev/null +++ b/queue-7.1/wifi-ath12k-fix-low-mlo-rx-throughput-on-wcn7850.patch @@ -0,0 +1,294 @@ +From 28da09a5dc7352921d78a695a39aea3e88605a59 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Jun 2026 22:33:15 -0700 +Subject: wifi: ath12k: Fix low MLO RX throughput on WCN7850 + +From: Yingying Tang + +[ Upstream commit a2fe9dc70f3b8d5716fbcfed5fbfb9cf3948d402 ] + +Commit [1] introduced a regression causing severely degraded MLO RX +throughput on WCN7850. + +On WCN7850, there is only a single ar instance, but MLO uses two +link IDs. ath12k_dp_peer->hw_links[] is indexed using ar->hw_link_id, +which causes both MLO link IDs to be stored at the same index. + +As a result, an incorrect link ID is assigned to MSDUs in +ath12k_dp_rx_deliver_msdu(), leading to severe MLO RX throughput loss. + +Different chipsets identify the per-MSDU link differently: + + - On QCN9274 / IPQ5332, the host owns multiple ar instances and the + per-MSDU hw_link_id from the RX descriptor maps cleanly through + dp_peer->hw_links[hw_link_id] to the IEEE link_id. + + - On single-ar chipsets like WCN7850 / QCC2072, there is only one ar + instance for both MLO links, so dp_peer->hw_links[] has just one + valid slot and cannot be used to distinguish the two links. To + resolve the link, walk dp_peer->link_peers[] and match by + rxcb->peer_id, which on the link_peer side identifies the link + peer for the MSDU. + +Add a new hw_op set_rx_link_id() so each chipset resolves the link +on the RX fast path using whatever signal it actually has, and let +the op itself decide whether to populate rx_status::link_valid and +rx_status::link_id: + + QCN9274 / IPQ5332 : always derive link_id from + dp_peer->hw_links[rxcb->hw_link_id] and set + link_valid. + WCN7850 / QCC2072 : walk the link_peers[] of dp_peer to find the + link_peer whose peer_id matches rxcb->peer_id, + and set link_valid only when a match is found. + Otherwise leave link_valid clear so that + mac80211 can fall back to its own link + resolution path (via addr2 / deflink). + +For WCN7850 / QCC2072, walking dp_peer->link_peers[] is bounded by +the number of links actually populated, so introduce a link_peers_map +bitmap (unsigned long) in struct ath12k_dp_peer that tracks populated +slots and use for_each_set_bit() to iterate. Non-MLO clients hit one +slot, current MLO clients hit two; the full ATH12K_NUM_MAX_LINKS +array is never scanned. The bitmap is maintained with WRITE_ONCE() on +the write side (under dp_hw->peer_lock) paired with READ_ONCE() on +both the lockless RX read side and the write-side RMW for KCSAN +correctness. + +Also guard the dp_peer dereference in ath12k_mac_peer_cleanup_all() +with a NULL check, since peer->dp_peer can be NULL for self-peers or +peers not yet fully assigned, the pre-existing rcu_assign_pointer() +call there had the same latent issue. + +This restores the correct link ID on WCN7850 without changing the +QCN9274 / IPQ5332 data path, which keeps its O(1) hw_links[] +indexing. + +Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3 + +Fixes: 11157e0910fd ("wifi: ath12k: Use ath12k_dp_peer in per packet Tx & Rx paths") # [1] +Signed-off-by: Yingying Tang +Reviewed-by: Baochen Qiang +Reviewed-by: Rameshkumar Sundaram +Link: https://patch.msgid.link/20260610053315.2249912-1-yingying.tang@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/dp_peer.c | 4 +++ + drivers/net/wireless/ath/ath12k/dp_peer.h | 1 + + drivers/net/wireless/ath/ath12k/dp_rx.c | 7 ++-- + drivers/net/wireless/ath/ath12k/hw.h | 16 +++++++++ + drivers/net/wireless/ath/ath12k/mac.c | 10 ++++-- + drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 33 +++++++++++++++++++ + drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h | 6 ++++ + drivers/net/wireless/ath/ath12k/wifi7/hw.c | 3 ++ + 8 files changed, 73 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c +index a1100782d45e6b..f57f1483c3e47f 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_peer.c ++++ b/drivers/net/wireless/ath/ath12k/dp_peer.c +@@ -570,6 +570,8 @@ int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw, + peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); + + rcu_assign_pointer(dp_peer->link_peers[peer->link_id], peer); ++ WRITE_ONCE(dp_peer->link_peers_map, ++ READ_ONCE(dp_peer->link_peers_map) | BIT(peer->link_id)); + + rcu_assign_pointer(dp_hw->dp_peers[peerid_index], dp_peer); + +@@ -632,6 +634,8 @@ void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_ + peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); + + rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); ++ WRITE_ONCE(dp_peer->link_peers_map, ++ READ_ONCE(dp_peer->link_peers_map) & ~BIT(peer->link_id)); + + rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); + +diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h +index 113b8040010fa3..d4d2ff16e83695 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_peer.h ++++ b/drivers/net/wireless/ath/ath12k/dp_peer.h +@@ -140,6 +140,7 @@ struct ath12k_dp_peer { + + /* Info used in MMIC verification of * RX fragments */ + struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; ++ unsigned long link_peers_map; + struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS]; + struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1]; + struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; +diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c +index b108ccd0f63703..b5dba7c0155f90 100644 +--- a/drivers/net/wireless/ath/ath12k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/dp_rx.c +@@ -1344,10 +1344,9 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc + + pubsta = peer ? peer->sta : NULL; + +- if (pubsta && pubsta->valid_links) { +- status->link_valid = 1; +- status->link_id = peer->hw_links[rxcb->hw_link_id]; +- } ++ status->link_valid = 0; ++ if (pubsta && pubsta->valid_links) ++ ath12k_hw_set_rx_link_id(dp->hw_params, peer, rxcb, status); + + ath12k_dbg(dp->ab, ATH12K_DBG_DATA, + "rx skb %p len %u peer %pM %d %s sn %u %s%s%s%s%s%s%s%s%s%s rate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n", +diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h +index a9888e0521a1d1..da75d19ae1a007 100644 +--- a/drivers/net/wireless/ath/ath12k/hw.h ++++ b/drivers/net/wireless/ath/ath12k/hw.h +@@ -13,6 +13,10 @@ + #include "wmi.h" + #include "hal.h" + ++struct ath12k_dp_peer; ++struct ath12k_skb_rxcb; ++struct ieee80211_rx_status; ++ + /* Target configuration defines */ + + /* Num VDEVS per radio */ +@@ -224,6 +228,9 @@ struct ath12k_hw_ops { + bool (*dp_srng_is_tx_comp_ring)(int ring_num); + bool (*is_frame_link_agnostic)(struct ath12k_link_vif *arvif, + struct ieee80211_mgmt *mgmt); ++ void (*set_rx_link_id)(struct ath12k_dp_peer *dp_peer, ++ struct ath12k_skb_rxcb *rxcb, ++ struct ieee80211_rx_status *status); + }; + + static inline +@@ -254,6 +261,15 @@ static inline int ath12k_hw_mac_id_to_srng_id(const struct ath12k_hw_params *hw, + return 0; + } + ++static inline void ath12k_hw_set_rx_link_id(const struct ath12k_hw_params *hw, ++ struct ath12k_dp_peer *dp_peer, ++ struct ath12k_skb_rxcb *rxcb, ++ struct ieee80211_rx_status *status) ++{ ++ if (hw->hw_ops->set_rx_link_id) ++ hw->hw_ops->set_rx_link_id(dp_peer, rxcb, status); ++} ++ + struct ath12k_fw_ie { + __le32 id; + __le32 len; +diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c +index 7190aafd3ae693..7408c2577dc2e6 100644 +--- a/drivers/net/wireless/ath/ath12k/mac.c ++++ b/drivers/net/wireless/ath/ath12k/mac.c +@@ -1234,9 +1234,13 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar) + /* cleanup dp peer */ + spin_lock_bh(&dp_hw->peer_lock); + dp_peer = peer->dp_peer; +- peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); +- rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); +- rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); ++ if (dp_peer) { ++ peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); ++ rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL); ++ WRITE_ONCE(dp_peer->link_peers_map, ++ READ_ONCE(dp_peer->link_peers_map) & ~BIT(peer->link_id)); ++ rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL); ++ } + spin_unlock_bh(&dp_hw->peer_lock); + + ath12k_dp_link_peer_rhash_delete(dp, peer); +diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +index a5e290edaa898c..99c56528346940 100644 +--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c ++++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c +@@ -5,6 +5,7 @@ + */ + + #include "dp_rx.h" ++#include "../dp_peer.h" + #include "../dp_tx.h" + #include "../peer.h" + #include "hal_qcn9274.h" +@@ -2242,3 +2243,35 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab, + + return tlv_tag == HAL_RX_MPDU_START; + } ++ ++void ++ath12k_wifi7_dp_rx_set_link_id_qcn9274(struct ath12k_dp_peer *dp_peer, ++ struct ath12k_skb_rxcb *rxcb, ++ struct ieee80211_rx_status *status) ++{ ++ status->link_valid = 1; ++ status->link_id = dp_peer->hw_links[rxcb->hw_link_id]; ++} ++ ++void ++ath12k_wifi7_dp_rx_set_link_id_wcn7850(struct ath12k_dp_peer *dp_peer, ++ struct ath12k_skb_rxcb *rxcb, ++ struct ieee80211_rx_status *status) ++{ ++ struct ath12k_dp_link_peer *link_peer; ++ unsigned long links_map; ++ int i; ++ ++ RCU_LOCKDEP_WARN(!rcu_read_lock_held(), ++ "ath12k set rx link id called without rcu lock"); ++ ++ links_map = READ_ONCE(dp_peer->link_peers_map); ++ for_each_set_bit(i, &links_map, ATH12K_NUM_MAX_LINKS) { ++ link_peer = rcu_dereference(dp_peer->link_peers[i]); ++ if (link_peer && link_peer->peer_id == rxcb->peer_id) { ++ status->link_valid = 1; ++ status->link_id = link_peer->link_id; ++ return; ++ } ++ } ++} +diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h +index 8aa79faf567fd0..1d3a4788a2dd91 100644 +--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h ++++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h +@@ -57,4 +57,10 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab, + struct hal_rx_desc *rx_desc); + int ath12k_wifi7_dp_rx_tid_delete_handler(struct ath12k_base *ab, + struct ath12k_dp_rx_tid_rxq *rx_tid); ++void ath12k_wifi7_dp_rx_set_link_id_qcn9274(struct ath12k_dp_peer *dp_peer, ++ struct ath12k_skb_rxcb *rxcb, ++ struct ieee80211_rx_status *status); ++void ath12k_wifi7_dp_rx_set_link_id_wcn7850(struct ath12k_dp_peer *dp_peer, ++ struct ath12k_skb_rxcb *rxcb, ++ struct ieee80211_rx_status *status); + #endif +diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c +index cb3185850439ee..f687eb69ea8da4 100644 +--- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c ++++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c +@@ -158,6 +158,7 @@ static const struct ath12k_hw_ops qcn9274_ops = { + .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_qcn9274, + .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_qcn9274, + .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_qcn9274, ++ .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_qcn9274, + }; + + static const struct ath12k_hw_ops wcn7850_ops = { +@@ -168,6 +169,7 @@ static const struct ath12k_hw_ops wcn7850_ops = { + .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850, + .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850, + .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850, ++ .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_wcn7850, + }; + + static const struct ath12k_hw_ops qcc2072_ops = { +@@ -178,6 +180,7 @@ static const struct ath12k_hw_ops qcc2072_ops = { + .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850, + .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850, + .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850, ++ .set_rx_link_id = ath12k_wifi7_dp_rx_set_link_id_wcn7850, + }; + + #define ATH12K_TX_RING_MASK_0 0x1 +-- +2.53.0 + diff --git a/queue-7.1/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch b/queue-7.1/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch new file mode 100644 index 0000000000..3f30f6d1c3 --- /dev/null +++ b/queue-7.1/wifi-ath12k-flush-the-posted-write-after-writing-to-.patch @@ -0,0 +1,62 @@ +From 7b40023703f224d139b8561a79a3dcb8632135a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jun 2026 16:16:49 +0200 +Subject: wifi: ath12k: Flush the posted write after writing to + PCIE_SOC_GLOBAL_RESET + +From: Manivannan Sadhasivam + +[ Upstream commit 55f3aa06951cac78b0206bde961c8cf11929a27a ] + +ath12k_pci_soc_global_reset() tries to reset the device by writing to the +PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure +that the write gets flushed to the device before the delay. + +This may lead to the delay on the host to be insufficient, if the posted +write doesn't reach the device before the delay. + +So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and +before the delay. + +Compile tested only. +Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1 + +Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices") +Reported-by: Alex Williamson +Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org +Signed-off-by: Manivannan Sadhasivam +Reviewed-by: Baochen Qiang +Reviewed-by: Raj Kumar Bhagat +Tested-by: Raj Kumar Bhagat +Link: https://patch.msgid.link/20260623141649.41087-2-manivannan.sadhasivam@oss.qualcomm.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath12k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c +index d9a22d6afbb020..fee4129ea4055b 100644 +--- a/drivers/net/wireless/ath/ath12k/pci.c ++++ b/drivers/net/wireless/ath/ath12k/pci.c +@@ -188,6 +188,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab) + val |= PCIE_SOC_GLOBAL_RESET_V; + + ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET); + + /* TODO: exact time to sleep is uncertain */ + delay = 10; +@@ -197,6 +199,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab) + val &= ~PCIE_SOC_GLOBAL_RESET_V; + + ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val); ++ /* Flush the posted write to the device */ ++ ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET); + + mdelay(delay); + +-- +2.53.0 + diff --git a/queue-7.1/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch b/queue-7.1/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch new file mode 100644 index 0000000000..079a215122 --- /dev/null +++ b/queue-7.1/wifi-ath6kl-fix-oob-read-from-firmware-ie-lengths-in.patch @@ -0,0 +1,49 @@ +From ce8de6fe437989032465e484c3160d92580ffacb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:50:08 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware IE lengths in connect event + +From: Tristan Madani + +[ Upstream commit 6b47b29730de3232b919d8362749f6814c5f2a33 ] + +The firmware-controlled beacon_ie_len, assoc_req_len, and assoc_resp_len +fields in ath6kl_wmi_connect_event_rx() are not validated against the +buffer length. Their sum (up to 765) can exceed the actual WMI event +data, causing out-of-bounds reads during IE parsing and state corruption +of wmi->is_wmm_enabled. + +Add a check that the total IE length fits within the buffer. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20260421135009.348084-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index 7e65a03be0b7bb..2b0c5038ae0403 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -874,6 +874,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, + + ev = (struct wmi_connect_event *) datap; + ++ if (len < sizeof(*ev) + ev->beacon_ie_len + ++ ev->assoc_req_len + ev->assoc_resp_len) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, ++ "connect event: IE lengths %u+%u+%u exceed buffer %d\n", ++ ev->beacon_ie_len, ev->assoc_req_len, ++ ev->assoc_resp_len, len); ++ return -EINVAL; ++ } + if (vif->nw_type == AP_NETWORK) { + /* AP mode start/STA connected event */ + struct net_device *dev = vif->ndev; +-- +2.53.0 + diff --git a/queue-7.1/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch b/queue-7.1/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch new file mode 100644 index 0000000000..829798623a --- /dev/null +++ b/queue-7.1/wifi-ath6kl-fix-oob-read-from-firmware-num_msg-in-tx.patch @@ -0,0 +1,53 @@ +From 850573cf187f6910dc45a4a8d3f3aac3abe66873 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jun 2026 23:29:07 +0000 +Subject: wifi: ath6kl: fix OOB read from firmware num_msg in TX complete + handler + +From: Tristan Madani + +[ Upstream commit 3a21c89215cc18f1a97c5e5bfd1da6d4f3d44495 ] + +The firmware-controlled num_msg field (u8, 0-255) drives the loop in +ath6kl_wmi_tx_complete_event_rx() without validation against the buffer +length. This allows out-of-bounds reads of up to 1020 bytes past the +WMI event buffer when the firmware sends an inflated num_msg. + +Add a check that the buffer is large enough to hold the fixed struct +and the num_msg variable-length entries. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Signed-off-by: Tristan Madani +Link: https://patch.msgid.link/20260625232907.3620746-1-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath6kl/wmi.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c +index 72611a2ceb9d8e..7e65a03be0b7bb 100644 +--- a/drivers/net/wireless/ath/ath6kl/wmi.c ++++ b/drivers/net/wireless/ath/ath6kl/wmi.c +@@ -484,6 +484,18 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) + + evt = (struct wmi_tx_complete_event *) datap; + ++ if (len < sizeof(*evt)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d\n", ++ len); ++ return -EINVAL; ++ } ++ ++ if (len < sizeof(*evt) + evt->num_msg * sizeof(struct tx_complete_msg_v1)) { ++ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d for %u msgs\n", ++ len, evt->num_msg); ++ return -EINVAL; ++ } ++ + ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", + evt->num_msg, evt->msg_len, evt->msg_type); + +-- +2.53.0 + diff --git a/queue-7.1/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch b/queue-7.1/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch new file mode 100644 index 0000000000..728ed370b6 --- /dev/null +++ b/queue-7.1/wifi-ath9k-hif_usb-don-t-dereference-hif_dev-after-r.patch @@ -0,0 +1,90 @@ +From 5c9f3e3786ac852812075c70e50e19eacec856a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Jun 2026 08:32:10 -0700 +Subject: wifi: ath9k: hif_usb: don't dereference hif_dev after re-arming + firmware request +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Cheng Yongkang + +[ Upstream commit dad9f96945d77ecd4708f730c06ef54dcd8cc057 ] + +ath9k_hif_request_firmware() re-arms an asynchronous firmware load via +request_firmware_nowait(), passing hif_dev as the completion context, and +then still dereferences hif_dev: + + dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", + hif_dev->fw_name); + +The re-armed callback ath9k_hif_usb_firmware_cb() runs on the "events" +workqueue and, when the firmware is missing, walks the retry chain into +ath9k_hif_usb_firmware_fail() -> complete_all(&hif_dev->fw_done). That +releases the wait_for_completion(&hif_dev->fw_done) in a concurrent +ath9k_hif_usb_disconnect(), which then kfree()s hif_dev. The trailing +dev_info() in the frame that re-armed the request can therefore read freed +memory (hif_dev->udev, the first field of struct hif_device_usb): + + BUG: KASAN: slab-use-after-free in ath9k_hif_request_firmware + Read of size 8 ... by task kworker/... + ath9k_hif_request_firmware + ath9k_hif_usb_firmware_cb drivers/net/wireless/ath/ath9k/hif_usb.c:1247 + request_firmware_work_func + Allocated by ...: + ath9k_hif_usb_probe drivers/net/wireless/ath/ath9k/hif_usb.c + Freed by ...: + ath9k_hif_usb_disconnect -> kfree drivers/net/wireless/ath/ath9k/hif_usb.c + +The fw_done barrier only makes disconnect wait for the firmware chain to +*terminate*; it does not protect the outer ath9k_hif_request_firmware() +frame that re-armed the request and keeps touching hif_dev afterwards. + +Drop the post-request dev_info(): it is the only use of hif_dev after the +async request is armed, and it is purely informational (the dev_err() on the +failure path runs only when request_firmware_nowait() did not arm a callback, +so hif_dev is still alive there). + +This was first reported by syzbot as a single, non-reproduced crash that was +later auto-obsoleted, and was independently rediscovered by the reFuzz fuzzer, +which produced a C reproducer (USB-gadget connect/disconnect of an ath9k_htc +device whose firmware download fails). The vulnerable code is unchanged and +still present in v7.1-rc6, where the slab-use-after-free reproduces under KASAN +once the (sub-microsecond) race window is widened. + +Fixes: e904cf6fe230 ("ath9k_htc: introduce support for different fw versions") +Reported-by: syzbot+50122cbc2874b1eb25b0@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=50122cbc2874b1eb25b0 +Signed-off-by: Cheng Yongkang +Acked-by: Toke Høiland-Jørgensen +Link: https://patch.msgid.link/20260605153210.20471-1-1020691186@qq.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c +index 821909b81ea917..44855ec5be7453 100644 +--- a/drivers/net/wireless/ath/ath9k/hif_usb.c ++++ b/drivers/net/wireless/ath/ath9k/hif_usb.c +@@ -1225,15 +1225,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, + ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, + &hif_dev->udev->dev, GFP_KERNEL, + hif_dev, ath9k_hif_usb_firmware_cb); +- if (ret) { ++ if (ret) + dev_err(&hif_dev->udev->dev, + "ath9k_htc: Async request for firmware %s failed\n", + hif_dev->fw_name); +- return ret; +- } +- +- dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", +- hif_dev->fw_name); + + return ret; + } +-- +2.53.0 + diff --git a/queue-7.1/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch b/queue-7.1/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch new file mode 100644 index 0000000000..09cd361afc --- /dev/null +++ b/queue-7.1/wifi-brcmfmac-fix-802.1x-sha256-call-trace-warning.patch @@ -0,0 +1,69 @@ +From faa10e44b2b6490c2c861683a7f94957b5b0371c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 May 2026 16:38:59 +0800 +Subject: wifi: brcmfmac: fix 802.1X-SHA256 call trace warning +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Shelley Yang + +[ Upstream commit 7cb34f6c4fe8a68af621d870abe63bfca2275dd6 ] + +Based on wpa_auth as 1x_256 mode, need to set up +"use_fwsup" with BRCMF_PROFILE_FWSUP_1X. +Or it will happen trace warning when call brcmf_cfg80211_set_pmk(). + +[ 4481.831101] ------------[ cut here ]------------ +[ 4481.831102] WARNING: CPU: 1 PID: 2997 at +drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:7242 brcmf_cfg80211_set_pmk+0x77/0xd0 [brcmfmac] +[...] +[ 4481.831202] Call Trace: +[ 4481.831204]   +[ 4481.831205]  nl80211_set_pmk+0x183/0x250 [cfg80211] +[ 4481.831233]  genl_family_rcv_msg_doit+0xea/0x150 +[ 4481.831237]  genl_rcv_msg+0x104/0x240 +[ 4481.831239]  ? cfg80211_probe_status+0x2c0/0x2c0 [cfg80211] +[ 4481.831257]  ? genl_family_rcv_msg_doit+0x150/0x150 +[ 4481.831259]  netlink_rcv_skb+0x4e/0x100 +[ 4481.831261]  genl_rcv+0x24/0x40 +[ 4481.831262]  netlink_unicast+0x236/0x380 +[ 4481.831264]  netlink_sendmsg+0x250/0x4b0 +[ 4481.831266]  sock_sendmsg+0x5c/0x70 +[ 4481.831269]  ____sys_sendmsg+0x236/0x2b0 +[ 4481.831271]  ? copy_msghdr_from_user+0x6d/0xa0 +[ 4481.831272]  ___sys_sendmsg+0x86/0xd0 +[ 4481.831274]  ? avc_has_perm+0x8c/0x1a0 +[ 4481.831276]  ? preempt_count_add+0x6a/0xa0 +[ 4481.831279]  ? sock_has_perm+0x82/0xa0 +[ 4481.831280]  __sys_sendmsg+0x57/0xa0 +[ 4481.831282]  do_syscall_64+0x38/0x90 +[ 4481.831284]  entry_SYSCALL_64_after_hwframe+0x63/0xcd +[ 4481.831286] RIP: 0033:0x7fd270d369b4 + +Fixes: 2526ff21aa77 ("brcmfmac: support 4-way handshake offloading for 802.1X") +Signed-off-by: Shelley Yang +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260525083859.581246-1-shelley.yang@infineon.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +index 0b55d445895f20..89f61710a21045 100644 +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -2146,7 +2146,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) + sme->crypto.akm_suites[0]); + return -EINVAL; + } +- } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { ++ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_1X_SHA256)) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + val = WPA2_AUTH_UNSPECIFIED; +-- +2.53.0 + diff --git a/queue-7.1/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch b/queue-7.1/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch new file mode 100644 index 0000000000..de958e63bf --- /dev/null +++ b/queue-7.1/wifi-carl9170-bound-memcpy-length-in-cmd-callback-to.patch @@ -0,0 +1,48 @@ +From a96e5e7b82452c716726fb3e916ce9c49bba0679 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:26 +0000 +Subject: wifi: carl9170: bound memcpy length in cmd callback to prevent OOB + read + +From: Tristan Madani + +[ Upstream commit 4cde55b2feff9504d1f993ab80e84e7ccb62791c ] + +When the firmware sends a command response with a length mismatch, +carl9170_cmd_callback() logs the mismatch and calls carl9170_restart() +but then falls through to memcpy(ar->readbuf, buffer + 4, len - 4). +Since len comes from the firmware and can exceed ar->readlen, this +copies more data than the readbuf was allocated for. + +Bound the memcpy to min(len - 4, ar->readlen) so that the response +is still completed -- avoiding repeated restarts from queued garbage -- +while preventing an overread past the response buffer. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-2-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index 6833430130f4ca..f6855efc05c0f1 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -150,7 +150,8 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer) + spin_lock(&ar->cmd_lock); + if (ar->readbuf) { + if (len >= 4) +- memcpy(ar->readbuf, buffer + 4, len - 4); ++ memcpy(ar->readbuf, buffer + 4, ++ min_t(u32, len - 4, ar->readlen)); + + ar->readbuf = NULL; + } +-- +2.53.0 + diff --git a/queue-7.1/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch b/queue-7.1/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch new file mode 100644 index 0000000000..e09813a324 --- /dev/null +++ b/queue-7.1/wifi-carl9170-fix-buffer-overflow-in-rx_stream-failo.patch @@ -0,0 +1,46 @@ +From 6b4e0ed87933729445332aa192dea68679b35446 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:28 +0000 +Subject: wifi: carl9170: fix buffer overflow in rx_stream failover path + +From: Tristan Madani + +[ Upstream commit a1a21995c2e1cc2ca6b2226cfe4f5f018370182a ] + +The failover continuation in carl9170_rx_stream() copies the full tlen +from the second USB transfer instead of capping at rx_failover_missing +bytes. When both transfers are near maximum size, the total exceeds the +65535-byte failover SKB, triggering skb_over_panic. + +Limit the copy size to the missing byte count. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-4-tristmd@gmail.com +[Fix checkpatch CHECK:PARENTHESIS_ALIGNMENT] +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/rx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c +index f6855efc05c0f1..0383d5c9698bfa 100644 +--- a/drivers/net/wireless/ath/carl9170/rx.c ++++ b/drivers/net/wireless/ath/carl9170/rx.c +@@ -918,7 +918,9 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) + } + } + +- skb_put_data(ar->rx_failover, tbuf, tlen); ++ skb_put_data(ar->rx_failover, tbuf, ++ min_t(unsigned int, tlen, ++ ar->rx_failover_missing)); + ar->rx_failover_missing -= tlen; + + if (ar->rx_failover_missing <= 0) { +-- +2.53.0 + diff --git a/queue-7.1/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch b/queue-7.1/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch new file mode 100644 index 0000000000..be9ec95a34 --- /dev/null +++ b/queue-7.1/wifi-carl9170-fix-oob-read-from-off-by-two-in-tx-sta.patch @@ -0,0 +1,42 @@ +From 33d58b5c53536e88776297ded0a56e29725cc79d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Apr 2026 13:49:27 +0000 +Subject: wifi: carl9170: fix OOB read from off-by-two in TX status handler + +From: Tristan Madani + +[ Upstream commit a3f42f1049ad80c65560d2b078ad426c3134f78d ] + +The bounds check in carl9170_tx_process_status() uses +`i > ((cmd->hdr.len / 2) + 1)` which is off by two, allowing +2 extra iterations past valid _tx_status entries when the firmware- +controlled hdr.ext exceeds hdr.len/2. Fix by using the correct +comparison `i >= (cmd->hdr.len / 2)`. + +Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend") +Signed-off-by: Tristan Madani +Acked-by: Christian Lamparter +Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac +Link: https://patch.msgid.link/20260421134929.325662-3-tristmd@gmail.com +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/ath/carl9170/tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c +index 59caf1e4b15893..06aaf281655b1e 100644 +--- a/drivers/net/wireless/ath/carl9170/tx.c ++++ b/drivers/net/wireless/ath/carl9170/tx.c +@@ -692,7 +692,7 @@ void carl9170_tx_process_status(struct ar9170 *ar, + unsigned int i; + + for (i = 0; i < cmd->hdr.ext; i++) { +- if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) { ++ if (WARN_ON(i >= (cmd->hdr.len / 2))) { + print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE, + (void *) cmd, cmd->hdr.len + 4); + break; +-- +2.53.0 + diff --git a/queue-7.1/wifi-iwlwifi-fix-pointer-arithmetic-in-iwl_add_mcc_t.patch b/queue-7.1/wifi-iwlwifi-fix-pointer-arithmetic-in-iwl_add_mcc_t.patch new file mode 100644 index 0000000000..70f3350161 --- /dev/null +++ b/queue-7.1/wifi-iwlwifi-fix-pointer-arithmetic-in-iwl_add_mcc_t.patch @@ -0,0 +1,46 @@ +From b4ed15780abf750e3705b997188f38558f4a76c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:06 +0300 +Subject: wifi: iwlwifi: fix pointer arithmetic in + iwl_add_mcc_to_tas_block_list + +From: Emmanuel Grumbach + +[ Upstream commit bc796f84ec9a95b356959ec7caf1d4fce33f3a76 ] + +The expression list[*size++] increments the pointer 'size' +rather than the u8 value it points to (operator precedence: ++ +binds to the pointer before the dereference). As a result the +block-list entry is written at the correct index but *size is +never incremented, so the caller's count stays at zero and +subsequent calls overwrite slot 0 every time. + +Change to list[(*size)++] so that the value pointed to by size +is incremented after use as the array index. + +Fixes: 5f4656610edb ("wifi: iwlwifi: extend TAS_CONFIG cmd support for v5") +Assisted-by: GitHubCopilot:gpt-5.3-codex +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.d2cd92242582.Ife4140a4e27be2a1cd9f886c5a9b376ce182a019@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/fw/regulatory.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +index 55128caac7ed9f..14c813cf530f66 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/regulatory.c +@@ -384,7 +384,7 @@ bool iwl_add_mcc_to_tas_block_list(u16 *list, u8 *size, u16 mcc) + if (*size >= IWL_WTAS_BLACK_LIST_MAX) + return false; + +- list[*size++] = mcc; ++ list[(*size)++] = mcc; + return true; + } + IWL_EXPORT_SYMBOL(iwl_add_mcc_to_tas_block_list); +-- +2.53.0 + diff --git a/queue-7.1/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch b/queue-7.1/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch new file mode 100644 index 0000000000..6e635136b9 --- /dev/null +++ b/queue-7.1/wifi-iwlwifi-mvm-fix-read-in-wake-packet-notificatio.patch @@ -0,0 +1,50 @@ +From 7ab450e88fa71a273ed45894c10c49165a382651 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:08 +0300 +Subject: wifi: iwlwifi: mvm: fix read in wake packet notification handler + +From: Shahar Tzarfati + +[ Upstream commit 9d7657aae8c1579584c67b0b66114a6a98db8b2f ] + +In iwl_mvm_wowlan_store_wake_pkt(), packet_len was initialized from +notif->wake_packet_length before the explicit check that len >= +sizeof(*notif). + +Move the assignment of packet_len to after the size check so that +notif->wake_packet_length is only accessed once the payload length +has been validated. + +Fixes: 219ed58feda9 ("wifi: iwlwifi: mvm: Add support for wowlan wake packet notification") +Signed-off-by: Shahar Tzarfati +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.99d5cf85a528.Ic4aa736011d4fe88e0cd19723d1d48bb24642198@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +index 9a74f60c91850f..72d7403de04d82 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +@@ -2756,7 +2756,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, + struct iwl_wowlan_status_data *status, + u32 len) + { +- u32 data_size, packet_len = le32_to_cpu(notif->wake_packet_length); ++ u32 data_size, packet_len; + + if (len < sizeof(*notif)) { + IWL_ERR(mvm, "Invalid WoWLAN wake packet notification!\n"); +@@ -2775,6 +2775,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm, + return -EIO; + } + ++ packet_len = le32_to_cpu(notif->wake_packet_length); + data_size = len - offsetof(struct iwl_wowlan_wake_pkt_notif, wake_packet); + + /* data_size got the padding from the notification, remove it. */ +-- +2.53.0 + diff --git a/queue-7.1/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch b/queue-7.1/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch new file mode 100644 index 0000000000..b5af63e8ae --- /dev/null +++ b/queue-7.1/wifi-iwlwifi-mvm-validate-sar-geo-response-payload-s.patch @@ -0,0 +1,56 @@ +From 4c8e8e353974421b4f329500c04bd9a1fbed9816 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:04 +0300 +Subject: wifi: iwlwifi: mvm: validate SAR GEO response payload size + +From: Pagadala Yesu Anjaneyulu + +[ Upstream commit 408d7da38272ce48e2db79b8a9895999f94d7655 ] + +The SAR GEO command response is cast to +iwl_geo_tx_power_profiles_resp without verifying the payload length. +A malformed or unexpected firmware response can lead to reading an +invalid structure layout. + +Add an explicit size check before accessing the response data and +return -EIO when the payload size is wrong. + +Fixes: f604324eefec ("iwlwifi: remove iwl_validate_sar_geo_profile() export") +Signed-off-by: Pagadala Yesu Anjaneyulu +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.7e749b7d374a.I4ef54548bff6c6e7c7a57bee771ac12508aad677@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +index 6e507d6dcdd2a1..fa523be91d8ad3 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +@@ -964,12 +964,22 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) + return ret; + } + ++ if (IWL_FW_CHECK(mvm, ++ iwl_rx_packet_payload_len(cmd.resp_pkt) != ++ sizeof(*resp), ++ "Wrong size for iwl_geo_tx_power_profiles_resp: %d\n", ++ iwl_rx_packet_payload_len(cmd.resp_pkt))) { ++ ret = -EIO; ++ goto out; ++ } ++ + resp = (void *)cmd.resp_pkt->data; + ret = le32_to_cpu(resp->profile_idx); + + if (WARN_ON(ret > BIOS_GEO_MAX_PROFILE_NUM)) + ret = -EIO; + ++out: + iwl_free_resp(&cmd); + return ret; + } +-- +2.53.0 + diff --git a/queue-7.1/wifi-iwlwifi-validate-payload-length-in-iwl_pnvm_com.patch b/queue-7.1/wifi-iwlwifi-validate-payload-length-in-iwl_pnvm_com.patch new file mode 100644 index 0000000000..99f1fca978 --- /dev/null +++ b/queue-7.1/wifi-iwlwifi-validate-payload-length-in-iwl_pnvm_com.patch @@ -0,0 +1,64 @@ +From aa60a8641ffd8bc0b4dc9950d8505ecbd5fe2b3a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 21:57:07 +0300 +Subject: wifi: iwlwifi: validate payload length in iwl_pnvm_complete_fn + +From: Emmanuel Grumbach + +[ Upstream commit daec24a5ed5da77a108e246ad77aa8b889911f93 ] + +iwl_pnvm_complete_fn() casts pkt->data directly to +struct iwl_pnvm_init_complete_ntfy and reads the status field +without first verifying that the firmware notification payload +is large enough to contain that structure. + +Add a WARN_ON_ONCE check against sizeof(*pnvm_ntf) and return +early without reading uninitialised memory if the payload is too +short. + +Fixes: b3e4c0f34c17 ("iwlwifi: move PNVM implementation to common code") +Assisted-by: GitHubCopilot:gpt-5.3-codex +Signed-off-by: Emmanuel Grumbach +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260715215523.7f2a669e5c75.I00465dcfcbccb250ae9af2d9bb305e24de1ba394@changeid +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/fw/pnvm.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +index afff8d51ca950c..ec0ff58ab312d5 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c ++++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright(c) 2020-2025 Intel Corporation ++ * Copyright(c) 2020-2026 Intel Corporation + */ + + #include "iwl-drv.h" +@@ -12,6 +12,7 @@ + #include "fw/api/alive.h" + #include "fw/uefi.h" + #include "fw/img.h" ++#include "fw/dbg.h" + + #define IWL_PNVM_REDUCED_CAP_BIT BIT(25) + +@@ -26,6 +27,12 @@ static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait, + struct iwl_trans *trans = (struct iwl_trans *)data; + struct iwl_pnvm_init_complete_ntfy *pnvm_ntf = (void *)pkt->data; + ++ if (IWL_FW_CHECK(trans, ++ iwl_rx_packet_payload_len(pkt) < sizeof(*pnvm_ntf), ++ "Bad notif len: %d\n", ++ iwl_rx_packet_payload_len(pkt))) ++ return true; ++ + IWL_DEBUG_FW(trans, + "PNVM complete notification received with status 0x%0x\n", + le32_to_cpu(pnvm_ntf->status)); +-- +2.53.0 + diff --git a/queue-7.1/wifi-mac80211-copy-aggregation-information.patch b/queue-7.1/wifi-mac80211-copy-aggregation-information.patch new file mode 100644 index 0000000000..317d534cdb --- /dev/null +++ b/queue-7.1/wifi-mac80211-copy-aggregation-information.patch @@ -0,0 +1,39 @@ +From 719176865d39d7a35669f6133a58c18e74d2ef19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Jul 2026 14:10:46 +0300 +Subject: wifi: mac80211: copy aggregation information + +From: Benjamin Berg + +[ Upstream commit 0fe2d5be7ab59717adb3f9cfab3832c6c4dd770c ] + +This information can be considered part of the capabilities and should +also be copied to the NAN data station. + +Fixes: 27e9b326b674 ("wifi: mac80211: support NAN stations") +Signed-off-by: Benjamin Berg +Signed-off-by: Miri Korenblit +Link: https://patch.msgid.link/20260714141038.15620aa5324b.I049254b854ac91c32e0768eb7c819f32eda34218@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index 0bc10136b816ef..80210ef4cbc843 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -2414,6 +2414,9 @@ static int sta_apply_parameters(struct ieee80211_local *local, + memcpy(&sta->deflink.pub->supp_rates, + &nmi_sta->deflink.pub->supp_rates, + sizeof(sta->deflink.pub->supp_rates)); ++ ++ sta->deflink.pub->agg = nmi_sta->deflink.pub->agg; ++ __ieee80211_sta_recalc_aggregates(sta, 0); + } + + /* set the STA state after all sta info from usermode has been set */ +-- +2.53.0 + diff --git a/queue-7.1/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch b/queue-7.1/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch new file mode 100644 index 0000000000..a390896b81 --- /dev/null +++ b/queue-7.1/wifi-mac80211-recalculate-tim-when-a-station-enters-.patch @@ -0,0 +1,56 @@ +From e3c773f303e473ee90d51f69bd2140185a363fa0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jul 2026 11:17:51 +1000 +Subject: wifi: mac80211: recalculate TIM when a station enters power save + +From: Andrew Pope + +[ Upstream commit a007a384c9eb17610f53a53e2f59944c31f1565a ] + +When an AP buffers frames for a station on its per-station TXQs and the +station subsequently enters power save, sta_ps_start() records the +buffered TIDs in txq_buffered_tids but does not update the TIM. The +station's TIM bit is only ever set when a further frame is buffered +while the station is already asleep +(ieee80211_tx_h_unicast_ps_buf() -> sta_info_recalc_tim()). + +If no further downlink frame arrives for that station the beacon +TIM never advertises the buffered traffic. A station relying on the +TIM then remains in doze indefinitely on top of a non-empty queue. Its +TXQs were removed from the scheduler's active list at PS entry, nothing +pages it, and the flow deadlocks until an unrelated event wakes the +station. + +Recalculate the TIM at the end of sta_ps_start(), so traffic +already buffered at PS entry is advertised immediately. +sta_info_recalc_tim() already consults txq_buffered_tids, which is +updated above, and is safe in this context (it is already called +from equivalent paths such as the tx handlers and +ieee80211_handle_filtered_frame()). + +Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation") +Signed-off-by: Andrew Pope +Link: https://patch.msgid.link/20260717011751.79524-1-andrew.pope@morsemicro.com +[add wifi: subject prefix] +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/rx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index fe583636d326eb..7372025831c5dc 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1717,6 +1717,8 @@ static void sta_ps_start(struct sta_info *sta) + else + clear_bit(tid, &sta->txq_buffered_tids); + } ++ ++ sta_info_recalc_tim(sta); + } + + static void sta_ps_end(struct sta_info *sta) +-- +2.53.0 + diff --git a/queue-7.1/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch b/queue-7.1/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch new file mode 100644 index 0000000000..9866c46a72 --- /dev/null +++ b/queue-7.1/wifi-mac80211-tear-down-new-links-on-vif-update-erro.patch @@ -0,0 +1,75 @@ +From c879ffeaf87150726c67b977b574d3b4a9cd9519 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Jul 2026 14:03:02 -0700 +Subject: wifi: mac80211: tear down new links on vif update error path + +From: Xiang Mei + +[ Upstream commit 952c02b33f56207a160421bcd61e7ac53c9c59ae ] + +When ieee80211_vif_update_links() adds new links it allocates a link +container for each and calls ieee80211_link_init() (which registers the +per-link debugfs files with file->private_data pointing into the container) +and ieee80211_link_setup(). If the subsequent drv_change_vif_links() fails, +the error path restores the old pointers and jumps to 'free', which frees +the new containers but never removes their debugfs entries or stops the +links. The debugfs files survive with file->private_data dangling at the +freed container, so a later open()+read() (e.g. link-1/txpower) +dereferences freed memory in ieee80211_if_read_link(), a use-after-free. + +The removal path already dismantles links correctly via +ieee80211_tear_down_links(), which removes each link's keys and debugfs +entries and calls ieee80211_link_stop(); the add path on the error branch +does not. Commit be1ba9ed221f ("wifi: mac80211: avoid weird state in error +path") hardened this same error path for the link-removal case +(new_links == 0) but left the newly-added links' teardown unaddressed. + +drv_change_vif_links() can fail at runtime on MLO drivers (internal +allocation / queue / firmware command failures). + +Remove the new links' debugfs entries and stop them before freeing. + + BUG: KASAN: slab-use-after-free in ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + Read of size 8 at addr ffff888011290000 by task exploit/145 + Call Trace: + ... + ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + short_proxy_read (fs/debugfs/file.c:373) + vfs_read (fs/read_write.c:572) + ksys_read (fs/read_write.c:716) + do_syscall_64 (arch/x86/entry/syscall_64.c:94) + entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) + ... + Oops: general protection fault, probably for non-canonical address 0xdffffc000000000a + RIP: 0010:ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) + Kernel panic - not syncing: Fatal exception + +Fixes: 170cd6a66d9a ("wifi: mac80211: add netdev per-link debugfs data and driver hook") +Reported-by: Weiming Shi +Assisted-by: Claude:claude-opus-4-8 +Signed-off-by: Xiang Mei +Link: https://patch.msgid.link/20260711210302.2098404-1-xmei5@asu.edu +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/link.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/mac80211/link.c b/net/mac80211/link.c +index 93e290dd783f2b..7e3dae12526b08 100644 +--- a/net/mac80211/link.c ++++ b/net/mac80211/link.c +@@ -394,6 +394,10 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata, + memcpy(sdata->link, old_data, sizeof(old_data)); + memcpy(sdata->vif.link_conf, old, sizeof(old)); + ieee80211_set_vif_links_bitmaps(sdata, old_links, dormant_links); ++ for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) { ++ ieee80211_link_debugfs_remove(&links[link_id]->data); ++ ieee80211_link_stop(&links[link_id]->data); ++ } + /* and free (only) the newly allocated links */ + memset(to_free, 0, sizeof(links)); + goto free; +-- +2.53.0 + diff --git a/queue-7.1/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch b/queue-7.1/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..0214174d79 --- /dev/null +++ b/queue-7.1/wifi-mt76-connac-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,38 @@ +From 2df775258f9ae778808cff2c4a02ec40019bd5a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:24:59 +0200 +Subject: wifi: mt76: connac: fix possible NULL-pointer deref in + mt76_connac_mcu_uni_bss_he_tlv() + +From: Lorenzo Bianconi + +[ Upstream commit 2c1fb2335f5e3afb34f91bc07ecb63517c328090 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: d0e274af2f2e4 ("mt76: mt76_connac: create mcu library") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-1-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +index 89bd52ea8bf704..ca290ccb6fd692 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +@@ -1446,6 +1446,8 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif, + struct bss_info_uni_he *he; + + cap = mt76_connac_get_he_phy_cap(phy, vif); ++ if (!cap) ++ return; + + he = (struct bss_info_uni_he *)tlv; + he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext; +-- +2.53.0 + diff --git a/queue-7.1/wifi-mt76-disable-napi-when-removing-device.patch b/queue-7.1/wifi-mt76-disable-napi-when-removing-device.patch new file mode 100644 index 0000000000..9a47885c82 --- /dev/null +++ b/queue-7.1/wifi-mt76-disable-napi-when-removing-device.patch @@ -0,0 +1,49 @@ +From 675fc25cf465f29a15e1d2db2cbcfd2e011ef6c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 16:43:47 +0200 +Subject: wifi: mt76: Disable napi when removing device + +From: Nicolas Cavallari + +[ Upstream commit 13b7e6a96a005c656d38f3da51581deaf9866375 ] + +Unloading the mt7915e module with a MT7916 triggers multiples WARN in +__netif_napi_del_locked() and in page_pool_disable_direct_recycling() +because the driver does not disable the napi before destroying it. + +This is troublesome since on MT7916 it is required to unload the module +and reinsert it with a different enable_6ghz parameter to change the +frequency. The system generally becomes unstable after reinserting the +module. + +Fix it by disabling napi before deleting it. Also, do not delete napi +on WED queues since napi is neither used nor initialized on them. + +Fixes: 17f1de56df05 ("mt76: add common code shared between multiple chipsets") +Signed-off-by: Nicolas Cavallari +Link: https://patch.msgid.link/20260708144615.24092-1-nicolas.cavallari@green-communications.fr +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/dma.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c +index f8c2fe5f2f5877..32204185921746 100644 +--- a/drivers/net/wireless/mediatek/mt76/dma.c ++++ b/drivers/net/wireless/mediatek/mt76/dma.c +@@ -1189,7 +1189,10 @@ void mt76_dma_cleanup(struct mt76_dev *dev) + mt76_for_each_q_rx(dev, i) { + struct mt76_queue *q = &dev->q_rx[i]; + +- netif_napi_del(&dev->napi[i]); ++ if (!mt76_queue_is_wed_rro(q)) { ++ napi_disable(&dev->napi[i]); ++ netif_napi_del(&dev->napi[i]); ++ } + mt76_dma_rx_cleanup(dev, q); + + page_pool_destroy(q->page_pool); +-- +2.53.0 + diff --git a/queue-7.1/wifi-mt76-fix-airoha_npu-dependency-tracking.patch b/queue-7.1/wifi-mt76-fix-airoha_npu-dependency-tracking.patch new file mode 100644 index 0000000000..3431c78298 --- /dev/null +++ b/queue-7.1/wifi-mt76-fix-airoha_npu-dependency-tracking.patch @@ -0,0 +1,96 @@ +From a573b322b97c501201c80e927f1718b7cd8032de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 Jun 2026 22:13:19 +0200 +Subject: wifi: mt76: fix airoha_npu dependency tracking + +From: Arnd Bergmann + +[ Upstream commit 7cd57ff6c6263519e6e463cbc2e0898828a70c42 ] + +There is a new build failure with MT7996E=m MT76_CORE=y and NET_AIROHA_NPU=m: + +ld.lld: error: undefined symbol: airoha_npu_get +ld.lld: error: undefined symbol: airoha_npu_put +>>> referenced by npu.c +>>> drivers/net/wireless/mediatek/mt76/npu.o:(mt76_npu_init) in archive vmlinux.a + +Fix this by reworking the dependency for the MT7996_NPU to only +allow enabling that when mt76_core can link against the npu driver. + +To make sure this gets caught more easily in the future when additional +mt76 variants need the same dependency, also turn CONFIG_MT76_NPU into +a tristate symbol that has the same dependency. + +Fixes: 7fb554b1b623 ("wifi: mt76: Introduce the NPU generic layer") +Acked-by: Lorenzo Bianconi +Signed-off-by: Arnd Bergmann +Link: https://patch.msgid.link/20260612201519.4054683-1-arnd@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/Kconfig | 4 ++-- + drivers/net/wireless/mediatek/mt76/Makefile | 6 +++++- + drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- + drivers/net/wireless/mediatek/mt76/mt7996/Kconfig | 2 +- + 4 files changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig +index 502303622a5382..2ca96e0527c029 100644 +--- a/drivers/net/wireless/mediatek/mt76/Kconfig ++++ b/drivers/net/wireless/mediatek/mt76/Kconfig +@@ -38,8 +38,8 @@ config MT792x_USB + select MT76_USB + + config MT76_NPU +- bool +- depends on MT76_CORE ++ tristate ++ depends on NET_AIROHA_NPU=y || MT76_CORE=NET_AIROHA_NPU + + source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" + source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig" +diff --git a/drivers/net/wireless/mediatek/mt76/Makefile b/drivers/net/wireless/mediatek/mt76/Makefile +index 1d42adfe803044..cacdd2b13d05bf 100644 +--- a/drivers/net/wireless/mediatek/mt76/Makefile ++++ b/drivers/net/wireless/mediatek/mt76/Makefile +@@ -12,7 +12,11 @@ mt76-y := \ + mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ + tx.o agg-rx.o mcu.o wed.o scan.o channel.o + +-mt76-$(CONFIG_MT76_NPU) += npu.o ++ifdef CONFIG_MT76_NPU ++# CONFIG_MT76_NPU is tristate to simplify dependency tracking, ++# but it behaves as a bool symbol here. ++mt76-y += npu.o ++endif + mt76-$(CONFIG_PCI) += pci.o + mt76-$(CONFIG_NL80211_TESTMODE) += testmode.o + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h +index 527bef97e122a1..0eea08553069cb 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76.h ++++ b/drivers/net/wireless/mediatek/mt76/mt76.h +@@ -1646,7 +1646,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, + int mt76_testmode_set_state(struct mt76_phy *phy, enum mt76_testmode_state state); + int mt76_testmode_alloc_skb(struct mt76_phy *phy, u32 len); + +-#ifdef CONFIG_MT76_NPU ++#if IS_ENABLED(CONFIG_MT76_NPU) + void mt76_npu_check_ppe(struct mt76_dev *dev, struct sk_buff *skb, + u32 info); + int mt76_npu_dma_add_buf(struct mt76_phy *phy, struct mt76_queue *q, +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig +index 5503d03bf62c65..5742bce12fbb58 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/Kconfig +@@ -16,6 +16,6 @@ config MT7996E + config MT7996_NPU + bool "MT7996 (PCIe) NPU support" + depends on MT7996E +- depends on NET_AIROHA_NPU=y || MT7996E=NET_AIROHA_NPU ++ depends on NET_AIROHA_NPU=y || MT76_CORE=NET_AIROHA_NPU + select MT76_NPU + default n +-- +2.53.0 + diff --git a/queue-7.1/wifi-mt76-mt7915-guard-he-capability-lookups.patch b/queue-7.1/wifi-mt76-mt7915-guard-he-capability-lookups.patch new file mode 100644 index 0000000000..44dd0c95f9 --- /dev/null +++ b/queue-7.1/wifi-mt76-mt7915-guard-he-capability-lookups.patch @@ -0,0 +1,90 @@ +From 9523135fafca127bc4f60aa894beb5beed41191f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 20 Jun 2026 23:53:32 +0800 +Subject: wifi: mt76: mt7915: guard HE capability lookups + +From: Ruoyu Wang + +[ Upstream commit 8e9db062654a388d0fa587acbeeae68dd33eba41 ] + +mt7915_mcu_bss_he_tlv() and mt7915_mcu_sta_bfer_tlv() both run after +checking HE support, then dereference the HE PHY capability returned by +mt76_connac_get_he_phy_cap(). That helper can return NULL when no +capability entry matches the vif type. + +Fetch the capability before appending the TLV and skip the HE-specific +setup when no matching capability is available. + +Fixes: e6d557a78b60 ("mt76: mt7915: rely on mt76_connac_get_phy utilities") +Signed-off-by: Ruoyu Wang +Acked-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260620155332.81120-1-ruoyuw560@gmail.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +index 318c3814946372..391c9167513075 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +@@ -595,6 +595,8 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!cap) ++ return; + + tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he)); + +@@ -1177,13 +1179,12 @@ mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy, + } + + static void +-mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, +- struct mt7915_phy *phy, struct sta_rec_bf *bf) ++mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, ++ const struct ieee80211_sta_he_cap *vc, ++ struct sta_rec_bf *bf) + { + struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap; + struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; +- const struct ieee80211_sta_he_cap *vc = +- mt76_connac_get_he_phy_cap(phy->mt76, vif); + const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; + u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); + u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map); +@@ -1242,6 +1243,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + { + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_phy *phy = mvif->phy; ++ const struct ieee80211_sta_he_cap *vc = NULL; + int tx_ant = hweight8(phy->mt76->chainmask) - 1; + struct sta_rec_bf *bf; + struct tlv *tlv; +@@ -1260,6 +1262,12 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + if (!ebf && !dev->ibf) + return; + ++ if (sta->deflink.he_cap.has_he && ebf) { ++ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!vc) ++ return; ++ } ++ + tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); + bf = (struct sta_rec_bf *)tlv; + +@@ -1268,7 +1276,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, + * ht: iBF only, since mac80211 lacks of eBF support + */ + if (sta->deflink.he_cap.has_he && ebf) +- mt7915_mcu_sta_bfer_he(sta, vif, phy, bf); ++ mt7915_mcu_sta_bfer_he(sta, vc, bf); + else if (sta->deflink.vht_cap.vht_supported) + mt7915_mcu_sta_bfer_vht(sta, phy, bf, ebf); + else if (sta->deflink.ht_cap.ht_supported) +-- +2.53.0 + diff --git a/queue-7.1/wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch b/queue-7.1/wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch new file mode 100644 index 0000000000..6cd76b9d53 --- /dev/null +++ b/queue-7.1/wifi-mt76-mt7925-fix-crash-in-reset-link-replay.patch @@ -0,0 +1,55 @@ +From a57c728a41d07193ede80d4c2879656946b78513 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jun 2026 11:10:16 -0500 +Subject: wifi: mt76: mt7925: fix crash in reset link replay + +From: Sean Wang + +[ Upstream commit bd8b2ec838184236c3fcbf738a926328836adf12 ] + +During reset recovery, mt7925_vif_connect_iter() replays firmware state +for links tracked in mvif->valid_links. After MLO link changes or MCU +timeout recovery, the driver bitmap can temporarily contain a link whose +mac80211 bss_conf has already gone away. + +This can pass a NULL bss_conf to mt76_connac_mcu_uni_add_dev(), matching +the crash where x1, the second argument, is NULL: + +pc : mt76_connac_mcu_uni_add_dev+0x8c/0x1f8 [mt76_connac_lib] +lr : mt7925_vif_connect_iter+0x9c/0x168 [mt7925_common] +x2 : ffffff80a77f6018 x1 : 0000000000000000 x0 : ffffff8099402080 +Call trace: +mt76_connac_mcu_uni_add_dev+0x8c/0x1f8 [mt76_connac_lib] +mt7925_vif_connect_iter+0x9c/0x168 [mt7925_common] +mt7925_mac_reset_work+0x264/0x2f8 [mt7925_common] + +Skip missing bss_conf entries before replaying the link. Non-MLO AP/STA +reset replay is unchanged because the helper still returns &vif->bss_conf +for the legacy link. + +Fixes: 14061994184d ("wifi: mt76: mt7925: add link handling in mt7925_vif_connect_iter") +Signed-off-by: Sean Wang +Link: https://patch.msgid.link/20260616161016.19346-1-sean.wang@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +index 50034d7c04f0cf..717c52ad9c1e36 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c +@@ -1275,6 +1275,9 @@ mt7925_vif_connect_iter(void *priv, u8 *mac, + + for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { + bss_conf = mt792x_vif_to_bss_conf(vif, i); ++ if (!bss_conf) ++ continue; ++ + mconf = mt792x_vif_to_link(mvif, i); + + mt76_connac_mcu_uni_add_dev(&dev->mphy, bss_conf, &mconf->mt76, +-- +2.53.0 + diff --git a/queue-7.1/wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch b/queue-7.1/wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..7651e484ea --- /dev/null +++ b/queue-7.1/wifi-mt76-mt7925-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,38 @@ +From ebb17a846415f406672c686682cb9420c31accfb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:00 +0200 +Subject: wifi: mt76: mt7925: fix possible NULL-pointer deref in + mt7925_mcu_bss_he_tlv() + +From: Lorenzo Bianconi + +[ Upstream commit 8d1b6738c1ab48c086b17e7994034aca94258931 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: c948b5da6bbec ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-2-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +index 37cdf3e8a06706..4f20f62fb70a3c 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +@@ -2694,6 +2694,8 @@ mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, link_conf->vif); ++ if (!cap) ++ return; + + tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he)); + +-- +2.53.0 + diff --git a/queue-7.1/wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch b/queue-7.1/wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch new file mode 100644 index 0000000000..7f1549424b --- /dev/null +++ b/queue-7.1/wifi-mt76-mt7925-guard-link-sta-in-decap-offload.patch @@ -0,0 +1,46 @@ +From 533db1ecf38bba2dbcb1b9d861436808bc017be5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 8 Jul 2026 15:55:39 +0800 +Subject: wifi: mt76: mt7925: guard link STA in decap offload + +From: Guangshuo Li + +[ Upstream commit 96ea44f2269f30364cffa054ee3a87e595bef0d4 ] + +mt7925_sta_set_decap_offload() iterates over the vif valid_links mask +when updating decap offload state for an MLO station. The station may not +have a link STA for every valid link of the vif, so mt792x_sta_to_link() +can return NULL for a link that belongs to the vif but not to the station. + +The function currently dereferences mlink before checking whether the +link WCID is ready. If mlink is NULL, setting or clearing +MT_WCID_FLAG_HDR_TRANS dereferences a NULL pointer. + +Skip links without a station link before touching mlink->wcid. + +Fixes: b859ad65309a ("wifi: mt76: mt7925: add link handling in mt7925_sta_set_decap_offload") +Signed-off-by: Guangshuo Li +Link: https://patch.msgid.link/20260708075539.726200-1-lgs201920130244@gmail.com +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7925/main.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c +index 8765121b916a26..e7fb49d0715011 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c +@@ -1678,6 +1678,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, + mconf = mt792x_vif_to_link(mvif, i); + mlink = mt792x_sta_to_link(msta, i); + ++ if (!mlink) ++ continue; ++ + if (enabled) + set_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags); + else +-- +2.53.0 + diff --git a/queue-7.1/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch b/queue-7.1/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch new file mode 100644 index 0000000000..61b7d75b87 --- /dev/null +++ b/queue-7.1/wifi-mt76-mt7996-check-pointer-returned-by-mt76_conn.patch @@ -0,0 +1,60 @@ +From bcee6fc8965f9cf03a61319855a3573f1c826cb7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:01 +0200 +Subject: wifi: mt76: mt7996: check pointer returned by + mt76_connac_get_he_phy_cap() + +From: Lorenzo Bianconi + +[ Upstream commit e858cf6bf99880343348ff1e8c942aaff1d9d592 ] + +mt76_connac_get_he_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: 98686cd21624c ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-3-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +index 2748bfeb479744..a6a21ddd17a2a0 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +@@ -935,6 +935,8 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct tlv *tlv; + + cap = mt76_connac_get_he_phy_cap(phy->mt76, vif); ++ if (!cap) ++ return; + + tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he)); + +@@ -1851,17 +1853,18 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_link_sta *link_sta, + { + struct ieee80211_sta_he_cap *pc = &link_sta->he_cap; + struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; +- const struct ieee80211_sta_he_cap *vc = +- mt76_connac_get_he_phy_cap(phy->mt76, vif); +- const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem; + u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80); + u8 nss_mcs = mt7996_mcu_get_sta_nss(mcs_map); ++ const struct ieee80211_he_cap_elem *ve; ++ const struct ieee80211_sta_he_cap *vc; + u8 snd_dim, sts; + ++ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif); + if (!vc) + return; + + bf->tx_mode = MT_PHY_TYPE_HE_SU; ++ ve = &vc->he_cap_elem; + + mt7996_mcu_sta_sounding_rate(bf, phy); + +-- +2.53.0 + diff --git a/queue-7.1/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch b/queue-7.1/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch new file mode 100644 index 0000000000..5710fc0eb3 --- /dev/null +++ b/queue-7.1/wifi-mt76-mt7996-fix-possible-null-pointer-deref-in-.patch @@ -0,0 +1,51 @@ +From 6a24ef729fa2886299caaa2579d796f37e53b10b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 21 Jun 2026 15:25:02 +0200 +Subject: wifi: mt76: mt7996: fix possible NULL-pointer deref in + mt7996_mcu_sta_bfer_eht() + +From: Lorenzo Bianconi + +[ Upstream commit 2fffc472bec490c8357defcee9c075ca74467352 ] + +mt76_connac_get_eht_phy_cap routine can theoretically return NULL so +check cap pointer before dereferencing it. + +Fixes: ba01944adee9f ("wifi: mt76: mt7996: add EHT beamforming support") +Signed-off-by: Lorenzo Bianconi +Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-4-ed4ccf7a0363@kernel.org +Signed-off-by: Felix Fietkau +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +index a6a21ddd17a2a0..9772475c5e6b28 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c ++++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +@@ -1920,14 +1920,18 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_link_sta *link_sta, + struct ieee80211_sta_eht_cap *pc = &link_sta->eht_cap; + struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; + struct ieee80211_eht_mcs_nss_supp *eht_nss = &pc->eht_mcs_nss_supp; +- const struct ieee80211_sta_eht_cap *vc = +- mt76_connac_get_eht_phy_cap(phy->mt76, vif); +- const struct ieee80211_eht_cap_elem_fixed *ve = &vc->eht_cap_elem; + u8 nss_mcs = u8_get_bits(eht_nss->bw._80.rx_tx_mcs9_max_nss, + IEEE80211_EHT_MCS_NSS_RX) - 1; ++ const struct ieee80211_eht_cap_elem_fixed *ve; ++ const struct ieee80211_sta_eht_cap *vc; + u8 snd_dim, sts; + ++ vc = mt76_connac_get_eht_phy_cap(phy->mt76, vif); ++ if (!vc) ++ return; ++ + bf->tx_mode = MT_PHY_TYPE_EHT_MU; ++ ve = &vc->eht_cap_elem; + + mt7996_mcu_sta_sounding_rate(bf, phy); + +-- +2.53.0 + diff --git a/queue-7.1/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch b/queue-7.1/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch new file mode 100644 index 0000000000..611a07e2a1 --- /dev/null +++ b/queue-7.1/wifi-mwifiex-bound-uap-association-event-ies-to-the-.patch @@ -0,0 +1,104 @@ +From 2d757235c20163d61da7dfeac7ea44b0c66873de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 15 Jul 2026 22:57:11 +0900 +Subject: wifi: mwifiex: bound uAP association event IEs to the event buffer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: HE WEI (ギカク) + +[ Upstream commit f0858bfc7d3cab411a447b88e3ef970e575032c9 ] + +mwifiex_process_uap_event() handles EVENT_UAP_STA_ASSOC by exposing the +(re)association request IEs that the firmware copies into the event: + + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - (u8 *)&event->frame_control; + sinfo->assoc_req_ies_len = le16_to_cpu(event->len) - (u16)len; + +event->len is supplied by the device firmware and is never validated, +and the subtraction is unchecked. assoc_req_ies points into +adapter->event_body[MAX_EVENT_SIZE], a fixed-size array embedded in the +kmalloc()'d struct mwifiex_adapter. + +On the ap_11n_enabled path mwifiex_set_sta_ht_cap() walks these IEs with +cfg80211_find_ie(), whose for_each_element() loop dereferences each +element header. A firmware-reported event->len larger than the bytes +actually received makes assoc_req_ies_len describe IEs that extend past +event_body, so the walk reads out of the adapter slab object, a +slab-out-of-bounds read (KASAN: slab-out-of-bounds in cfg80211_find_ie). +An event->len smaller than the header instead makes the int subtraction +negative, which wraps to a huge size_t when stored in assoc_req_ies_len. +The same length is handed to cfg80211_new_sta(), so a more modest +over-claim can also copy stale event_body bytes into the +NL80211_CMD_NEW_STATION notification. + +A malicious or malfunctioning mwifiex device (USB/SDIO/PCIe) can deliver +such an event while the interface is in AP/uAP mode. + +Validate event->len before use: reject a length that underflows the +header or that would place the IEs outside the event_body[] buffer the +event was copied into. event->len here is struct mwifiex_assoc_event.len, +a payload field internal to this event, not the transport frame length, +so it is validated in this handler rather than at the generic +MWIFIEX_TYPE_EVENT receive path, which only sees the event cause and the +transport frame length. The bound is against event_body[MAX_EVENT_SIZE] +rather than the actually-received length because the transports store the +event differently (USB and SDIO leave the 4-byte event header in +event_skb, PCIe strips it via skb_pull), whereas event_body is the single +fixed buffer all of them copy the event into. This is the event-path +analogue of the receive-path bounds checks added in commit 119585281617 +("wifi: mwifiex: Fix OOB and integer underflow when rx packets"). + +Fixes: e568634ae7ac ("mwifiex: add AP event handling framework") +Signed-off-by: HE WEI (ギカク) +Reviewed-by: Francesco Dolcini +Link: https://patch.msgid.link/20260715135711.34688-1-skyexpoc@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + .../net/wireless/marvell/mwifiex/uap_event.c | 24 +++++++++++++++++-- + 1 file changed, 22 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c +index 679fdae0f001a1..ba1bdbbff687be 100644 +--- a/drivers/net/wireless/marvell/mwifiex/uap_event.c ++++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c +@@ -123,11 +123,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) + len = ETH_ALEN; + + if (len != -1) { ++ u16 evt_len = le16_to_cpu(event->len); ++ + sinfo->assoc_req_ies = &event->data[len]; + len = (u8 *)sinfo->assoc_req_ies - + (u8 *)&event->frame_control; +- sinfo->assoc_req_ies_len = +- le16_to_cpu(event->len) - (u16)len; ++ ++ /* ++ * event->len is reported by the device firmware ++ * and is not otherwise validated. Reject a ++ * length that underflows the header, or that ++ * would place the association request IEs ++ * outside the fixed-size event_body[] buffer the ++ * event was copied into; otherwise the IE walk ++ * in mwifiex_set_sta_ht_cap() reads past ++ * event_body and out of the adapter slab object. ++ */ ++ if (evt_len < len || ++ (u8 *)&event->frame_control + evt_len > ++ adapter->event_body + MAX_EVENT_SIZE) { ++ mwifiex_dbg(adapter, ERROR, ++ "invalid STA assoc event length\n"); ++ kfree(sinfo); ++ return -1; ++ } ++ sinfo->assoc_req_ies_len = evt_len - (u16)len; + } + } + cfg80211_new_sta(priv->netdev->ieee80211_ptr, event->sta_addr, +-- +2.53.0 +