From 417b7736fe8087d8a8219c1f81ed85faa5942364 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 7 Jul 2025 20:37:05 -0400 Subject: [PATCH] Fixes for 6.1 Signed-off-by: Sasha Levin --- ...record_snapshot_destroy-during-rmdir.patch | 65 +++++ .../dpaa2-eth-fix-xdp_rxq_info-leak.patch | 101 +++++++ ...-interrupts-before-resetting-the-gpu.patch | 209 +++++++++++++++ ...fix-warn-in-__netif_napi_del_locked-.patch | 96 +++++++ ...fix-handling-of-nfs-level-errors-in-.patch | 250 ++++++++++++++++++ ...l-wmi-sysman-fix-class-device-unregi.patch | 52 ++++ ...nk-lmi-fix-class-device-unregistrati.patch | 52 ++++ ...le-function-handles-in-error-handlin.patch | 71 +++++ queue-6.1/series | 9 + ...e-the-received-length-does-not-excee.patch | 115 ++++++++ 10 files changed, 1020 insertions(+) create mode 100644 queue-6.1/btrfs-use-btrfs_record_snapshot_destroy-during-rmdir.patch create mode 100644 queue-6.1/dpaa2-eth-fix-xdp_rxq_info-leak.patch create mode 100644 queue-6.1/drm-v3d-disable-interrupts-before-resetting-the-gpu.patch create mode 100644 queue-6.1/net-usb-lan78xx-fix-warn-in-__netif_napi_del_locked-.patch create mode 100644 queue-6.1/nfsv4-flexfiles-fix-handling-of-nfs-level-errors-in-.patch create mode 100644 queue-6.1/platform-x86-dell-wmi-sysman-fix-class-device-unregi.patch create mode 100644 queue-6.1/platform-x86-think-lmi-fix-class-device-unregistrati.patch create mode 100644 queue-6.1/s390-pci-fix-stale-function-handles-in-error-handlin.patch create mode 100644 queue-6.1/virtio-net-ensure-the-received-length-does-not-excee.patch diff --git a/queue-6.1/btrfs-use-btrfs_record_snapshot_destroy-during-rmdir.patch b/queue-6.1/btrfs-use-btrfs_record_snapshot_destroy-during-rmdir.patch new file mode 100644 index 0000000000..12d518e27e --- /dev/null +++ b/queue-6.1/btrfs-use-btrfs_record_snapshot_destroy-during-rmdir.patch @@ -0,0 +1,65 @@ +From af790cdd2e61f13f3dbb692af153aba1a126a96e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Jun 2025 16:37:01 +0100 +Subject: btrfs: use btrfs_record_snapshot_destroy() during rmdir + +From: Filipe Manana + +[ Upstream commit 157501b0469969fc1ba53add5049575aadd79d80 ] + +We are setting the parent directory's last_unlink_trans directly which +may result in a concurrent task starting to log the directory not see the +update and therefore can log the directory after we removed a child +directory which had a snapshot within instead of falling back to a +transaction commit. Replaying such a log tree would result in a mount +failure since we can't currently delete snapshots (and subvolumes) during +log replay. This is the type of failure described in commit 1ec9a1ae1e30 +("Btrfs: fix unreplayable log after snapshot delete + parent dir fsync"). + +Fix this by using btrfs_record_snapshot_destroy() which updates the +last_unlink_trans field while holding the inode's log_mutex lock. + +Fixes: 44f714dae50a ("Btrfs: improve performance on fsync against new inode after rename/unlink") +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Sasha Levin +--- + fs/btrfs/inode.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index f7f97cd3cdf06..5ecc2f3dc3a99 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -4856,7 +4856,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) + struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info; + int err = 0; + struct btrfs_trans_handle *trans; +- u64 last_unlink_trans; + struct fscrypt_name fname; + + if (inode->i_size > BTRFS_EMPTY_DIR_SIZE) +@@ -4891,8 +4890,6 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) + if (err) + goto out; + +- last_unlink_trans = BTRFS_I(inode)->last_unlink_trans; +- + /* now the directory is empty */ + err = btrfs_unlink_inode(trans, BTRFS_I(dir), BTRFS_I(d_inode(dentry)), + &fname.disk_name); +@@ -4909,8 +4906,8 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) + * 5) mkdir foo + * 6) fsync foo or some file inside foo + */ +- if (last_unlink_trans >= trans->transid) +- BTRFS_I(dir)->last_unlink_trans = last_unlink_trans; ++ if (BTRFS_I(inode)->last_unlink_trans >= trans->transid) ++ btrfs_record_snapshot_destroy(trans, BTRFS_I(dir)); + } + out: + btrfs_end_transaction(trans); +-- +2.39.5 + diff --git a/queue-6.1/dpaa2-eth-fix-xdp_rxq_info-leak.patch b/queue-6.1/dpaa2-eth-fix-xdp_rxq_info-leak.patch new file mode 100644 index 0000000000..54206caa4b --- /dev/null +++ b/queue-6.1/dpaa2-eth-fix-xdp_rxq_info-leak.patch @@ -0,0 +1,101 @@ +From 349212293e1f0b0773593a4d6b329ea191002aaf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Jul 2025 12:34:31 -0400 +Subject: dpaa2-eth: fix xdp_rxq_info leak + +From: Fushuai Wang + +[ Upstream commit 2def09ead4ad5907988b655d1e1454003aaf8297 ] + +The driver registered xdp_rxq_info structures via xdp_rxq_info_reg() +but failed to properly unregister them in error paths and during +removal. + +Fixes: d678be1dc1ec ("dpaa2-eth: add XDP_REDIRECT support") +Signed-off-by: Fushuai Wang +Reviewed-by: Simon Horman +Reviewed-by: Ioana Ciornei +Link: https://patch.msgid.link/20250626133003.80136-1-wangfushuai@baidu.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../net/ethernet/freescale/dpaa2/dpaa2-eth.c | 26 +++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +index bbbe7c5b5d35a..5ef117c9d0eca 100644 +--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c ++++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +@@ -3729,6 +3729,7 @@ static int dpaa2_eth_setup_rx_flow(struct dpaa2_eth_priv *priv, + MEM_TYPE_PAGE_ORDER0, NULL); + if (err) { + dev_err(dev, "xdp_rxq_info_reg_mem_model failed\n"); ++ xdp_rxq_info_unreg(&fq->channel->xdp_rxq); + return err; + } + +@@ -4221,17 +4222,25 @@ static int dpaa2_eth_bind_dpni(struct dpaa2_eth_priv *priv) + return -EINVAL; + } + if (err) +- return err; ++ goto out; + } + + err = dpni_get_qdid(priv->mc_io, 0, priv->mc_token, + DPNI_QUEUE_TX, &priv->tx_qdid); + if (err) { + dev_err(dev, "dpni_get_qdid() failed\n"); +- return err; ++ goto out; + } + + return 0; ++ ++out: ++ while (i--) { ++ if (priv->fq[i].type == DPAA2_RX_FQ && ++ xdp_rxq_info_is_reg(&priv->fq[i].channel->xdp_rxq)) ++ xdp_rxq_info_unreg(&priv->fq[i].channel->xdp_rxq); ++ } ++ return err; + } + + /* Allocate rings for storing incoming frame descriptors */ +@@ -4588,6 +4597,17 @@ static void dpaa2_eth_del_ch_napi(struct dpaa2_eth_priv *priv) + } + } + ++static void dpaa2_eth_free_rx_xdp_rxq(struct dpaa2_eth_priv *priv) ++{ ++ int i; ++ ++ for (i = 0; i < priv->num_fqs; i++) { ++ if (priv->fq[i].type == DPAA2_RX_FQ && ++ xdp_rxq_info_is_reg(&priv->fq[i].channel->xdp_rxq)) ++ xdp_rxq_info_unreg(&priv->fq[i].channel->xdp_rxq); ++ } ++} ++ + static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev) + { + struct device *dev; +@@ -4786,6 +4806,7 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev) + free_percpu(priv->percpu_stats); + err_alloc_percpu_stats: + dpaa2_eth_del_ch_napi(priv); ++ dpaa2_eth_free_rx_xdp_rxq(priv); + err_bind: + dpaa2_eth_free_dpbp(priv); + err_dpbp_setup: +@@ -4840,6 +4861,7 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev) + free_percpu(priv->percpu_extras); + + dpaa2_eth_del_ch_napi(priv); ++ dpaa2_eth_free_rx_xdp_rxq(priv); + dpaa2_eth_free_dpbp(priv); + dpaa2_eth_free_dpio(priv); + dpaa2_eth_free_dpni(priv); +-- +2.39.5 + diff --git a/queue-6.1/drm-v3d-disable-interrupts-before-resetting-the-gpu.patch b/queue-6.1/drm-v3d-disable-interrupts-before-resetting-the-gpu.patch new file mode 100644 index 0000000000..e2484d20f3 --- /dev/null +++ b/queue-6.1/drm-v3d-disable-interrupts-before-resetting-the-gpu.patch @@ -0,0 +1,209 @@ +From d501c92864a6bfc47ad73c441701144c42ed5c0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 28 Jun 2025 19:42:42 -0300 +Subject: drm/v3d: Disable interrupts before resetting the GPU +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maíra Canal + +[ Upstream commit 226862f50a7a88e4e4de9abbf36c64d19acd6fd0 ] + +Currently, an interrupt can be triggered during a GPU reset, which can +lead to GPU hangs and NULL pointer dereference in an interrupt context +as shown in the following trace: + + [ 314.035040] Unable to handle kernel NULL pointer dereference at virtual address 00000000000000c0 + [ 314.043822] Mem abort info: + [ 314.046606] ESR = 0x0000000096000005 + [ 314.050347] EC = 0x25: DABT (current EL), IL = 32 bits + [ 314.055651] SET = 0, FnV = 0 + [ 314.058695] EA = 0, S1PTW = 0 + [ 314.061826] FSC = 0x05: level 1 translation fault + [ 314.066694] Data abort info: + [ 314.069564] ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000 + [ 314.075039] CM = 0, WnR = 0, TnD = 0, TagAccess = 0 + [ 314.080080] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 + [ 314.085382] user pgtable: 4k pages, 39-bit VAs, pgdp=0000000102728000 + [ 314.091814] [00000000000000c0] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000 + [ 314.100511] Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP + [ 314.106770] Modules linked in: v3d i2c_brcmstb vc4 snd_soc_hdmi_codec gpu_sched drm_shmem_helper drm_display_helper cec drm_dma_helper drm_kms_helper drm drm_panel_orientation_quirks snd_soc_core snd_compress snd_pcm_dmaengine snd_pcm snd_timer snd backlight + [ 314.129654] CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 6.12.25+rpt-rpi-v8 #1 Debian 1:6.12.25-1+rpt1 + [ 314.139388] Hardware name: Raspberry Pi 4 Model B Rev 1.4 (DT) + [ 314.145211] pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) + [ 314.152165] pc : v3d_irq+0xec/0x2e0 [v3d] + [ 314.156187] lr : v3d_irq+0xe0/0x2e0 [v3d] + [ 314.160198] sp : ffffffc080003ea0 + [ 314.163502] x29: ffffffc080003ea0 x28: ffffffec1f184980 x27: 021202b000000000 + [ 314.170633] x26: ffffffec1f17f630 x25: ffffff8101372000 x24: ffffffec1f17d9f0 + [ 314.177764] x23: 000000000000002a x22: 000000000000002a x21: ffffff8103252000 + [ 314.184895] x20: 0000000000000001 x19: 00000000deadbeef x18: 0000000000000000 + [ 314.192026] x17: ffffff94e51d2000 x16: ffffffec1dac3cb0 x15: c306000000000000 + [ 314.199156] x14: 0000000000000000 x13: b2fc982e03cc5168 x12: 0000000000000001 + [ 314.206286] x11: ffffff8103f8bcc0 x10: ffffffec1f196868 x9 : ffffffec1dac3874 + [ 314.213416] x8 : 0000000000000000 x7 : 0000000000042a3a x6 : ffffff810017a180 + [ 314.220547] x5 : ffffffec1ebad400 x4 : ffffffec1ebad320 x3 : 00000000000bebeb + [ 314.227677] x2 : 0000000000000000 x1 : 0000000000000000 x0 : 0000000000000000 + [ 314.234807] Call trace: + [ 314.237243] v3d_irq+0xec/0x2e0 [v3d] + [ 314.240906] __handle_irq_event_percpu+0x58/0x218 + [ 314.245609] handle_irq_event+0x54/0xb8 + [ 314.249439] handle_fasteoi_irq+0xac/0x240 + [ 314.253527] handle_irq_desc+0x48/0x68 + [ 314.257269] generic_handle_domain_irq+0x24/0x38 + [ 314.261879] gic_handle_irq+0x48/0xd8 + [ 314.265533] call_on_irq_stack+0x24/0x58 + [ 314.269448] do_interrupt_handler+0x88/0x98 + [ 314.273624] el1_interrupt+0x34/0x68 + [ 314.277193] el1h_64_irq_handler+0x18/0x28 + [ 314.281281] el1h_64_irq+0x64/0x68 + [ 314.284673] default_idle_call+0x3c/0x168 + [ 314.288675] do_idle+0x1fc/0x230 + [ 314.291895] cpu_startup_entry+0x3c/0x50 + [ 314.295810] rest_init+0xe4/0xf0 + [ 314.299030] start_kernel+0x5e8/0x790 + [ 314.302684] __primary_switched+0x80/0x90 + [ 314.306691] Code: 940029eb 360ffc13 f9442ea0 52800001 (f9406017) + [ 314.312775] ---[ end trace 0000000000000000 ]--- + [ 314.317384] Kernel panic - not syncing: Oops: Fatal exception in interrupt + [ 314.324249] SMP: stopping secondary CPUs + [ 314.328167] Kernel Offset: 0x2b9da00000 from 0xffffffc080000000 + [ 314.334076] PHYS_OFFSET: 0x0 + [ 314.336946] CPU features: 0x08,00002013,c0200000,0200421b + [ 314.342337] Memory Limit: none + [ 314.345382] ---[ end Kernel panic - not syncing: Oops: Fatal exception in interrupt ]--- + +Before resetting the GPU, it's necessary to disable all interrupts and +deal with any interrupt handler still in-flight. Otherwise, the GPU might +reset with jobs still running, or yet, an interrupt could be handled +during the reset. + +Cc: stable@vger.kernel.org +Fixes: 57692c94dcbe ("drm/v3d: Introduce a new DRM driver for Broadcom V3D V3.x+") +Reviewed-by: Juan A. Suarez +Reviewed-by: Iago Toral Quiroga +Link: https://lore.kernel.org/r/20250628224243.47599-1-mcanal@igalia.com +Signed-off-by: Maíra Canal +Signed-off-by: Sasha Levin +--- + drivers/gpu/drm/v3d/v3d_drv.h | 8 ++++++++ + drivers/gpu/drm/v3d/v3d_gem.c | 2 ++ + drivers/gpu/drm/v3d/v3d_irq.c | 37 +++++++++++++++++++++++++---------- + 3 files changed, 37 insertions(+), 10 deletions(-) + +diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h +index b74b1351bfc83..a366ea208787d 100644 +--- a/drivers/gpu/drm/v3d/v3d_drv.h ++++ b/drivers/gpu/drm/v3d/v3d_drv.h +@@ -62,6 +62,12 @@ struct v3d_perfmon { + u64 values[]; + }; + ++enum v3d_irq { ++ V3D_CORE_IRQ, ++ V3D_HUB_IRQ, ++ V3D_MAX_IRQS, ++}; ++ + struct v3d_dev { + struct drm_device drm; + +@@ -71,6 +77,8 @@ struct v3d_dev { + int ver; + bool single_irq_line; + ++ int irq[V3D_MAX_IRQS]; ++ + void __iomem *hub_regs; + void __iomem *core_regs[3]; + void __iomem *bridge_regs; +diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c +index b8980440d137f..8b6450a96ebc3 100644 +--- a/drivers/gpu/drm/v3d/v3d_gem.c ++++ b/drivers/gpu/drm/v3d/v3d_gem.c +@@ -119,6 +119,8 @@ v3d_reset(struct v3d_dev *v3d) + if (false) + v3d_idle_axi(v3d, 0); + ++ v3d_irq_disable(v3d); ++ + v3d_idle_gca(v3d); + v3d_reset_v3d(v3d); + +diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c +index b2d59a1686972..641315dbee8b2 100644 +--- a/drivers/gpu/drm/v3d/v3d_irq.c ++++ b/drivers/gpu/drm/v3d/v3d_irq.c +@@ -215,7 +215,7 @@ v3d_hub_irq(int irq, void *arg) + int + v3d_irq_init(struct v3d_dev *v3d) + { +- int irq1, ret, core; ++ int irq, ret, core; + + INIT_WORK(&v3d->overflow_mem_work, v3d_overflow_mem_work); + +@@ -226,17 +226,24 @@ v3d_irq_init(struct v3d_dev *v3d) + V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS); + V3D_WRITE(V3D_HUB_INT_CLR, V3D_HUB_IRQS); + +- irq1 = platform_get_irq_optional(v3d_to_pdev(v3d), 1); +- if (irq1 == -EPROBE_DEFER) +- return irq1; +- if (irq1 > 0) { +- ret = devm_request_irq(v3d->drm.dev, irq1, ++ irq = platform_get_irq_optional(v3d_to_pdev(v3d), 1); ++ if (irq == -EPROBE_DEFER) ++ return irq; ++ if (irq > 0) { ++ v3d->irq[V3D_CORE_IRQ] = irq; ++ ++ ret = devm_request_irq(v3d->drm.dev, v3d->irq[V3D_CORE_IRQ], + v3d_irq, IRQF_SHARED, + "v3d_core0", v3d); + if (ret) + goto fail; +- ret = devm_request_irq(v3d->drm.dev, +- platform_get_irq(v3d_to_pdev(v3d), 0), ++ ++ irq = platform_get_irq(v3d_to_pdev(v3d), 0); ++ if (irq < 0) ++ return irq; ++ v3d->irq[V3D_HUB_IRQ] = irq; ++ ++ ret = devm_request_irq(v3d->drm.dev, v3d->irq[V3D_HUB_IRQ], + v3d_hub_irq, IRQF_SHARED, + "v3d_hub", v3d); + if (ret) +@@ -244,8 +251,12 @@ v3d_irq_init(struct v3d_dev *v3d) + } else { + v3d->single_irq_line = true; + +- ret = devm_request_irq(v3d->drm.dev, +- platform_get_irq(v3d_to_pdev(v3d), 0), ++ irq = platform_get_irq(v3d_to_pdev(v3d), 0); ++ if (irq < 0) ++ return irq; ++ v3d->irq[V3D_CORE_IRQ] = irq; ++ ++ ret = devm_request_irq(v3d->drm.dev, v3d->irq[V3D_CORE_IRQ], + v3d_irq, IRQF_SHARED, + "v3d", v3d); + if (ret) +@@ -286,6 +297,12 @@ v3d_irq_disable(struct v3d_dev *v3d) + V3D_CORE_WRITE(core, V3D_CTL_INT_MSK_SET, ~0); + V3D_WRITE(V3D_HUB_INT_MSK_SET, ~0); + ++ /* Finish any interrupt handler still in flight. */ ++ for (int i = 0; i < V3D_MAX_IRQS; i++) { ++ if (v3d->irq[i]) ++ synchronize_irq(v3d->irq[i]); ++ } ++ + /* Clear any pending interrupts we might have left. */ + for (core = 0; core < v3d->cores; core++) + V3D_CORE_WRITE(core, V3D_CTL_INT_CLR, V3D_CORE_IRQS); +-- +2.39.5 + diff --git a/queue-6.1/net-usb-lan78xx-fix-warn-in-__netif_napi_del_locked-.patch b/queue-6.1/net-usb-lan78xx-fix-warn-in-__netif_napi_del_locked-.patch new file mode 100644 index 0000000000..6fd7e3deba --- /dev/null +++ b/queue-6.1/net-usb-lan78xx-fix-warn-in-__netif_napi_del_locked-.patch @@ -0,0 +1,96 @@ +From 5904a8ad2b3e05b659d59973afcc26f1cc8013ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 27 Jun 2025 07:13:46 +0200 +Subject: net: usb: lan78xx: fix WARN in __netif_napi_del_locked on disconnect + +From: Oleksij Rempel + +[ Upstream commit 6c7ffc9af7186ed79403a3ffee9a1e5199fc7450 ] + +Remove redundant netif_napi_del() call from disconnect path. + +A WARN may be triggered in __netif_napi_del_locked() during USB device +disconnect: + + WARNING: CPU: 0 PID: 11 at net/core/dev.c:7417 __netif_napi_del_locked+0x2b4/0x350 + +This happens because netif_napi_del() is called in the disconnect path while +NAPI is still enabled. However, it is not necessary to call netif_napi_del() +explicitly, since unregister_netdev() will handle NAPI teardown automatically +and safely. Removing the redundant call avoids triggering the warning. + +Full trace: + lan78xx 1-1:1.0 enu1: Failed to read register index 0x000000c4. ret = -ENODEV + lan78xx 1-1:1.0 enu1: Failed to set MAC down with error -ENODEV + lan78xx 1-1:1.0 enu1: Link is Down + lan78xx 1-1:1.0 enu1: Failed to read register index 0x00000120. ret = -ENODEV + ------------[ cut here ]------------ + WARNING: CPU: 0 PID: 11 at net/core/dev.c:7417 __netif_napi_del_locked+0x2b4/0x350 + Modules linked in: flexcan can_dev fuse + CPU: 0 UID: 0 PID: 11 Comm: kworker/0:1 Not tainted 6.16.0-rc2-00624-ge926949dab03 #9 PREEMPT + Hardware name: SKOV IMX8MP CPU revC - bd500 (DT) + Workqueue: usb_hub_wq hub_event + pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : __netif_napi_del_locked+0x2b4/0x350 + lr : __netif_napi_del_locked+0x7c/0x350 + sp : ffffffc085b673c0 + x29: ffffffc085b673c0 x28: ffffff800b7f2000 x27: ffffff800b7f20d8 + x26: ffffff80110bcf58 x25: ffffff80110bd978 x24: 1ffffff0022179eb + x23: ffffff80110bc000 x22: ffffff800b7f5000 x21: ffffff80110bc000 + x20: ffffff80110bcf38 x19: ffffff80110bcf28 x18: dfffffc000000000 + x17: ffffffc081578940 x16: ffffffc08284cee0 x15: 0000000000000028 + x14: 0000000000000006 x13: 0000000000040000 x12: ffffffb0022179e8 + x11: 1ffffff0022179e7 x10: ffffffb0022179e7 x9 : dfffffc000000000 + x8 : 0000004ffdde8619 x7 : ffffff80110bcf3f x6 : 0000000000000001 + x5 : ffffff80110bcf38 x4 : ffffff80110bcf38 x3 : 0000000000000000 + x2 : 0000000000000000 x1 : 1ffffff0022179e7 x0 : 0000000000000000 + Call trace: + __netif_napi_del_locked+0x2b4/0x350 (P) + lan78xx_disconnect+0xf4/0x360 + usb_unbind_interface+0x158/0x718 + device_remove+0x100/0x150 + device_release_driver_internal+0x308/0x478 + device_release_driver+0x1c/0x30 + bus_remove_device+0x1a8/0x368 + device_del+0x2e0/0x7b0 + usb_disable_device+0x244/0x540 + usb_disconnect+0x220/0x758 + hub_event+0x105c/0x35e0 + process_one_work+0x760/0x17b0 + worker_thread+0x768/0xce8 + kthread+0x3bc/0x690 + ret_from_fork+0x10/0x20 + irq event stamp: 211604 + hardirqs last enabled at (211603): [] _raw_spin_unlock_irqrestore+0x84/0x98 + hardirqs last disabled at (211604): [] el1_dbg+0x24/0x80 + softirqs last enabled at (211296): [] handle_softirqs+0x820/0xbc8 + softirqs last disabled at (210993): [] __do_softirq+0x18/0x20 + ---[ end trace 0000000000000000 ]--- + lan78xx 1-1:1.0 enu1: failed to kill vid 0081/0 + +Fixes: ec4c7e12396b ("lan78xx: Introduce NAPI polling support") +Suggested-by: Jakub Kicinski +Signed-off-by: Oleksij Rempel +Link: https://patch.msgid.link/20250627051346.276029-1-o.rempel@pengutronix.de +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/usb/lan78xx.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c +index feff1265cad6f..0f1c9009d793e 100644 +--- a/drivers/net/usb/lan78xx.c ++++ b/drivers/net/usb/lan78xx.c +@@ -4231,8 +4231,6 @@ static void lan78xx_disconnect(struct usb_interface *intf) + + set_bit(EVENT_DEV_DISCONNECT, &dev->flags); + +- netif_napi_del(&dev->napi); +- + udev = interface_to_usbdev(intf); + net = dev->net; + +-- +2.39.5 + diff --git a/queue-6.1/nfsv4-flexfiles-fix-handling-of-nfs-level-errors-in-.patch b/queue-6.1/nfsv4-flexfiles-fix-handling-of-nfs-level-errors-in-.patch new file mode 100644 index 0000000000..50132245b3 --- /dev/null +++ b/queue-6.1/nfsv4-flexfiles-fix-handling-of-nfs-level-errors-in-.patch @@ -0,0 +1,250 @@ +From df3da4f9d578ed1acfe55d1a2bcc178060f031ab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 19 Jun 2025 15:16:11 -0400 +Subject: NFSv4/flexfiles: Fix handling of NFS level errors in I/O + +From: Trond Myklebust + +[ Upstream commit 38074de35b015df5623f524d6f2b49a0cd395c40 ] + +Allow the flexfiles error handling to recognise NFS level errors (as +opposed to RPC level errors) and handle them separately. The main +motivator is the NFSERR_PERM errors that get returned if the NFS client +connects to the data server through a port number that is lower than +1024. In that case, the client should disconnect and retry a READ on a +different data server, or it should retry a WRITE after reconnecting. + +Reviewed-by: Tigran Mkrtchyan +Fixes: d67ae825a59d ("pnfs/flexfiles: Add the FlexFile Layout Driver") +Signed-off-by: Trond Myklebust +Signed-off-by: Anna Schumaker +Signed-off-by: Sasha Levin +--- + fs/nfs/flexfilelayout/flexfilelayout.c | 121 ++++++++++++++++++------- + 1 file changed, 87 insertions(+), 34 deletions(-) + +diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c +index 07e5ea64dcd68..aa55b5df065bc 100644 +--- a/fs/nfs/flexfilelayout/flexfilelayout.c ++++ b/fs/nfs/flexfilelayout/flexfilelayout.c +@@ -1096,6 +1096,7 @@ static void ff_layout_reset_read(struct nfs_pgio_header *hdr) + } + + static int ff_layout_async_handle_error_v4(struct rpc_task *task, ++ u32 op_status, + struct nfs4_state *state, + struct nfs_client *clp, + struct pnfs_layout_segment *lseg, +@@ -1106,32 +1107,42 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, + struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx); + struct nfs4_slot_table *tbl = &clp->cl_session->fc_slot_table; + +- switch (task->tk_status) { +- case -NFS4ERR_BADSESSION: +- case -NFS4ERR_BADSLOT: +- case -NFS4ERR_BAD_HIGH_SLOT: +- case -NFS4ERR_DEADSESSION: +- case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: +- case -NFS4ERR_SEQ_FALSE_RETRY: +- case -NFS4ERR_SEQ_MISORDERED: ++ switch (op_status) { ++ case NFS4_OK: ++ case NFS4ERR_NXIO: ++ break; ++ case NFSERR_PERM: ++ if (!task->tk_xprt) ++ break; ++ xprt_force_disconnect(task->tk_xprt); ++ goto out_retry; ++ case NFS4ERR_BADSESSION: ++ case NFS4ERR_BADSLOT: ++ case NFS4ERR_BAD_HIGH_SLOT: ++ case NFS4ERR_DEADSESSION: ++ case NFS4ERR_CONN_NOT_BOUND_TO_SESSION: ++ case NFS4ERR_SEQ_FALSE_RETRY: ++ case NFS4ERR_SEQ_MISORDERED: + dprintk("%s ERROR %d, Reset session. Exchangeid " + "flags 0x%x\n", __func__, task->tk_status, + clp->cl_exchange_flags); + nfs4_schedule_session_recovery(clp->cl_session, task->tk_status); +- break; +- case -NFS4ERR_DELAY: +- case -NFS4ERR_GRACE: ++ goto out_retry; ++ case NFS4ERR_DELAY: ++ nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY); ++ fallthrough; ++ case NFS4ERR_GRACE: + rpc_delay(task, FF_LAYOUT_POLL_RETRY_MAX); +- break; +- case -NFS4ERR_RETRY_UNCACHED_REP: +- break; ++ goto out_retry; ++ case NFS4ERR_RETRY_UNCACHED_REP: ++ goto out_retry; + /* Invalidate Layout errors */ +- case -NFS4ERR_PNFS_NO_LAYOUT: +- case -ESTALE: /* mapped NFS4ERR_STALE */ +- case -EBADHANDLE: /* mapped NFS4ERR_BADHANDLE */ +- case -EISDIR: /* mapped NFS4ERR_ISDIR */ +- case -NFS4ERR_FHEXPIRED: +- case -NFS4ERR_WRONG_TYPE: ++ case NFS4ERR_PNFS_NO_LAYOUT: ++ case NFS4ERR_STALE: ++ case NFS4ERR_BADHANDLE: ++ case NFS4ERR_ISDIR: ++ case NFS4ERR_FHEXPIRED: ++ case NFS4ERR_WRONG_TYPE: + dprintk("%s Invalid layout error %d\n", __func__, + task->tk_status); + /* +@@ -1144,6 +1155,11 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, + pnfs_destroy_layout(NFS_I(inode)); + rpc_wake_up(&tbl->slot_tbl_waitq); + goto reset; ++ default: ++ break; ++ } ++ ++ switch (task->tk_status) { + /* RPC connection errors */ + case -ECONNREFUSED: + case -EHOSTDOWN: +@@ -1159,26 +1175,56 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, + nfs4_delete_deviceid(devid->ld, devid->nfs_client, + &devid->deviceid); + rpc_wake_up(&tbl->slot_tbl_waitq); +- fallthrough; ++ break; + default: +- if (ff_layout_avoid_mds_available_ds(lseg)) +- return -NFS4ERR_RESET_TO_PNFS; +-reset: +- dprintk("%s Retry through MDS. Error %d\n", __func__, +- task->tk_status); +- return -NFS4ERR_RESET_TO_MDS; ++ break; + } ++ ++ if (ff_layout_avoid_mds_available_ds(lseg)) ++ return -NFS4ERR_RESET_TO_PNFS; ++reset: ++ dprintk("%s Retry through MDS. Error %d\n", __func__, ++ task->tk_status); ++ return -NFS4ERR_RESET_TO_MDS; ++ ++out_retry: + task->tk_status = 0; + return -EAGAIN; + } + + /* Retry all errors through either pNFS or MDS except for -EJUKEBOX */ + static int ff_layout_async_handle_error_v3(struct rpc_task *task, ++ u32 op_status, ++ struct nfs_client *clp, + struct pnfs_layout_segment *lseg, + u32 idx) + { + struct nfs4_deviceid_node *devid = FF_LAYOUT_DEVID_NODE(lseg, idx); + ++ switch (op_status) { ++ case NFS_OK: ++ case NFSERR_NXIO: ++ break; ++ case NFSERR_PERM: ++ if (!task->tk_xprt) ++ break; ++ xprt_force_disconnect(task->tk_xprt); ++ goto out_retry; ++ case NFSERR_ACCES: ++ case NFSERR_BADHANDLE: ++ case NFSERR_FBIG: ++ case NFSERR_IO: ++ case NFSERR_NOSPC: ++ case NFSERR_ROFS: ++ case NFSERR_STALE: ++ goto out_reset_to_pnfs; ++ case NFSERR_JUKEBOX: ++ nfs_inc_stats(lseg->pls_layout->plh_inode, NFSIOS_DELAY); ++ goto out_retry; ++ default: ++ break; ++ } ++ + switch (task->tk_status) { + /* File access problems. Don't mark the device as unavailable */ + case -EACCES: +@@ -1197,6 +1243,7 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task, + nfs4_delete_deviceid(devid->ld, devid->nfs_client, + &devid->deviceid); + } ++out_reset_to_pnfs: + /* FIXME: Need to prevent infinite looping here. */ + return -NFS4ERR_RESET_TO_PNFS; + out_retry: +@@ -1207,6 +1254,7 @@ static int ff_layout_async_handle_error_v3(struct rpc_task *task, + } + + static int ff_layout_async_handle_error(struct rpc_task *task, ++ u32 op_status, + struct nfs4_state *state, + struct nfs_client *clp, + struct pnfs_layout_segment *lseg, +@@ -1225,10 +1273,11 @@ static int ff_layout_async_handle_error(struct rpc_task *task, + + switch (vers) { + case 3: +- return ff_layout_async_handle_error_v3(task, lseg, idx); +- case 4: +- return ff_layout_async_handle_error_v4(task, state, clp, ++ return ff_layout_async_handle_error_v3(task, op_status, clp, + lseg, idx); ++ case 4: ++ return ff_layout_async_handle_error_v4(task, op_status, state, ++ clp, lseg, idx); + default: + /* should never happen */ + WARN_ON_ONCE(1); +@@ -1281,6 +1330,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, + switch (status) { + case NFS4ERR_DELAY: + case NFS4ERR_GRACE: ++ case NFS4ERR_PERM: + break; + case NFS4ERR_NXIO: + ff_layout_mark_ds_unreachable(lseg, idx); +@@ -1313,7 +1363,8 @@ static int ff_layout_read_done_cb(struct rpc_task *task, + trace_ff_layout_read_error(hdr); + } + +- err = ff_layout_async_handle_error(task, hdr->args.context->state, ++ err = ff_layout_async_handle_error(task, hdr->res.op_status, ++ hdr->args.context->state, + hdr->ds_clp, hdr->lseg, + hdr->pgio_mirror_idx); + +@@ -1483,7 +1534,8 @@ static int ff_layout_write_done_cb(struct rpc_task *task, + trace_ff_layout_write_error(hdr); + } + +- err = ff_layout_async_handle_error(task, hdr->args.context->state, ++ err = ff_layout_async_handle_error(task, hdr->res.op_status, ++ hdr->args.context->state, + hdr->ds_clp, hdr->lseg, + hdr->pgio_mirror_idx); + +@@ -1529,8 +1581,9 @@ static int ff_layout_commit_done_cb(struct rpc_task *task, + trace_ff_layout_commit_error(data); + } + +- err = ff_layout_async_handle_error(task, NULL, data->ds_clp, +- data->lseg, data->ds_commit_index); ++ err = ff_layout_async_handle_error(task, data->res.op_status, ++ NULL, data->ds_clp, data->lseg, ++ data->ds_commit_index); + + trace_nfs4_pnfs_commit_ds(data, err); + switch (err) { +-- +2.39.5 + diff --git a/queue-6.1/platform-x86-dell-wmi-sysman-fix-class-device-unregi.patch b/queue-6.1/platform-x86-dell-wmi-sysman-fix-class-device-unregi.patch new file mode 100644 index 0000000000..90a9889ebe --- /dev/null +++ b/queue-6.1/platform-x86-dell-wmi-sysman-fix-class-device-unregi.patch @@ -0,0 +1,52 @@ +From f7b15cf12c5c7bb3cfa495b60447a353de7eb891 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Jun 2025 22:17:37 -0300 +Subject: platform/x86: dell-wmi-sysman: Fix class device unregistration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kurt Borja + +[ Upstream commit 314e5ad4782d08858b3abc325c0487bd2abc23a1 ] + +Devices under the firmware_attributes_class do not have unique a dev_t. +Therefore, device_unregister() should be used instead of +device_destroy(), since the latter may match any device with a given +dev_t. + +Fixes: e8a60aa7404b ("platform/x86: Introduce support for Systems Management Driver over WMI for Dell Systems") +Signed-off-by: Kurt Borja +Link: https://lore.kernel.org/r/20250625-dest-fix-v1-3-3a0f342312bb@gmail.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/dell/dell-wmi-sysman/sysman.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c +index 660f00173f2ea..fb5eb4342c6ed 100644 +--- a/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c ++++ b/drivers/platform/x86/dell/dell-wmi-sysman/sysman.c +@@ -605,7 +605,7 @@ static int __init sysman_init(void) + release_attributes_data(); + + err_destroy_classdev: +- device_destroy(fw_attr_class, MKDEV(0, 0)); ++ device_unregister(wmi_priv.class_dev); + + err_unregister_class: + fw_attributes_class_put(); +@@ -622,7 +622,7 @@ static int __init sysman_init(void) + static void __exit sysman_exit(void) + { + release_attributes_data(); +- device_destroy(fw_attr_class, MKDEV(0, 0)); ++ device_unregister(wmi_priv.class_dev); + fw_attributes_class_put(); + exit_bios_attr_set_interface(); + exit_bios_attr_pass_interface(); +-- +2.39.5 + diff --git a/queue-6.1/platform-x86-think-lmi-fix-class-device-unregistrati.patch b/queue-6.1/platform-x86-think-lmi-fix-class-device-unregistrati.patch new file mode 100644 index 0000000000..fd47402fde --- /dev/null +++ b/queue-6.1/platform-x86-think-lmi-fix-class-device-unregistrati.patch @@ -0,0 +1,52 @@ +From 36092e72cf1c7c1814ee6d853a88e90611f2bad3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 25 Jun 2025 22:17:36 -0300 +Subject: platform/x86: think-lmi: Fix class device unregistration +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Kurt Borja + +[ Upstream commit 5ff1fbb3059730700b4823f43999fc1315984632 ] + +Devices under the firmware_attributes_class do not have unique a dev_t. +Therefore, device_unregister() should be used instead of +device_destroy(), since the latter may match any device with a given +dev_t. + +Fixes: a40cd7ef22fb ("platform/x86: think-lmi: Add WMI interface support on Lenovo platforms") +Signed-off-by: Kurt Borja +Link: https://lore.kernel.org/r/20250625-dest-fix-v1-2-3a0f342312bb@gmail.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/think-lmi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/platform/x86/think-lmi.c b/drivers/platform/x86/think-lmi.c +index 6641f934f15bf..804e2493d7d21 100644 +--- a/drivers/platform/x86/think-lmi.c ++++ b/drivers/platform/x86/think-lmi.c +@@ -1380,7 +1380,7 @@ static int tlmi_sysfs_init(void) + fail_create_attr: + tlmi_release_attr(); + fail_device_created: +- device_destroy(fw_attr_class, MKDEV(0, 0)); ++ device_unregister(tlmi_priv.class_dev); + fail_class_created: + fw_attributes_class_put(); + return ret; +@@ -1602,7 +1602,7 @@ static int tlmi_analyze(void) + static void tlmi_remove(struct wmi_device *wdev) + { + tlmi_release_attr(); +- device_destroy(fw_attr_class, MKDEV(0, 0)); ++ device_unregister(tlmi_priv.class_dev); + fw_attributes_class_put(); + } + +-- +2.39.5 + diff --git a/queue-6.1/s390-pci-fix-stale-function-handles-in-error-handlin.patch b/queue-6.1/s390-pci-fix-stale-function-handles-in-error-handlin.patch new file mode 100644 index 0000000000..4da7ff07eb --- /dev/null +++ b/queue-6.1/s390-pci-fix-stale-function-handles-in-error-handlin.patch @@ -0,0 +1,71 @@ +From a7fafb96b43bba18087a6ae3998e0da6d1fee109 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Jul 2025 04:35:20 -0400 +Subject: s390/pci: Fix stale function handles in error handling + +From: Niklas Schnelle + +[ Upstream commit 45537926dd2aaa9190ac0fac5a0fbeefcadfea95 ] + +The error event information for PCI error events contains a function +handle for the respective function. This handle is generally captured at +the time the error event was recorded. Due to delays in processing or +cascading issues, it may happen that during firmware recovery multiple +events are generated. When processing these events in order Linux may +already have recovered an affected function making the event information +stale. Fix this by doing an unconditional CLP List PCI function +retrieving the current function handle with the zdev->state_lock held +and ignoring the event if its function handle is stale. + +Cc: stable@vger.kernel.org +Fixes: 4cdf2f4e24ff ("s390/pci: implement minimal PCI error recovery") +Reviewed-by: Julian Ruess +Reviewed-by: Gerd Bayer +Reviewed-by: Farhan Ali +Signed-off-by: Niklas Schnelle +Signed-off-by: Alexander Gordeev +Signed-off-by: Sasha Levin +--- + arch/s390/pci/pci_event.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c +index d969f36bf186f..dc512c8f82324 100644 +--- a/arch/s390/pci/pci_event.c ++++ b/arch/s390/pci/pci_event.c +@@ -257,6 +257,8 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf) + struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); + struct pci_dev *pdev = NULL; + pci_ers_result_t ers_res; ++ u32 fh = 0; ++ int rc; + + zpci_dbg(3, "err fid:%x, fh:%x, pec:%x\n", + ccdf->fid, ccdf->fh, ccdf->pec); +@@ -264,9 +266,23 @@ static void __zpci_event_error(struct zpci_ccdf_err *ccdf) + zpci_err_hex(ccdf, sizeof(*ccdf)); + + if (zdev) { ++ mutex_lock(&zdev->state_lock); ++ rc = clp_refresh_fh(zdev->fid, &fh); ++ if (rc) { ++ mutex_unlock(&zdev->state_lock); ++ goto no_pdev; ++ } ++ if (!fh || ccdf->fh != fh) { ++ /* Ignore events with stale handles */ ++ zpci_dbg(3, "err fid:%x, fh:%x (stale %x)\n", ++ ccdf->fid, fh, ccdf->fh); ++ mutex_unlock(&zdev->state_lock); ++ goto no_pdev; ++ } + zpci_update_fh(zdev, ccdf->fh); + if (zdev->zbus->bus) + pdev = pci_get_slot(zdev->zbus->bus, zdev->devfn); ++ mutex_unlock(&zdev->state_lock); + } + + pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n", +-- +2.39.5 + diff --git a/queue-6.1/series b/queue-6.1/series index e8a22db7cd..0b02ec3234 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -56,3 +56,12 @@ wifi-ath6kl-remove-warn-on-bad-firmware-input.patch acpica-refuse-to-evaluate-a-method-if-arguments-are-.patch mtd-spinand-fix-memory-leak-of-ecc-engine-conf.patch rcu-return-early-if-callback-is-not-specified.patch +virtio-net-ensure-the-received-length-does-not-excee.patch +s390-pci-fix-stale-function-handles-in-error-handlin.patch +drm-v3d-disable-interrupts-before-resetting-the-gpu.patch +nfsv4-flexfiles-fix-handling-of-nfs-level-errors-in-.patch +btrfs-use-btrfs_record_snapshot_destroy-during-rmdir.patch +dpaa2-eth-fix-xdp_rxq_info-leak.patch +platform-x86-think-lmi-fix-class-device-unregistrati.patch +platform-x86-dell-wmi-sysman-fix-class-device-unregi.patch +net-usb-lan78xx-fix-warn-in-__netif_napi_del_locked-.patch diff --git a/queue-6.1/virtio-net-ensure-the-received-length-does-not-excee.patch b/queue-6.1/virtio-net-ensure-the-received-length-does-not-excee.patch new file mode 100644 index 0000000000..2fafe6b302 --- /dev/null +++ b/queue-6.1/virtio-net-ensure-the-received-length-does-not-excee.patch @@ -0,0 +1,115 @@ +From b4d2801cd0ce9ca42a51c90f5346a1f3cb72c18f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 7 Jul 2025 04:14:54 -0400 +Subject: virtio-net: ensure the received length does not exceed allocated size + +From: Bui Quang Minh + +[ Upstream commit 315dbdd7cdf6aa533829774caaf4d25f1fd20e73 ] + +In xdp_linearize_page, when reading the following buffers from the ring, +we forget to check the received length with the true allocate size. This +can lead to an out-of-bound read. This commit adds that missing check. + +Cc: +Fixes: 4941d472bf95 ("virtio-net: do not reset during XDP set") +Signed-off-by: Bui Quang Minh +Acked-by: Jason Wang +Link: https://patch.msgid.link/20250630144212.48471-2-minhquangbui99@gmail.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/virtio_net.c | 38 ++++++++++++++++++++++++++++++++++---- + 1 file changed, 34 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c +index 11aa0a7d54cd7..1b4cf8eb7e136 100644 +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -440,6 +440,26 @@ static unsigned int mergeable_ctx_to_truesize(void *mrg_ctx) + return (unsigned long)mrg_ctx & ((1 << MRG_CTX_HEADER_SHIFT) - 1); + } + ++static int check_mergeable_len(struct net_device *dev, void *mrg_ctx, ++ unsigned int len) ++{ ++ unsigned int headroom, tailroom, room, truesize; ++ ++ truesize = mergeable_ctx_to_truesize(mrg_ctx); ++ headroom = mergeable_ctx_to_headroom(mrg_ctx); ++ tailroom = headroom ? sizeof(struct skb_shared_info) : 0; ++ room = SKB_DATA_ALIGN(headroom + tailroom); ++ ++ if (len > truesize - room) { ++ pr_debug("%s: rx error: len %u exceeds truesize %lu\n", ++ dev->name, len, (unsigned long)(truesize - room)); ++ DEV_STATS_INC(dev, rx_length_errors); ++ return -1; ++ } ++ ++ return 0; ++} ++ + /* Called from bottom half context */ + static struct sk_buff *page_to_skb(struct virtnet_info *vi, + struct receive_queue *rq, +@@ -719,7 +739,8 @@ static unsigned int virtnet_get_headroom(struct virtnet_info *vi) + * across multiple buffers (num_buf > 1), and we make sure buffers + * have enough headroom. + */ +-static struct page *xdp_linearize_page(struct receive_queue *rq, ++static struct page *xdp_linearize_page(struct net_device *dev, ++ struct receive_queue *rq, + u16 *num_buf, + struct page *p, + int offset, +@@ -739,18 +760,27 @@ static struct page *xdp_linearize_page(struct receive_queue *rq, + memcpy(page_address(page) + page_off, page_address(p) + offset, *len); + page_off += *len; + ++ /* Only mergeable mode can go inside this while loop. In small mode, ++ * *num_buf == 1, so it cannot go inside. ++ */ + while (--*num_buf) { + unsigned int buflen; + void *buf; ++ void *ctx; + int off; + +- buf = virtqueue_get_buf(rq->vq, &buflen); ++ buf = virtqueue_get_buf_ctx(rq->vq, &buflen, &ctx); + if (unlikely(!buf)) + goto err_buf; + + p = virt_to_head_page(buf); + off = buf - page_address(p); + ++ if (check_mergeable_len(dev, ctx, buflen)) { ++ put_page(p); ++ goto err_buf; ++ } ++ + /* guard against a misconfigured or uncooperative backend that + * is sending packet larger than the MTU. + */ +@@ -831,7 +861,7 @@ static struct sk_buff *receive_small(struct net_device *dev, + headroom = vi->hdr_len + header_offset; + buflen = SKB_DATA_ALIGN(GOOD_PACKET_LEN + headroom) + + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); +- xdp_page = xdp_linearize_page(rq, &num_buf, page, ++ xdp_page = xdp_linearize_page(dev, rq, &num_buf, page, + offset, header_offset, + &tlen); + if (!xdp_page) +@@ -1006,7 +1036,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, + if (unlikely(num_buf > 1 || + headroom < virtnet_get_headroom(vi))) { + /* linearize data for XDP */ +- xdp_page = xdp_linearize_page(rq, &num_buf, ++ xdp_page = xdp_linearize_page(dev, rq, &num_buf, + page, offset, + VIRTIO_XDP_HEADROOM, + &len); +-- +2.39.5 + -- 2.47.2