6.1.191-rc1 review
Subsystems (12)
Greg Kroah-Hartman
maintainerPATCH 739/1887 x86/PCI: Avoid PME from D3hot/D3cold for AMD Rembrandt and Phoenix USB4
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit 7d08f21f8c6307cb05cabb8d86e90ff6ccba57e9 ]
Iain reports that USB devices can't be used to wake a Lenovo Z13 from suspend. This occurs because on some AMD platforms, even though the Root Ports advertise PME_Support for D3hot and D3cold, wakeup events from devices on a USB4 controller don't result in wakeup interrupts from the Root Port when amd-pmc has put the platform in a hardware sleep state.
If amd-pmc will be involved in the suspend, remove D3hot and D3cold from the PME_Support mask of Root Ports above USB4 controllers so we avoid those states if we need wakeups.
Restore D3 support at resume so that it can be used by runtime suspend.
This affects both AMD Rembrandt and Phoenix SoCs.
"pm_suspend_target_state == PM_SUSPEND_ON" means we're doing runtime suspend, and amd-pmc will not be involved. In that case PMEs work as advertised in D3hot/D3cold, so we don't need to do anything.
Note that amd-pmc is technically optional, and there's no need for this quirk if it's not present, but we assume it's always present because power consumption is so high without it.
Stable-dep-of: b1049f2d6869 ("PCI: Avoid putting some root ports into D3 on TUXEDO Sirius Gen1")
--- arch/x86/pci/fixup.c | 59 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+)
arch/x86/pci/fixup.c +59 -0
@@ -3,9 +3,11 @@* Exceptions for specific devices. Usually work-arounds for fatal design flaws. */ +#include <linux/bitfield.h> #include <linux/delay.h> #include <linux/dmi.h> #include <linux/pci.h> +#include <linux/suspend.h> #include <linux/vgaarb.h> #include <asm/amd_nb.h> #include <asm/hpet.h>
@@ -944,3 +946,60 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1122, quirk_amd_nbio_7_11_disable_enhanced_atomic);#endif + +#ifdef CONFIG_SUSPEND +/* +* Root Ports on some AMD SoCs advertise PME_Support for D3hot and D3cold, but +* if the SoC is put into a hardware sleep state by the amd-pmc driver, the +* Root Ports don't generate wakeup interrupts for USB devices. +* +* When suspending, remove D3hot and D3cold from the PME_Support advertised +* by the Root Port so we don't use those states if we're expecting wakeup +* interrupts. Restore the advertised PME_Support when resuming. +*/ +static void amd_rp_pme_suspend (struct pci_dev *dev) +{ +struct pci_dev *rp; + +/* +* PM_SUSPEND_ON means we're doing runtime suspend, which means +* amd-pmc will not be involved so PMEs during D3 work as advertised. +* +* The PMEs *do* work if amd-pmc doesn't put the SoC in the hardware +* sleep state, but we assume amd-pmc is always present. +*/ +if (pm_suspend_target_state ==PM_SUSPEND_ON ) +return ; + + rp =pcie_find_root_port (dev); +if (!rp->pm_cap) +return ; + + rp->pme_support &= ~((PCI_PM_CAP_PME_D3hot|PCI_PM_CAP_PME_D3cold) >> +PCI_PM_CAP_PME_SHIFT ); +dev_info_once (&rp->dev,"quirk: disabling D3cold for suspend\n" ); +} + +static void amd_rp_pme_resume (struct pci_dev *dev) +{ +struct pci_dev *rp; +u16 pmc; + + rp =pcie_find_root_port (dev); +if (!rp->pm_cap) +return ; + +pci_read_config_word (rp, rp->pm_cap +PCI_PM_PMC , &pmc); + rp->pme_support =FIELD_GET (PCI_PM_CAP_PME_MASK , pmc); +} +/* Rembrandt (yellow_carp) */ +DECLARE_PCI_FIXUP_SUSPEND (PCI_VENDOR_ID_AMD ,0x162e , amd_rp_pme_suspend); +DECLARE_PCI_FIXUP_RESUME (PCI_VENDOR_ID_AMD ,0x162e , amd_rp_pme_resume); +DECLARE_PCI_FIXUP_SUSPEND (PCI_VENDOR_ID_AMD ,0x162f , amd_rp_pme_suspend); +DECLARE_PCI_FIXUP_RESUME (PCI_VENDOR_ID_AMD ,0x162f , amd_rp_pme_resume); +/* Phoenix (pink_sardine) */ +DECLARE_PCI_FIXUP_SUSPEND (PCI_VENDOR_ID_AMD ,0x1668 , amd_rp_pme_suspend); +DECLARE_PCI_FIXUP_RESUME (PCI_VENDOR_ID_AMD ,0x1668 , amd_rp_pme_resume); +DECLARE_PCI_FIXUP_SUSPEND (PCI_VENDOR_ID_AMD ,0x1669 , amd_rp_pme_suspend); +DECLARE_PCI_FIXUP_RESUME (PCI_VENDOR_ID_AMD ,0x1669 , amd_rp_pme_resume); +#endif /* CONFIG_SUSPEND */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 740/1887 PCI: Avoid putting some root ports into D3 on TUXEDO Sirius Gen1
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Werner Sembach <[email protected]>
[ Upstream commit b1049f2d68693c80a576c4578d96774a68df2bad ]
commit 9d26d3a8f1b0 ("PCI: Put PCIe ports into D3 during suspend") sets the policy that all PCIe ports are allowed to use D3. When the system is suspended if the port is not power manageable by the platform and won't be used for wakeup via a PME this sets up the policy for these ports to go into D3hot.
This policy generally makes sense from an OSPM perspective but it leads to problems with wakeup from suspend on the TUXEDO Sirius 16 Gen 1 with a specific old BIOS. This manifests as a system hang.
On the affected Device + BIOS combination, add a quirk for the root port of the problematic controller to ensure that these root ports are not put into D3hot at suspend.
This patch is based on
https://lore.kernel.org/linux-pci/[email protected]
but with the added condition both in the documentation and in the code to apply only to the TUXEDO Sirius 16 Gen 1 with a specific old BIOS and only the affected root ports.
--- arch/x86/pci/fixup.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
arch/x86/pci/fixup.c +30 -0
@@ -1002,4 +1002,34 @@ DECLARE_PCI_FIXUP_SUSPEND(PCI_VENDOR_ID_AMD, 0x1668, amd_rp_pme_suspend);DECLARE_PCI_FIXUP_RESUME (PCI_VENDOR_ID_AMD ,0x1668 , amd_rp_pme_resume);DECLARE_PCI_FIXUP_SUSPEND (PCI_VENDOR_ID_AMD ,0x1669 , amd_rp_pme_suspend);DECLARE_PCI_FIXUP_RESUME (PCI_VENDOR_ID_AMD ,0x1669 , amd_rp_pme_resume); + +/* +* Putting PCIe root ports on Ryzen SoCs with USB4 controllers into D3hot +* may cause problems when the system attempts wake up from s2idle. +* +* On the TUXEDO Sirius 16 Gen 1 with a specific old BIOS this manifests as +* a system hang. +*/ +static const struct dmi_system_id quirk_tuxeo_rp_d3_dmi_table[] = { + { + .matches = { +DMI_EXACT_MATCH (DMI_SYS_VENDOR ,"TUXEDO" ), +DMI_EXACT_MATCH (DMI_BOARD_NAME ,"APX958" ), +DMI_EXACT_MATCH (DMI_BIOS_VERSION ,"V1.00A00_20240108" ), + }, + }, + {} +}; + +static void quirk_tuxeo_rp_d3 (struct pci_dev *pdev) +{ +struct pci_dev *root_pdev; + +if (dmi_check_system (quirk_tuxeo_rp_d3_dmi_table)) { + root_pdev =pcie_find_root_port (pdev); +if (root_pdev) + root_pdev->dev_flags |=PCI_DEV_FLAGS_NO_D3 ; + } +} +DECLARE_PCI_FIXUP_FINAL (PCI_VENDOR_ID_AMD ,0x1502 , quirk_tuxeo_rp_d3);#endif /* CONFIG_SUSPEND */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 741/1887 ASoC: SOF: ipc4-topology: Harden loops for looking up ALH copiers
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Ujfalusi <[email protected]>
[ Upstream commit 6fd60136d256b3b948333ebdb3835f41a95ab7ef ]
Other, non DAI copier widgets could have the same stream name (sname) as the ALH copier and in that case the copier->data is NULL, no alh_data is attached, which could lead to NULL pointer dereference.
We could check for this NULL pointer in sof_ipc4_prepare_copier_module() and avoid the crash, but a similar loop in sof_ipc4_widget_setup_comp_dai() will miscalculate the ALH device count, causing broken audio.
The correct fix is to harden the matching logic by making sure that the
1. widget is a DAI widget - so dai = w->private is valid
2. the dai (and thus the copier) is ALH copier
--- sound/soc/sof/ipc4-topology.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
sound/soc/sof/ipc4-topology.c +5 -2
@@ -515,7 +515,7 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) }list_for_each_entry (w, &sdev->widget_list, list) { -if (w->widget->sname && +if (!WIDGET_IS_DAI (w->id) || !w->widget->sname ||strcmp (w->widget->sname, swidget->widget->sname))continue ;
@@ -1237,17 +1237,20 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,*/ i =0 ;list_for_each_entry (w, &sdev->widget_list, list) { -if (w->widget->sname && +if (!WIDGET_IS_DAI (w->id) || !w->widget->sname ||strcmp (w->widget->sname, swidget->widget->sname))continue ; dai = w->private; alh_copier = (struct sof_ipc4_copier *)dai->private; +if (alh_copier->dai_type !=SOF_DAI_INTEL_ALH ) +continue ; alh_data = &alh_copier->data; blob->alh_cfg.mapping[i].alh_id = alh_data->gtw_cfg.node_id; blob->alh_cfg.mapping[i].channel_mask = ch_mask; i++; } + blob->alh_cfg.count = i;if (blob->alh_cfg.count >1 ) {int group_id;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 742/1887 efi: Dont map the entire mokvar table to determine its size
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Jones <[email protected]>
[ Upstream commit 2b90e7ace79774a3540ce569e000388f8d22c9e0 ]
Currently, when validating the mokvar table, we (re)map the entire table on each iteration of the loop, adding space as we discover new entries. If the table grows over a certain size, this fails due to limitations of early_memmap(), and we get a failure and traceback:
------------[ cut here ]------------ WARNING: CPU: 0 PID: 0 at mm/early_ioremap.c:139 __early_ioremap+0xef/0x220 ... Call Trace: <TASK> ? __early_ioremap+0xef/0x220 ? __warn.cold+0x93/0xfa ? __early_ioremap+0xef/0x220 ? report_bug+0xff/0x140 ? early_fixup_exception+0x5d/0xb0 ? early_idt_handler_common+0x2f/0x3a ? __early_ioremap+0xef/0x220 ? efi_mokvar_table_init+0xce/0x1d0 ? setup_arch+0x864/0xc10 ? start_kernel+0x6b/0xa10 ? x86_64_start_reservations+0x24/0x30 ? x86_64_start_kernel+0xed/0xf0 ? common_startup_64+0x13e/0x141 </TASK> ---[ end trace 0000000000000000 ]--- mokvar: Failed to map EFI MOKvar config table pa=0x7c4c3000, size=265187.
Mapping the entire structure isn't actually necessary, as we don't ever need more than one entry header mapped at once.
Changes efi_mokvar_table_init() to only map each entry header, not the entire table, when determining the table size. Since we're not mapping any data past the variable name, it also changes the code to enforce that each variable name is NUL terminated, rather than attempting to verify it in place.
--- drivers/firmware/efi/mokvar-table.c | 42 +++++++++-------------------- 1 file changed, 13 insertions(+), 29 deletions(-)
drivers/firmware/efi/mokvar-table.c +13 -29
@@ -103,9 +103,7 @@ void __init efi_mokvar_table_init(void)void *va =NULL ;unsigned long cur_offset =0 ;unsigned long offset_limit; -unsigned long map_size =0 ;unsigned long map_size_needed =0 ; -unsigned long size;struct efi_mokvar_table_entry *mokvar_entry;int err;
@@ -134,48 +132,34 @@ void __init efi_mokvar_table_init(void)*/ err = -EINVAL ;while (cur_offset +sizeof (*mokvar_entry) <= offset_limit) { - mokvar_entry = va + cur_offset; - map_size_needed = cur_offset +sizeof (*mokvar_entry); -if (map_size_needed > map_size) { -if (va) -early_memunmap (va, map_size); -/* -* Map a little more than the fixed size entry -* header, anticipating some data. It's safe to -* do so as long as we stay within current memory -* descriptor. -*/ - map_size =min (map_size_needed +2 *EFI_PAGE_SIZE , - offset_limit); - va =early_memremap (efi.mokvar_table, map_size); -if (!va) { -pr_err ("Failed to map EFI MOKvar config table pa=0x%lx, size=%lu.\n" , - efi.mokvar_table, map_size); -return ; - } - mokvar_entry = va + cur_offset; +if (va) +early_memunmap (va,sizeof (*mokvar_entry)); + va =early_memremap (efi.mokvar_table + cur_offset,sizeof (*mokvar_entry)); +if (!va) { +pr_err ("Failed to map EFI MOKvar config table pa=0x%lx, size=%zu.\n" , + efi.mokvar_table + cur_offset,sizeof (*mokvar_entry)); +return ; } + mokvar_entry = va;/* Check for last sentinel entry */ if (mokvar_entry->name[0 ] =='\0' ) {if (mokvar_entry->data_size !=0 )break ; err =0 ; + map_size_needed = cur_offset +sizeof (*mokvar_entry);break ; } -/* Sanity check that the name is null terminated */ - size =strnlen (mokvar_entry->name, -sizeof (mokvar_entry->name)); -if (size >=sizeof (mokvar_entry->name)) -break ; +/* Enforce that the name is NUL terminated */ + mokvar_entry->name[sizeof (mokvar_entry->name) -1 ] ='\0' ;/* Advance to the next entry */ - cur_offset = map_size_needed + mokvar_entry->data_size; + cur_offset +=sizeof (*mokvar_entry) + mokvar_entry->data_size; }if (va) -early_memunmap (va, map_size); +early_memunmap (va,sizeof (*mokvar_entry));if (err) {pr_err ("EFI MOKvar config table is not valid\n" );return ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 743/1887 RDMA/bnxt_re: Fix the page details for the srq created by kernel consumers
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kashyap Desai <[email protected]>
[ Upstream commit b66535356a4834a234f99e16a97eb51f2c6c5a7d ]
While using nvme target with use_srq on, below kernel panic is noticed.
[ 549.698111] bnxt_en 0000:41:00.0 enp65s0np0: FEC autoneg off encoding: Clause 91 RS(544,514) [ 566.393619] Oops: divide error: 0000 [#1] PREEMPT SMP NOPTI .. [ 566.393799] <TASK> [ 566.393807] ? __die_body+0x1a/0x60 [ 566.393823] ? die+0x38/0x60 [ 566.393835] ? do_trap+0xe4/0x110 [ 566.393847] ? bnxt_qplib_alloc_init_hwq+0x1d4/0x580 [bnxt_re] [ 566.393867] ? bnxt_qplib_alloc_init_hwq+0x1d4/0x580 [bnxt_re] [ 566.393881] ? do_error_trap+0x7c/0x120 [ 566.393890] ? bnxt_qplib_alloc_init_hwq+0x1d4/0x580 [bnxt_re] [ 566.393911] ? exc_divide_error+0x34/0x50 [ 566.393923] ? bnxt_qplib_alloc_init_hwq+0x1d4/0x580 [bnxt_re] [ 566.393939] ? asm_exc_divide_error+0x16/0x20 [ 566.393966] ? bnxt_qplib_alloc_init_hwq+0x1d4/0x580 [bnxt_re] [ 566.393997] bnxt_qplib_create_srq+0xc9/0x340 [bnxt_re] [ 566.394040] bnxt_re_create_srq+0x335/0x3b0 [bnxt_re] [ 566.394057] ? srso_return_thunk+0x5/0x5f [ 566.394068] ? __init_swait_queue_head+0x4a/0x60 [ 566.394090] ib_create_srq_user+0xa7/0x150 [ib_core] [ 566.394147] nvmet_rdma_queue_connect+0x7d0/0xbe0 [nvmet_rdma] [ 566.394174] ? lock_release+0x22c/0x3f0 [ 566.394187] ? srso_return_thunk+0x5/0x5f
Page size and shift info is set only for the user space SRQs. Set page size and page shift for kernel space SRQs also.
--- drivers/infiniband/hw/bnxt_re/ib_verbs.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/infiniband/hw/bnxt_re/ib_verbs.c +2 -0
@@ -1659,6 +1659,8 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq, srq->qplib_srq.threshold = srq_init_attr->attr.srq_limit; srq->srq_limit = srq_init_attr->attr.srq_limit; srq->qplib_srq.eventq_hw_ring_id = rdev->nq[0 ].ring_id; + srq->qplib_srq.sg_info.pgsize =PAGE_SIZE ; + srq->qplib_srq.sg_info.pgshft =PAGE_SHIFT ; nq = &rdev->nq[0 ];if (udata) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 744/1887 RDMA/mlx5: Fix a WARN during dereg_mr for DM type
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yishai Hadas <[email protected]>
[ Upstream commit abc7b3f1f056d69a8f11d6dceecc0c9549ace770 ]
Memory regions (MR) of type DM (device memory) do not have an associated umem.
In the __mlx5_ib_dereg_mr() -> mlx5_free_priv_descs() flow, the code incorrectly takes the wrong branch, attempting to call dma_unmap_single() on a DMA address that is not mapped.
This results in a WARN [1], as shown below.
The issue is resolved by properly accounting for the DM type and ensuring the correct branch is selected in mlx5_free_priv_descs().
[1]
WARNING: CPU: 12 PID: 1346 at drivers/iommu/dma-iommu.c:1230 iommu_dma_unmap_page+0x79/0x90 Modules linked in: ip6table_mangle ip6table_nat ip6table_filter ip6_tables iptable_mangle xt_conntrack xt_MASQUERADE nf_conntrack_netlink nfnetlink xt_addrtype iptable_nat nf_nat br_netfilter rpcsec_gss_krb5 auth_rpcgss oid_registry ovelay rpcrdma rdma_ucm ib_iser libiscsi scsi_transport_iscsi ib_umad rdma_cm ib_ipoib iw_cm ib_cm mlx5_ib ib_uverbs ib_core fuse mlx5_core CPU: 12 UID: 0 PID: 1346 Comm: ibv_rc_pingpong Not tainted 6.12.0-rc7+ #1631 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 RIP: 0010:iommu_dma_unmap_page+0x79/0x90 Code: 2b 49 3b 29 72 26 49 3b 69 08 73 20 4d 89 f0 44 89 e9 4c 89 e2 48 89 ee 48 89 df 5b 5d 41 5c 41 5d 41 5e 41 5f e9 07 b8 88 ff <0f> 0b 5b 5d 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 66 0f 1f 44 00 RSP: 0018:ffffc90001913a10 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff88810194b0a8 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000001 RBP: ffff88810194b0a8 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000 R13: 0000000000000001 R14: 0000000000000000 R15: 0000000000000000 FS: 00007f537abdd740(0000) GS:ffff88885fb00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f537aeb8000 CR3: 000000010c248001 CR4: 0000000000372eb0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> ? __warn+0x84/0x190 ? iommu_dma_unmap_page+0x79/0x90 ? report_bug+0xf8/0x1c0 ? handle_bug+0x55/0x90 ? exc_invalid_op+0x13/0x60 ? asm_exc_invalid_op+0x16/0x20 ? iommu_dma_unmap_page+0x79/0x90 dma_unmap_page_attrs+0xe6/0x290 mlx5_free_priv_descs+0xb0/0xe0 [mlx5_ib] __mlx5_ib_dereg_mr+0x37e/0x520 [mlx5_ib] ? _raw_spin_unlock_irq+0x24/0x40 ? wait_for_completion+0xfe/0x130 ? rdma_restrack_put+0x63/0xe0 [ib_core] ib_dereg_mr_user+0x5f/0x120 [ib_core] ? lock_release+0xc6/0x280 destroy_hw_idr_uobject+0x1d/0x60 [ib_uverbs] uverbs_destroy_uobject+0x58/0x1d0 [ib_uverbs] uobj_destroy+0x3f/0x70 [ib_uverbs] ib_uverbs_cmd_verbs+0x3e4/0xbb0 [ib_uverbs] ? __pfx_uverbs_destroy_def_handler+0x10/0x10 [ib_uverbs] ? lock_acquire+0xc1/0x2f0 ? ib_uverbs_ioctl+0xcb/0x170 [ib_uverbs] ? ib_uverbs_ioctl+0x116/0x170 [ib_uverbs] ? lock_release+0xc6/0x280 ib_uverbs_ioctl+0xe7/0x170 [ib_uverbs] ? ib_uverbs_ioctl+0xcb/0x170 [ib_uverbs] __x64_sys_ioctl+0x1b0/0xa70 do_syscall_64+0x6b/0x140 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7f537adaf17b Code: 0f 1e fa 48 8b 05 1d ad 0c 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d ed ac 0c 00 f7 d8 64 89 01 48 RSP: 002b:00007ffff218f0b8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007ffff218f1d8 RCX: 00007f537adaf17b RDX: 00007ffff218f1c0 RSI: 00000000c0181b01 RDI: 0000000000000003 RBP: 00007ffff218f1a0 R08: 00007f537aa8d010 R09: 0000561ee2e4f270 R10: 00007f537aace3a8 R11: 0000000000000246 R12: 00007ffff218f190 R13: 000000000000001c R14: 0000561ee2e4d7c0 R15: 00007ffff218f450 </TASK>
--- drivers/infiniband/hw/mlx5/mr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/mr.c +1 -1
@@ -1571,7 +1571,7 @@ mlx5_alloc_priv_descs(struct ib_device *device,static void mlx5_free_priv_descs (struct mlx5_ib_mr *mr) { -if (!mr->umem && mr->descs) { +if (!mr->umem && mr->ibmr.type !=IB_MR_TYPE_DM && mr->descs) {struct ib_device *device = mr->ibmr.device;int size = mr->max_descs * mr->desc_size;struct mlx5_ib_dev *dev =to_mdev (device);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 745/1887 RDMA/mlx5: Dont keep umrable page_shift in cache entries
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aharon Landau <[email protected]>
[ Upstream commit a2a88b8e22d1b202225d0e40b02ad068afab2ccb ]
mkc.log_page_size can be changed using UMR. Therefore, don't treat it as a cache entry property.
Removing it from struct mlx5_cache_ent.
All cache mkeys will be created with default PAGE_SHIFT, and updated with the needed page_shift using UMR when passing them to a user.
Stable-dep-of: d97505baea64 ("RDMA/mlx5: Fix the recovery flow of the UMR QP")
--- drivers/infiniband/hw/mlx5/mlx5_ib.h | 1 - drivers/infiniband/hw/mlx5/mr.c | 3 +-- drivers/infiniband/hw/mlx5/odp.c | 2 -- 3 files changed, 1 insertion(+), 5 deletions(-)
drivers/infiniband/hw/mlx5/mlx5_ib.h +0 -1
@@ -759,7 +759,6 @@ struct mlx5_cache_ent {char name[4 ];u32 order;u32 access_mode; -u32 page;unsigned int ndescs; u8 disabled:1;
drivers/infiniband/hw/mlx5/mr.c +1 -2
@@ -297,7 +297,7 @@ static void set_cache_mkc(struct mlx5_cache_ent *ent, void *mkc)MLX5_SET (mkc, mkc, translations_octword_size,get_mkc_octo_size (ent->access_mode, ent->ndescs)); -MLX5_SET (mkc, mkc, log_page_size, ent->page); +MLX5_SET (mkc, mkc, log_page_size,PAGE_SHIFT ); }/* Asynchronously schedule new MRs to be populated in the cache. */
@@ -765,7 +765,6 @@ int mlx5_mkey_cache_init(struct mlx5_ib_dev *dev)if (ent->order >mkey_cache_max_order (dev))continue ; - ent->page =PAGE_SHIFT ; ent->ndescs =1 << ent->order; ent->access_mode =MLX5_MKC_ACCESS_MODE_MTT ; if ((dev->mdev->profile.mask & MLX5_PROF_MASK_MR_CACHE) &&
drivers/infiniband/hw/mlx5/odp.c +0 -2
@@ -1616,14 +1616,12 @@ void mlx5_odp_init_mkey_cache_entry(struct mlx5_cache_ent *ent)switch (ent->order -2 ) {case MLX5_IMR_MTT_CACHE_ENTRY : - ent->page =PAGE_SHIFT ; ent->ndescs =MLX5_IMR_MTT_ENTRIES ; ent->access_mode =MLX5_MKC_ACCESS_MODE_MTT ; ent->limit =0 ;break ;case MLX5_IMR_KSM_CACHE_ENTRY : - ent->page =MLX5_KSM_PAGE_SHIFT ; ent->ndescs = mlx5_imr_ksm_entries; ent->access_mode =MLX5_MKC_ACCESS_MODE_KSM ; ent->limit =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 746/1887 RDMA/mlx5: Remove implicit ODP cache entry
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aharon Landau <[email protected]>
[ Upstream commit 18b1746bddf5e7f6b2618966596d9517172a5cd7 ]
Implicit ODP mkey doesn't have unique properties. It shares the same properties as the order 18 cache entry. There is no need to devote a special entry for that.
Stable-dep-of: d97505baea64 ("RDMA/mlx5: Fix the recovery flow of the UMR QP")
--- drivers/infiniband/hw/mlx5/odp.c | 20 +++++--------------- include/linux/mlx5/driver.h | 1 - 2 files changed, 5 insertions(+), 16 deletions(-)
drivers/infiniband/hw/mlx5/odp.c +5 -15
@@ -424,6 +424,7 @@ static void mlx5_ib_page_fault_resume(struct mlx5_ib_dev *dev,static struct mlx5_ib_mr *implicit_get_child_mr (struct mlx5_ib_mr *imr,unsigned long idx) { +int order =order_base_2 (MLX5_IMR_MTT_ENTRIES );struct mlx5_ib_dev *dev =mr_to_mdev (imr);struct ib_umem_odp *odp;struct mlx5_ib_mr *mr;
@@ -436,7 +437,8 @@ static struct mlx5_ib_mr *implicit_get_child_mr(struct mlx5_ib_mr *imr,if (IS_ERR (odp))return ERR_CAST (odp); - mr =mlx5_mr_cache_alloc (dev, &dev->cache.ent[MLX5_IMR_MTT_CACHE_ENTRY ], +BUILD_BUG_ON (order >MKEY_CACHE_LAST_STD_ENTRY ); + mr =mlx5_mr_cache_alloc (dev, &dev->cache.ent[order], imr->access_flags);if (IS_ERR (mr)) {ib_umem_odp_release (odp);
@@ -1613,20 +1615,8 @@ void mlx5_odp_init_mkey_cache_entry(struct mlx5_cache_ent *ent) {if (!(ent->dev->odp_caps.general_caps &IB_ODP_SUPPORT_IMPLICIT ))return ; - -switch (ent->order -2 ) { -case MLX5_IMR_MTT_CACHE_ENTRY : - ent->ndescs =MLX5_IMR_MTT_ENTRIES ; - ent->access_mode =MLX5_MKC_ACCESS_MODE_MTT ; - ent->limit =0 ; -break ; - -case MLX5_IMR_KSM_CACHE_ENTRY : - ent->ndescs = mlx5_imr_ksm_entries; - ent->access_mode =MLX5_MKC_ACCESS_MODE_KSM ; - ent->limit =0 ; -break ; - } + ent->ndescs = mlx5_imr_ksm_entries; + ent->access_mode =MLX5_MKC_ACCESS_MODE_KSM ; }static const struct ib_device_ops mlx5_ib_dev_odp_ops = {
include/linux/mlx5/driver.h +0 -1
@@ -747,7 +747,6 @@ enum {enum {MKEY_CACHE_LAST_STD_ENTRY =20 , -MLX5_IMR_MTT_CACHE_ENTRY ,MLX5_IMR_KSM_CACHE_ENTRY ,MAX_MKEY_CACHE_ENTRIES };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 747/1887 RDMA/mlx5: Change the cache structure to an RB-tree
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Guralnik <[email protected]>
[ Upstream commit b9584517832858a0f78d6851d09b697a829514cd ]
Currently, the cache structure is a static linear array. Therefore, his size is limited to the number of entries in it and is not expandable. The entries are dedicated to mkeys of size 2^x and no access_flags. Mkeys with different properties are not cacheable.
In this patch, we change the cache structure to an RB-tree. This will allow to extend the cache to support more entries with different mkey properties.
Stable-dep-of: d97505baea64 ("RDMA/mlx5: Fix the recovery flow of the UMR QP")
--- drivers/infiniband/hw/mlx5/mlx5_ib.h | 11 +- drivers/infiniband/hw/mlx5/mr.c | 160 ++++++++++++++++++++------- drivers/infiniband/hw/mlx5/odp.c | 8 +- 3 files changed, 132 insertions(+), 47 deletions(-)
drivers/infiniband/hw/mlx5/mlx5_ib.h +9 -2
@@ -761,6 +761,8 @@ struct mlx5_cache_ent {u32 access_mode;unsigned int ndescs; +struct rb_node node; + u8 disabled:1; u8 fill_to_high_water:1;
@@ -790,8 +792,9 @@ struct mlx5r_async_create_mkey {struct mlx5_mkey_cache {struct workqueue_struct *wq; -struct mlx5_cache_ent ent[MAX_MKEY_CACHE_ENTRIES ]; -struct dentry *root; +struct rb_root rb_root; +struct mutex rb_lock; +struct dentry *fs_root;unsigned long last_add; };
@@ -1336,11 +1339,15 @@ void mlx5_ib_copy_pas(u64 *old, u64 *new, int step, int num);int mlx5_ib_get_cqe_size (struct ib_cq *ibcq);int mlx5_mkey_cache_init (struct mlx5_ib_dev *dev);int mlx5_mkey_cache_cleanup (struct mlx5_ib_dev *dev); +struct mlx5_cache_ent *mlx5r_cache_create_ent (struct mlx5_ib_dev *dev, +int order);struct mlx5_ib_mr *mlx5_mr_cache_alloc (struct mlx5_ib_dev *dev,struct mlx5_cache_ent *ent,int access_flags); +struct mlx5_ib_mr *mlx5_mr_cache_alloc_order (struct mlx5_ib_dev *dev,u32 order, +int access_flags);int mlx5_ib_check_mr_status (struct ib_mr *ibmr,u32 check_mask,struct ib_mr_status *mr_status); struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd,
drivers/infiniband/hw/mlx5/mr.c +120 -40
240 lines not on this page · raw message
drivers/infiniband/hw/mlx5/odp.c +3 -5
@@ -438,8 +438,7 @@ static struct mlx5_ib_mr *implicit_get_child_mr(struct mlx5_ib_mr *imr,return ERR_CAST (odp);BUILD_BUG_ON (order >MKEY_CACHE_LAST_STD_ENTRY ); - mr =mlx5_mr_cache_alloc (dev, &dev->cache.ent[order], - imr->access_flags); + mr =mlx5_mr_cache_alloc_order (dev, order, imr->access_flags);if (IS_ERR (mr)) {ib_umem_odp_release (odp);return mr;
@@ -513,9 +512,8 @@ struct mlx5_ib_mr *mlx5_ib_alloc_implicit_mr(struct mlx5_ib_pd *pd,if (IS_ERR (umem_odp))return ERR_CAST (umem_odp); - imr =mlx5_mr_cache_alloc (dev, - &dev->cache.ent[MLX5_IMR_KSM_CACHE_ENTRY ], - access_flags); + imr =mlx5_mr_cache_alloc_order (dev,MLX5_IMR_KSM_CACHE_ENTRY , + access_flags);if (IS_ERR (imr)) {ib_umem_odp_release (umem_odp);return imr;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 748/1887 RDMA/mlx5: Introduce mlx5r_cache_rb_key
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Guralnik <[email protected]>
[ Upstream commit 73d09b2fe8336f5f37935e46418666ddbcd3c343 ]
Switch from using the mkey order to using the new struct as the key to the RB tree of cache entries.
The key is all the mkey properties that UMR operations can't modify. Using this key to define the cache entries and to search and create cache mkeys.
Stable-dep-of: d97505baea64 ("RDMA/mlx5: Fix the recovery flow of the UMR QP")
--- drivers/infiniband/hw/mlx5/mlx5_ib.h | 27 ++-- drivers/infiniband/hw/mlx5/mr.c | 228 +++++++++++++++++++-------- drivers/infiniband/hw/mlx5/odp.c | 30 ++-- 3 files changed, 201 insertions(+), 84 deletions(-)
drivers/infiniband/hw/mlx5/mlx5_ib.h +17 -10
@@ -637,6 +637,13 @@ enum mlx5_mkey_type { MLX5_MKEY_INDIRECT_DEVX, }; +struct mlx5r_cache_rb_key { +u8 ats:1 ; +unsigned int access_mode; +unsigned int access_flags; +unsigned int ndescs; +}; +struct mlx5_ib_mkey {u32 key;enum mlx5_mkey_type type;
@@ -757,11 +764,9 @@ struct mlx5_cache_ent {unsigned long reserved;char name[4 ]; -u32 order; -u32 access_mode; -unsigned int ndescs;struct rb_node node; +struct mlx5r_cache_rb_key rb_key; u8 disabled:1; u8 fill_to_high_water:1;
@@ -1340,14 +1345,13 @@ int mlx5_ib_get_cqe_size(struct ib_cq *ibcq);int mlx5_mkey_cache_init (struct mlx5_ib_dev *dev);int mlx5_mkey_cache_cleanup (struct mlx5_ib_dev *dev);struct mlx5_cache_ent *mlx5r_cache_create_ent (struct mlx5_ib_dev *dev, -int order); +struct mlx5r_cache_rb_key rb_key, +bool persistent_entry);struct mlx5_ib_mr *mlx5_mr_cache_alloc (struct mlx5_ib_dev *dev, -struct mlx5_cache_ent *ent, -int access_flags); +int access_flags,int access_mode, +int ndescs); -struct mlx5_ib_mr *mlx5_mr_cache_alloc_order (struct mlx5_ib_dev *dev,u32 order, -int access_flags);int mlx5_ib_check_mr_status (struct ib_mr *ibmr,u32 check_mask,struct ib_mr_status *mr_status); struct ib_wq *mlx5_ib_create_wq(struct ib_pd *pd,
@@ -1370,7 +1374,7 @@ int mlx5r_odp_create_eq(struct mlx5_ib_dev *dev, struct mlx5_ib_pf_eq *eq);void mlx5_ib_odp_cleanup_one (struct mlx5_ib_dev *ibdev);int __init mlx5_ib_odp_init (void );void mlx5_ib_odp_cleanup (void ); -void mlx5_odp_init_mkey_cache_entry (struct mlx5_cache_ent *ent); +int mlx5_odp_init_mkey_cache (struct mlx5_ib_dev *dev);void mlx5_odp_populate_xlt (void *xlt,size_t idx,size_t nentries,struct mlx5_ib_mr *mr,int flags);
@@ -1389,7 +1393,10 @@ static inline int mlx5r_odp_create_eq(struct mlx5_ib_dev *dev,static inline void mlx5_ib_odp_cleanup_one (struct mlx5_ib_dev *ibdev) {}static inline int mlx5_ib_odp_init (void ) {return 0 ; }static inline void mlx5_ib_odp_cleanup (void ) {} -static inline void mlx5_odp_init_mkey_cache_entry (struct mlx5_cache_ent *ent) {} +static inline int mlx5_odp_init_mkey_cache (struct mlx5_ib_dev *dev) +{ +return 0 ; +}static inline void mlx5_odp_populate_xlt (void *xlt,size_t idx,size_t nentries,struct mlx5_ib_mr *mr,int flags) {}
drivers/infiniband/hw/mlx5/mr.c +164 -64
382 lines not on this page · raw message
drivers/infiniband/hw/mlx5/odp.c +20 -10
@@ -424,7 +424,6 @@ static void mlx5_ib_page_fault_resume(struct mlx5_ib_dev *dev,static struct mlx5_ib_mr *implicit_get_child_mr (struct mlx5_ib_mr *imr,unsigned long idx) { -int order =order_base_2 (MLX5_IMR_MTT_ENTRIES );struct mlx5_ib_dev *dev =mr_to_mdev (imr);struct ib_umem_odp *odp;struct mlx5_ib_mr *mr;
@@ -437,8 +436,9 @@ static struct mlx5_ib_mr *implicit_get_child_mr(struct mlx5_ib_mr *imr,if (IS_ERR (odp))return ERR_CAST (odp); -BUILD_BUG_ON (order >MKEY_CACHE_LAST_STD_ENTRY ); - mr =mlx5_mr_cache_alloc_order (dev, order, imr->access_flags); + mr =mlx5_mr_cache_alloc (dev, imr->access_flags, +MLX5_MKC_ACCESS_MODE_MTT , +MLX5_IMR_MTT_ENTRIES );if (IS_ERR (mr)) {ib_umem_odp_release (odp);return mr;
@@ -512,8 +512,8 @@ struct mlx5_ib_mr *mlx5_ib_alloc_implicit_mr(struct mlx5_ib_pd *pd,if (IS_ERR (umem_odp))return ERR_CAST (umem_odp); - imr =mlx5_mr_cache_alloc_order (dev,MLX5_IMR_KSM_CACHE_ENTRY , - access_flags); + imr =mlx5_mr_cache_alloc (dev, access_flags,MLX5_MKC_ACCESS_MODE_KSM , + mlx5_imr_ksm_entries);if (IS_ERR (imr)) {ib_umem_odp_release (umem_odp);return imr;
@@ -1609,12 +1609,22 @@ mlx5_ib_odp_destroy_eq(struct mlx5_ib_dev *dev, struct mlx5_ib_pf_eq *eq)return err; } -void mlx5_odp_init_mkey_cache_entry (struct mlx5_cache_ent *ent) +int mlx5_odp_init_mkey_cache (struct mlx5_ib_dev *dev) { -if (!(ent->dev->odp_caps.general_caps &IB_ODP_SUPPORT_IMPLICIT )) -return ; - ent->ndescs = mlx5_imr_ksm_entries; - ent->access_mode =MLX5_MKC_ACCESS_MODE_KSM ; +struct mlx5r_cache_rb_key rb_key = { + .access_mode =MLX5_MKC_ACCESS_MODE_KSM , + .ndescs = mlx5_imr_ksm_entries, + }; +struct mlx5_cache_ent *ent; + +if (!(dev->odp_caps.general_caps &IB_ODP_SUPPORT_IMPLICIT )) +return 0 ; + + ent =mlx5r_cache_create_ent (dev, rb_key, true); +if (IS_ERR (ent)) +return PTR_ERR (ent); + +return 0 ; }static const struct ib_device_ops mlx5_ib_dev_odp_ops = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 749/1887 RDMA/mlx5: Implement mkeys management via LIFO queue
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shay Drory <[email protected]>
[ Upstream commit 57e7071683ef6148c9f5ea0ba84598d2ba681375 ]
Currently, mkeys are managed via xarray. This implementation leads to a degradation in cases many MRs are unregistered in parallel, due to xarray internal implementation, for example: deregistration 1M MRs via 64 threads is taking ~15% more time[1].
Hence, implement mkeys management via LIFO queue, which solved the degradation.
[1]
2.8us in kernel v5.19 compare to 3.2us in kernel v6.4
Only the umr.c hunk is kept: the UMR failure warning now also prints the mkey, which is the context the following UMR QP recovery fix builds on. The mkey cache rework in mr.c and mlx5_ib.h is dropped as the target fix does not depend on it.
Stable-dep-of: d97505baea64 ("RDMA/mlx5: Fix the recovery flow of the UMR QP")
--- drivers/infiniband/hw/mlx5/umr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/infiniband/hw/mlx5/umr.c +2 -2
@@ -333,8 +333,8 @@ static int mlx5r_umr_post_send_wait(struct mlx5_ib_dev *dev, u32 mkey,WARN_ON_ONCE (1 );mlx5_ib_warn (dev, -"reg umr failed (%u). Trying to recover and resubmit the flushed WQEs\n" , - umr_context.status); +"reg umr failed (%u). Trying to recover and resubmit the flushed WQEs, mkey = %u\n" , + umr_context.status, mkey);mutex_lock (&umrc->lock); err =mlx5r_umr_recover (dev);mutex_unlock (&umrc->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 750/1887 RDMA/mlx5: Fix the recovery flow of the UMR QP
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yishai Hadas <[email protected]>
[ Upstream commit d97505baea64d93538b16baf14ce7b8c1fbad746 ]
This patch addresses an issue in the recovery flow of the UMR QP, ensuring tasks do not get stuck, as highlighted by the call trace [1].
During recovery, before transitioning the QP to the RESET state, the software must wait for all outstanding WRs to complete.
Failing to do so can cause the firmware to skip sending some flushed CQEs with errors and simply discard them upon the RESET, as per the IB specification.
This race condition can result in lost CQEs and tasks becoming stuck.
To resolve this, the patch sends a final WR which serves only as a barrier before moving the QP state to RESET.
Once a CQE is received for that final WR, it guarantees that no outstanding WRs remain, making it safe to transition the QP to RESET and subsequently back to RTS, restoring proper functionality.
Note:
For the barrier WR, we simply reuse the failed and ready WR. Since the QP is in an error state, it will only receive IB_WC_WR_FLUSH_ERR. However, as it serves only as a barrier we don't care about its status.
[1]
INFO: task rdma_resource_l:1922 blocked for more than 120 seconds.
Tainted: G W 6.12.0-rc7+ #1626
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
task:rdma_resource_l state:D stack:0 pid:1922 tgid:1922 ppid:1369
flags:0x00004004
Call Trace:
<TASK>
__schedule+0x420/0xd30
schedule+0x47/0x130
schedule_timeout+0x280/0x300
? mark_held_locks+0x48/0x80
? lockdep_hardirqs_on_prepare+0xe5/0x1a0
wait_for_completion+0x75/0x130
mlx5r_umr_post_send_wait+0x3c2/0x5b0 [mlx5_ib]
? __pfx_mlx5r_umr_done+0x10/0x10 [mlx5_ib]
mlx5r_umr_revoke_mr+0x93/0xc0 [mlx5_ib]
__mlx5_ib_dereg_mr+0x299/0x520 [mlx5_ib]
? _raw_spin_unlock_irq+0x24/0x40
? wait_for_completion+0xfe/0x130
? rdma_restrack_put+0x63/0xe0 [ib_core]
ib_dereg_mr_user+0x5f/0x120 [ib_core]
? lock_release+0xc6/0x280
destroy_hw_idr_uobject+0x1d/0x60 [ib_uverbs]
uverbs_destroy_uobject+0x58/0x1d0 [ib_uverbs]
uobj_destroy+0x3f/0x70 [ib_uverbs]
ib_uverbs_cmd_verbs+0x3e4/0xbb0 [ib_uverbs]
? __pfx_uverbs_destroy_def_handler+0x10/0x10 [ib_uverbs]
? __lock_acquire+0x64e/0x2080
? mark_held_locks+0x48/0x80
? find_held_lock+0x2d/0xa0
? lock_acquire+0xc1/0x2f0
? ib_uverbs_ioctl+0xcb/0x170 [ib_uverbs]
? __fget_files+0xc3/0x1b0
ib_uverbs_ioctl+0xe7/0x170 [ib_uverbs]
? ib_uverbs_ioctl+0xcb/0x170 [ib_uverbs]
__x64_sys_ioctl+0x1b0/0xa70
do_syscall_64+0x6b/0x140
entry_SYSCALL_64_after_hwframe+0x76/0x7e
RIP: 0033:0x7f99c918b17b
RSP: 002b:00007ffc766d0468 EFLAGS: 00000246 ORIG_RAX:
0000000000000010
RAX: ffffffffffffffda RBX: 00007ffc766d0578 RCX:
00007f99c918b17b
RDX: 00007ffc766d0560 RSI: 00000000c0181b01 RDI:
0000000000000003
RBP: 00007ffc766d0540 R08: 00007f99c8f99010 R09:
000000000000bd7e
R10: 00007f99c94c1c70 R11: 0000000000000246 R12:
00007ffc766d0530
R13: 000000000000001c R14: 0000000040246a80 R15:
0000000000000000
</TASK>--- drivers/infiniband/hw/mlx5/umr.c | 83 +++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 27 deletions(-)
drivers/infiniband/hw/mlx5/umr.c +56 -27
@@ -200,30 +200,6 @@ void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev)ib_dealloc_pd (dev->umrc.pd); } -static int mlx5r_umr_recover (struct mlx5_ib_dev *dev) -{ -struct umr_common *umrc = &dev->umrc; -struct ib_qp_attr attr; -int err; - - attr.qp_state =IB_QPS_RESET ; - err =ib_modify_qp (umrc->qp, &attr,IB_QP_STATE ); -if (err) { -mlx5_ib_dbg (dev,"Couldn't modify UMR QP\n" ); - goto err; - } - - err =mlx5r_umr_qp_rst2rts (dev, umrc->qp); -if (err) - goto err; - - umrc->state =MLX5_UMR_STATE_ACTIVE ; -return 0 ; - -err: - umrc->state =MLX5_UMR_STATE_ERR ; -return err; -}static int mlx5r_umr_post_send (struct ib_qp *ibqp,u32 mkey,struct ib_cqe *cqe,struct mlx5r_umr_wqe *wqe,bool with_data)
@@ -271,6 +247,61 @@ static int mlx5r_umr_post_send(struct ib_qp *ibqp, u32 mkey, struct ib_cqe *cqe,return err; } +static int mlx5r_umr_recover (struct mlx5_ib_dev *dev,u32 mkey, +struct mlx5r_umr_context *umr_context, +struct mlx5r_umr_wqe *wqe,bool with_data) +{ +struct umr_common *umrc = &dev->umrc; +struct ib_qp_attr attr; +int err; + +mutex_lock (&umrc->lock); +/* Preventing any further WRs to be sent now */ +if (umrc->state !=MLX5_UMR_STATE_RECOVER ) { +mlx5_ib_warn (dev,"UMR recovery encountered an unexpected state=%d\n" , + umrc->state); + umrc->state =MLX5_UMR_STATE_RECOVER ; + } +mutex_unlock (&umrc->lock); + +/* Sending a final/barrier WR (the failed one) and wait for its completion. +* This will ensure that all the previous WRs got a completion before +* we set the QP state to RESET. +*/ + err =mlx5r_umr_post_send (umrc->qp, mkey, &umr_context->cqe, wqe, + with_data); +if (err) { +mlx5_ib_warn (dev,"UMR recovery post send failed, err %d\n" , err); + goto err; + } + +/* Since the QP is in an error state, it will only receive +* IB_WC_WR_FLUSH_ERR. However, as it serves only as a barrier +* we don't care about its status. +*/ +wait_for_completion (&umr_context->done); + + attr.qp_state =IB_QPS_RESET ; + err =ib_modify_qp (umrc->qp, &attr,IB_QP_STATE ); +if (err) { +mlx5_ib_warn (dev,"Couldn't modify UMR QP to RESET, err=%d\n" , err); + goto err; + } + + err =mlx5r_umr_qp_rst2rts (dev, umrc->qp); +if (err) { +mlx5_ib_warn (dev,"Couldn't modify UMR QP to RTS, err=%d\n" , err); + goto err; + } + + umrc->state =MLX5_UMR_STATE_ACTIVE ; +return 0 ; + +err: + umrc->state =MLX5_UMR_STATE_ERR ; +return err; +} +static void mlx5r_umr_done (struct ib_cq *cq,struct ib_wc *wc) { struct mlx5_ib_umr_context *context =
@@ -335,9 +366,7 @@ static int mlx5r_umr_post_send_wait(struct mlx5_ib_dev *dev, u32 mkey,mlx5_ib_warn (dev,"reg umr failed (%u). Trying to recover and resubmit the flushed WQEs, mkey = %u\n" , umr_context.status, mkey); -mutex_lock (&umrc->lock); - err =mlx5r_umr_recover (dev); -mutex_unlock (&umrc->lock); + err =mlx5r_umr_recover (dev, mkey, &umr_context, wqe, with_data);if (err)mlx5_ib_warn (dev,"couldn't recover UMR, err %d\n" , err);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 751/1887 net: enetc: VFs do not support HWTSTAMP_TX_ONESTEP_SYNC
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wei Fang <[email protected]>
[ Upstream commit a562d0c4a893eae3ea51d512c4d90ab858a6b7ec ]
Actually ENETC VFs do not support HWTSTAMP_TX_ONESTEP_SYNC because only ENETC PF can access PMa_SINGLE_STEP registers. And there will be a crash if VFs are used to test one-step timestamp, the crash log as follows.
[ 129.110909] Unable to handle kernel paging request at virtual address 00000000000080c0 [ 129.287769] Call trace: [ 129.290219] enetc_port_mac_wr+0x30/0xec (P) [ 129.294504] enetc_start_xmit+0xda4/0xe74 [ 129.298525] enetc_xmit+0x70/0xec [ 129.301848] dev_hard_start_xmit+0x98/0x118
--- drivers/net/ethernet/freescale/enetc/enetc.c | 3 +++ drivers/net/ethernet/freescale/enetc/enetc_ethtool.c | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-)
drivers/net/ethernet/freescale/enetc/enetc.c +3 -0
@@ -2713,6 +2713,9 @@ static int enetc_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr) priv->active_offloads |=ENETC_F_TX_TSTAMP ;break ;case HWTSTAMP_TX_ONESTEP_SYNC : +if (!enetc_si_is_pf (priv->si)) +return -EOPNOTSUPP ; + priv->active_offloads &= ~ENETC_F_TX_TSTAMP_MASK ; priv->active_offloads |=ENETC_F_TX_ONESTEP_SYNC_TSTAMP ;break ;
drivers/net/ethernet/freescale/enetc/enetc_ethtool.c +8 -2
@@ -772,6 +772,9 @@ static int enetc_set_coalesce(struct net_device *ndev,static int enetc_get_ts_info (struct net_device *ndev,struct ethtool_ts_info *info) { +#ifdef CONFIG_FSL_ENETC_PTP_CLOCK +struct enetc_ndev_priv *priv =netdev_priv (ndev); +#endif int *phc_idx; phc_idx =symbol_get (enetc_phc_index);
@@ -791,8 +794,11 @@ static int enetc_get_ts_info(struct net_device *ndev,SOF_TIMESTAMPING_SOFTWARE ; info->tx_types = (1 <<HWTSTAMP_TX_OFF ) | - (1 <<HWTSTAMP_TX_ON ) | - (1 <<HWTSTAMP_TX_ONESTEP_SYNC ); + (1 <<HWTSTAMP_TX_ON ); + +if (enetc_si_is_pf (priv->si)) + info->tx_types |= (1 <<HWTSTAMP_TX_ONESTEP_SYNC ); + info->rx_filters = (1 <<HWTSTAMP_FILTER_NONE ) | (1 <<HWTSTAMP_FILTER_ALL );#else
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 752/1887 nvme-tcp: fix potential memory corruption in nvme_tcp_recv_pdu()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maurizio Lombardi <[email protected]>
[ Upstream commit ad95bab0cd28ed77c2c0d0b6e76e03e031391064 ]
nvme_tcp_recv_pdu() doesn't check the validity of the header length. When header digests are enabled, a target might send a packet with an invalid header length (e.g. 255), causing nvme_tcp_verify_hdgst() to access memory outside the allocated area and cause memory corruptions by overwriting it with the calculated digest.
Fix this by rejecting packets with an unexpected header length.
--- drivers/nvme/host/tcp.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-)
drivers/nvme/host/tcp.c +29 -3
@@ -189,6 +189,19 @@ static inline int nvme_tcp_queue_id(struct nvme_tcp_queue *queue)return queue - queue->ctrl->queues; } +static inline bool nvme_tcp_recv_pdu_supported (enum nvme_tcp_pdu_type type) +{ +switch (type) { +case nvme_tcp_c2h_term: +case nvme_tcp_c2h_data: +case nvme_tcp_r2t: +case nvme_tcp_rsp: +return true; +default : +return false; + } +} +static inline struct blk_mq_tags *nvme_tcp_tagset (struct nvme_tcp_queue *queue) {u32 queue_idx =nvme_tcp_queue_id (queue);
@@ -792,6 +805,16 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb,return 0 ; hdr = queue->pdu; +if (unlikely (hdr->hlen !=sizeof (struct nvme_tcp_rsp_pdu ))) { +if (!nvme_tcp_recv_pdu_supported (hdr->type)) + goto unsupported_pdu; + +dev_err (queue->ctrl->ctrl.device, +"pdu type %d has unexpected header length (%d)\n" , + hdr->type, hdr->hlen); +return -EPROTO ; + } +if (unlikely (hdr->type == nvme_tcp_c2h_term)) {/* * C2HTermReq never includes Header or Data digests.
@@ -824,10 +847,13 @@ static int nvme_tcp_recv_pdu(struct nvme_tcp_queue *queue, struct sk_buff *skb,nvme_tcp_init_recv_ctx (queue);return nvme_tcp_handle_r2t (queue, (void *)queue->pdu);default : -dev_err (queue->ctrl->ctrl.device, -"unsupported pdu type (%d)\n" , hdr->type); -return -EINVAL ; + goto unsupported_pdu; } + +unsupported_pdu: +dev_err (queue->ctrl->ctrl.device, +"unsupported pdu type (%d)\n" , hdr->type); +return -EINVAL ; }static inline void nvme_tcp_end_request (struct request *rq,u16 status)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 753/1887 ksmbd: prevent connection release during oplock break notification
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit 3aa660c059240e0c795217182cf7df32909dd917 ]
ksmbd_work could be freed when after connection release. Increment r_count of ksmbd_conn to indicate that requests are not finished yet and to not release the connection.
--- fs/smb/server/connection.c | 19 +++++++++++++++++++ fs/smb/server/connection.h | 2 ++ fs/smb/server/oplock.c | 6 ++++++ fs/smb/server/server.c | 10 ++-------- 4 files changed, 29 insertions(+), 8 deletions(-)
fs/smb/server/connection.c +19 -0
@@ -442,6 +442,25 @@ void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops) default_conn_ops.terminate_fn = ops->terminate_fn; } +void ksmbd_conn_r_count_inc (struct ksmbd_conn *conn) +{ +atomic_inc (&conn->r_count); +} + +void ksmbd_conn_r_count_dec (struct ksmbd_conn *conn) +{ +/* +* Checking waitqueue to dropping pending requests on +* disconnection. waitqueue_active is safe because it +* uses atomic operation for condition. +*/ +atomic_inc (&conn->refcnt); +if (!atomic_dec_return (&conn->r_count) &&waitqueue_active (&conn->r_count_q)) +wake_up (&conn->r_count_q); + +ksmbd_conn_put (conn); +} +int ksmbd_conn_transport_init (void ) {int ret;
fs/smb/server/connection.h +2 -0
@@ -176,6 +176,8 @@ int ksmbd_conn_transport_init(void);void ksmbd_conn_transport_destroy (void );void ksmbd_conn_lock (struct ksmbd_conn *conn);void ksmbd_conn_unlock (struct ksmbd_conn *conn); +void ksmbd_conn_r_count_inc (struct ksmbd_conn *conn); +void ksmbd_conn_r_count_dec (struct ksmbd_conn *conn);/* * WARNING
fs/smb/server/oplock.c +6 -0
@@ -657,6 +657,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) {struct smb2_oplock_break *rsp =NULL ; struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work); +struct ksmbd_conn *conn = work->conn;struct oplock_break_info *br_info = work->request_buf;struct smb2_hdr *rsp_hdr;struct ksmbd_file *fp;
@@ -712,6 +713,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) out:ksmbd_free_work_struct (work); +ksmbd_conn_r_count_dec (conn); }/**
@@ -746,6 +748,7 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo) work->sess = opinfo->sess;if (opinfo->op_state ==OPLOCK_ACK_WAIT ) { +ksmbd_conn_r_count_inc (conn);INIT_WORK (&work->work, __smb2_oplock_break_noti);ksmbd_queue_work (work);
@@ -767,6 +770,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) {struct smb2_lease_break *rsp =NULL ; struct ksmbd_work *work = container_of(wk, struct ksmbd_work, work); +struct ksmbd_conn *conn = work->conn;struct lease_break_info *br_info = work->request_buf;struct smb2_hdr *rsp_hdr;
@@ -813,6 +817,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) out:ksmbd_free_work_struct (work); +ksmbd_conn_r_count_dec (conn); }/**
@@ -863,6 +868,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)list_del_init (&in_work->interim_entry);release_async_work (in_work); } +ksmbd_conn_r_count_inc (conn);INIT_WORK (&work->work, __smb2_lease_break_noti);ksmbd_queue_work (work);wait_for_break_ack (opinfo);
fs/smb/server/server.c +2 -8
@@ -291,13 +291,7 @@ static void handle_ksmbd_work(struct work_struct *wk)ksmbd_conn_try_dequeue_request (work);ksmbd_free_work_struct (work);atomic_dec (&conn->mux_smb_requests); -/* -* Checking waitqueue to dropping pending requests on -* disconnection. waitqueue_active is safe because it -* uses atomic operation for condition. -*/ -if (!atomic_dec_return (&conn->r_count) &&waitqueue_active (&conn->r_count_q)) -wake_up (&conn->r_count_q); +ksmbd_conn_r_count_dec (conn); }/**
@@ -332,7 +326,7 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn) conn->request_buf =NULL ;ksmbd_conn_enqueue_request (work); -atomic_inc (&conn->r_count); +ksmbd_conn_r_count_inc (conn);/* update activity on connection */ conn->last_active = jiffies;INIT_WORK (&work->work, handle_ksmbd_work);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 754/1887 eth: bnxt: fix truesize for mb-xdp-pass case
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Taehee Yoo <[email protected]>
[ Upstream commit 9f7b2aa5034e24d3c49db73d5f760c0435fe31c2 ]
When mb-xdp is set and return is XDP_PASS, packet is converted from xdp_buff to sk_buff with xdp_update_skb_shared_info() in bnxt_xdp_build_skb().bnxt_xdp_build_skb() passes incorrect truesize argument to xdp_update_skb_shared_info().
The truesize is calculated as BNXT_RX_PAGE_SIZE * sinfo->nr_frags but the skb_shared_info was wiped by napi_build_skb() before.
So it stores sinfo->nr_frags before bnxt_xdp_build_skb() and use it instead of getting skb_shared_info from xdp_get_shared_info_from_buff().
Splat looks like:
------------[ cut here ]------------ WARNING: CPU: 2 PID: 0 at net/core/skbuff.c:6072 skb_try_coalesce+0x504/0x590 Modules linked in: xt_nat xt_tcpudp veth af_packet xt_conntrack nft_chain_nat xt_MASQUERADE nf_conntrack_netlink xfrm_user xt_addrtype nft_coms CPU: 2 UID: 0 PID: 0 Comm: swapper/2 Not tainted 6.14.0-rc2+ #3 RIP: 0010:skb_try_coalesce+0x504/0x590 Code: 4b fd ff ff 49 8b 34 24 40 80 e6 40 0f 84 3d fd ff ff 49 8b 74 24 48 40 f6 c6 01 0f 84 2e fd ff ff 48 8d 4e ff e9 25 fd ff ff <0f> 0b e99 RSP: 0018:ffffb62c4120caa8 EFLAGS: 00010287 RAX: 0000000000000003 RBX: ffffb62c4120cb14 RCX: 0000000000000ec0 RDX: 0000000000001000 RSI: ffffa06e5d7dc000 RDI: 0000000000000003 RBP: ffffa06e5d7ddec0 R08: ffffa06e6120a800 R09: ffffa06e7a119900 R10: 0000000000002310 R11: ffffa06e5d7dcec0 R12: ffffe4360575f740 R13: ffffe43600000000 R14: 0000000000000002 R15: 0000000000000002 FS: 0000000000000000(0000) GS:ffffa0755f700000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f147b76b0f8 CR3: 00000001615d4000 CR4: 00000000007506f0 PKRU: 55555554 Call Trace: <IRQ> ? __warn+0x84/0x130 ? skb_try_coalesce+0x504/0x590 ? report_bug+0x18a/0x1a0 ? handle_bug+0x53/0x90 ? exc_invalid_op+0x14/0x70 ? asm_exc_invalid_op+0x16/0x20 ? skb_try_coalesce+0x504/0x590 inet_frag_reasm_finish+0x11f/0x2e0 ip_defrag+0x37a/0x900 ip_local_deliver+0x51/0x120 ip_sublist_rcv_finish+0x64/0x70 ip_sublist_rcv+0x179/0x210 ip_list_rcv+0xf9/0x130
How to reproduce:
<Node A>
ip link set $interface1 xdp obj xdp_pass.o
ip link set $interface1 mtu 9000 up
ip a a 10.0.0.1/24 dev $interface1
<Node B>
ip link set $interfac2 mtu 9000 up
ip a a 10.0.0.2/24 dev $interface2
ping 10.0.0.1 -s 65000
Following ping.py patch adds xdp-mb-pass case. so ping.py is going to be able to reproduce this issue.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 8 ++++++++ drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +8 -0
@@ -1833,6 +1833,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,struct rx_cmp_ext *rxcmp1;u32 tmp_raw_cons = *raw_cons;u16 cfa_code, cons, prod, cp_cons =RING_CMP (tmp_raw_cons); +struct skb_shared_info *sinfo;struct bnxt_sw_rx_bd *rx_buf;unsigned int len;u8 *data_ptr, agg_bufs, cmp_type;
@@ -1957,6 +1958,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, false);if (!frag_len) goto oom_next_rx; + } xdp_active = true; }
@@ -1966,6 +1968,12 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, rc =1 ; goto next_rx; } +if (xdp_buff_has_frags (&xdp)) { + sinfo =xdp_get_shared_info_from_buff (&xdp); + agg_bufs = sinfo->nr_frags; + }else { + agg_bufs =0 ; + } }if (len <= bp->rx_copy_thresh) {
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +1 -1
@@ -464,7 +464,7 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,xdp_update_skb_shared_info (skb, num_frags, sinfo->xdp_frags_size, -BNXT_RX_PAGE_SIZE * sinfo->nr_frags, +BNXT_RX_PAGE_SIZE * num_frags,xdp_buff_is_frag_pfmemalloc (xdp));return skb; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 755/1887 ksmbd: fix use-after-free in ksmbd_free_work_struct
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit bb39ed47065455604729404729d9116868638d31 ]
->interim_entry of ksmbd_work could be deleted after oplock is freed. We don't need to manage it with linked list. The interim request could be immediately sent whenever a oplock break wait is needed.
--- fs/smb/server/ksmbd_work.c | 3 --- fs/smb/server/ksmbd_work.h | 1 - fs/smb/server/oplock.c | 37 +++++++++++++++---------------------- fs/smb/server/oplock.h | 1 - 4 files changed, 15 insertions(+), 27 deletions(-)
fs/smb/server/ksmbd_work.c +0 -3
@@ -26,7 +26,6 @@ struct ksmbd_work *ksmbd_alloc_work_struct(void)INIT_LIST_HEAD (&work->request_entry);INIT_LIST_HEAD (&work->async_request_entry);INIT_LIST_HEAD (&work->fp_entry); -INIT_LIST_HEAD (&work->interim_entry);INIT_LIST_HEAD (&work->aux_read_list); work->iov_alloc_cnt =4 ; work->iov = kcalloc(work->iov_alloc_cnt, sizeof(struct kvec),
@@ -56,8 +55,6 @@ void ksmbd_free_work_struct(struct ksmbd_work *work)kfree (work->tr_buf);kvfree (work->request_buf);kfree (work->iov); -if (!list_empty (&work->interim_entry)) -list_del (&work->interim_entry);if (work->async_id)ksmbd_release_id (&work->conn->async_ida, work->async_id);
fs/smb/server/ksmbd_work.h +0 -1
@@ -96,7 +96,6 @@ struct ksmbd_work {/* List head at conn->async_requests */ struct list_head async_request_entry;struct list_head fp_entry; -struct list_head interim_entry; };/**
fs/smb/server/oplock.c +15 -22
@@ -45,7 +45,6 @@ static struct oplock_info *alloc_opinfo(struct ksmbd_work *work, opinfo->fid = id; opinfo->Tid = Tid;INIT_LIST_HEAD (&opinfo->op_entry); -INIT_LIST_HEAD (&opinfo->interim_list);init_waitqueue_head (&opinfo->oplock_q);init_waitqueue_head (&opinfo->oplock_brk);atomic_set (&opinfo->refcount,1 );
@@ -830,7 +829,6 @@ static void __smb2_lease_break_noti(struct work_struct *wk)static int smb2_lease_break_noti (struct oplock_info *opinfo) {struct ksmbd_conn *conn = opinfo->conn; -struct list_head *tmp, *t;struct ksmbd_work *work;struct lease_break_info *br_info;struct lease *lease = opinfo->o_lease;
@@ -858,16 +856,6 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) work->sess = opinfo->sess;if (opinfo->op_state ==OPLOCK_ACK_WAIT ) { -list_for_each_safe (tmp, t, &opinfo->interim_list) { -struct ksmbd_work *in_work; - - in_work = list_entry(tmp, struct ksmbd_work, - interim_entry); -setup_async_work (in_work,NULL ,NULL ); -smb2_send_interim_resp (in_work,STATUS_PENDING ); -list_del_init (&in_work->interim_entry); -release_async_work (in_work); - }ksmbd_conn_r_count_inc (conn);INIT_WORK (&work->work, __smb2_lease_break_noti);ksmbd_queue_work (work);
@@ -899,7 +887,8 @@ static void wait_lease_breaking(struct oplock_info *opinfo) } } -static int oplock_break (struct oplock_info *brk_opinfo,int req_op_level) +static int oplock_break (struct oplock_info *brk_opinfo,int req_op_level, +struct ksmbd_work *in_work) {int err =0 ;
@@ -942,9 +931,15 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level) }if (lease->state & (SMB2_LEASE_WRITE_CACHING_LE | -SMB2_LEASE_HANDLE_CACHING_LE )) +SMB2_LEASE_HANDLE_CACHING_LE )) { +if (in_work) { +setup_async_work (in_work,NULL ,NULL ); +smb2_send_interim_resp (in_work,STATUS_PENDING ); +release_async_work (in_work); + } + brk_opinfo->op_state =OPLOCK_ACK_WAIT ; -else + }else atomic_dec (&brk_opinfo->breaking_cnt); }else { err =oplock_break_pending (brk_opinfo, req_op_level);
@@ -1151,7 +1146,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, }read_unlock (&p_ci->m_lock); -oplock_break (opinfo,SMB2_OPLOCK_LEVEL_NONE ); +oplock_break (opinfo,SMB2_OPLOCK_LEVEL_NONE ,NULL );opinfo_conn_put (opinfo);read_lock (&p_ci->m_lock); }
@@ -1192,7 +1187,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)continue ; }read_unlock (&p_ci->m_lock); -oplock_break (opinfo,SMB2_OPLOCK_LEVEL_NONE ); +oplock_break (opinfo,SMB2_OPLOCK_LEVEL_NONE ,NULL );opinfo_conn_put (opinfo);read_lock (&p_ci->m_lock); }
@@ -1293,8 +1288,7 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid, goto op_break_not_needed; } -list_add (&work->interim_entry, &prev_opinfo->interim_list); - err =oplock_break (prev_opinfo,SMB2_OPLOCK_LEVEL_II ); + err =oplock_break (prev_opinfo,SMB2_OPLOCK_LEVEL_II , work);opinfo_conn_put (prev_opinfo);if (err == -ENOENT ) goto set_lev;
@@ -1363,8 +1357,7 @@ static void smb_break_all_write_oplock(struct ksmbd_work *work, } brk_opinfo->open_trunc = is_trunc; -list_add (&work->interim_entry, &brk_opinfo->interim_list); -oplock_break (brk_opinfo,SMB2_OPLOCK_LEVEL_II ); +oplock_break (brk_opinfo,SMB2_OPLOCK_LEVEL_II , work);opinfo_conn_put (brk_opinfo); }
@@ -1427,7 +1420,7 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp, SMB2_LEASE_KEY_SIZE)) goto next; brk_op->open_trunc = is_trunc; -oplock_break (brk_op,SMB2_OPLOCK_LEVEL_NONE ); +oplock_break (brk_op,SMB2_OPLOCK_LEVEL_NONE ,NULL ); next:opinfo_conn_put (brk_op);rcu_read_lock ();
fs/smb/server/oplock.h +0 -1
@@ -74,7 +74,6 @@ struct oplock_info {bool is_lease;bool open_trunc;/* truncate on open */ struct lease *o_lease; -struct list_head interim_list;struct list_head op_entry;struct list_head lease_entry;wait_queue_head_t oplock_q;/* Other server threads */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 756/1887 Bluetooth: L2CAP: Fix slab-use-after-free Read in l2cap_send_cmd
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit b4f82f9ed43aefa79bec2504ae8c29be0c0f5d1d ]
After the hci sync command releases l2cap_conn, the hci receive data work queue references the released l2cap_conn when sending to the upper layer. Add hci dev lock to the hci receive data work queue to synchronize the two.
[1]
BUG: KASAN: slab-use-after-free in l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954 Read of size 8 at addr ffff8880271a4000 by task kworker/u9:2/5837 CPU: 0 UID: 0 PID: 5837 Comm: kworker/u9:2 Not tainted 6.13.0-rc5-syzkaller-00163-gab75170520d4 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 Workqueue: hci1 hci_rx_work Call Trace: <TASK> __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 [inline] print_report+0x169/0x550 mm/kasan/report.c:489 kasan_report+0x143/0x180 mm/kasan/report.c:602 l2cap_build_cmd net/bluetooth/l2cap_core.c:2964 [inline] l2cap_send_cmd+0x187/0x8d0 net/bluetooth/l2cap_core.c:954 l2cap_sig_send_rej net/bluetooth/l2cap_core.c:5502 [inline] l2cap_sig_channel net/bluetooth/l2cap_core.c:5538 [inline] l2cap_recv_frame+0x221f/0x10db0 net/bluetooth/l2cap_core.c:6817 hci_acldata_packet net/bluetooth/hci_core.c:3797 [inline] hci_rx_work+0x508/0xdb0 net/bluetooth/hci_core.c:4040 process_one_work kernel/workqueue.c:3229 [inline] process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310 worker_thread+0x870/0xd30 kernel/workqueue.c:3391 kthread+0x2f0/0x390 kernel/kthread.c:389 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 </TASK> Allocated by task 5837: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 poison_kmalloc_redzone mm/kasan/common.c:377 [inline] __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:394 kasan_kmalloc include/linux/kasan.h:260 [inline] __kmalloc_cache_noprof+0x243/0x390 mm/slub.c:4329 kmalloc_noprof include/linux/slab.h:901 [inline] kzalloc_noprof include/linux/slab.h:1037 [inline] l2cap_conn_add+0xa9/0x8e0 net/bluetooth/l2cap_core.c:6860 l2cap_connect_cfm+0x115/0x1090 net/bluetooth/l2cap_core.c:7239 hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline] hci_remote_features_evt+0x68e/0xac0 net/bluetooth/hci_event.c:3726 hci_event_func net/bluetooth/hci_event.c:7473 [inline] hci_event_packet+0xac2/0x1540 net/bluetooth/hci_event.c:7525 hci_rx_work+0x3f3/0xdb0 net/bluetooth/hci_core.c:4035 process_one_work kernel/workqueue.c:3229 [inline] process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310 worker_thread+0x870/0xd30 kernel/workqueue.c:3391 kthread+0x2f0/0x390 kernel/kthread.c:389 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 Freed by task 54: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 kasan_save_free_info+0x40/0x50 mm/kasan/generic.c:582 poison_slab_object mm/kasan/common.c:247 [inline] __kasan_slab_free+0x59/0x70 mm/kasan/common.c:264 kasan_slab_free include/linux/kasan.h:233 [inline] slab_free_hook mm/slub.c:2353 [inline] slab_free mm/slub.c:4613 [inline] kfree+0x196/0x430 mm/slub.c:4761 l2cap_connect_cfm+0xcc/0x1090 net/bluetooth/l2cap_core.c:7235 hci_connect_cfm include/net/bluetooth/hci_core.h:2057 [inline] hci_conn_failed+0x287/0x400 net/bluetooth/hci_conn.c:1266 hci_abort_conn_sync+0x56c/0x11f0 net/bluetooth/hci_sync.c:5603 hci_cmd_sync_work+0x22b/0x400 net/bluetooth/hci_sync.c:332 process_one_work kernel/workqueue.c:3229 [inline] process_scheduled_works+0xa66/0x1840 kernel/workqueue.c:3310 worker_thread+0x870/0xd30 kernel/workqueue.c:3391 kthread+0x2f0/0x390 kernel/kthread.c:389 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
--- net/bluetooth/l2cap_core.c | 39 +++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-)
net/bluetooth/l2cap_core.c +34 -5
@@ -998,6 +998,16 @@ static int l2cap_get_ident(struct l2cap_conn *conn)return ident; } +static void l2cap_send_acl (struct l2cap_conn *conn,struct sk_buff *skb, +u8 flags) +{ +/* Check if the hcon still valid before attempting to send */ +if (hci_conn_valid (conn->hcon->hdev, conn->hcon)) +hci_send_acl (conn->hchan, skb, flags); +else +kfree_skb (skb); +} +static void l2cap_send_cmd (struct l2cap_conn *conn,u8 ident,u8 code,u16 len,void *data) {
@@ -1020,7 +1030,7 @@ static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,bt_cb (skb)->force_active =BT_POWER_FORCE_ACTIVE_ON ; skb->priority =HCI_PRIO_MAX ; -hci_send_acl (conn->hchan, skb, flags); +l2cap_send_acl (conn, skb, flags); }static void l2cap_do_send (struct l2cap_chan *chan,struct sk_buff *skb)
@@ -1843,10 +1853,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)mutex_unlock (&conn->chan_lock); -hci_chan_del (conn->hchan); - hcon->l2cap_data =NULL ; - conn->hchan =NULL ;l2cap_conn_put (conn); }
@@ -1854,6 +1861,7 @@ static void l2cap_conn_free(struct kref *ref) { struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); +hci_chan_del (conn->hchan);hci_conn_put (conn->hcon);kfree (conn); }
@@ -7813,14 +7821,33 @@ static void l2cap_recv_reset(struct l2cap_conn *conn) conn->rx_len =0 ; } +static struct l2cap_conn *l2cap_conn_hold_unless_zero (struct l2cap_conn *c) +{ +BT_DBG ("conn %p orig refcnt %u" , c,kref_read (&c->ref)); + +if (!kref_get_unless_zero (&c->ref)) +return NULL ; + +return c; +} +void l2cap_recv_acldata (struct hci_conn *hcon,struct sk_buff *skb,u16 flags) { -struct l2cap_conn *conn = hcon->l2cap_data; +struct l2cap_conn *conn;int len; +/* Lock hdev to access l2cap_data to avoid race with l2cap_conn_del */ +hci_dev_lock (hcon->hdev); + + conn = hcon->l2cap_data; +if (!conn) conn =l2cap_conn_add (hcon); + conn =l2cap_conn_hold_unless_zero (conn); + +hci_dev_unlock (hcon->hdev); +if (!conn) goto drop;
@@ -7912,6 +7939,8 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)break ; } +l2cap_conn_put (conn); + drop:kfree_skb (skb); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 757/1887 net: mctp: unshare packets when reassembling
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Johnston <[email protected]>
[ Upstream commit f5d83cf0eeb90fade4d5c4d17d24b8bee9ceeecc ]
Ensure that the frag_list used for reassembly isn't shared with other packets. This avoids incorrect reassembly when packets are cloned, and prevents a memory leak due to circular references between fragments and their skb_shared_info.
The upcoming MCTP-over-USB driver uses skb_clone which can trigger the problem - other MCTP drivers don't share SKBs.
A kunit test is added to reproduce the issue.
--- net/mctp/route.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-)
net/mctp/route.c +29 -14
@@ -298,8 +298,14 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb) &MCTP_HDR_SEQ_MASK ;if (!key->reasm_head) { - key->reasm_head = skb; - key->reasm_tailp = &(skb_shinfo (skb)->frag_list); +/* Since we're manipulating the shared frag_list, ensure it isn't +* shared with any other SKBs. +*/ + key->reasm_head =skb_unshare (skb,GFP_ATOMIC ); +if (!key->reasm_head) +return -ENOMEM ; + + key->reasm_tailp = &(skb_shinfo (key->reasm_head)->frag_list); key->last_seq = this_seq;return 0 ; }
@@ -429,18 +435,26 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)/* we can queue without the key lock here, as the * key isn't observable yet */ -mctp_frag_queue (key, skb); - -/* if the key_add fails, we've raced with another -* SOM packet with the same src, dest and tag. There's -* no way to distinguish future packets, so all we -* can do is drop; we'll free the skb on exit from -* this function. -*/ - rc =mctp_key_add (key, msk); -if (!rc) { -trace_mctp_key_acquire (key); + rc =mctp_frag_queue (key, skb); +if (rc == -ENOMEM ) { +/* skb_unshare() has already freed the skb */ + skb =NULL ; + }else if (!rc) { +/* reasm_head owns the (possibly copied) skb */ skb =NULL ; + +/* if the key_add fails, we've raced with +* another SOM packet with the same src, dest +* and tag. There's no way to distinguish +* future packets, so all we can do is drop. +*/ + rc =mctp_key_add (key, msk); +if (!rc) { +trace_mctp_key_acquire (key); + }else { +kfree_skb (key->reasm_head); + key->reasm_head =NULL ; + } }/* we don't need to release key->lock on exit, so
@@ -459,7 +473,8 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb) key =NULL ; }else { rc =mctp_frag_queue (key, skb); -if (!rc) +/* -ENOMEM: skb_unshare() already freed the skb */ +if (!rc || rc == -ENOMEM ) skb =NULL ; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 758/1887 ksmbd: fix null pointer dereference in alloc_preauth_hash()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit c8b5b7c5da7d0c31c9b7190b4a7bba5281fc4780 ]
The Client send malformed smb2 negotiate request. ksmbd return error response. Subsequently, the client can send smb2 session setup even thought conn->preauth_info is not allocated.
This patch add KSMBD_SESS_NEED_SETUP status of connection to ignore session setup request if smb2 negotiate phase is not complete.
--- fs/smb/server/connection.h | 11 +++++++++++ fs/smb/server/smb2pdu.c | 14 +++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-)
fs/smb/server/connection.h +11 -0
@@ -27,6 +27,7 @@ enum {KSMBD_SESS_EXITING ,KSMBD_SESS_NEED_RECONNECT ,KSMBD_SESS_NEED_NEGOTIATE , +KSMBD_SESS_NEED_SETUP , KSMBD_SESS_RELEASING };
@@ -200,6 +201,11 @@ static inline bool ksmbd_conn_need_negotiate(struct ksmbd_conn *conn)return READ_ONCE (conn->status) ==KSMBD_SESS_NEED_NEGOTIATE ; } +static inline bool ksmbd_conn_need_setup (struct ksmbd_conn *conn) +{ +return READ_ONCE (conn->status) ==KSMBD_SESS_NEED_SETUP ; +} +static inline bool ksmbd_conn_need_reconnect (struct ksmbd_conn *conn) {return READ_ONCE (conn->status) ==KSMBD_SESS_NEED_RECONNECT ;
@@ -230,6 +236,11 @@ static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_conn *conn)WRITE_ONCE (conn->status,KSMBD_SESS_NEED_NEGOTIATE ); } +static inline void ksmbd_conn_set_need_setup (struct ksmbd_conn *conn) +{ +WRITE_ONCE (conn->status,KSMBD_SESS_NEED_SETUP ); +} +static inline void ksmbd_conn_set_need_reconnect (struct ksmbd_conn *conn) {WRITE_ONCE (conn->status,KSMBD_SESS_NEED_RECONNECT );
fs/smb/server/smb2pdu.c +11 -3
@@ -1269,7 +1269,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work) } conn->srv_sec_mode =le16_to_cpu (rsp->SecurityMode); -ksmbd_conn_set_need_negotiate (conn); +ksmbd_conn_set_need_setup (conn); err_out:if (rc && rsp->hdr.Status ==STATUS_SUCCESS )
@@ -1290,6 +1290,9 @@ static int alloc_preauth_hash(struct ksmbd_session *sess,if (sess->Preauth_HashValue)return 0 ; +if (!conn->preauth_info) +return -ENOMEM ; + sess->Preauth_HashValue =kmemdup (conn->preauth_info->Preauth_HashValue,PREAUTH_HASHVALUE_SIZE ,GFP_KERNEL );if (!sess->Preauth_HashValue)
@@ -1704,6 +1707,11 @@ int smb2_sess_setup(struct ksmbd_work *work)ksmbd_debug (SMB ,"Received request for session setup\n" ); +if (!ksmbd_conn_need_setup (conn) && !ksmbd_conn_good (conn)) { + work->send_no_response =1 ; +return rc; + } +WORK_BUFFERS (work, req, rsp); rsp->StructureSize =cpu_to_le16 (9 );
@@ -1949,7 +1957,7 @@ int smb2_sess_setup(struct ksmbd_work *work)if (try_delay) {ksmbd_conn_set_need_reconnect (conn);ssleep (5 ); -ksmbd_conn_set_need_negotiate (conn); +ksmbd_conn_set_need_setup (conn); } }smb2_set_err_rsp (work);
@@ -2268,7 +2276,7 @@ int smb2_session_logoff(struct ksmbd_work *work) sess->state =SMB2_SESSION_EXPIRED ;up_write (&conn->session_lock); -ksmbd_all_conn_set_status (sess_id,KSMBD_SESS_NEED_NEGOTIATE ); +ksmbd_all_conn_set_status (sess_id,KSMBD_SESS_NEED_SETUP ); rsp->StructureSize =cpu_to_le16 (4 ); err =ksmbd_iov_pin_rsp (work, rsp,sizeof (struct smb2_logoff_rsp ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 759/1887 LoongArch: BPF: Dont override subprogs return value
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hengqi Chen <[email protected]>
[ Upstream commit 60f3caff1492e5b8616b9578c4bedb5c0a88ed14 ]
The verifier test calls: div by 0 in subprog triggers a panic at the ld.bu instruction. The ld.bu insn is trying to load byte from memory address returned by the subprog. The subprog actually set the correct address at the a5 register (dedicated register for BPF return values). But at commit 73c359d1d356 ("LoongArch: BPF: Sign-extend return values") we also sign extended a5 to the a0 register (return value in LoongArch). For function call insn, we later propagate the a0 register back to a5 register. This is right for native calls but wrong for bpf2bpf calls which expect zero-extended return value in a5 register. So only move a0 to a5 for native calls (i.e. non-BPF_PSEUDO_CALL).
--- arch/loongarch/net/bpf_jit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/loongarch/net/bpf_jit.c +4 -1
@@ -775,7 +775,10 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool extmove_addr (ctx, t1, func_addr);emit_insn (ctx, jirl, t1,LOONGARCH_GPR_RA ,0 ); -move_reg (ctx, regmap[BPF_REG_0 ],LOONGARCH_GPR_A0 ); + +if (insn->src_reg !=BPF_PSEUDO_CALL ) +move_reg (ctx, regmap[BPF_REG_0 ],LOONGARCH_GPR_A0 ); +break ;/* tail call */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 760/1887 ibmveth: Always stop tx queues during close
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nick Child <[email protected]>
[ Upstream commit 127b7218bfdd60205cfe2fa3f06d95e85a2650ed ]
netif_stop_all_queues must be called before calling H_FREE_LOGICAL_LAN. As a result, we can remove the pool_config field from the ibmveth adapter structure.
Some device configuration changes call ibmveth_close in order to free the current resources held by the device. These functions then make their changes and call ibmveth_open to reallocate and reserve resources for the device.
Prior to this commit, the flag pool_config was used to tell ibmveth_close that it should not halt the transmit queue. pool_config was introduced in commit 860f242eb534 ("[PATCH] ibmveth change buffer pools dynamically") to avoid interrupting the tx flow when making rx config changes. Since then, other commits adopted this approach, even if making tx config changes.
The issue with this approach was that the hypervisor freed all of the devices control structures after the hcall H_FREE_LOGICAL_LAN was performed but the transmit queues were never stopped. So the higher layers in the network stack would continue transmission but any H_SEND_LOGICAL_LAN hcall would fail with H_PARAMETER until the hypervisor's structures for the device were allocated with the H_REGISTER_LOGICAL_LAN hcall in ibmveth_open. This resulted in no real networking harm but did cause several of these error messages to be logged: "h_send_logical_lan failed with rc=-4"
So, instead of trying to keep the transmit queues alive during network configuration changes, just stop the queues, make necessary changes then restart the queues.
Stable-dep-of: 053f3ff67d7f ("net: ibmveth: make veth_pool_store stop hanging")
--- drivers/net/ethernet/ibm/ibmveth.c | 18 +----------------- drivers/net/ethernet/ibm/ibmveth.h | 1 - 2 files changed, 1 insertion(+), 18 deletions(-)
drivers/net/ethernet/ibm/ibmveth.c +1 -17
@@ -692,8 +692,7 @@ static int ibmveth_close(struct net_device *netdev)napi_disable (&adapter->napi); -if (!adapter->pool_config) -netif_tx_stop_all_queues (netdev); +netif_tx_stop_all_queues (netdev);h_vio_signal (adapter->vdev->unit_address,VIO_IRQ_DISABLE );
@@ -801,9 +800,7 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data)if (netif_running (dev)) { restart =1 ; - adapter->pool_config =1 ;ibmveth_close (dev); - adapter->pool_config =0 ; } set_attr =0 ;
@@ -885,9 +882,7 @@ static int ibmveth_set_tso(struct net_device *dev, u32 data)if (netif_running (dev)) { restart =1 ; - adapter->pool_config =1 ;ibmveth_close (dev); - adapter->pool_config =0 ; } set_attr =0 ;
@@ -1536,9 +1531,7 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)only the buffer pools necessary to hold the new MTU */ if (netif_running (adapter->netdev)) { need_restart =1 ; - adapter->pool_config =1 ;ibmveth_close (adapter->netdev); - adapter->pool_config =0 ; }/* Look for an active buffer pool that can hold the new MTU */
@@ -1724,7 +1717,6 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) adapter->vdev = dev; adapter->netdev = netdev; adapter->mcastFilterSize =be32_to_cpu (*mcastFilterSize_p); - adapter->pool_config =0 ;ibmveth_init_link_settings (netdev);netif_napi_add_weight (netdev, &adapter->napi, ibmveth_poll,16 );
@@ -1865,9 +1857,7 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr,return -ENOMEM ; } pool->active =1 ; - adapter->pool_config =1 ;ibmveth_close (netdev); - adapter->pool_config =0 ;if ((rc =ibmveth_open (netdev)))return rc; }else {
@@ -1893,10 +1883,8 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr, }if (netif_running (netdev)) { - adapter->pool_config =1 ;ibmveth_close (netdev); pool->active =0 ; - adapter->pool_config =0 ;if ((rc =ibmveth_open (netdev)))return rc; }
@@ -1907,9 +1895,7 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr,return -EINVAL ; }else {if (netif_running (netdev)) { - adapter->pool_config =1 ;ibmveth_close (netdev); - adapter->pool_config =0 ; pool->size = value;if ((rc =ibmveth_open (netdev)))return rc;
@@ -1922,9 +1908,7 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr,return -EINVAL ; }else {if (netif_running (netdev)) { - adapter->pool_config =1 ;ibmveth_close (netdev); - adapter->pool_config =0 ; pool->buff_size = value;if ((rc =ibmveth_open (netdev)))return rc;
drivers/net/ethernet/ibm/ibmveth.h +0 -1
@@ -148,7 +148,6 @@ struct ibmveth_adapter {dma_addr_t filter_list_dma;struct ibmveth_buff_pool rx_buff_pool[IBMVETH_NUM_BUFF_POOLS ];struct ibmveth_rx_q rx_queue; -int pool_config;int rx_csum;int large_send;bool is_active_trunk;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 761/1887 net: ibmveth: make veth_pool_store stop hanging
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Marquardt <[email protected]>
[ Upstream commit 053f3ff67d7feefc75797863f3d84b47ad47086f ]
v2:
- Created a single error handling unlock and exit in veth_pool_store
- Greatly expanded commit message with previous explanatory-only text
Summary: Use rtnl_mutex to synchronize veth_pool_store with itself, ibmveth_close and ibmveth_open, preventing multiple calls in a row to napi_disable.
Background: Two (or more) threads could call veth_pool_store through writing to /sys/devices/vio/30000002/pool*/*. You can do this easily with a little shell script. This causes a hang.
I configured LOCKDEP, compiled ibmveth.c with DEBUG, and built a new kernel. I ran this test again and saw:
Setting pool0/active to 0
Setting pool1/active to 1
[ 73.911067][ T4365] ibmveth 30000002 eth0: close starting
Setting pool1/active to 1
Setting pool1/active to 0
[ 73.911367][ T4366] ibmveth 30000002 eth0: close starting
[ 73.916056][ T4365] ibmveth 30000002 eth0: close complete
[ 73.916064][ T4365] ibmveth 30000002 eth0: open starting
[ 110.808564][ T712] systemd-journald[712]: Sent WATCHDOG=1 notification.
[ 230.808495][ T712] systemd-journald[712]: Sent WATCHDOG=1 notification.
[ 243.683786][ T123] INFO: task stress.sh:4365 blocked for more than 122 seconds.
[ 243.683827][ T123] Not tainted 6.14.0-01103-g2df0c02dab82-dirty #8
[ 243.683833][ T123] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 243.683838][ T123] task:stress.sh state:D stack:28096 pid:4365 tgid:4365 ppid:4364 task_flags:0x400040 flags:0x00042000
[ 243.683852][ T123] Call Trace:
[ 243.683857][ T123] [c00000000c38f690] [0000000000000001] 0x1 (unreliable)
[ 243.683868][ T123] [c00000000c38f840] [c00000000001f908] __switch_to+0x318/0x4e0
[ 243.683878][ T123] [c00000000c38f8a0] [c000000001549a70] __schedule+0x500/0x12a0
[ 243.683888][ T123] [c00000000c38f9a0] [c00000000154a878] schedule+0x68/0x210
[ 243.683896][ T123] [c00000000c38f9d0] [c00000000154ac80] schedule_preempt_disabled+0x30/0x50
[ 243.683904][ T123] [c00000000c38fa00] [c00000000154dbb0] __mutex_lock+0x730/0x10f0
[ 243.683913][ T123] [c00000000c38fb10] [c000000001154d40] napi_enable+0x30/0x60
[ 243.683921][ T123] [c00000000c38fb40] [c000000000f4ae94] ibmveth_open+0x68/0x5dc
[ 243.683928][ T123] [c00000000c38fbe0] [c000000000f4aa20] veth_pool_store+0x220/0x270
[ 243.683936][ T123] [c00000000c38fc70] [c000000000826278] sysfs_kf_write+0x68/0xb0
[ 243.683944][ T123] [c00000000c38fcb0] [c0000000008240b8] kernfs_fop_write_iter+0x198/0x2d0
[ 243.683951][ T123] [c00000000c38fd00] [c00000000071b9ac] vfs_write+0x34c/0x650
[ 243.683958][ T123] [c00000000c38fdc0] [c00000000071bea8] ksys_write+0x88/0x150
[ 243.683966][ T123] [c00000000c38fe10] [c0000000000317f4] system_call_exception+0x124/0x340
[ 243.683973][ T123] [c00000000c38fe50] [c00000000000d05c] system_call_vectored_common+0x15c/0x2ec
...
[ 243.684087][ T123] Showing all locks held in the system:
[ 243.684095][ T123] 1 lock held by khungtaskd/123:
[ 243.684099][ T123] #0: c00000000278e370 (rcu_read_lock){....}-{1:2}, at: debug_show_all_locks+0x50/0x248
[ 243.684114][ T123] 4 locks held by stress.sh/4365:
[ 243.684119][ T123] #0: c00000003a4cd3f8 (sb_writers#3){.+.+}-{0:0}, at: ksys_write+0x88/0x150
[ 243.684132][ T123] #1: c000000041aea888 (&of->mutex#2){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x154/0x2d0
[ 243.684143][ T123] #2: c0000000366fb9a8 (kn->active#64){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x160/0x2d0
[ 243.684155][ T123] #3: c000000035ff4cb8 (&dev->lock){+.+.}-{3:3}, at: napi_enable+0x30/0x60
[ 243.684166][ T123] 5 locks held by stress.sh/4366:
[ 243.684170][ T123] #0: c00000003a4cd3f8 (sb_writers#3){.+.+}-{0:0}, at: ksys_write+0x88/0x150
[ 243.684183][ T123] #1: c00000000aee2288 (&of->mutex#2){+.+.}-{3:3}, at: kernfs_fop_write_iter+0x154/0x2d0
[ 243.684194][ T123] #2: c0000000366f4ba8 (kn->active#64){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x160/0x2d0
[ 243.684205][ T123] #3: c000000035ff4cb8 (&dev->lock){+.+.}-{3:3}, at: napi_disable+0x30/0x60
[ 243.684216][ T123] #4: c0000003ff9bbf18 (&rq->__lock){-.-.}-{2:2}, at: __schedule+0x138/0x12a0Quoted 1 line
From the ibmveth debug, two threads are calling
veth_pool_store, which
calls ibmveth_close and ibmveth_open. Here's the sequence:
T4365 T4366
----------------- ----------------- ---------
veth_pool_store veth_pool_store
ibmveth_close
ibmveth_close
napi_disable
napi_disable
ibmveth_open
napi_enable <- HANG
ibmveth_close calls napi_disable at the top and ibmveth_open calls napi_enable at the top.
https://docs.kernel.org/networking/napi.html]] says
The control APIs are not idempotent. Control API calls are safe against concurrent use of datapath APIs but an incorrect sequence of control API calls may result in crashes, deadlocks, or race conditions. For example, calling napi_disable() multiple times in a row will deadlock.
In the normal open and close paths, rtnl_mutex is acquired to prevent other callers. This is missing from veth_pool_store. Use rtnl_mutex in veth_pool_store fixes these hangs.
--- drivers/net/ethernet/ibm/ibmveth.c | 39 +++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-)
drivers/net/ethernet/ibm/ibmveth.c +27 -12
@@ -1848,18 +1848,22 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr,long value =simple_strtol (buf,NULL ,10 );long rc; +rtnl_lock (); +if (attr == &veth_active_attr) {if (value && !pool->active) {if (netif_running (netdev)) {if (ibmveth_alloc_buffer_pool (pool)) {netdev_err (netdev,"unable to alloc pool\n" ); -return -ENOMEM ; + rc = -ENOMEM ; + goto unlock_err; } pool->active =1 ;ibmveth_close (netdev); -if ((rc =ibmveth_open (netdev))) -return rc; + rc =ibmveth_open (netdev); +if (rc) + goto unlock_err; }else { pool->active =1 ; }
@@ -1879,48 +1883,59 @@ static ssize_t veth_pool_store(struct kobject *kobj, struct attribute *attr,if (i ==IBMVETH_NUM_BUFF_POOLS ) {netdev_err (netdev,"no active pool >= MTU\n" ); -return -EPERM ; + rc = -EPERM ; + goto unlock_err; }if (netif_running (netdev)) {ibmveth_close (netdev); pool->active =0 ; -if ((rc =ibmveth_open (netdev))) -return rc; + rc =ibmveth_open (netdev); +if (rc) + goto unlock_err; } pool->active =0 ; } }else if (attr == &veth_num_attr) {if (value <=0 || value >IBMVETH_MAX_POOL_COUNT ) { -return -EINVAL ; + rc = -EINVAL ; + goto unlock_err; }else {if (netif_running (netdev)) {ibmveth_close (netdev); pool->size = value; -if ((rc =ibmveth_open (netdev))) -return rc; + rc =ibmveth_open (netdev); +if (rc) + goto unlock_err; }else { pool->size = value; } } }else if (attr == &veth_size_attr) {if (value <=IBMVETH_BUFF_OH || value >IBMVETH_MAX_BUF_SIZE ) { -return -EINVAL ; + rc = -EINVAL ; + goto unlock_err; }else {if (netif_running (netdev)) {ibmveth_close (netdev); pool->buff_size = value; -if ((rc =ibmveth_open (netdev))) -return rc; + rc =ibmveth_open (netdev); +if (rc) + goto unlock_err; }else { pool->buff_size = value; } } } +rtnl_unlock ();/* kick the interrupt handler to allocate/deallocate pools */ ibmveth_interrupt (netdev->irq, netdev);return count; + +unlock_err: +rtnl_unlock (); +return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 762/1887 net: decrease cached dst counters in dst_release
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Antoine Tenart <[email protected]>
[ Upstream commit 3a0a3ff6593d670af2451ec363ccb7b18aec0c0a ]
Upstream fix ac888d58869b ("net: do not delay dst_entries_add() in dst_release()") moved decrementing the dst count from dst_destroy to dst_release to avoid accessing already freed data in case of netns dismantle. However in case CONFIG_DST_CACHE is enabled and OvS+tunnels are used, this fix is incomplete as the same issue will be seen for cached dsts:
Unable to handle kernel paging request at virtual address ffff5aabf6b5c000 Call trace: percpu_counter_add_batch+0x3c/0x160 (P) dst_release+0xec/0x108 dst_cache_destroy+0x68/0xd8 dst_destroy+0x13c/0x168 dst_destroy_rcu+0x1c/0xb0 rcu_do_batch+0x18c/0x7d0 rcu_core+0x174/0x378 rcu_core_si+0x18/0x30
Fix this by invalidating the cache, and thus decrementing cached dst counters, in dst_release too.
--- net/core/dst.c | 8 ++++++++ 1 file changed, 8 insertions(+)
net/core/dst.c +8 -0
@@ -173,6 +173,14 @@ void dst_release(struct dst_entry *dst)net_warn_ratelimited ("%s: dst:%p refcnt:%d\n" , __func__, dst, newrefcnt);if (!newrefcnt){ +#ifdef CONFIG_DST_CACHE +if (dst->flags &DST_METADATA ) { +struct metadata_dst *md_dst = (struct metadata_dst *)dst; + +if (md_dst->type ==METADATA_IP_TUNNEL ) +dst_cache_reset_now (&md_dst->u.tun_info.dst_cache); + } +#endif dst_count_dec (dst);call_rcu (&dst->rcu_head, dst_destroy_rcu); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 763/1887 fs/9p: fix NULL pointer dereference on mkdir
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Schoenebeck <[email protected]>
[ Upstream commit 3f61ac7c65bdb26accb52f9db66313597e759821 ]
When a 9p tree was mounted with option 'posixacl', parent directory had a default ACL set for its subdirectories, e.g.:
setfacl -m default:group:simpsons:rwx parentdir
then creating a subdirectory crashed 9p client, as v9fs_fid_add() call in function v9fs_vfs_mkdir_dotl() sets the passed 'fid' pointer to NULL (since dafbe689736) even though the subsequent v9fs_set_create_acl() call expects a valid non-NULL 'fid' pointer:
[ 37.273191] BUG: kernel NULL pointer dereference, address: 0000000000000000 ... [ 37.322338] Call Trace: [ 37.323043] <TASK> [ 37.323621] ? __die (arch/x86/kernel/dumpstack.c:421 arch/x86/kernel/dumpstack.c:434) [ 37.324448] ? page_fault_oops (arch/x86/mm/fault.c:714) [ 37.325532] ? search_module_extables (kernel/module/main.c:3733) [ 37.326742] ? p9_client_walk (net/9p/client.c:1165) 9pnet [ 37.328006] ? search_bpf_extables (kernel/bpf/core.c:804) [ 37.329142] ? exc_page_fault (./arch/x86/include/asm/paravirt.h:686 arch/x86/mm/fault.c:1488 arch/x86/mm/fault.c:1538) [ 37.330196] ? asm_exc_page_fault (./arch/x86/include/asm/idtentry.h:574) [ 37.331330] ? p9_client_walk (net/9p/client.c:1165) 9pnet [ 37.332562] ? v9fs_fid_xattr_get (fs/9p/xattr.c:30) 9p [ 37.333824] v9fs_fid_xattr_set (fs/9p/fid.h:23 fs/9p/xattr.c:121) 9p [ 37.335077] v9fs_set_acl (fs/9p/acl.c:276) 9p [ 37.336112] v9fs_set_create_acl (fs/9p/acl.c:307) 9p [ 37.337326] v9fs_vfs_mkdir_dotl (fs/9p/vfs_inode_dotl.c:411) 9p [ 37.338590] vfs_mkdir (fs/namei.c:4313) [ 37.339535] do_mkdirat (fs/namei.c:4336) [ 37.340465] __x64_sys_mkdir (fs/namei.c:4354) [ 37.341455] do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83) [ 37.342447] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
Fix this by simply swapping the sequence of these two calls in v9fs_vfs_mkdir_dotl(), i.e. calling v9fs_set_create_acl() before v9fs_fid_add().
Message-ID: <[email protected]>
--- fs/9p/vfs_inode_dotl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/9p/vfs_inode_dotl.c +1 -1
@@ -424,8 +424,8 @@ static int v9fs_vfs_mkdir_dotl(struct user_namespace *mnt_userns, err); goto error; } -v9fs_fid_add (dentry, &fid);v9fs_set_create_acl (inode, fid, dacl, pacl); +v9fs_fid_add (dentry, &fid);d_instantiate (dentry, inode); err =0 ; }else {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 764/1887 ax25: Remove broken autobind
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Murad Masimov <[email protected]>
[ Upstream commit 2f6efbabceb6b2914ee9bafb86d9a51feae9cce8 ]
Binding AX25 socket by using the autobind feature leads to memory leaks in ax25_connect() and also refcount leaks in ax25_release(). Memory leak was detected with kmemleak:
================================================================
unreferenced object 0xffff8880253cd680 (size 96):
backtrace:__kmalloc_node_track_caller_noprof (./include/linux/kmemleak.h:43) kmemdup_noprof (mm/util.c:136)ax25_rt_autobind (net/ax25/ax25_route.c:428)ax25_connect (net/ax25/af_ax25.c:1282)__sys_connect_file (net/socket.c:2045)__sys_connect (net/socket.c:2064)__x64_sys_connect (net/socket.c:2067)do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
================================================================
When socket is bound, refcounts must be incremented the way it is done in ax25_bind() and ax25_setsockopt() (SO_BINDTODEVICE). In case of autobind, the refcounts are not incremented.
This bug leads to the following issue reported by Syzkaller:
================================================================ax25_connect(): syz-executor318 uses autobind, please contact [email protected]
------------[ cut here ]------------ refcount_t: decrement hit 0; leaking memory. WARNING: CPU: 0 PID: 5317 at lib/refcount.c:31 refcount_warn_saturate+0xfa/0x1d0 lib/refcount.c:31 Modules linked in: CPU: 0 UID: 0 PID: 5317 Comm: syz-executor318 Not tainted 6.14.0-rc4-syzkaller-00278-gece144f151ac #0 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:refcount_warn_saturate+0xfa/0x1d0 lib/refcount.c:31 ... Call Trace: <TASK> __refcount_dec include/linux/refcount.h:336 [inline] refcount_dec include/linux/refcount.h:351 [inline] ref_tracker_free+0x6af/0x7e0 lib/ref_tracker.c:236 netdev_tracker_free include/linux/netdevice.h:4302 [inline] netdev_put include/linux/netdevice.h:4319 [inline] ax25_release+0x368/0x960 net/ax25/af_ax25.c:1080 __sock_release net/socket.c:647 [inline] sock_close+0xbc/0x240 net/socket.c:1398 __fput+0x3e9/0x9f0 fs/file_table.c:464 __do_sys_close fs/open.c:1580 [inline] __se_sys_close fs/open.c:1565 [inline] __x64_sys_close+0x7f/0x110 fs/open.c:1565 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f ... </TASK> ================================================================
Considering the issues above and the comments left in the code that say:
"check if we can remove this feature. It is broken."; "autobinding in this may or may not work"; - it is better to completely remove this feature than to fix it because it is broken and leads to various kinds of memory bugs.
Now calling connect() without first binding socket will result in an error (-EINVAL). Userspace software that relies on the autobind feature might get broken. However, this feature does not seem widely used with this specific driver as it was not reliable at any point of time, and it is already broken anyway. E.g. ax25-tools and ax25-apps packages for popular distributions do not use the autobind feature for AF_AX25.
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
--- include/net/ax25.h | 1 - net/ax25/af_ax25.c | 30 ++++++------------ net/ax25/ax25_route.c | 74 ------------------------------------------- 3 files changed, 10 insertions(+), 95 deletions(-)
include/net/ax25.h +0 -1
@@ -419,7 +419,6 @@ void ax25_rt_device_down(struct net_device *);int ax25_rt_ioctl (unsigned int ,void __user *);extern const struct seq_operations ax25_rt_seqops;ax25_route *ax25_get_route (ax25_address *addr,struct net_device *dev); -int ax25_rt_autobind (ax25_cb *,ax25_address *);struct sk_buff *ax25_rt_build_path (struct sk_buff *,ax25_address *,ax25_address *,ax25_digi *);void ax25_rt_free (void );
net/ax25/af_ax25.c +10 -20
@@ -1270,28 +1270,18 @@ static int __must_check ax25_connect(struct socket *sock, } } -/* -* Must bind first - autobinding in this may or may not work. If -* the socket is already bound, check to see if the device has -* been filled in, error if it hasn't. -*/ +/* Must bind first - autobinding does not work. */ if (sock_flag (sk,SOCK_ZAPPED )) { -/* check if we can remove this feature. It is broken. */ -printk (KERN_WARNING "ax25_connect(): %s uses autobind, please contact [email protected]\n" , - current->comm); -if ((err =ax25_rt_autobind (ax25, &fsa->fsa_ax25.sax25_call)) <0 ) { -kfree (digi); - goto out_release; - } +kfree (digi); + err = -EINVAL ; + goto out_release; + } -ax25_fillin_cb (ax25, ax25->ax25_dev); -ax25_cb_add (ax25); - }else { -if (ax25->ax25_dev ==NULL ) { -kfree (digi); - err = -EHOSTUNREACH ; - goto out_release; - } +/* Check to see if the device has been filled in, error if it hasn't. */ +if (ax25->ax25_dev ==NULL ) { +kfree (digi); + err = -EHOSTUNREACH ; + goto out_release; } if (sk->sk_type == SOCK_SEQPACKET &&
net/ax25/ax25_route.c +0 -74
80 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 765/1887 btrfs: fix block group refcount race in btrfs_create_pending_block_groups()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boris Burkov <[email protected]>
[ Upstream commit 2d8e5168d48a91e7a802d3003e72afb4304bebfa ]
Block group creation is done in two phases, which results in a slightly unintuitive property: a block group can be allocated/deallocated from after btrfs_make_block_group() adds it to the space_info with btrfs_add_bg_to_space_info(), but before creation is completely completed in btrfs_create_pending_block_groups(). As a result, it is possible for a block group to go unused and have 'btrfs_mark_bg_unused' called on it concurrently with 'btrfs_create_pending_block_groups'. This causes a number of issues, which were fixed with the block group flag 'BLOCK_GROUP_FLAG_NEW'.
However, this fix is not quite complete. Since it does not use the unused_bg_lock, it is possible for the following race to occur:
btrfs_create_pending_block_groups btrfs_mark_bg_unused
if list_empty // false
list_del_init
clear_bit
else if (test_bit) // true
list_move_tail
And we get into the exact same broken ref count and invalid new_bgs state for transaction cleanup that BLOCK_GROUP_FLAG_NEW was designed to prevent.
The broken refcount aspect will result in a warning like:
[1272.943527] refcount_t: underflow; use-after-free. [1272.943967] WARNING: CPU: 1 PID: 61 at lib/refcount.c:28 refcount_warn_saturate+0xba/0x110 [1272.944731] Modules linked in: btrfs virtio_net xor zstd_compress raid6_pq null_blk [last unloaded: btrfs] [1272.945550] CPU: 1 UID: 0 PID: 61 Comm: kworker/u32:1 Kdump: loaded Tainted: G W 6.14.0-rc5+ #108 [1272.946368] Tainted: [W]=WARN [1272.946585] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.3-1-1 04/01/2014 [1272.947273] Workqueue: btrfs_discard btrfs_discard_workfn [btrfs] [1272.947788] RIP: 0010:refcount_warn_saturate+0xba/0x110 [1272.949532] RSP: 0018:ffffbf1200247df0 EFLAGS: 00010282 [1272.949901] RAX: 0000000000000000 RBX: ffffa14b00e3f800 RCX: 0000000000000000 [1272.950437] RDX: 0000000000000000 RSI: ffffbf1200247c78 RDI: 00000000ffffdfff [1272.950986] RBP: ffffa14b00dc2860 R08: 00000000ffffdfff R09: ffffffff90526268 [1272.951512] R10: ffffffff904762c0 R11: 0000000063666572 R12: ffffa14b00dc28c0 [1272.952024] R13: 0000000000000000 R14: ffffa14b00dc2868 R15: 000001285dcd12c0 [1272.952850] FS: 0000000000000000(0000) GS:ffffa14d33c40000(0000) knlGS:0000000000000000 [1272.953458] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [1272.953931] CR2: 00007f838cbda000 CR3: 000000010104e000 CR4: 00000000000006f0 [1272.954474] Call Trace: [1272.954655] <TASK> [1272.954812] ? refcount_warn_saturate+0xba/0x110 [1272.955173] ? __warn.cold+0x93/0xd7 [1272.955487] ? refcount_warn_saturate+0xba/0x110 [1272.955816] ? report_bug+0xe7/0x120 [1272.956103] ? handle_bug+0x53/0x90 [1272.956424] ? exc_invalid_op+0x13/0x60 [1272.956700] ? asm_exc_invalid_op+0x16/0x20 [1272.957011] ? refcount_warn_saturate+0xba/0x110 [1272.957399] btrfs_discard_cancel_work.cold+0x26/0x2b [btrfs] [1272.957853] btrfs_put_block_group.cold+0x5d/0x8e [btrfs] [1272.958289] btrfs_discard_workfn+0x194/0x380 [btrfs] [1272.958729] process_one_work+0x130/0x290 [1272.959026] worker_thread+0x2ea/0x420 [1272.959335] ? __pfx_worker_thread+0x10/0x10 [1272.959644] kthread+0xd7/0x1c0 [1272.959872] ? __pfx_kthread+0x10/0x10 [1272.960172] ret_from_fork+0x30/0x50 [1272.960474] ? __pfx_kthread+0x10/0x10 [1272.960745] ret_from_fork_asm+0x1a/0x30 [1272.961035] </TASK> [1272.961238] ---[ end trace 0000000000000000 ]---
Though we have seen them in the async discard workfn as well. It is most likely to happen after a relocation finishes which cancels discard, tears down the block group, etc.
Fix this fully by taking the lock around the list_del_init + clear_bit so that the two are done atomically.
--- fs/btrfs/block-group.c | 3 +++ 1 file changed, 3 insertions(+)
fs/btrfs/block-group.c +3 -0
@@ -2586,8 +2586,11 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans)/* Already aborted the transaction if it failed. */ next:btrfs_delayed_refs_rsv_release (fs_info,1 ); + +spin_lock (&fs_info->unused_bgs_lock);list_del_init (&block_group->bg_list);clear_bit (BLOCK_GROUP_FLAG_NEW , &block_group->runtime_flags); +spin_unlock (&fs_info->unused_bgs_lock); }btrfs_trans_release_chunk_metadata (trans); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 766/1887 f2fs: convert f2fs_handle_page_eio() to use folio
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 763a0dc792f9d7c79c1d85415c6cebc1f79bba16 ]
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1].
[1] https://lore.kernel.org/all/[email protected]/
Stable-dep-of: 3147ee567dd9 ("f2fs: fix potential deadloop in prepare_compress_overwrite()")
--- fs/f2fs/checkpoint.c | 2 +- fs/f2fs/f2fs.h | 6 ++++-- fs/f2fs/node.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-)
fs/f2fs/checkpoint.c +1 -1
@@ -102,7 +102,7 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index, }if (unlikely (!PageUptodate (page))) { -f2fs_handle_page_eio (sbi, page->index,META ); +f2fs_handle_page_eio (sbi,page_folio (page),META );f2fs_put_page (page,1 );return ERR_PTR (-EIO ); }
fs/f2fs/f2fs.h +4 -2
@@ -4581,9 +4581,11 @@ static inline void f2fs_io_schedule_timeout(long timeout)io_schedule_timeout (timeout); } -static inline void f2fs_handle_page_eio (struct f2fs_sb_info *sbi,pgoff_t ofs, -enum page_type type) +static inline void f2fs_handle_page_eio (struct f2fs_sb_info *sbi, +struct folio *folio,enum page_type type) { +pgoff_t ofs = folio->index; +if (unlikely (f2fs_cp_error (sbi)))return ;
fs/f2fs/node.c +1 -1
@@ -1512,7 +1512,7 @@ static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid, out_put_err:/* ENOENT comes from read_node_page which is not an error. */ if (err != -ENOENT ) -f2fs_handle_page_eio (sbi, page->index,NODE ); +f2fs_handle_page_eio (sbi,page_folio (page),NODE );f2fs_put_page (page,1 );return ERR_PTR (err); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 767/1887 f2fs: fix potential deadloop in prepare_compress_overwrite()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <[email protected]>
[ Upstream commit 3147ee567dd9004a49826ddeaf0a4b12865d4409 ]
Jan Prusakowski reported a kernel hang issue as below:
When running xfstests on linux-next kernel (6.14.0-rc3, 6.12) I encountered a problem in generic/475 test where fsstress process gets blocked in __f2fs_write_data_pages() and the test hangs. The options I used are:
MKFS_OPTIONS -- -O compression -O extra_attr -O project_quota -O quota /dev/vdc MOUNT_OPTIONS -- -o acl,user_xattr -o discard,compress_extension=* /dev/vdc /vdc
INFO: task kworker/u8:0:11 blocked for more than 122 seconds.
Not tainted 6.14.0-rc3-xfstests-lockdep #1
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
task:kworker/u8:0 state:D stack:0 pid:11 tgid:11 ppid:2 task_flags:0x4208160 flags:0x00004000
Workqueue: writeback wb_workfn (flush-253:0)
Call Trace:
<TASK>
__schedule+0x309/0x8e0
schedule+0x3a/0x100
schedule_preempt_disabled+0x15/0x30
__mutex_lock+0x59a/0xdb0
__f2fs_write_data_pages+0x3ac/0x400
do_writepages+0xe8/0x290
__writeback_single_inode+0x5c/0x360
writeback_sb_inodes+0x22f/0x570
wb_writeback+0xb0/0x410
wb_do_writeback+0x47/0x2f0
wb_workfn+0x5a/0x1c0
process_one_work+0x223/0x5b0
worker_thread+0x1d5/0x3c0
kthread+0xfd/0x230
ret_from_fork+0x31/0x50
ret_from_fork_asm+0x1a/0x30
</TASK>The root cause is: once generic/475 starts toload error table to dm device, f2fs_prepare_compress_overwrite() will loop reading compressed cluster pages due to IO error, meanwhile it has held .writepages lock, it can block all other writeback tasks.
Let's fix this issue w/ below changes:
- add f2fs_handle_page_eio() in prepare_compress_overwrite() to detect IO error.
- detect cp_error earler in f2fs_read_multi_pages().
--- fs/f2fs/compress.c | 1 + fs/f2fs/data.c | 6 ++++++ 2 files changed, 7 insertions(+)
fs/f2fs/compress.c +1 -0
@@ -1123,6 +1123,7 @@ static int prepare_compress_overwrite(struct compress_ctx *cc,f2fs_compress_ctx_add_page (cc, page);if (!PageUptodate (page)) { +f2fs_handle_page_eio (sbi,page_folio (page),DATA ); release_and_retry:f2fs_put_rpages (cc);f2fs_unlock_rpages (cc, i +1 );
fs/f2fs/data.c +6 -0
@@ -2241,6 +2241,12 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,int i;int ret =0 ; +if (unlikely (f2fs_cp_error (sbi))) { + ret = -EIO ; + from_dnode = false; + goto out_put_dnode; + } +f2fs_bug_on (sbi,f2fs_cluster_is_empty (cc)); last_block_in_file = bytes_to_blks(inode,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 768/1887 perf: Fix hang while freeing sigtrap event
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frederic Weisbecker <[email protected]>
[ Upstream commit 56799bc035658738f362acec3e7647bb84e68933 ]
Perf can hang while freeing a sigtrap event if a related deferred signal hadn't managed to be sent before the file got closed:
perf_event_overflow()
task_work_add(perf_pending_task)
fput()
task_work_add(____fput())
task_work_run()
____fput()
perf_release()
perf_event_release_kernel()
_free_event()
perf_pending_task_sync()
task_work_cancel() -> FAILED
rcuwait_wait_event()Once task_work_run() is running, the list of pending callbacks is removed from the task_struct and from this point on task_work_cancel() can't remove any pending and not yet started work items, hence the task_work_cancel() failure and the hang on rcuwait_wait_event().
Task work could be changed to remove one work at a time, so a work running on the current task can always cancel a pending one, however the wait / wake design is still subject to inverted dependencies when remote targets are involved, as pictured by Oleg:
T1 T2
fd = perf_event_open(pid => T2->pid); fd = perf_event_open(pid => T1->pid);
close(fd) close(fd)
<IRQ> <IRQ>
perf_event_overflow() perf_event_overflow()
task_work_add(perf_pending_task) task_work_add(perf_pending_task)
</IRQ> </IRQ>
fput() fput()
task_work_add(____fput()) task_work_add(____fput()) task_work_run() task_work_run()
____fput() ____fput()
perf_release() perf_release()
perf_event_release_kernel() perf_event_release_kernel()
_free_event() _free_event()
perf_pending_task_sync() perf_pending_task_sync()
rcuwait_wait_event() rcuwait_wait_event()
Therefore the only option left is to acquire the event reference count upon queueing the perf task work and release it from the task work, just like it was done before 3a5465418f5f ("perf: Fix event leak upon exec and file release") but without the leaks it fixed.
Some adjustments are necessary to make it work:
* A child event might dereference its parent upon freeing. Care must be taken to release the parent last.
* Some places assuming the event doesn't have any reference held and therefore can be freed right away must instead put the reference and let the reference counting to its job.
--- include/linux/perf_event.h | 1 - kernel/events/core.c | 64 +++++++++++--------------------------- 2 files changed, 19 insertions(+), 46 deletions(-)
include/linux/perf_event.h +0 -1
@@ -765,7 +765,6 @@ struct perf_event {struct irq_work pending_irq;struct callback_head pending_task;unsigned int pending_work; -struct rcuwait pending_work_wait;atomic_t event_limit;
kernel/events/core.c +19 -45
146 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 769/1887 smb: client: fix UAF in decryption with multichannel
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
[ Upstream commit 9502dd5c7029902f4a425bf959917a5a9e7c0e50 ]
After commit f7025d861694 ("smb: client: allocate crypto only for primary server") and commit b0abcd65ec54 ("smb: client: fix UAF in async decryption"), the channels started reusing AEAD TFM from primary channel to perform synchronous decryption, but that can't done as there could be multiple cifsd threads (one per channel) simultaneously accessing it to perform decryption.
This fixes the following KASAN splat when running fstest generic/249 with 'vers=3.1.1,multichannel,max_channels=4,seal' against Windows Server 2022:
BUG: KASAN: slab-use-after-free in gf128mul_4k_lle+0xba/0x110 Read of size 8 at addr ffff8881046c18a0 by task cifsd/986 CPU: 3 UID: 0 PID: 986 Comm: cifsd Not tainted 6.15.0-rc1 #1 PREEMPT(voluntary) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-3.fc41 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x5d/0x80 print_report+0x156/0x528 ? gf128mul_4k_lle+0xba/0x110 ? __virt_addr_valid+0x145/0x300 ? __phys_addr+0x46/0x90 ? gf128mul_4k_lle+0xba/0x110 kasan_report+0xdf/0x1a0 ? gf128mul_4k_lle+0xba/0x110 gf128mul_4k_lle+0xba/0x110 ghash_update+0x189/0x210 shash_ahash_update+0x295/0x370 ? __pfx_shash_ahash_update+0x10/0x10 ? __pfx_shash_ahash_update+0x10/0x10 ? __pfx_extract_iter_to_sg+0x10/0x10 ? ___kmalloc_large_node+0x10e/0x180 ? __asan_memset+0x23/0x50 crypto_ahash_update+0x3c/0xc0 gcm_hash_assoc_remain_continue+0x93/0xc0 crypt_message+0xe09/0xec0 [cifs] ? __pfx_crypt_message+0x10/0x10 [cifs] ? _raw_spin_unlock+0x23/0x40 ? __pfx_cifs_readv_from_socket+0x10/0x10 [cifs] decrypt_raw_data+0x229/0x380 [cifs] ? __pfx_decrypt_raw_data+0x10/0x10 [cifs] ? __pfx_cifs_read_iter_from_socket+0x10/0x10 [cifs] smb3_receive_transform+0x837/0xc80 [cifs] ? __pfx_smb3_receive_transform+0x10/0x10 [cifs] ? __pfx___might_resched+0x10/0x10 ? __pfx_smb3_is_transform_hdr+0x10/0x10 [cifs] cifs_demultiplex_thread+0x692/0x1570 [cifs] ? __pfx_cifs_demultiplex_thread+0x10/0x10 [cifs] ? rcu_is_watching+0x20/0x50 ? rcu_lockdep_current_cpu_online+0x62/0xb0 ? find_held_lock+0x32/0x90 ? kvm_sched_clock_read+0x11/0x20 ? local_clock_noinstr+0xd/0xd0 ? trace_irq_enable.constprop.0+0xa8/0xe0 ? __pfx_cifs_demultiplex_thread+0x10/0x10 [cifs] kthread+0x1fe/0x380 ? kthread+0x10f/0x380 ? __pfx_kthread+0x10/0x10 ? local_clock_noinstr+0xd/0xd0 ? ret_from_fork+0x1b/0x60 ? local_clock+0x15/0x30 ? lock_release+0x29b/0x390 ? rcu_is_watching+0x20/0x50 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x31/0x60 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 </TASK>
--- fs/smb/client/smb2ops.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/smb/client/smb2ops.c +3 -3
@@ -4781,9 +4781,9 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,return rc; } }else { -if (unlikely (!server->secmech.dec)) -return -EIO ; - + rc =smb3_crypto_aead_allocate (server); +if (unlikely (rc)) +return rc; tfm = server->secmech.dec; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 770/1887 fs/ntfs3: Keep write operations atomic
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lizhi Xu <[email protected]>
[ Upstream commit 285cec318bf5a7a6c8ba999b2b6ec96f9a20590f ]
syzbot reported a NULL pointer dereference in __generic_file_write_iter. [1]
Before the write operation is completed, the user executes ioctl[2] to clear the compress flag of the file, which causes the is_compressed() judgment to return 0, further causing the program to enter the wrong process and call the wrong ops ntfs_aops_cmpr, which triggers the null pointer dereference of write_begin.
Use inode lock to synchronize ioctl and write to avoid this case.
[1]
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
Mem abort info:
ESR = 0x0000000086000006
EC = 0x21: IABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
FSC = 0x06: level 2 translation fault
user pgtable: 4k pages, 48-bit VAs, pgdp=000000011896d000
[0000000000000000] pgd=0800000118b44403, p4d=0800000118b44403, pud=0800000117517403, pmd=0000000000000000
Internal error: Oops: 0000000086000006 [#1] PREEMPT SMP Modules linked in: CPU: 0 UID: 0 PID: 6427 Comm: syz-executor347 Not tainted 6.13.0-rc3-syzkaller-g573067a5a685 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024 pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : 0x0 lr : generic_perform_write+0x29c/0x868 mm/filemap.c:4055
sp : ffff80009d4978a0
x29: ffff80009d4979c0 x28: dfff800000000000 x27: ffff80009d497bc8
x26: 0000000000000000 x25: ffff80009d497960 x24: ffff80008ba71c68
x23: 0000000000000000 x22: ffff0000c655dac0 x21: 0000000000001000
x20: 000000000000000c x19: 1ffff00013a92f2c x18: ffff0000e183aa1c
x17: 0004060000000014 x16: ffff800083275834 x15: 0000000000000001
x14: 0000000000000000 x13: 0000000000000001 x12: ffff0000c655dac0
x11: 0000000000ff0100 x10: 0000000000ff0100 x9 : 0000000000000000 x8 : 0000000000000000 x7 : 0000000000000000 x6 : 0000000000000000 x5 : ffff80009d497980 x4 : ffff80009d497960 x3 : 0000000000001000 x2 : 0000000000000000 x1 : ffff0000e183a928 x0 : ffff0000d60b0fc0
Call trace: 0x0 (P) __generic_file_write_iter+0xfc/0x204 mm/filemap.c:4156 ntfs_file_write_iter+0x54c/0x630 fs/ntfs3/file.c:1267 new_sync_write fs/read_write.c:586 [inline] vfs_write+0x920/0xcf4 fs/read_write.c:679 ksys_write+0x15c/0x26c fs/read_write.c:731 __do_sys_write fs/read_write.c:742 [inline] __se_sys_write fs/read_write.c:739 [inline] __arm64_sys_write+0x7c/0x90 fs/read_write.c:739 __invoke_syscall arch/arm64/kernel/syscall.c:35 [inline] invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:49 el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:132 do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:151 el0_svc+0x54/0x168 arch/arm64/kernel/entry-common.c:744 el0t_64_sync_handler+0x84/0x108 arch/arm64/kernel/entry-common.c:762
[2]
ioctl$FS_IOC_SETFLAGS(r0, 0x40086602, &(0x7f00000000c0)=0x20)
--- fs/ntfs3/file.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-)
fs/ntfs3/file.c +12 -9
@@ -1049,25 +1049,28 @@ static ssize_t ntfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)ssize_t ret;struct ntfs_inode *ni =ntfs_i (inode); +if (!inode_trylock (inode)) { +if (iocb->ki_flags &IOCB_NOWAIT ) +return -EAGAIN ; +inode_lock (inode); + } +if (is_encrypted (ni)) {ntfs_inode_warn (inode,"encrypted i/o not supported" ); -return -EOPNOTSUPP ; + ret = -EOPNOTSUPP ; + goto out; }if (is_compressed (ni) && (iocb->ki_flags &IOCB_DIRECT )) {ntfs_inode_warn (inode,"direct i/o + compressed not supported" ); -return -EOPNOTSUPP ; + ret = -EOPNOTSUPP ; + goto out; }if (is_dedup (ni)) {ntfs_inode_warn (inode,"write into deduplicated not supported" ); -return -EOPNOTSUPP ; - } - -if (!inode_trylock (inode)) { -if (iocb->ki_flags &IOCB_NOWAIT ) -return -EAGAIN ; -inode_lock (inode); + ret = -EOPNOTSUPP ; + goto out; } ret =generic_write_checks (iocb, from);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 771/1887 bpf: Fix kmemleak warning for percpu hashmap
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonghong Song <[email protected]>
[ Upstream commit 11ba7ce076e5903e7bdc1fd1498979c331b3c286 ]
Vlad Poenaru reported the following kmemleak issue:
unreferenced object 0x606fd7c44ac8 (size 32):
backtrace (crc 0):
pcpu_alloc_noprof+0x730/0xeb0
bpf_map_alloc_percpu+0x69/0xc0
prealloc_init+0x9d/0x1b0
htab_map_alloc+0x363/0x510
map_create+0x215/0x3a0
__sys_bpf+0x16b/0x3e0
__x64_sys_bpf+0x18/0x20
do_syscall_64+0x7b/0x150
entry_SYSCALL_64_after_hwframe+0x4b/0x53Further investigation shows the reason is due to not 8-byte aligned store of percpu pointer in htab_elem_set_ptr():
*(void __percpu **)(l->key + key_size) = pptr;
Note that the whole htab_elem alignment is 8 (for x86_64). If the key_size is 4, that means pptr is stored in a location which is 4 byte aligned but not 8 byte aligned. In mm/kmemleak.c, scan_block() scans the memory based on 8 byte stride, so it won't detect above pptr, hence reporting the memory leak.
In htab_map_alloc(), we already have
htab->elem_size = sizeof(struct htab_elem) +
round_up(htab->map.key_size, 8);
if (percpu)
htab->elem_size += sizeof(void *);
else
htab->elem_size += round_up(htab->map.value_size, 8);So storing pptr with 8-byte alignment won't cause any problem and can fix kmemleak too.
The issue can be reproduced with bpf selftest as well:
1. Enable CONFIG_DEBUG_KMEMLEAK config
2. Add a getchar() before skel destroy in test_hash_map() in prog_tests/for_each.c. The purpose is to keep map available so kmemleak can be detected.
3. run './test_progs -t for_each/hash_map &' and a kmemleak should be reported.
--- kernel/bpf/hashtab.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/bpf/hashtab.c +2 -2
@@ -197,12 +197,12 @@ static bool htab_is_percpu(const struct bpf_htab *htab)static inline void htab_elem_set_ptr (struct htab_elem *l,u32 key_size,void __percpu *pptr) { - *(void __percpu **)(l->key + key_size) = pptr; + *(void __percpu **)(l->key +roundup (key_size,8 )) = pptr; }static inline void __percpu *htab_elem_get_ptr (struct htab_elem *l,u32 key_size) { -return *(void __percpu **)(l->key + key_size); +return *(void __percpu **)(l->key +roundup (key_size,8 )); }static void *fd_htab_map_get_ptr (const struct bpf_map *map,struct htab_elem *l)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 772/1887 spi: fsl-qspi: use devm function instead of driver remove
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Han Xu <[email protected]>
[ Upstream commit 40369bfe717e96e26650eeecfa5a6363563df6e4 ]
Driver use devm APIs to manage clk/irq/resources and register the spi controller, but the legacy remove function will be called first during device detach and trigger kernel panic. Drop the remove function and use devm_add_action_or_reset() for driver cleanup to ensure the release sequence.
Trigger kernel panic on i.MX8MQ by
echo 30bb0000.spi >/sys/bus/platform/drivers/fsl-quadspi/unbind
--- drivers/spi/spi-fsl-qspi.c | 42 +++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 23 deletions(-)
drivers/spi/spi-fsl-qspi.c +19 -23
@@ -840,6 +840,19 @@ static const struct spi_controller_mem_ops fsl_qspi_mem_ops = { .get_name = fsl_qspi_get_name, }; +static void fsl_qspi_cleanup (void *data) +{ +struct fsl_qspi *q = data; + +/* disable the hardware */ +qspi_writel (q,QUADSPI_MCR_MDIS_MASK , q->iobase +QUADSPI_MCR ); +qspi_writel (q,0x0 , q->iobase +QUADSPI_RSER ); + +fsl_qspi_clk_disable_unprep (q); + +mutex_destroy (&q->lock); +} +static int fsl_qspi_probe (struct platform_device *pdev) {struct spi_controller *ctlr;
@@ -849,7 +862,7 @@ static int fsl_qspi_probe(struct platform_device *pdev)struct fsl_qspi *q;int ret; - ctlr =spi_alloc_master (&pdev->dev,sizeof (*q)); + ctlr =devm_spi_alloc_master (&pdev->dev,sizeof (*q));if (!ctlr)return -ENOMEM ;
@@ -930,40 +943,24 @@ static int fsl_qspi_probe(struct platform_device *pdev) ctlr->dev.of_node = np; + ret =devm_add_action_or_reset (dev, fsl_qspi_cleanup, q); +if (ret) + goto err_put_ctrl; + ret =devm_spi_register_controller (dev, ctlr);if (ret) - goto err_destroy_mutex; + goto err_put_ctrl;return 0 ; -err_destroy_mutex: -mutex_destroy (&q->lock); - err_disable_clk:fsl_qspi_clk_disable_unprep (q); err_put_ctrl: -spi_controller_put (ctlr); -dev_err (dev,"Freescale QuadSPI probe failed\n" );return ret; } -static int fsl_qspi_remove (struct platform_device *pdev) -{ -struct fsl_qspi *q =platform_get_drvdata (pdev); - -/* disable the hardware */ -qspi_writel (q,QUADSPI_MCR_MDIS_MASK , q->iobase +QUADSPI_MCR ); -qspi_writel (q,0x0 , q->iobase +QUADSPI_RSER ); - -fsl_qspi_clk_disable_unprep (q); - -mutex_destroy (&q->lock); - -return 0 ; -} -static int fsl_qspi_suspend (struct device *dev) {return 0 ;
@@ -1001,7 +998,6 @@ static struct platform_driver fsl_qspi_driver = { .pm = &fsl_qspi_pm_ops, }, .probe = fsl_qspi_probe, - .remove = fsl_qspi_remove, };module_platform_driver (fsl_qspi_driver);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 773/1887 drm/amdkfd: debugfs hang_hws skip GPU with MES
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Philip Yang <[email protected]>
[ Upstream commit fe9d0061c413f8fb8c529b18b592b04170850ded ]
debugfs hang_hws is used by GPU reset test with HWS, for MES this crash the kernel with NULL pointer access because dqm->packet_mgr is not setup for MES path.
Skip GPU with MES for now, MES hang_hws debugfs interface will be supported later.
--- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/amd/amdkfd/kfd_device.c +5 -0
@@ -1177,6 +1177,11 @@ int kfd_debugfs_hang_hws(struct kfd_dev *dev)return -EINVAL ; } +if (dev->shared_resources.enable_mes) { +dev_err (dev->adev->dev,"Inducing MES hang is not supported\n" ); +return -EINVAL ; + } +return dqm_debugfs_hang_hws (dev->dqm); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 774/1887 btrfs: harden block_group::bg_list against list_del() races
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boris Burkov <[email protected]>
[ Upstream commit 7511e29cf1355b2c47d0effb39e463119913e2f6 ]
As far as I can tell, these calls of list_del_init() on bg_list cannot run concurrently with btrfs_mark_bg_unused() or btrfs_mark_bg_to_reclaim(), as they are in transaction error paths and situations where the block group is readonly.
However, if there is any chance at all of racing with mark_bg_unused(), or a different future user of bg_list, better to be safe than sorry.
Otherwise we risk the following interleaving (bg_list refcount in parens)
T1 (some random op) T2 (btrfs_mark_bg_unused)
!list_empty(&bg->bg_list); (1)
list_del_init(&bg->bg_list); (1)
list_move_tail (1)
btrfs_put_block_group (0)
btrfs_delete_unused_bgs
bg = list_first_entry
list_del_init(&bg->bg_list);
btrfs_put_block_group(bg); (-1)Ultimately, this results in a broken ref count that hits zero one deref early and the real final deref underflows the refcount, resulting in a WARNING.
--- fs/btrfs/extent-tree.c | 8 ++++++++ fs/btrfs/transaction.c | 12 ++++++++++++ 2 files changed, 20 insertions(+)
fs/btrfs/extent-tree.c +8 -0
@@ -2834,7 +2834,15 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans) block_group->length, &trimmed); +/* +* Not strictly necessary to lock, as the block_group should be +* read-only from btrfs_delete_unused_bgs(). +*/ +ASSERT (block_group->ro); +spin_lock (&fs_info->unused_bgs_lock);list_del_init (&block_group->bg_list); +spin_unlock (&fs_info->unused_bgs_lock); +btrfs_unfreeze_block_group (block_group);btrfs_put_block_group (block_group);
fs/btrfs/transaction.c +12 -0
@@ -148,7 +148,13 @@ void btrfs_put_transaction(struct btrfs_transaction *transaction) cache =list_first_entry (&transaction->deleted_bgs, struct btrfs_block_group, bg_list); +/* +* Not strictly necessary to lock, as no other task will be using a +* block_group on the deleted_bgs list during a transaction abort. +*/ +spin_lock (&transaction->fs_info->unused_bgs_lock);list_del_init (&cache->bg_list); +spin_unlock (&transaction->fs_info->unused_bgs_lock);btrfs_unfreeze_block_group (cache);btrfs_put_block_group (cache); }
@@ -2104,7 +2110,13 @@ static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans)list_for_each_entry_safe (block_group, tmp, &trans->new_bgs, bg_list) {btrfs_delayed_refs_rsv_release (fs_info,1 ); +/* +* Not strictly necessary to lock, as no other task will be using a +* block_group on the new_bgs list during a transaction abort. +*/ +spin_lock (&fs_info->unused_bgs_lock);list_del_init (&block_group->bg_list); +spin_unlock (&fs_info->unused_bgs_lock); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 775/1887 sfc: fix NULL dereferences in ef100_process_design_param()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Cree <[email protected]>
[ Upstream commit 8241ecec1cdc6699ae197d52d58e76bddd995fa5 ]
Since cited commit, ef100_probe_main() and hence also
ef100_check_design_params() run before efx->net_dev is created; consequently, we cannot netif_set_tso_max_size() or _segs() at this point.
Move those netif calls to ef100_probe_netdev(), and also replace
netif_err within the design params code with pci_err.
--- drivers/net/ethernet/sfc/ef100_netdev.c | 6 ++-- drivers/net/ethernet/sfc/ef100_nic.c | 47 +++++++++++-------------- 2 files changed, 25 insertions(+), 28 deletions(-)
drivers/net/ethernet/sfc/ef100_netdev.c +4 -2
@@ -354,6 +354,7 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data) {struct efx_nic *efx = &probe_data->efx;struct efx_probe_data **probe_ptr; +struct ef100_nic_data *nic_data;struct net_device *net_dev;int rc;
@@ -379,8 +380,9 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data) net_dev->hw_enc_features |= efx->type->offload_features; net_dev->vlan_features |=NETIF_F_HW_CSUM |NETIF_F_SG |NETIF_F_HIGHDMA |NETIF_F_ALL_TSO ; -netif_set_tso_max_segs (net_dev, -ESE_EF100_DP_GZ_TSO_MAX_HDR_NUM_SEGS_DEFAULT ); + nic_data = efx->nic_data; +netif_set_tso_max_size (efx->net_dev, nic_data->tso_max_payload_len); +netif_set_tso_max_segs (efx->net_dev, nic_data->tso_max_payload_num_segs); efx->mdio.dev = net_dev; rc =efx_ef100_init_datapath_caps (efx);
drivers/net/ethernet/sfc/ef100_nic.c +21 -26
93 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 776/1887 scsi: mpi3mr: Synchronous access b/w reset and tm thread for reply queue
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ranjan Kumar <[email protected]>
[ Upstream commit f195fc060c738d303a21fae146dbf85e1595fb4c ]
When the task management thread processes reply queues while the reset thread resets them, the task management thread accesses an invalid queue ID (0xFFFF), set by the reset thread, which points to unallocated memory, causing a crash.
Add flag 'io_admin_reset_sync' to synchronize access between the reset, I/O, and admin threads. Before a reset, the reset handler sets this flag to block I/O and admin processing threads. If any thread bypasses the initial check, the reset thread waits up to 10 seconds for processing to finish. If the wait exceeds 10 seconds, the controller is marked as unrecoverable.
--- drivers/scsi/mpi3mr/mpi3mr.h | 2 + drivers/scsi/mpi3mr/mpi3mr_fw.c | 67 +++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 3 deletions(-)
drivers/scsi/mpi3mr/mpi3mr.h +2 -0
@@ -969,6 +969,7 @@ struct scmd_priv {* @ts_update_counter: Timestamp update counter * @reset_in_progress: Reset in progress flag * @unrecoverable: Controller unrecoverable flag +* @io_admin_reset_sync: Manage state of I/O ops during an admin reset process * @prev_reset_result: Result of previous reset * @reset_mutex: Controller reset mutex * @reset_waitq: Controller reset wait queue
@@ -1141,6 +1142,7 @@ struct mpi3mr_ioc {u32 ts_update_counter;u8 reset_in_progress;u8 unrecoverable; +u8 io_admin_reset_sync;int prev_reset_result;struct mutex reset_mutex;wait_queue_head_t reset_waitq;
drivers/scsi/mpi3mr/mpi3mr_fw.c +64 -3
109 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 777/1887 um: fix time-travel syscall scheduling hack
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 381d2f95c8aa575d5d42bf1fe0ea9a70c4bec0cf ]
The schedule() call there really never did anything at least since the introduction of the EEVDF scheduler, but now I found a case where we permanently hang in a loop of -ERESTARTNOINTR (due to locking.) Work around it by making any syscalls with error return take time (and then schedule after) so we cannot hang in such a loop forever.
Stable-dep-of: 887c5c12e80c ("um: work around sched_yield not yielding in time-travel mode")
--- arch/um/kernel/skas/syscall.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-)
arch/um/kernel/skas/syscall.c +20 -14
@@ -12,23 +12,13 @@#include <sysdep/syscalls.h> #include <linux/time-internal.h> #include <asm/unistd.h> +#include <asm/delay.h> void handle_syscall (struct uml_pt_regs *r) { struct pt_regs *regs = container_of(r, struct pt_regs, regs);int syscall; -/* -* If we have infinite CPU resources, then make every syscall also a -* preemption point, since we don't have any other preemption in this -* case, and kernel threads would basically never run until userspace -* went to sleep, even if said userspace interacts with the kernel in -* various ways. -*/ -if (time_travel_mode ==TT_MODE_INFCPU || - time_travel_mode ==TT_MODE_EXTERNAL ) -schedule (); -/* Initialize the syscall number and default return value. */ UPT_SYSCALL_NR (r) =PT_SYSCALL_NR (r->gp);PT_REGS_SET_SYSCALL_RETURN (regs, -ENOSYS );
@@ -41,9 +31,25 @@ void handle_syscall(struct uml_pt_regs *r) goto out; syscall =UPT_SYSCALL_NR (r); -if (syscall >=0 && syscall < __NR_syscalls) -PT_REGS_SET_SYSCALL_RETURN (regs, -EXECUTE_SYSCALL (syscall, regs)); +if (syscall >=0 && syscall < __NR_syscalls) { +unsigned long ret =EXECUTE_SYSCALL (syscall, regs); + +PT_REGS_SET_SYSCALL_RETURN (regs, ret); + +/* +* An error value here can be some form of -ERESTARTSYS +* and then we'd just loop. Make any error syscalls take +* some time, so that it won't just loop if something is +* not ready, and hopefully other things will make some +* progress. +*/ +if (IS_ERR_VALUE (ret) && + (time_travel_mode ==TT_MODE_INFCPU || + time_travel_mode ==TT_MODE_EXTERNAL )) { +um_udelay (1 ); +schedule (); + } + } out:syscall_trace_leave (regs);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 778/1887 ksmbd: Fix UAF in __close_file_table_ids
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Heelan <[email protected]>
[ Upstream commit 36991c1ccde2d5a521577c448ffe07fcccfe104d ]
A use-after-free is possible if one thread destroys the file via __ksmbd_close_fd while another thread holds a reference to it. The existing checks on fp->refcount are not sufficient to prevent this.
The fix takes ft->lock around the section which removes the file from the file table. This prevents two threads acquiring the same file pointer via __close_file_table_ids, as well as the other functions which retrieve a file from the IDR and which already use this same lock.
--- fs/smb/server/vfs_cache.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-)
fs/smb/server/vfs_cache.c +31 -6
@@ -648,21 +648,46 @@ __close_file_table_ids(struct ksmbd_file_table *ft,bool (*skip)(struct ksmbd_tree_connect *tcon, struct ksmbd_file *fp)) { -unsigned int id; -struct ksmbd_file *fp; -int num =0 ; +struct ksmbd_file *fp; +unsigned int id =0 ; +int num =0 ; + +while (1 ) { +write_lock (&ft->lock); + fp =idr_get_next (ft->idr, &id); +if (!fp) { +write_unlock (&ft->lock); +break ; + } -idr_for_each_entry (ft->idr, fp, id) { -if (skip (tcon, fp)) +if (skip (tcon, fp)) { + id++; +write_unlock (&ft->lock);continue ; + }set_close_state_blocked_works (fp); -if (!atomic_dec_and_test (&fp->refcount)) +if (!atomic_dec_and_test (&fp->refcount)) { + id++; +write_unlock (&ft->lock);continue ; + } + +idr_remove (ft->idr, fp->volatile_id); + fp->volatile_id =KSMBD_NO_FID ; +write_unlock (&ft->lock); + +write_lock (&fp->f_ci->m_lock); +list_del_init (&fp->node); +write_unlock (&fp->f_ci->m_lock); +__ksmbd_close_fd (ft, fp); + num++; + id++; } +return num; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 779/1887 ksmbd: prevent rename with empty string
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit 53e3e5babc0963a92d856a5ec0ce92c59f54bc12 ]
Client can send empty newname string to ksmbd server. It will cause a kernel oops from d_alloc. This patch return the error when attempting to rename a file or directory with an empty new name string.
--- fs/smb/server/smb2pdu.c | 5 +++++ 1 file changed, 5 insertions(+)
fs/smb/server/smb2pdu.c +5 -0
@@ -665,6 +665,11 @@ smb2_get_name(const char *src, const int maxlen, struct nls_table *local_nls)return name; } +if (*name =='\0' ) { +kfree (name); +return ERR_PTR (-EINVAL ); + } +ksmbd_conv_path_to_unix (name);ksmbd_strip_last_slash (name);return name;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 780/1887 KVM: SVM: Forcibly leave SMM mode on SHUTDOWN interception
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikhail Lobanov <[email protected]>
[ Upstream commit a2620f8932fa9fdabc3d78ed6efb004ca409019f ]
Previously, commit ed129ec9057f ("KVM: x86: forcibly leave nested mode on vCPU reset") addressed an issue where a triple fault occurring in nested mode could lead to use-after-free scenarios. However, the commit did not handle the analogous situation for System Management Mode (SMM).
This omission results in triggering a WARN when KVM forces a vCPU INIT after SHUTDOWN interception while the vCPU is in SMM. This situation was reprodused using Syzkaller by:
1) Creating a KVM VM and vCPU
2) Sending a KVM_SMI ioctl to explicitly enter SMM
3) Executing invalid instructions causing consecutive exceptions and eventually a triple fault
The issue manifests as follows:
WARNING: CPU: 0 PID: 25506 at arch/x86/kvm/x86.c:12112 kvm_vcpu_reset+0x1d2/0x1530 arch/x86/kvm/x86.c:12112 Modules linked in: CPU: 0 PID: 25506 Comm: syz-executor.0 Not tainted 6.1.130-syzkaller-00157-g164fe5dde9b6 #0 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014 RIP: 0010:kvm_vcpu_reset+0x1d2/0x1530 arch/x86/kvm/x86.c:12112 Call Trace: <TASK> shutdown_interception+0x66/0xb0 arch/x86/kvm/svm/svm.c:2136 svm_invoke_exit_handler+0x110/0x530 arch/x86/kvm/svm/svm.c:3395 svm_handle_exit+0x424/0x920 arch/x86/kvm/svm/svm.c:3457 vcpu_enter_guest arch/x86/kvm/x86.c:10959 [inline] vcpu_run+0x2c43/0x5a90 arch/x86/kvm/x86.c:11062 kvm_arch_vcpu_ioctl_run+0x50f/0x1cf0 arch/x86/kvm/x86.c:11283 kvm_vcpu_ioctl+0x570/0xf00 arch/x86/kvm/../../../virt/kvm/kvm_main.c:4122 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:870 [inline] __se_sys_ioctl fs/ioctl.c:856 [inline] __x64_sys_ioctl+0x19a/0x210 fs/ioctl.c:856 do_syscall_x64 arch/x86/entry/common.c:51 [inline] do_syscall_64+0x35/0x80 arch/x86/entry/common.c:81 entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Architecturally, INIT is blocked when the CPU is in SMM, hence KVM's WARN() in kvm_vcpu_reset() to guard against KVM bugs, e.g. to detect improper emulation of INIT. SHUTDOWN on SVM is a weird edge case where KVM needs to do _something_ sane with the VMCB, since it's technically undefined, and INIT is the least awful choice given KVM's ABI.
So, double down on stuffing INIT on SHUTDOWN, and force the vCPU out of SMM to avoid any weirdness (and the WARN).
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
--- arch/x86/kvm/svm/svm.c | 2 ++ arch/x86/kvm/x86.c | 5 ++--- arch/x86/kvm/x86.h | 1 + 3 files changed, 5 insertions(+), 3 deletions(-)
arch/x86/kvm/svm/svm.c +2 -0
@@ -2130,6 +2130,8 @@ static int shutdown_interception(struct kvm_vcpu *vcpu)* in response to shutdown. */ clear_page (svm->vmcb); +if (is_smm (vcpu)) +kvm_smm_changed (vcpu, false);kvm_vcpu_reset (vcpu, true); kvm_run->exit_reason =KVM_EXIT_SHUTDOWN ;
arch/x86/kvm/x86.c +2 -3
@@ -5165,8 +5165,6 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,memset (&events->reserved,0 ,sizeof (events->reserved)); } -static void kvm_smm_changed (struct kvm_vcpu *vcpu,bool entering_smm); -static int kvm_vcpu_ioctl_x86_set_vcpu_events (struct kvm_vcpu *vcpu,struct kvm_vcpu_events *events) {
@@ -8676,7 +8674,7 @@ static bool retry_instruction(struct x86_emulate_ctxt *ctxt,static int complete_emulated_mmio (struct kvm_vcpu *vcpu);static int complete_emulated_pio (struct kvm_vcpu *vcpu); -static void kvm_smm_changed (struct kvm_vcpu *vcpu,bool entering_smm) +void kvm_smm_changed (struct kvm_vcpu *vcpu,bool entering_smm) {trace_kvm_smm_transition (vcpu->vcpu_id, vcpu->arch.smbase, entering_smm);
@@ -8698,6 +8696,7 @@ static void kvm_smm_changed(struct kvm_vcpu *vcpu, bool entering_smm)kvm_mmu_reset_context (vcpu); } +EXPORT_SYMBOL_GPL (kvm_smm_changed);static int kvm_vcpu_check_hw_bp (unsigned long addr,u32 type,u32 dr7,unsigned long *db)
arch/x86/kvm/x86.h +1 -0
@@ -82,6 +82,7 @@ static inline unsigned int __shrink_ple_window(unsigned int val,void kvm_service_local_tlb_flush_requests (struct kvm_vcpu *vcpu);int kvm_check_nested_events (struct kvm_vcpu *vcpu); +void kvm_smm_changed (struct kvm_vcpu *vcpu,bool entering_smm);static inline bool kvm_is_exception_pending (struct kvm_vcpu *vcpu) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 781/1887 scsi: ufs: exynos: Disable iocc if dma-coherent property isnt set
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Griffin <[email protected]>
[ Upstream commit f92bb7436802f8eb7ee72dc911a33c8897fde366 ]
If dma-coherent property isn't set then descriptors are non-cacheable and the iocc shareability bits should be disabled. Without this UFS can end up in an incompatible configuration and suffer from random cache related stability issues.
--- drivers/ufs/host/ufs-exynos.c | 17 +++++++++++++---- drivers/ufs/host/ufs-exynos.h | 3 ++- 2 files changed, 15 insertions(+), 5 deletions(-)
drivers/ufs/host/ufs-exynos.c +13 -4
@@ -200,8 +200,8 @@ static int exynosauto_ufs_drv_init(struct device *dev, struct exynos_ufs *ufs)/* IO Coherency setting */ if (ufs->sysreg) {return regmap_update_bits (ufs->sysreg, - ufs->shareability_reg_offset, -UFS_SHARABLE ,UFS_SHARABLE ); + ufs->iocc_offset, +UFS_SHARABLE , ufs->iocc_val); } attr->tx_dif_p_nsec =3200000 ;
@@ -1102,12 +1102,21 @@ static int exynos_ufs_parse_dt(struct device *dev, struct exynos_ufs *ufs) ufs->sysreg =NULL ; else {if (of_property_read_u32_index (np,"samsung,sysreg" ,1 , - &ufs->shareability_reg_offset)) { + &ufs->iocc_offset)) {dev_warn (dev,"can't get an offset from sysreg. Set to default value\n" ); - ufs->shareability_reg_offset =UFS_SHAREABILITY_OFFSET ; + ufs->iocc_offset =UFS_SHAREABILITY_OFFSET ; } } +/* +* no 'dma-coherent' property means the descriptors are +* non-cacheable so iocc shareability should be disabled. +*/ +if (of_dma_is_coherent (dev->of_node)) + ufs->iocc_val =UFS_SHARABLE ; +else + ufs->iocc_val =0 ; + ufs->pclk_avail_min =PCLK_AVAIL_MIN ; ufs->pclk_avail_max =PCLK_AVAIL_MAX ;
drivers/ufs/host/ufs-exynos.h +2 -1
@@ -212,7 +212,8 @@ struct exynos_ufs {ktime_t entry_hibern8_t;const struct exynos_ufs_drv_data *drv_data;struct regmap *sysreg; -u32 shareability_reg_offset; +u32 iocc_offset; +u32 iocc_val;u32 opts;#define EXYNOS_UFS_OPT_HAS_APB_CLK_CTRL BIT(0)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 782/1887 net: mctp: Dont access ifa_index when missing
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Johnston <[email protected]>
[ Upstream commit f11cf946c0a92c560a890d68e4775723353599e1 ]
In mctp_dump_addrinfo, ifa_index can be used to filter interfaces, but only when the struct ifaddrmsg is provided. Otherwise it will be comparing to uninitialised memory - reproducible in the syzkaller case from dhcpd, or busybox "ip addr show".
The kernel MCTP implementation has always filtered by ifa_index, so existing userspace programs expecting to dump MCTP addresses must already be passing a valid ifa_index value (either 0 or a real index).
BUG: KMSAN: uninit-value in mctp_dump_addrinfo+0x208/0xac0 net/mctp/device.c:128 mctp_dump_addrinfo+0x208/0xac0 net/mctp/device.c:128 rtnl_dump_all+0x3ec/0x5b0 net/core/rtnetlink.c:4380 rtnl_dumpit+0xd5/0x2f0 net/core/rtnetlink.c:6824 netlink_dump+0x97b/0x1690 net/netlink/af_netlink.c:2309
--- net/mctp/device.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
net/mctp/device.c +11 -4
@@ -120,12 +120,19 @@ static int mctp_dump_addrinfo(struct sk_buff *skb, struct netlink_callback *cb)struct net_device *dev;struct ifaddrmsg *hdr;struct mctp_dev *mdev; -int ifindex; +int ifindex =0 ;int idx =0 , rc; - hdr =nlmsg_data (cb->nlh); -// filter by ifindex if requested - ifindex = hdr->ifa_index; +/* Filter by ifindex if a header is provided */ +if (cb->nlh->nlmsg_len >=nlmsg_msg_size (sizeof (*hdr))) { + hdr =nlmsg_data (cb->nlh); + ifindex = hdr->ifa_index; + }else { +if (cb->strict_check) { +NL_SET_ERR_MSG (cb->extack,"mctp: Invalid header for addr dump request" ); +return -EINVAL ; + } + }rcu_read_lock ();for (; mcb->h <NETDEV_HASHENTRIES ; mcb->h++, mcb->idx =0 ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 783/1887 kasan: use unchecked __memset internally
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrey Konovalov <[email protected]>
[ Upstream commit 01a5ad81637672940844052404678678a0ec8854 ]
KASAN code is supposed to use the unchecked __memset implementation when accessing its metadata.
Change uses of memset to __memset in mm/kasan/.
Stable-dep-of: b6ea95a34cbd ("kasan: avoid sleepable page allocation from atomic context")
--- mm/kasan/report.c | 4 ++-- mm/kasan/shadow.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
mm/kasan/report.c +2 -2
@@ -477,7 +477,7 @@ void kasan_report_invalid_free(void *ptr, unsigned long ip, enum kasan_report_tystart_report (&flags, true); -memset (&info,0 ,sizeof (info)); +__memset (&info,0 ,sizeof (info)); info.type = type; info.access_addr = ptr; info.access_size =0 ;
@@ -512,7 +512,7 @@ bool kasan_report(unsigned long addr, size_t size, bool is_write,start_report (&irq_flags, true); -memset (&info,0 ,sizeof (info)); +__memset (&info,0 ,sizeof (info)); info.type =KASAN_REPORT_ACCESS ; info.access_addr = ptr; info.access_size = size;
mm/kasan/shadow.c +1 -1
@@ -272,7 +272,7 @@ static int kasan_populate_vmalloc_pte(pte_t *ptep, unsigned long addr,if (!page)return -ENOMEM ; -memset ((void *)page,KASAN_VMALLOC_INVALID ,PAGE_SIZE ); +__memset ((void *)page,KASAN_VMALLOC_INVALID ,PAGE_SIZE ); pte =pfn_pte (PFN_DOWN (__pa (page)),PAGE_KERNEL );spin_lock (&init_mm.page_table_lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 784/1887 kasan: avoid sleepable page allocation from atomic context
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Gordeev <[email protected]>
[ Upstream commit b6ea95a34cbd014ab6ade4248107b86b0aaf2d6c ]
apply_to_pte_range() enters the lazy MMU mode and then invokes kasan_populate_vmalloc_pte() callback on each page table walk iteration. However, the callback can go into sleep when trying to allocate a single page, e.g. if an architecutre disables preemption on lazy MMU mode enter.
On s390 if make arch_enter_lazy_mmu_mode() -> preempt_enable() and arch_leave_lazy_mmu_mode() -> preempt_disable(), such crash occurs:
[ 0.663336] BUG: sleeping function called from invalid context at ./include/linux/sched/mm.h:321 [ 0.663348] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 2, name: kthreadd [ 0.663358] preempt_count: 1, expected: 0 [ 0.663366] RCU nest depth: 0, expected: 0 [ 0.663375] no locks held by kthreadd/2. [ 0.663383] Preemption disabled at: [ 0.663386] [<0002f3284cbb4eda>] apply_to_pte_range+0xfa/0x4a0 [ 0.663405] CPU: 0 UID: 0 PID: 2 Comm: kthreadd Not tainted 6.15.0-rc5-gcc-kasan-00043-gd76bb1ebb558-dirty #162 PREEMPT [ 0.663408] Hardware name: IBM 3931 A01 701 (KVM/Linux) [ 0.663409] Call Trace: [ 0.663410] [<0002f3284c385f58>] dump_stack_lvl+0xe8/0x140 [ 0.663413] [<0002f3284c507b9e>] __might_resched+0x66e/0x700 [ 0.663415] [<0002f3284cc4f6c0>] __alloc_frozen_pages_noprof+0x370/0x4b0 [ 0.663419] [<0002f3284ccc73c0>] alloc_pages_mpol+0x1a0/0x4a0 [ 0.663421] [<0002f3284ccc8518>] alloc_frozen_pages_noprof+0x88/0xc0 [ 0.663424] [<0002f3284ccc8572>] alloc_pages_noprof+0x22/0x120 [ 0.663427] [<0002f3284cc341ac>] get_free_pages_noprof+0x2c/0xc0 [ 0.663429] [<0002f3284cceba70>] kasan_populate_vmalloc_pte+0x50/0x120 [ 0.663433] [<0002f3284cbb4ef8>] apply_to_pte_range+0x118/0x4a0 [ 0.663435] [<0002f3284cbc7c14>] apply_to_pmd_range+0x194/0x3e0 [ 0.663437] [<0002f3284cbc99be>] __apply_to_page_range+0x2fe/0x7a0 [ 0.663440] [<0002f3284cbc9e88>] apply_to_page_range+0x28/0x40 [ 0.663442] [<0002f3284ccebf12>] kasan_populate_vmalloc+0x82/0xa0 [ 0.663445] [<0002f3284cc1578c>] alloc_vmap_area+0x34c/0xc10 [ 0.663448] [<0002f3284cc1c2a6>] __get_vm_area_node+0x186/0x2a0 [ 0.663451] [<0002f3284cc1e696>] __vmalloc_node_range_noprof+0x116/0x310 [ 0.663454] [<0002f3284cc1d950>] __vmalloc_node_noprof+0xd0/0x110 [ 0.663457] [<0002f3284c454b88>] alloc_thread_stack_node+0xf8/0x330 [ 0.663460] [<0002f3284c458d56>] dup_task_struct+0x66/0x4d0 [ 0.663463] [<0002f3284c45be90>] copy_process+0x280/0x4b90 [ 0.663465] [<0002f3284c460940>] kernel_clone+0xd0/0x4b0 [ 0.663467] [<0002f3284c46115e>] kernel_thread+0xbe/0xe0 [ 0.663469] [<0002f3284c4e440e>] kthreadd+0x50e/0x7f0 [ 0.663472] [<0002f3284c38c04a>] __ret_from_fork+0x8a/0xf0 [ 0.663475] [<0002f3284ed57ff2>] ret_from_fork+0xa/0x38
Instead of allocating single pages per-PTE, bulk-allocate the shadow memory prior to applying kasan_populate_vmalloc_pte() callback on a page range.
--- mm/kasan/shadow.c | 92 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 14 deletions(-)
mm/kasan/shadow.c +78 -14
@@ -259,33 +259,99 @@ void __init __weak kasan_populate_early_vm_area_shadow(void *start, { } +struct vmalloc_populate_data { +unsigned long start; +struct page **pages; +}; +static int kasan_populate_vmalloc_pte (pte_t *ptep,unsigned long addr, -void *unused) +void *_data) { -unsigned long page; +struct vmalloc_populate_data *data = _data; +struct page *page;pte_t pte; +int index;if (likely (!pte_none (*ptep)))return 0 ; - page =__get_free_page (GFP_KERNEL ); -if (!page) -return -ENOMEM ; - -__memset ((void *)page,KASAN_VMALLOC_INVALID ,PAGE_SIZE ); - pte =pfn_pte (PFN_DOWN (__pa (page)),PAGE_KERNEL ); + index =PFN_DOWN (addr - data->start); + page = data->pages[index]; +__memset (page_to_virt (page),KASAN_VMALLOC_INVALID ,PAGE_SIZE ); + pte =pfn_pte (page_to_pfn (page),PAGE_KERNEL );spin_lock (&init_mm.page_table_lock);if (likely (pte_none (*ptep))) {set_pte_at (&init_mm, addr, ptep, pte); - page =0 ; + data->pages[index] =NULL ; }spin_unlock (&init_mm.page_table_lock); -if (page) -free_page (page); + +return 0 ; +} + +static void ___free_pages_bulk (struct page **pages,int nr_pages) +{ +int i; + +for (i =0 ; i < nr_pages; i++) { +if (pages[i]) { +__free_pages (pages[i],0 ); + pages[i] =NULL ; + } + } +} + +static int ___alloc_pages_bulk (struct page **pages,int nr_pages) +{ +unsigned long nr_populated, nr_total = nr_pages; +struct page **page_array = pages; + +while (nr_pages) { + nr_populated =alloc_pages_bulk_array (GFP_KERNEL , nr_pages, pages); +if (!nr_populated) { +___free_pages_bulk (page_array, nr_total - nr_pages); +return -ENOMEM ; + } + pages += nr_populated; + nr_pages -= nr_populated; + } +return 0 ; } +static int __kasan_populate_vmalloc (unsigned long start,unsigned long end) +{ +unsigned long nr_pages, nr_total =PFN_UP (end - start); +struct vmalloc_populate_data data; +int ret =0 ; + + data.pages = (struct page **)__get_free_page (GFP_KERNEL | __GFP_ZERO); +if (!data.pages) +return -ENOMEM ; + +while (nr_total) { + nr_pages =min (nr_total,PAGE_SIZE /sizeof (data.pages[0 ])); + ret =___alloc_pages_bulk (data.pages, nr_pages); +if (ret) +break ; + + data.start = start; + ret =apply_to_page_range (&init_mm, start, nr_pages *PAGE_SIZE , + kasan_populate_vmalloc_pte, &data); +___free_pages_bulk (data.pages, nr_pages); +if (ret) +break ; + + start += nr_pages *PAGE_SIZE ; + nr_total -= nr_pages; + } + +free_page ((unsigned long )data.pages); + +return ret; +} +int kasan_populate_vmalloc (unsigned long addr,unsigned long size) {unsigned long shadow_start, shadow_end;
@@ -315,9 +381,7 @@ int kasan_populate_vmalloc(unsigned long addr, unsigned long size) shadow_start =PAGE_ALIGN_DOWN (shadow_start); shadow_end =PAGE_ALIGN (shadow_end); - ret =apply_to_page_range (&init_mm, shadow_start, - shadow_end - shadow_start, - kasan_populate_vmalloc_pte,NULL ); + ret =__kasan_populate_vmalloc (shadow_start, shadow_end);if (ret)return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 785/1887 clk: sunxi-ng: h616: Reparent CPU clock during frequency changes
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andre Przywara <[email protected]>
[ Upstream commit 087b4083d3f9d202266debc6b684b0662c96f51b ]
The H616 user manual recommends to re-parent the CPU clock during frequency changes of the PLL, and recommends PLL_PERI0(1X), which runs at 600 MHz. Also it asks to disable and then re-enable the PLL lock bit, after the factor changes have been applied.
Add clock notifiers for the PLL and the CPU mux clock, using the existing notifier callbacks, and tell them to use mux 4 (the PLL_PERI0(1X) source), and bit 29 (the LOCK_ENABLE) bit. The existing code already follows the correct algorithms.
Stable-dep-of: eb963d7948ce ("clk: sunxi-ng: h616: Reparent GPU clock during frequency changes")
--- drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 28 ++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
drivers/clk/sunxi-ng/ccu-sun50i-h616.c +26 -2
@@ -1090,11 +1090,24 @@ static const u32 usb2_clk_regs[] = { SUN50I_H616_USB3_CLK_REG, }; +static struct ccu_mux_nb sun50i_h616_cpu_nb = { + .common = &cpux_clk.common, + .cm = &cpux_clk.mux, + .delay_us =1 ,/* manual doesn't really say */ + .bypass_index =4 ,/* PLL_PERI0@600MHz, as recommended by manual */ +}; + +static struct ccu_pll_nb sun50i_h616_pll_cpu_nb = { + .common = &pll_cpux_clk.common, + .enable =BIT (29 ),/* LOCK_ENABLE */ + .lock =BIT (28 ), +}; +static int sun50i_h616_ccu_probe (struct platform_device *pdev) {void __iomem *reg;u32 val; -int i; +int ret, i; reg =devm_platform_ioremap_resource (pdev,0 );if (IS_ERR (reg))
@@ -1147,7 +1160,18 @@ static int sun50i_h616_ccu_probe(struct platform_device *pdev) val |=BIT (24 );writel (val, reg +SUN50I_H616_HDMI_CEC_CLK_REG ); -return devm_sunxi_ccu_probe (&pdev->dev, reg, &sun50i_h616_ccu_desc); + ret =devm_sunxi_ccu_probe (&pdev->dev, reg, &sun50i_h616_ccu_desc); +if (ret) +return ret; + +/* Reparent CPU during CPU PLL rate changes */ +ccu_mux_notifier_register (pll_cpux_clk.common.hw.clk, + &sun50i_h616_cpu_nb); + +/* Re-lock the CPU PLL after any rate changes */ +ccu_pll_notifier_register (&sun50i_h616_pll_cpu_nb); + +return 0 ; }static const struct of_device_id sun50i_h616_ccu_ids[] = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 786/1887 clk: sunxi-ng: h616: Reparent GPU clock during frequency changes
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Philippe Simons <[email protected]>
[ Upstream commit eb963d7948ce6571939c6875424b557b25f16610 ]
The H616 manual does not state that the GPU PLL supports dynamic frequency configuration, so we must take extra care when changing the frequency. Currently any attempt to do device DVFS on the GPU lead to panfrost various ooops, and GPU hangs.
The manual describes the algorithm for changing the PLL frequency, which the CPU PLL notifier code already support, so we reuse that to reparent the GPU clock to GPU1 clock during frequency changes.
--- drivers/clk/sunxi-ng/ccu-sun50i-h616.c | 36 +++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-)
drivers/clk/sunxi-ng/ccu-sun50i-h616.c +35 -1
@@ -318,10 +318,16 @@ static SUNXI_CCU_M_WITH_MUX_GATE(gpu0_clk, "gpu0", gpu0_parents, 0x670,24 ,1 ,/* mux */ BIT (31 ),/* gate */ CLK_SET_RATE_PARENT); + +/* +* This clk is needed as a temporary fall back during GPU PLL freq changes. +* Set CLK_IS_CRITICAL flag to prevent from being disabled. +*/ +#define SUN50I_H616_GPU_CLK1_REG 0x674 static SUNXI_CCU_M_WITH_GATE(gpu1_clk, "gpu1", "pll-periph0-2x", 0x674,0 ,2 ,/* M */ BIT (31 ),/* gate */ - 0); + CLK_IS_CRITICAL); static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2", 0x67c, BIT(0), 0);
@@ -1103,6 +1109,19 @@ static struct ccu_pll_nb sun50i_h616_pll_cpu_nb = { .lock = BIT(28), }; +static struct ccu_mux_nb sun50i_h616_gpu_nb = { + .common = &gpu0_clk.common, + .cm = &gpu0_clk.mux, + .delay_us =1 ,/* manual doesn't really say */ + .bypass_index =1 ,/* GPU_CLK1@400MHz */ +}; + +static struct ccu_pll_nb sun50i_h616_pll_gpu_nb = { + .common = &pll_gpu_clk.common, + .enable =BIT (29 ),/* LOCK_ENABLE */ + .lock =BIT (28 ), +}; +static int sun50i_h616_ccu_probe (struct platform_device *pdev) {void __iomem *reg;
@@ -1151,6 +1170,14 @@ static int sun50i_h616_ccu_probe(struct platform_device *pdev) val &= ~(GENMASK (21 ,16 ) |BIT (0 ));writel (val | (11 <<16 ) |BIT (0 ), reg +SUN50I_H616_PLL_AUDIO_REG ); +/* +* Set the input-divider for the gpu1 clock to 3, to reach a safe 400 MHz. +*/ + val =readl (reg +SUN50I_H616_GPU_CLK1_REG ); + val &= ~GENMASK (1 ,0 ); + val |=2 ; +writel (val, reg +SUN50I_H616_GPU_CLK1_REG ); +/* * First clock parent (osc32K) is unusable for CEC. But since there * is no good way to force parent switch (both run with same frequency),
@@ -1171,6 +1198,13 @@ static int sun50i_h616_ccu_probe(struct platform_device *pdev)/* Re-lock the CPU PLL after any rate changes */ ccu_pll_notifier_register (&sun50i_h616_pll_cpu_nb); +/* Reparent GPU during GPU PLL rate changes */ +ccu_mux_notifier_register (pll_gpu_clk.common.hw.clk, + &sun50i_h616_gpu_nb); + +/* Re-lock the GPU PLL after any rate changes */ +ccu_pll_notifier_register (&sun50i_h616_pll_gpu_nb); +return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 787/1887 dmaengine: ti: k3-udma-glue: Drop skip_fdq argument from k3_udma_glue_reset_rx_chn
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Roger Quadros <[email protected]>
[ Upstream commit 0da30874729baeb01889b0eca16cfda122687503 ]
The user of k3_udma_glue_reset_rx_chn() e.g. ti_am65_cpsw_nuss can run on multiple platforms having different DMA architectures. On some platforms there can be one FDQ for all flows in the RX channel while for others there is a separate FDQ for each flow in the RX channel.
So far we have been relying on the skip_fdq argument of k3_udma_glue_reset_rx_chn().
Instead of relying on the user to provide this information, infer it based on DMA architecture during k3_udma_glue_request_rx_chn() and save it in an internal flag 'single_fdq'. Use that flag at k3_udma_glue_reset_rx_chn() to deicide if the FDQ needs
to be cleared for every flow or just for flow 0.
Fixes the below issue on ti_am65_cpsw_nuss driver on AM62-SK.
Quoted 5 lines
ip link set eth1 down
ip link set eth0 down
ethtool -L eth0 rx 8
ip link set eth0 up
modprobe -rti_am65_cpsw_nuss
[ 103.045726] ------------[ cut here ]------------ [ 103.050505] k3_knav_desc_pool size 512000 != avail 64000 [ 103.050703] WARNING: CPU: 1 PID: 450 at drivers/net/ethernet/ti/k3-cppi-desc-pool.c:33 k3_cppi_desc_pool_destroy+0xa0/0xa8 [k3_cppi_desc_pool] [ 103.068810] Modules linked in: ti_am65_cpsw_nuss(-) k3_cppi_desc_pool snd_soc_hdmi_codec crct10dif_ce snd_soc_simple_card snd_soc_simple_card_utils display_connector rtc_ti_k3 k3_j72xx_bandgap tidss drm_client_lib snd_soc_davinci_mcas p drm_dma_helper tps6598x phylink snd_soc_ti_udma rti_wdt drm_display_helper snd_soc_tlv320aic3x_i2c typec at24 phy_gmii_sel snd_soc_ti_edma snd_soc_tlv320aic3x sii902x snd_soc_ti_sdma sa2ul omap_mailbox drm_kms_helper authenc cfg80211 r fkill fuse drm drm_panel_orientation_quirks backlight ip_tables x_tables ipv6 [last unloaded: k3_cppi_desc_pool] [ 103.119950] CPU: 1 UID: 0 PID: 450 Comm: modprobe Not tainted 6.13.0-rc7-00001-g9c5e3435fa66 #1011 [ 103.119968] Hardware name: Texas Instruments AM625 SK (DT) [ 103.119974] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 103.119983] pc : k3_cppi_desc_pool_destroy+0xa0/0xa8 [k3_cppi_desc_pool] [ 103.148007] lr : k3_cppi_desc_pool_destroy+0xa0/0xa8 [k3_cppi_desc_pool] [ 103.154709] sp : ffff8000826ebbc0 [ 103.158015] x29: ffff8000826ebbc0 x28: ffff0000090b6300 x27: 0000000000000000 [ 103.165145] x26: 0000000000000000 x25: 0000000000000000 x24: ffff0000019df6b0 [ 103.172271] x23: ffff0000019df6b8 x22: ffff0000019df410 x21: ffff8000826ebc88 [ 103.179397] x20: 000000000007d000 x19: ffff00000a3b3000 x18: 0000000000000000 [ 103.186522] x17: 0000000000000000 x16: 0000000000000000 x15: 000001e8c35e1cde [ 103.193647] x14: 0000000000000396 x13: 000000000000035c x12: 0000000000000000 [ 103.200772] x11: 000000000000003a x10: 00000000000009c0 x9 : ffff8000826eba20 [ 103.207897] x8 : ffff0000090b6d20 x7 : ffff00007728c180 x6 : ffff00007728c100 [ 103.215022] x5 : 0000000000000001 x4 : ffff000000508a50 x3 : ffff7ffff6146000 [ 103.222147] x2 : 0000000000000000 x1 : e300b4173ee6b200 x0 : 0000000000000000 [ 103.229274] Call trace: [ 103.231714] k3_cppi_desc_pool_destroy+0xa0/0xa8 [k3_cppi_desc_pool] (P) [ 103.238408] am65_cpsw_nuss_free_rx_chns+0x28/0x4c [ti_am65_cpsw_nuss] [ 103.244942] devm_action_release+0x14/0x20 [ 103.249040] release_nodes+0x3c/0x68 [ 103.252610] devres_release_all+0x8c/0xdc [ 103.256614] device_unbind_cleanup+0x18/0x60 [ 103.260876] device_release_driver_internal+0xf8/0x178 [ 103.266004] driver_detach+0x50/0x9c [ 103.269571] bus_remove_driver+0x6c/0xbc [ 103.273485] driver_unregister+0x30/0x60 [ 103.277401] platform_driver_unregister+0x14/0x20 [ 103.282096] am65_cpsw_nuss_driver_exit+0x18/0xff4 [ti_am65_cpsw_nuss] [ 103.288620] __arm64_sys_delete_module+0x17c/0x25c [ 103.293404] invoke_syscall+0x44/0x100 [ 103.297149] el0_svc_common.constprop.0+0xc0/0xe0 [ 103.301845] do_el0_svc+0x1c/0x28 [ 103.305155] el0_svc+0x28/0x98 [ 103.308207] el0t_64_sync_handler+0xc8/0xcc [ 103.312384] el0t_64_sync+0x198/0x19c [ 103.316040] ---[ end trace 0000000000000000 ]---
--- drivers/dma/ti/k3-udma-glue.c | 15 +++++++++++---- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 4 ++-- include/linux/dma/k3-udma-glue.h | 3 +-- 3 files changed, 14 insertions(+), 8 deletions(-)
drivers/dma/ti/k3-udma-glue.c +11 -4
@@ -83,6 +83,7 @@ struct k3_udma_glue_rx_channel {struct k3_udma_glue_rx_flow *flows;u32 flow_num;u32 flows_ready; +bool single_fdq;/* one FDQ for all flows */ };static void k3_udma_chan_dev_release (struct device *dev)
@@ -896,10 +897,13 @@ k3_udma_glue_request_rx_chn_priv(struct device *dev, const char *name, ep_cfg = rx_chn->common.ep_config; -if (xudma_is_pktdma (rx_chn->common.udmax)) +if (xudma_is_pktdma (rx_chn->common.udmax)) { rx_chn->udma_rchan_id = ep_cfg->mapped_channel_id; -else + rx_chn->single_fdq = false; + }else { rx_chn->udma_rchan_id =-1 ; + rx_chn->single_fdq = true; + }/* request and cfg UDMAP RX channel */ rx_chn->udma_rchanx = xudma_rchan_get(rx_chn->common.udmax,
@@ -1060,6 +1064,9 @@ k3_udma_glue_request_remote_rx_chn(struct device *dev, const char *name, rx_chn->common.chan_dev.dma_coherent = true;dma_coerce_mask_and_coherent (&rx_chn->common.chan_dev,DMA_BIT_MASK (48 )); + rx_chn->single_fdq = false; + }else { + rx_chn->single_fdq = true; } ret =k3_udma_glue_allocate_rx_flows (rx_chn, cfg);
@@ -1321,7 +1328,7 @@ EXPORT_SYMBOL_GPL(k3_udma_glue_tdown_rx_chn);void k3_udma_glue_reset_rx_chn (struct k3_udma_glue_rx_channel *rx_chn,u32 flow_num,void *data, -void (*cleanup)(void *data,dma_addr_t desc_dma),bool skip_fdq) +void (*cleanup)(void *data,dma_addr_t desc_dma)) {struct k3_udma_glue_rx_flow *flow = &rx_chn->flows[flow_num];struct device *dev = rx_chn->common.dev;
@@ -1333,7 +1340,7 @@ void k3_udma_glue_reset_rx_chn(struct k3_udma_glue_rx_channel *rx_chn,dev_dbg (dev,"RX reset flow %u occ_rx %u\n" , flow_num, occ_rx);/* Skip RX FDQ in case one FDQ is used for the set of flows */ -if (skip_fdq) +if (rx_chn->single_fdq && flow_num) goto do_reset;/*
drivers/net/ethernet/ti/am65-cpsw-nuss.c +2 -2
@@ -514,7 +514,7 @@ static int am65_cpsw_nuss_common_stop(struct am65_cpsw_common *common)for (i =0 ; i <AM65_CPSW_MAX_RX_FLOWS ; i++)k3_udma_glue_reset_rx_chn (common->rx_chns.rx_chn, i, &common->rx_chns, - am65_cpsw_nuss_rx_cleanup, !!i); + am65_cpsw_nuss_rx_cleanup);k3_udma_glue_disable_rx_chn (common->rx_chns.rx_chn);
@@ -2583,7 +2583,7 @@ static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)for (i =0 ; i <AM65_CPSW_MAX_RX_FLOWS ; i++)k3_udma_glue_reset_rx_chn (rx_chan->rx_chn, i, rx_chan, - am65_cpsw_nuss_rx_cleanup, !!i); + am65_cpsw_nuss_rx_cleanup);k3_udma_glue_disable_rx_chn (rx_chan->rx_chn);
include/linux/dma/k3-udma-glue.h +1 -2
@@ -130,8 +130,7 @@ void k3_udma_glue_rx_put_irq(struct k3_udma_glue_rx_channel *rx_chn, u32 flow_num);void k3_udma_glue_reset_rx_chn (struct k3_udma_glue_rx_channel *rx_chn,u32 flow_num,void *data, -void (*cleanup)(void *data,dma_addr_t desc_dma), -bool skip_fdq); +void (*cleanup)(void *data,dma_addr_t desc_dma));int k3_udma_glue_rx_flow_enable (struct k3_udma_glue_rx_channel *rx_chn,u32 flow_idx); int k3_udma_glue_rx_flow_disable(struct k3_udma_glue_rx_channel *rx_chn,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 788/1887 wifi: iwlwifi: dbg-tlv: fix DRAM data init
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit c2a2f505e0bcb45052131d173504887041e1faae ]
Given the existing code in iwl_dbg_tlv_update_drams(), the following can happen and cause firmware asserts, and even the device to become unusable:
* We set the magic so the firmware will use the data;
* we try to fill multiple allocation IDs, with at least one successful, but - crucially - one failing and thus not touching the data;
* we don't clear the data since there was one success.
This doesn't seem like much of a problem just yet, however, what happens now is that the allocation ID(s) that failed are not initialized.
There are two additional things to know:
* we never free these allocations across FW restart or interface down/up etc., in fact we never free them until the driver is unbound from the device (e.g. unloaded)
* the firmware uses the DRAM info structure for real debug data when it has used it completely
Given that, and the fact that we never initialize the data on restart, we can be unlucky and end up with an allocation that looks for the most part valid (valid ID, valid number of buffers, etc.) but has bad sizes - causing the firmware to throw an assert we can never recover from.
Fixing the code to have the entire buffers cleared (which we should do so old debug data isn't sticking around) is a bit more complex, so as a first step make the actual code that fills the information more robust by clearing the structure first, and filling the magic values only if it actually succeeded for one, rather than doing it the other way around.
Stable-dep-of: eb29b4ffafb2 ("wifi: iwlwifi: fix debug actions order")
--- drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +6 -8
@@ -1,6 +1,6 @@// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* -* Copyright (C) 2018-2022 Intel Corporation +* Copyright (C) 2018-2023 Intel Corporation */ #include <linux/firmware.h> #include "iwl-drv.h"
@@ -797,8 +797,7 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt) IWL_UCODE_TLV_CAPA_DRAM_FRAG_SUPPORT))return ; - dram_info->first_word =cpu_to_le32 (DRAM_INFO_FIRST_MAGIC_WORD ); - dram_info->second_word =cpu_to_le32 (DRAM_INFO_SECOND_MAGIC_WORD ); +memset (dram_info,0 ,sizeof (*dram_info));for (i =IWL_FW_INI_ALLOCATION_ID_DBGC1 ; i <=IWL_FW_INI_ALLOCATION_ID_DBGC3 ; i++) {
@@ -811,11 +810,10 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt) i, ret); } -if (dram_alloc) -IWL_DEBUG_FW (fwrt,"block data after %08x\n" , - dram_info->first_word); -else -memset (frags->block,0 ,sizeof (*dram_info)); +if (dram_alloc) { + dram_info->first_word =cpu_to_le32 (DRAM_INFO_FIRST_MAGIC_WORD ); + dram_info->second_word =cpu_to_le32 (DRAM_INFO_SECOND_MAGIC_WORD ); + } } static void iwl_dbg_tlv_send_hcmds(struct iwl_fw_runtime *fwrt,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 789/1887 wifi: iwlwifi: fix debug actions order
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit eb29b4ffafb20281624dcd2cbb768d6f30edf600 ]
The order of actions taken for debug was implemented incorrectly. Now we implemented the dump split and do the FW reset only in the middle of the dump (rather than the FW killing itself on error.) As a result, some of the actions taken when applying the config will now crash the device, so we need to fix the order.
--- drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +5 -5
@@ -1,6 +1,6 @@// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* -* Copyright (C) 2018-2023 Intel Corporation +* Copyright (C) 2018-2025 Intel Corporation */ #include <linux/firmware.h> #include "iwl-drv.h"
@@ -1361,15 +1361,15 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,switch (tp_id) {case IWL_FW_INI_TIME_POINT_EARLY :iwl_dbg_tlv_init_cfg (fwrt); -iwl_dbg_tlv_apply_config (fwrt, conf_list);iwl_dbg_tlv_update_drams (fwrt);iwl_dbg_tlv_tp_trigger (fwrt, sync, trig_list, tp_data,NULL ); +iwl_dbg_tlv_apply_config (fwrt, conf_list);break ;case IWL_FW_INI_TIME_POINT_AFTER_ALIVE :iwl_dbg_tlv_apply_buffers (fwrt);iwl_dbg_tlv_send_hcmds (fwrt, hcmd_list); -iwl_dbg_tlv_apply_config (fwrt, conf_list);iwl_dbg_tlv_tp_trigger (fwrt, sync, trig_list, tp_data,NULL ); +iwl_dbg_tlv_apply_config (fwrt, conf_list);break ;case IWL_FW_INI_TIME_POINT_PERIODIC :iwl_dbg_tlv_set_periodic_trigs (fwrt);
@@ -1379,14 +1379,14 @@ void _iwl_dbg_tlv_time_point(struct iwl_fw_runtime *fwrt,case IWL_FW_INI_TIME_POINT_MISSED_BEACONS :case IWL_FW_INI_TIME_POINT_FW_DHC_NOTIFICATION :iwl_dbg_tlv_send_hcmds (fwrt, hcmd_list); -iwl_dbg_tlv_apply_config (fwrt, conf_list);iwl_dbg_tlv_tp_trigger (fwrt, sync, trig_list, tp_data, iwl_dbg_tlv_check_fw_pkt); +iwl_dbg_tlv_apply_config (fwrt, conf_list);break ;default :iwl_dbg_tlv_send_hcmds (fwrt, hcmd_list); -iwl_dbg_tlv_apply_config (fwrt, conf_list);iwl_dbg_tlv_tp_trigger (fwrt, sync, trig_list, tp_data,NULL ); +iwl_dbg_tlv_apply_config (fwrt, conf_list);break ; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 790/1887 virtio: break and reset virtio devices on device_shutdown()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael S. Tsirkin <[email protected]>
[ Upstream commit 8bd2fa086a04886798b505f28db4002525895203 ]
Hongyu reported a hang on kexec in a VM. QEMU reported invalid memory accesses during the hang.
Invalid read at addr 0x102877002, size 2, region '(null)', reason: rejected Invalid write at addr 0x102877A44, size 2, region '(null)', reason: rejected ...
It was traced down to virtio-console. Kexec works fine if virtio-console is not in use.
The issue is that virtio-console continues to write to the MMIO even after underlying virtio-pci device is reset.
Additionally, Eric noticed that IOMMUs are reset before devices, if devices are not reset on shutdown they continue to poke at guest memory and get errors from the IOMMU. Some devices get wedged then.
The problem can be solved by breaking all virtio devices on virtio bus shutdown, then resetting them.
Message-ID: <c1dbc7dbad9b445245d3348f19e6742b0be07347.1740094946.git.mst@redhat.com>
--- drivers/virtio/virtio.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
drivers/virtio/virtio.c +29 -0
@@ -340,6 +340,34 @@ static void virtio_dev_remove(struct device *_d)of_node_put (dev->dev.of_node); } +static void virtio_dev_shutdown (struct device *_d) +{ +struct virtio_device *dev =dev_to_virtio (_d); +struct virtio_driver *drv =drv_to_virtio (dev->dev.driver); + +/* +* Stop accesses to or from the device. +* We only need to do it if there's a driver - no accesses otherwise. +*/ +if (!drv) +return ; + +/* +* Some devices get wedged if you kick them after they are +* reset. Mark all vqs as broken to make sure we don't. +*/ +virtio_break_device (dev); +/* +* Guarantee that any callback will see vq->broken as true. +*/ +virtio_synchronize_cbs (dev); +/* +* As IOMMUs are reset on shutdown, this will block device access to memory. +* Some devices get wedged if this happens, so reset to make sure it does not. +*/ + dev->config->reset (dev); +} +static struct bus_type virtio_bus = { .name ="virtio" , .match = virtio_dev_match,
@@ -347,6 +375,7 @@ static struct bus_type virtio_bus = { .uevent = virtio_uevent, .probe = virtio_dev_probe, .remove = virtio_dev_remove, + .shutdown = virtio_dev_shutdown, };int register_virtio_driver (struct virtio_driver *driver)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 791/1887 PCI: endpoint: pci-epf-test: Fix double free that causes kernel to oops
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Bruel <[email protected]>
[ Upstream commit 934e9d137d937706004c325fa1474f9e3f1ba10a ]
Fix a kernel oops found while testing the stm32_pcie Endpoint driver with handling of PERST# deassertion:
During EP initialization, pci_epf_test_alloc_space() allocates all BARs, which are further freed if epc_set_bar() fails (for instance, due to no free inbound window).
However, when pci_epc_set_bar() fails, the error path:
pci_epc_set_bar() ->
pci_epf_free_space()
does not clear the previous assignment to epf_test->reg[bar].
Then, if the host reboots, the PERST# deassertion restarts the BAR allocation sequence with the same allocation failure (no free inbound window), creating a double free situation since epf_test->reg[bar] was deallocated and is still non-NULL.
Thus, make sure that pci_epf_alloc_space() and pci_epf_free_space() invocations are symmetric, and as such, set epf_test->reg[bar] to NULL when memory is freed.
--- drivers/pci/endpoint/functions/pci-epf-test.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/pci/endpoint/functions/pci-epf-test.c +2 -0
@@ -735,6 +735,7 @@ static void pci_epf_test_unbind(struct pci_epf *epf) epf_bar);pci_epf_free_space (epf, epf_test->reg[bar], bar,PRIMARY_INTERFACE ); + epf_test->reg[bar] =NULL ; } } }
@@ -769,6 +770,7 @@ static int pci_epf_test_set_bar(struct pci_epf *epf)if (ret) {pci_epf_free_space (epf, epf_test->reg[bar], bar,PRIMARY_INTERFACE ); + epf_test->reg[bar] =NULL ;dev_err (dev,"Failed to set BAR%d\n" , bar);if (bar == test_reg_bar)return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 792/1887 spi-rockchip: Fix register out of bounds access
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luis de Arquer <[email protected]>
[ Upstream commit 7a874e8b54ea21094f7fd2d428b164394c6cb316 ]
Do not write native chip select stuff for GPIO chip selects. GPIOs can be numbered much higher than native CS. Also, it makes no sense.
--- drivers/spi/spi-rockchip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-rockchip.c +1 -1
@@ -541,7 +541,7 @@ static int rockchip_spi_config(struct rockchip_spi *rs, cr0 |= (spi->mode &0x3U ) <<CR0_SCPH_OFFSET ;if (spi->mode &SPI_LSB_FIRST ) cr0 |=CR0_FBM_LSB <<CR0_FBM_OFFSET ; -if (spi->mode &SPI_CS_HIGH ) +if ((spi->mode &SPI_CS_HIGH ) && !spi->cs_gpiod) cr0 |=BIT (spi->chip_select) <<CR0_SOI_OFFSET ;if (xfer->rx_buf && xfer->tx_buf)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 793/1887 wifi: iwlwifi: dont warn when if there is a FW error
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miri Korenblit <[email protected]>
[ Upstream commit c7f50d0433a016d43681592836a3d484817bfb34 ]
iwl_trans_reclaim is warning if it is called when the FW is not alive. But if it is called when there is a pending restart, i.e. after a FW error, there is no need to warn, instead - return silently.
--- drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/intel/iwlwifi/iwl-trans.h +3 -0
@@ -1194,6 +1194,9 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue, int ssn, struct sk_buff_head *skbs, bool is_flush) { + if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status))) + return; +if (WARN_ON_ONCE (trans->state !=IWL_TRANS_FW_ALIVE )) {IWL_ERR (trans,"%s bad state = %d\n" , __func__, trans->state);return ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 794/1887 ice: fix Tx scheduler error handling in XDP callback
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Kubiak <[email protected]>
[ Upstream commit 0153f36041b8e52019ebfa8629c13bf8f9b0a951 ]
When the XDP program is loaded, the XDP callback adds new Tx queues. This means that the callback must update the Tx scheduler with the new queue number. In the event of a Tx scheduler failure, the XDP callback should also fail and roll back any changes previously made for XDP preparation.
The previous implementation had a bug that not all changes made by the XDP callback were rolled back. This caused the crash with the following call trace:
[ +9.549584] ice 0000:ca:00.0: Failed VSI LAN queue config for XDP, error: -5 [ +0.382335] Oops: general protection fault, probably for non-canonical address 0x50a2250a90495525: 0000 [#1] SMP NOPTI [ +0.010710] CPU: 103 UID: 0 PID: 0 Comm: swapper/103 Not tainted 6.14.0-net-next-mar-31+ #14 PREEMPT(voluntary) [ +0.010175] Hardware name: Intel Corporation M50CYP2SBSTD/M50CYP2SBSTD, BIOS SE5C620.86B.01.01.0005.2202160810 02/16/2022 [ +0.010946] RIP: 0010:__ice_update_sample+0x39/0xe0 [ice]
[...]
[ +0.002715] Call Trace: [ +0.002452] <IRQ> [ +0.002021] ? __die_body.cold+0x19/0x29 [ +0.003922] ? die_addr+0x3c/0x60 [ +0.003319] ? exc_general_protection+0x17c/0x400 [ +0.004707] ? asm_exc_general_protection+0x26/0x30 [ +0.004879] ? __ice_update_sample+0x39/0xe0 [ice] [ +0.004835] ice_napi_poll+0x665/0x680 [ice] [ +0.004320] __napi_poll+0x28/0x190 [ +0.003500] net_rx_action+0x198/0x360 [ +0.003752] ? update_rq_clock+0x39/0x220 [ +0.004013] handle_softirqs+0xf1/0x340 [ +0.003840] ? sched_clock_cpu+0xf/0x1f0 [ +0.003925] __irq_exit_rcu+0xc2/0xe0 [ +0.003665] common_interrupt+0x85/0xa0 [ +0.003839] </IRQ> [ +0.002098] <TASK> [ +0.002106] asm_common_interrupt+0x26/0x40 [ +0.004184] RIP: 0010:cpuidle_enter_state+0xd3/0x690
Fix this by performing the missing unmapping of XDP queues from q_vectors and setting the XDP rings pointer back to NULL after all those queues are released.
Also, add an immediate exit from the XDP callback in case of ring preparation failure.
--- drivers/net/ethernet/intel/ice/ice_main.c | 46 ++++++++++++++++------- 1 file changed, 32 insertions(+), 14 deletions(-)
drivers/net/ethernet/intel/ice/ice_main.c +32 -14
@@ -2642,6 +2642,27 @@ static void ice_vsi_assign_bpf_prog(struct ice_vsi *vsi, struct bpf_prog *prog)bpf_prog_put (old_prog); } +/** +* ice_unmap_xdp_rings - Unmap XDP rings from interrupt vectors +* @vsi: the VSI with XDP rings being unmapped +*/ +static void ice_unmap_xdp_rings (struct ice_vsi *vsi) +{ +int v_idx; + +ice_for_each_q_vector (vsi, v_idx) { +struct ice_q_vector *q_vector = vsi->q_vectors[v_idx]; +struct ice_tx_ring *ring; + +ice_for_each_tx_ring (ring, q_vector->tx) +if (!ring->tx_buf || !ice_ring_is_xdp (ring)) +break ; + +/* restore the value of last node prior to XDP setup */ + q_vector->tx.tx_ring = ring; + } +} +/** * ice_prepare_xdp_rings - Allocate, configure and setup Tx rings for XDP * @vsi: VSI to bring up Tx rings used by XDP
@@ -2739,7 +2760,7 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog)if (status) {dev_err (dev,"Failed VSI LAN queue config for XDP, error: %d\n" , status); - goto clear_xdp_rings; + goto unmap_xdp_rings; }/* assign the prog only when it's not already present on VSI;
@@ -2755,6 +2776,8 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog)ice_vsi_assign_bpf_prog (vsi, prog);return 0 ; +unmap_xdp_rings: +ice_unmap_xdp_rings (vsi); clear_xdp_rings:ice_for_each_xdp_txq (vsi, i)if (vsi->xdp_rings[i]) {
@@ -2772,6 +2795,7 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog)devm_kfree (dev, vsi->xdp_rings); vsi->xdp_rings =NULL ; +return -ENOMEM ; }
@@ -2786,7 +2810,7 @@ int ice_destroy_xdp_rings(struct ice_vsi *vsi) {u16 max_txqs[ICE_MAX_TRAFFIC_CLASS ] = {0 };struct ice_pf *pf = vsi->back; -int i, v_idx; +int i;/* q_vectors are freed in reset path so there's no point in detaching * rings; in case of rebuild being triggered not from reset bits
@@ -2796,17 +2820,7 @@ int ice_destroy_xdp_rings(struct ice_vsi *vsi)if (ice_is_reset_in_progress (pf->state) || !vsi->q_vectors[0 ]) goto free_qmap; -ice_for_each_q_vector (vsi, v_idx) { -struct ice_q_vector *q_vector = vsi->q_vectors[v_idx]; -struct ice_tx_ring *ring; - -ice_for_each_tx_ring (ring, q_vector->tx) -if (!ring->tx_buf || !ice_ring_is_xdp (ring)) -break ; - -/* restore the value of last node prior to XDP setup */ - q_vector->tx.tx_ring = ring; - } +ice_unmap_xdp_rings (vsi); free_qmap:mutex_lock (&pf->avail_q_mutex);
@@ -2943,10 +2957,13 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog, xdp_ring_err =ice_vsi_determine_xdp_res (vsi);if (xdp_ring_err) {NL_SET_ERR_MSG_MOD (extack,"Not enough Tx resources for XDP" ); + goto resume_if; }else { xdp_ring_err =ice_prepare_xdp_rings (vsi, prog); -if (xdp_ring_err) +if (xdp_ring_err) {NL_SET_ERR_MSG_MOD (extack,"Setting up XDP Tx resources failed" ); + goto resume_if; + } }/* reallocate Rx queues that are used for zero-copy */ xdp_ring_err =ice_realloc_zc_buf (vsi, true);
@@ -2962,6 +2979,7 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,NL_SET_ERR_MSG_MOD (extack,"Freeing XDP Rx resources failed" ); } +resume_if:if (if_running) ret =ice_up (vsi);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 795/1887 coresight: holding cscfg_csdev_lock while removing cscfg from csdev
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yeoreum Yun <[email protected]>
[ Upstream commit 53b9e2659719b04f5ba7593f2af0f2335f75e94a ]
There'll be possible race scenario for coresight config:
CPU0 CPU1
(perf enable) load module
cscfg_load_config_sets() activate config. // sysfs (sys_active_cnt == 1)
...cscfg_csdev_enable_active_config()
lock(csdev->cscfg_csdev_lock)
deactivate config // sysfs (sys_activec_cnt == 0) cscfg_unload_config_sets()
<iterating config_csdev_list> cscfg_remove_owned_csdev_configs()
// here load config activate by CPU1 unlock(csdev->cscfg_csdev_lock)
iterating config_csdev_list could be raced with config_csdev_list's entry delete.
To resolve this race , hold csdev->cscfg_csdev_lock() while cscfg_remove_owned_csdev_configs()
--- drivers/hwtracing/coresight/coresight-syscfg.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/hwtracing/coresight/coresight-syscfg.c +2 -0
@@ -395,6 +395,8 @@ static void cscfg_remove_owned_csdev_configs(struct coresight_device *csdev, voiif (list_empty (&csdev->config_csdev_list))return ; +guard (spinlock_irqsave)(&csdev->cscfg_csdev_lock); +list_for_each_entry_safe (config_csdev, tmp, &csdev->config_csdev_list, node) {if (config_csdev->config_desc->load_owner == load_owner)list_del (&config_csdev->node);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 796/1887 ublk: santizize the arguments from userspace when adding a device
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ronnie Sahlberg <[email protected]>
[ Upstream commit 8c8472855884355caf3d8e0c50adf825f83454b2 ]
Sanity check the values for queue depth and number of queues we get from userspace when adding a device.
--- drivers/block/ublk_drv.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/block/ublk_drv.c +4 -0
@@ -1697,6 +1697,10 @@ static int ublk_ctrl_add_dev(struct io_uring_cmd *cmd)if (copy_from_user (&info, argp,sizeof (info)))return -EFAULT ;ublk_dump_dev_info (&info); + +if (info.queue_depth >UBLK_MAX_QUEUE_DEPTH ) +return -EINVAL ; +if (header->dev_id != info.dev_id) {pr_warn ("%s: dev id not match %u %u\n" , __func__, header->dev_id, info.dev_id);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 797/1887 LoongArch: Fix panic caused by NULL-PMD in huge_pte_offset()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tianyang Zhang <[email protected]>
[ Upstream commit ee084fa96123ede8b0563a1b5a9b23adc43cd50d ]
ERROR INFO:
CPU 25 Unable to handle kernel paging request at virtual address 0x0
... Call Trace: [<900000000023c30c>] huge_pte_offset+0x3c/0x58 [<900000000057fd4c>] hugetlb_follow_page_mask+0x74/0x438 [<900000000051fee8>] __get_user_pages+0xe0/0x4c8 [<9000000000522414>] faultin_page_range+0x84/0x380 [<9000000000564e8c>] madvise_vma_behavior+0x534/0xa48 [<900000000056689c>] do_madvise+0x1bc/0x3e8 [<9000000000566df4>] sys_madvise+0x24/0x38 [<90000000015b9e88>] do_syscall+0x78/0x98 [<9000000000221f18>] handle_syscall+0xb8/0x158
In some cases, pmd may be NULL and rely on NULL as the return value for processing, so it is necessary to determine this situation here.
--- arch/loongarch/mm/hugetlbpage.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/loongarch/mm/hugetlbpage.c +2 -1
@@ -47,7 +47,8 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, pmd =pmd_offset (pud, addr); } } -return pmd_none (*pmd) ?NULL : (pte_t *) pmd; + +return (!pmd ||pmd_none (*pmd)) ?NULL : (pte_t *) pmd; }/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 798/1887 sched/rt: Fix race in push_rt_task
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harshit Agarwal <[email protected]>
[ Upstream commit 690e47d1403e90b7f2366f03b52ed3304194c793 ]
Overview
========
When a CPU chooses to call push_rt_task and picks a task to push to another CPU's runqueue then it will call find_lock_lowest_rq method which would take a double lock on both CPUs' runqueues. If one of the locks aren't readily available, it may lead to dropping the current runqueue lock and reacquiring both the locks at once. During this window it is possible that the task is already migrated and is running on some other CPU. These cases are already handled. However, if the task is migrated and has already been executed and another CPU is now trying to wake it up (ttwu) such that it is queued again on the runqeue (on_rq is 1) and also if the task was run by the same CPU, then the current checks will pass even though the task was migrated out and is no longer in the pushable tasks list.
Crashes
=======
This bug resulted in quite a few flavors of crashes triggering kernel panics with various crash signatures such as assert failures, page faults, null pointer dereferences, and queue corruption errors all coming from scheduler itself.
Some of the crashes:
-> kernel BUG at kernel/sched/rt.c:1616! BUG_ON(idx >= MAX_RT_PRIO)
Call Trace: ? __die_body+0x1a/0x60 ? die+0x2a/0x50 ? do_trap+0x85/0x100 ? pick_next_task_rt+0x6e/0x1d0 ? do_error_trap+0x64/0xa0 ? pick_next_task_rt+0x6e/0x1d0 ? exc_invalid_op+0x4c/0x60 ? pick_next_task_rt+0x6e/0x1d0 ? asm_exc_invalid_op+0x12/0x20 ? pick_next_task_rt+0x6e/0x1d0 __schedule+0x5cb/0x790 ? update_ts_time_stats+0x55/0x70 schedule_idle+0x1e/0x40 do_idle+0x15e/0x200 cpu_startup_entry+0x19/0x20 start_secondary+0x117/0x160 secondary_startup_64_no_verify+0xb0/0xbb
-> BUG: kernel NULL pointer dereference, address: 00000000000000c0
Call Trace: ? __die_body+0x1a/0x60 ? no_context+0x183/0x350 ? __warn+0x8a/0xe0 ? exc_page_fault+0x3d6/0x520 ? asm_exc_page_fault+0x1e/0x30 ? pick_next_task_rt+0xb5/0x1d0 ? pick_next_task_rt+0x8c/0x1d0 __schedule+0x583/0x7e0 ? update_ts_time_stats+0x55/0x70 schedule_idle+0x1e/0x40 do_idle+0x15e/0x200 cpu_startup_entry+0x19/0x20 start_secondary+0x117/0x160 secondary_startup_64_no_verify+0xb0/0xbb
-> BUG: unable to handle page fault for address: ffff9464daea5900
kernel BUG at kernel/sched/rt.c:1861! BUG_ON(rq->cpu != task_cpu(p))
-> kernel BUG at kernel/sched/rt.c:1055! BUG_ON(!rq->nr_running)
Call Trace: ? __die_body+0x1a/0x60 ? die+0x2a/0x50 ? do_trap+0x85/0x100 ? dequeue_top_rt_rq+0xa2/0xb0 ? do_error_trap+0x64/0xa0 ? dequeue_top_rt_rq+0xa2/0xb0 ? exc_invalid_op+0x4c/0x60 ? dequeue_top_rt_rq+0xa2/0xb0 ? asm_exc_invalid_op+0x12/0x20 ? dequeue_top_rt_rq+0xa2/0xb0 dequeue_rt_entity+0x1f/0x70 dequeue_task_rt+0x2d/0x70 __schedule+0x1a8/0x7e0 ? blk_finish_plug+0x25/0x40 schedule+0x3c/0xb0 futex_wait_queue_me+0xb6/0x120 futex_wait+0xd9/0x240 do_futex+0x344/0xa90 ? get_mm_exe_file+0x30/0x60 ? audit_exe_compare+0x58/0x70 ? audit_filter_rules.constprop.26+0x65e/0x1220 __x64_sys_futex+0x148/0x1f0 do_syscall_64+0x30/0x80 entry_SYSCALL_64_after_hwframe+0x62/0xc7
-> BUG: unable to handle page fault for address: ffff8cf3608bc2c0
Call Trace: ? __die_body+0x1a/0x60 ? no_context+0x183/0x350 ? spurious_kernel_fault+0x171/0x1c0 ? exc_page_fault+0x3b6/0x520 ? plist_check_list+0x15/0x40 ? plist_check_list+0x2e/0x40 ? asm_exc_page_fault+0x1e/0x30 ? _cond_resched+0x15/0x30 ? futex_wait_queue_me+0xc8/0x120 ? futex_wait+0xd9/0x240 ? try_to_wake_up+0x1b8/0x490 ? futex_wake+0x78/0x160 ? do_futex+0xcd/0xa90 ? plist_check_list+0x15/0x40 ? plist_check_list+0x2e/0x40 ? plist_del+0x6a/0xd0 ? plist_check_list+0x15/0x40 ? plist_check_list+0x2e/0x40 ? dequeue_pushable_task+0x20/0x70 ? __schedule+0x382/0x7e0 ? asm_sysvec_reschedule_ipi+0xa/0x20 ? schedule+0x3c/0xb0 ? exit_to_user_mode_prepare+0x9e/0x150 ? irqentry_exit_to_user_mode+0x5/0x30 ? asm_sysvec_reschedule_ipi+0x12/0x20
Above are some of the common examples of the crashes that were observed due to this issue.
Details
=======
Let's look at the following scenario to understand this race.
1) CPU A enters push_rt_task
a) CPU A has chosen next_task = task p.
b) CPU A calls find_lock_lowest_rq(Task p, CPU Z’s rq).
c) CPU A identifies CPU X as a destination CPU (X < Z).
d) CPU A enters double_lock_balance(CPU Z’s rq, CPU X’s rq).
e) Since X is lower than Z, CPU A unlocks CPU Z’s rq. Someone else has locked CPU X’s rq, and thus, CPU A must wait.
2) At CPU Z
a) Previous task has completed execution and thus, CPU Z enters schedule, locks its own rq after CPU A releases it.
b) CPU Z dequeues previous task and begins executing task p.
c) CPU Z unlocks its rq.
d) Task p yields the CPU (ex. by doing IO or waiting to acquire a lock) which triggers the schedule function on CPU Z.
e) CPU Z enters schedule again, locks its own rq, and dequeues task p.
f) As part of dequeue, it sets p.on_rq = 0 and unlocks its rq.
3) At CPU B
a) CPU B enters try_to_wake_up with input task p.
b) Since CPU Z dequeued task p, p.on_rq = 0, and CPU B updates B.state = WAKING.
c) CPU B via select_task_rq determines CPU Y as the target CPU.
4) The race
a) CPU A acquires CPU X’s lock and relocks CPU Z.
b) CPU A reads task p.cpu = Z and incorrectly concludes task p is still on CPU Z.
c) CPU A failed to notice task p had been dequeued from CPU Z while CPU A was waiting for locks in double_lock_balance. If CPU A knew that task p had been dequeued, it would return NULL forcing push_rt_task to give up the task p's migration.
d) CPU B updates task p.cpu = Y and calls ttwu_queue.
e) CPU B locks Ys rq. CPU B enqueues task p onto Y and sets task
p.on_rq = 1.
f) CPU B unlocks CPU Y, triggering memory synchronization.
g) CPU A reads task p.on_rq = 1, cementing its assumption that task p has not migrated.
h) CPU A decides to migrate p to CPU X.
This leads to A dequeuing p from Y's queue and various crashes down the line.
Solution
========
The solution here is fairly simple. After obtaining the lock (at 4a), the check is enhanced to make sure that the task is still at the head of the pushable tasks list. If not, then it is anyway not suitable for being pushed out.
Testing
=======
The fix is tested on a cluster of 3 nodes, where the panics due to this are hit every couple of days. A fix similar to this was deployed on such cluster and was stable for more than 30 days.
--- kernel/sched/rt.c | 52 +++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 27 deletions(-)
kernel/sched/rt.c +25 -27
@@ -1972,6 +1972,26 @@ static int find_lowest_rq(struct task_struct *task)return -1 ; } +static struct task_struct *pick_next_pushable_task (struct rq *rq) +{ +struct task_struct *p; + +if (!has_pushable_tasks (rq)) +return NULL ; + + p =plist_first_entry (&rq->rt.pushable_tasks, + struct task_struct, pushable_tasks); + +BUG_ON (rq->cpu !=task_cpu (p)); +BUG_ON (task_current (rq, p)); +BUG_ON (p->nr_cpus_allowed <=1 ); + +BUG_ON (!task_on_rq_queued (p)); +BUG_ON (!rt_task (p)); + +return p; +} +/* Will lock the rq it finds */ static struct rq *find_lock_lowest_rq (struct task_struct *task,struct rq *rq) {
@@ -2002,18 +2022,16 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)/* * We had to unlock the run queue. In * the mean time, task could have -* migrated already or had its affinity changed. -* Also make sure that it wasn't scheduled on its rq. +* migrated already or had its affinity changed, +* therefore check if the task is still at the +* head of the pushable tasks list. * It is possible the task was scheduled, set * "migrate_disabled" and then got preempted, so we must * check the task migration disable flag here too. */ -if (unlikely (task_rq (task) != rq || +if (unlikely (is_migration_disabled (task) || !cpumask_test_cpu (lowest_rq->cpu, &task->cpus_mask) || -task_on_cpu (rq, task) || - !rt_task (task) || -is_migration_disabled (task) || - !task_on_rq_queued (task))) { + task !=pick_next_pushable_task (rq))) {double_unlock_balance (rq, lowest_rq); lowest_rq =NULL ;
@@ -2033,26 +2051,6 @@ static struct rq *find_lock_lowest_rq(struct task_struct *task, struct rq *rq)return lowest_rq; } -static struct task_struct *pick_next_pushable_task (struct rq *rq) -{ -struct task_struct *p; - -if (!has_pushable_tasks (rq)) -return NULL ; - - p =plist_first_entry (&rq->rt.pushable_tasks, - struct task_struct, pushable_tasks); - -BUG_ON (rq->cpu !=task_cpu (p)); -BUG_ON (task_current (rq, p)); -BUG_ON (p->nr_cpus_allowed <=1 ); - -BUG_ON (!task_on_rq_queued (p)); -BUG_ON (!rt_task (p)); - -return p; -} -/* * If the current CPU has more than one RT task, see if the non * running task can migrate over to a CPU that is running a task
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 799/1887 smb: client: fix potential deadlock when reconnecting channels
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
[ Upstream commit 711741f94ac3cf9f4e3aa73aa171e76d188c0819 ]
Fix cifs_signal_cifsd_for_reconnect() to take the correct lock order and prevent the following deadlock from happening
======================================================
WARNING: possible circular locking dependency detected
6.16.0-rc3-build2+ #1301 Tainted: G S W
------------------------------------------------------
cifsd/6055 is trying to acquire lock:ffff88810ad56038 (&tcp_ses->srv_lock){+.+.}-{3:3}, at: cifs_signal_cifsd_for_reconnect+0x134/0x200
but task is already holding lock:ffff888119c64330 (&ret_buf->chan_lock){+.+.}-{3:3}, at: cifs_signal_cifsd_for_reconnect+0xcf/0x200
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (&ret_buf->chan_lock){+.+.}-{3:3}:
validate_chain+0x1cf/0x270
__lock_acquire+0x60e/0x780
lock_acquire.part.0+0xb4/0x1f0
_raw_spin_lock+0x2f/0x40
cifs_setup_session+0x81/0x4b0
cifs_get_smb_ses+0x771/0x900
cifs_mount_get_session+0x7e/0x170
cifs_mount+0x92/0x2d0
cifs_smb3_do_mount+0x161/0x460
smb3_get_tree+0x55/0x90
vfs_get_tree+0x46/0x180
do_new_mount+0x1b0/0x2e0
path_mount+0x6ee/0x740
do_mount+0x98/0xe0
__do_sys_mount+0x148/0x180
do_syscall_64+0xa4/0x260
entry_SYSCALL_64_after_hwframe+0x76/0x7e-> #1 (&ret_buf->ses_lock){+.+.}-{3:3}:
validate_chain+0x1cf/0x270
__lock_acquire+0x60e/0x780
lock_acquire.part.0+0xb4/0x1f0
_raw_spin_lock+0x2f/0x40
cifs_match_super+0x101/0x320
sget+0xab/0x270
cifs_smb3_do_mount+0x1e0/0x460
smb3_get_tree+0x55/0x90
vfs_get_tree+0x46/0x180
do_new_mount+0x1b0/0x2e0
path_mount+0x6ee/0x740
do_mount+0x98/0xe0
__do_sys_mount+0x148/0x180
do_syscall_64+0xa4/0x260
entry_SYSCALL_64_after_hwframe+0x76/0x7e-> #0 (&tcp_ses->srv_lock){+.+.}-{3:3}:
check_noncircular+0x95/0xc0
check_prev_add+0x115/0x2f0
validate_chain+0x1cf/0x270
__lock_acquire+0x60e/0x780
lock_acquire.part.0+0xb4/0x1f0
_raw_spin_lock+0x2f/0x40
cifs_signal_cifsd_for_reconnect+0x134/0x200
__cifs_reconnect+0x8f/0x500
cifs_handle_standard+0x112/0x280
cifs_demultiplex_thread+0x64d/0xbc0
kthread+0x2f7/0x310
ret_from_fork+0x2a/0x230
ret_from_fork_asm+0x1a/0x30other info that might help us debug this:
Chain exists of: &tcp_ses->srv_lock --> &ret_buf->ses_lock --> &ret_buf->chan_lock Possible unsafe locking scenario:
CPU0 CPU1
---- ----
lock(&ret_buf->chan_lock);
lock(&ret_buf->ses_lock);
lock(&ret_buf->chan_lock); lock(&tcp_ses->srv_lock);
*** DEADLOCK ***
3 locks held by cifsd/6055:
#0: ffffffff857de398 (&cifs_tcp_ses_lock){+.+.}-{3:3}, at: cifs_signal_cifsd_for_reconnect+0x7b/0x200 #1: ffff888119c64060 (&ret_buf->ses_lock){+.+.}-{3:3}, at: cifs_signal_cifsd_for_reconnect+0x9c/0x200 #2: ffff888119c64330 (&ret_buf->chan_lock){+.+.}-{3:3}, at: cifs_signal_cifsd_for_reconnect+0xcf/0x200
--- fs/smb/client/cifsglob.h | 1 + fs/smb/client/connect.c | 56 ++++++++++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 19 deletions(-)
fs/smb/client/cifsglob.h +1 -0
@@ -589,6 +589,7 @@ get_rfc1002_length(void *buf)struct TCP_Server_Info {struct list_head tcp_ses_list;struct list_head smb_ses_list; +struct list_head rlist;/* reconnect list */ spinlock_t srv_lock;/* protect anything here that is not protected */ __u64 conn_id;/* connection identifier (useful for debugging) */ int srv_count;/* reference counter */
fs/smb/client/connect.c +37 -19
78 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 800/1887 bnxt: properly flush XDP redirect lists
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yan Zhai <[email protected]>
[ Upstream commit 9caca6ac0e26cd20efd490d8b3b2ffb1c7c00f6f ]
We encountered following crash when testing a XDP_REDIRECT feature in production:
[56251.579676] list_add corruption. next->prev should be prev (ffff93120dd40f30), but was ffffb301ef3a6740. (next=ffff93120dd 40f30). [56251.601413] ------------[ cut here ]------------ [56251.611357] kernel BUG at lib/list_debug.c:29! [56251.621082] Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI [56251.632073] CPU: 111 UID: 0 PID: 0 Comm: swapper/111 Kdump: loaded Tainted: P O 6.12.33-cloudflare-2025.6. 3 #1 [56251.653155] Tainted: [P]=PROPRIETARY_MODULE, [O]=OOT_MODULE [56251.663877] Hardware name: MiTAC GC68B-B8032-G11P6-GPU/S8032GM-HE-CFR, BIOS V7.020.B10-sig 01/22/2025 [56251.682626] RIP: 0010:__list_add_valid_or_report+0x4b/0xa0 [56251.693203] Code: 0e 48 c7 c7 68 e7 d9 97 e8 42 16 fe ff 0f 0b 48 8b 52 08 48 39 c2 74 14 48 89 f1 48 c7 c7 90 e7 d9 97 48 89 c6 e8 25 16 fe ff <0f> 0b 4c 8b 02 49 39 f0 74 14 48 89 d1 48 c7 c7 e8 e7 d9 97 4c 89 [56251.725811] RSP: 0018:ffff93120dd40b80 EFLAGS: 00010246 [56251.736094] RAX: 0000000000000075 RBX: ffffb301e6bba9d8 RCX: 0000000000000000 [56251.748260] RDX: 0000000000000000 RSI: ffff9149afda0b80 RDI: ffff9149afda0b80 [56251.760349] RBP: ffff9131e49c8000 R08: 0000000000000000 R09: ffff93120dd40a18 [56251.772382] R10: ffff9159cf2ce1a8 R11: 0000000000000003 R12: ffff911a80850000 [56251.784364] R13: ffff93120fbc7000 R14: 0000000000000010 R15: ffff9139e7510e40 [56251.796278] FS: 0000000000000000(0000) GS:ffff9149afd80000(0000) knlGS:0000000000000000 [56251.809133] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [56251.819561] CR2: 00007f5e85e6f300 CR3: 00000038b85e2006 CR4: 0000000000770ef0 [56251.831365] PKRU: 55555554 [56251.838653] Call Trace: [56251.845560] <IRQ> [56251.851943] cpu_map_enqueue.cold+0x5/0xa [56251.860243] xdp_do_redirect+0x2d9/0x480 [56251.868388] bnxt_rx_xdp+0x1d8/0x4c0 [bnxt_en] [56251.877028] bnxt_rx_pkt+0x5f7/0x19b0 [bnxt_en] [56251.885665] ? cpu_max_write+0x1e/0x100 [56251.893510] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.902276] __bnxt_poll_work+0x190/0x340 [bnxt_en] [56251.911058] bnxt_poll+0xab/0x1b0 [bnxt_en] [56251.919041] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.927568] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.935958] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.944250] __napi_poll+0x2b/0x160 [56251.951155] bpf_trampoline_6442548651+0x79/0x123 [56251.959262] __napi_poll+0x5/0x160 [56251.966037] net_rx_action+0x3d2/0x880 [56251.973133] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.981265] ? srso_alias_return_thunk+0x5/0xfbef5 [56251.989262] ? __hrtimer_run_queues+0x162/0x2a0 [56251.996967] ? srso_alias_return_thunk+0x5/0xfbef5 [56252.004875] ? srso_alias_return_thunk+0x5/0xfbef5 [56252.012673] ? bnxt_msix+0x62/0x70 [bnxt_en] [56252.019903] handle_softirqs+0xcf/0x270 [56252.026650] irq_exit_rcu+0x67/0x90 [56252.032933] common_interrupt+0x85/0xa0 [56252.039498] </IRQ> [56252.044246] <TASK> [56252.048935] asm_common_interrupt+0x26/0x40 [56252.055727] RIP: 0010:cpuidle_enter_state+0xb8/0x420 [56252.063305] Code: dc 01 00 00 e8 f9 79 3b ff e8 64 f7 ff ff 49 89 c5 0f 1f 44 00 00 31 ff e8 a5 32 3a ff 45 84 ff 0f 85 ae 01 00 00 fb 45 85 f6 <0f> 88 88 01 00 00 48 8b 04 24 49 63 ce 4c 89 ea 48 6b f1 68 48 29 [56252.088911] RSP: 0018:ffff93120c97fe98 EFLAGS: 00000202 [56252.096912] RAX: ffff9149afd80000 RBX: ffff9141d3a72800 RCX: 0000000000000000 [56252.106844] RDX: 00003329176c6b98 RSI: ffffffe36db3fdc7 RDI: 0000000000000000 [56252.116733] RBP: 0000000000000002 R08: 0000000000000002 R09: 000000000000004e [56252.126652] R10: ffff9149afdb30c4 R11: 071c71c71c71c71c R12: ffffffff985ff860 [56252.136637] R13: 00003329176c6b98 R14: 0000000000000002 R15: 0000000000000000 [56252.146667] ? cpuidle_enter_state+0xab/0x420 [56252.153909] cpuidle_enter+0x2d/0x40 [56252.160360] do_idle+0x176/0x1c0 [56252.166456] cpu_startup_entry+0x29/0x30 [56252.173248] start_secondary+0xf7/0x100 [56252.179941] common_startup_64+0x13e/0x141 [56252.186886] </TASK>
Quoted 1 line
From the crash dump, we found that the
cpu_map_flush_listinside
redirect info is partially corrupted: its list_head->next points to itself, but list_head->prev points to a valid list of unflushed bq entries.
This turned out to be a result of missed XDP flush on redirect lists. By digging in the actual source code, we found that
commit 7f0a168b0441 ("bnxt_en: Add completion ring pointer in TX and RX ring structures") incorrectly overwrites the event mask for XDP_REDIRECT in bnxt_rx_xdp. We can stably reproduce this crash by returning XDP_TX and XDP_REDIRECT randomly for incoming packets in a naive XDP program. Properly propagate the XDP_REDIRECT events back fixes the crash.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +4 -1
@@ -2543,6 +2543,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, {struct bnxt_napi *bnapi = cpr->bnapi;u32 raw_cons = cpr->cp_raw_cons; +bool flush_xdp = false;u32 cons;int tx_pkts =0 ;int rx_pkts =0 ;
@@ -2580,6 +2581,8 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,else rc =bnxt_force_rx_discard (bp, cpr, &raw_cons, &event); +if (event &BNXT_REDIRECT_EVENT ) + flush_xdp = true;if (likely (rc >=0 )) rx_pkts += rc;/* Increment rx_pkts when rc is -ENOMEM to count towards
@@ -2607,7 +2610,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, } } -if (event &BNXT_REDIRECT_EVENT ) +if (flush_xdp)xdp_do_flush ();if (event &BNXT_TX_EVENT ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 801/1887 bridge: mcast: Fix use-after-free during router port configuration
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit 7544f3f5b0b58c396f374d060898b5939da31709 ]
The bridge maintains a global list of ports behind which a multicast router resides. The list is consulted during forwarding to ensure multicast packets are forwarded to these ports even if the ports are not member in the matching MDB entry.
When per-VLAN multicast snooping is enabled, the per-port multicast context is disabled on each port and the port is removed from the global router port list:
# ip link add name br1 up type bridge vlan_filtering 1 mcast_snooping 1 # ip link add name dummy1 up master br1 type dummy # ip link set dev dummy1 type bridge_slave mcast_router 2 $ bridge -d mdb show | grep router router ports on br1: dummy1 # ip link set dev br1 type bridge mcast_vlan_snooping 1 $ bridge -d mdb show | grep router
However, the port can be re-added to the global list even when per-VLAN multicast snooping is enabled:
# ip link set dev dummy1 type bridge_slave mcast_router 0 # ip link set dev dummy1 type bridge_slave mcast_router 2 $ bridge -d mdb show | grep router router ports on br1: dummy1
Since commit 4b30ae9adb04 ("net: bridge: mcast: re-implement br_multicast_{enable, disable}_port functions"), when per-VLAN multicast snooping is enabled, multicast disablement on a port will disable the per-{port, VLAN} multicast contexts and not the per-port one. As a result, a port will remain in the global router port list even after it is deleted. This will lead to a use-after-free [1] when the list is traversed (when adding a new port to the list, for example):
# ip link del dev dummy1 # ip link add name dummy2 up master br1 type dummy # ip link set dev dummy2 type bridge_slave mcast_router 2
Similarly, stale entries can also be found in the per-VLAN router port list. When per-VLAN multicast snooping is disabled, the per-{port, VLAN} contexts are disabled on each port and the port is removed from the per-VLAN router port list:
# ip link add name br1 up type bridge vlan_filtering 1 mcast_snooping 1 mcast_vlan_snooping 1
# ip link add name dummy1 up master br1 type dummy
# bridge vlan add vid 2 dev dummy1
# bridge vlan global set vid 2 dev br1 mcast_snooping 1
# bridge vlan set vid 2 dev dummy1 mcast_router 2
$ bridge vlan global show dev br1 vid 2 | grep router
router ports: dummy1
# ip link set dev br1 type bridge mcast_vlan_snooping 0
$ bridge vlan global show dev br1 vid 2 | grep routerHowever, the port can be re-added to the per-VLAN list even when per-VLAN multicast snooping is disabled:
# bridge vlan set vid 2 dev dummy1 mcast_router 0
# bridge vlan set vid 2 dev dummy1 mcast_router 2
$ bridge vlan global show dev br1 vid 2 | grep router
router ports: dummy1When the VLAN is deleted from the port, the per-{port, VLAN} multicast context will not be disabled since multicast snooping is not enabled on the VLAN. As a result, the port will remain in the per-VLAN router port list even after it is no longer member in the VLAN. This will lead to a use-after-free [2] when the list is traversed (when adding a new port to the list, for example):
# ip link add name dummy2 up master br1 type dummy # bridge vlan add vid 2 dev dummy2 # bridge vlan del vid 2 dev dummy1 # bridge vlan set vid 2 dev dummy2 mcast_router 2
Fix these issues by removing the port from the relevant (global or per-VLAN) router port list in br_multicast_port_ctx_deinit(). The function is invoked during port deletion with the per-port multicast context and during VLAN deletion with the per-{port, VLAN} multicast context.
Note that deleting the multicast router timer is not enough as it only takes care of the temporary multicast router states (1 or 3) and not the permanent one (2).
[1]
BUG: KASAN: slab-out-of-bounds in br_multicast_add_router.part.0+0x3f1/0x560 Write of size 8 at addr ffff888004a67328 by task ip/384 [...] Call Trace: <TASK> dump_stack_lvl+0x6f/0xa0 print_address_description.constprop.0+0x6f/0x350 print_report+0x108/0x205 kasan_report+0xdf/0x110 br_multicast_add_router.part.0+0x3f1/0x560 br_multicast_set_port_router+0x74e/0xac0 br_setport+0xa55/0x1870 br_port_slave_changelink+0x95/0x120 __rtnl_newlink+0x5e8/0xa40 rtnl_newlink+0x627/0xb00 rtnetlink_rcv_msg+0x6fb/0xb70 netlink_rcv_skb+0x11f/0x350 netlink_unicast+0x426/0x710 netlink_sendmsg+0x75a/0xc20 __sock_sendmsg+0xc1/0x150 ____sys_sendmsg+0x5aa/0x7b0 ___sys_sendmsg+0xfc/0x180 __sys_sendmsg+0x124/0x1c0 do_syscall_64+0xbb/0x360 entry_SYSCALL_64_after_hwframe+0x4b/0x53
[2]
BUG: KASAN: slab-use-after-free in br_multicast_add_router.part.0+0x378/0x560 Read of size 8 at addr ffff888009f00840 by task bridge/391 [...] Call Trace: <TASK> dump_stack_lvl+0x6f/0xa0 print_address_description.constprop.0+0x6f/0x350 print_report+0x108/0x205 kasan_report+0xdf/0x110 br_multicast_add_router.part.0+0x378/0x560 br_multicast_set_port_router+0x6f9/0xac0 br_vlan_process_options+0x8b6/0x1430 br_vlan_rtm_process_one+0x605/0xa30 br_vlan_rtm_process+0x396/0x4c0 rtnetlink_rcv_msg+0x2f7/0xb70 netlink_rcv_skb+0x11f/0x350 netlink_unicast+0x426/0x710 netlink_sendmsg+0x75a/0xc20 __sock_sendmsg+0xc1/0x150 ____sys_sendmsg+0x5aa/0x7b0 ___sys_sendmsg+0xfc/0x180 __sys_sendmsg+0x124/0x1c0 do_syscall_64+0xbb/0x360 entry_SYSCALL_64_after_hwframe+0x4b/0x53
--- net/bridge/br_multicast.c | 9 +++++++++ 1 file changed, 9 insertions(+)
net/bridge/br_multicast.c +9 -0
@@ -1872,10 +1872,19 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port,void br_multicast_port_ctx_deinit (struct net_bridge_mcast_port *pmctx) { +struct net_bridge *br = pmctx->port->br; +bool del = false; +#if IS_ENABLED (CONFIG_IPV6 )del_timer_sync (&pmctx->ip6_mc_router_timer);#endif del_timer_sync (&pmctx->ip4_mc_router_timer); + +spin_lock_bh (&br->multicast_lock); + del |=br_ip6_multicast_rport_del (pmctx); + del |=br_ip4_multicast_rport_del (pmctx); +br_multicast_rport_del_notify (pmctx, del); +spin_unlock_bh (&br->multicast_lock); }int br_multicast_add_port (struct net_bridge_port *port)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 802/1887 riscv: save the SR_SUM status over switches
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Dooks <[email protected]>
[ Upstream commit 788aa64c01f1262310b4c1fb827a36df170d86ea ]
When threads/tasks are switched we need to ensure the old execution's SR_SUM state is saved and the new thread has the old SR_SUM state restored.
The issue was seen under heavy load especially with the syz-stress tool running, with crashes as follows in schedule_tail:
Unable to handle kernel access to user memory without uaccess routines at virtual address 000000002749f0d0 Oops [#1] Modules linked in: CPU: 1 PID: 4875 Comm: syz-executor.0 Not tainted 5.12.0-rc2-syzkaller-00467-g0d7588ab9ef9 #0 Hardware name: riscv-virtio,qemu (DT) epc : schedule_tail+0x72/0xb2 kernel/sched/core.c:4264 ra : task_pid_vnr include/linux/sched.h:1421 [inline] ra : schedule_tail+0x70/0xb2 kernel/sched/core.c:4264
epc : ffffffe00008c8b0 ra : ffffffe00008c8ae sp : ffffffe025d17ec0
gp : ffffffe005d25378 tp : ffffffe00f0d0000 t0 : 0000000000000000 t1 : 0000000000000001 t2 : 00000000000f4240 s0 : ffffffe025d17ee0 s1 : 000000002749f0d0 a0 : 000000000000002a a1 : 0000000000000003 a2 : 1ffffffc0cfac500 a3 : ffffffe0000c80cc a4 : 5ae9db91c19bbe00 a5 : 0000000000000000 a6 : 0000000000f00000 a7 : ffffffe000082eba s2 : 0000000000040000 s3 : ffffffe00eef96c0 s4 : ffffffe022c77fe0 s5 : 0000000000004000 s6 : ffffffe067d74e00 s7 : ffffffe067d74850 s8 : ffffffe067d73e18 s9 : ffffffe067d74e00 s10: ffffffe00eef96e8
s11: 000000ae6cdf8368 t3 : 5ae9db91c19bbe00 t4 : ffffffc4043cafb2 t5 : ffffffc4043cafba t6 : 0000000000040000
status: 0000000000000120 badaddr: 000000002749f0d0 cause:000000000000000f
Call Trace: [<ffffffe00008c8b0>] schedule_tail+0x72/0xb2 kernel/sched/core.c:4264 [<ffffffe000005570>] ret_from_exception+0x0/0x14 Dumping ftrace buffer: (ftrace buffer empty) ---[ end trace b5f8f9231dc87dda ]---
The issue comes from the put_user() in schedule_tail (kernel/sched/core.c) doing the following:
asmlinkage __visible void schedule_tail(struct task_struct *prev) {
...
if (current->set_child_tid)
put_user(task_pid_vnr(current), current->set_child_tid);...
}
the put_user() macro causes the code sequence to come out as follows:
1: __enable_user_access()
2: reg = task_pid_vnr(current);
3: *current->set_child_tid = reg;
4: __disable_user_access()
The problem is that we may have a sleeping function as argument which could clear SR_SUM causing the panic above. This was fixed by evaluating the argument of the put_user() macro outside the user-enabled section in commit 285a76bb2cf5 ("riscv: evaluate put_user() arg before enabling user access")"
In order for riscv to take advantage of unsafe_get/put_XXX() macros and to avoid the same issue we had with put_user() and sleeping functions we must ensure code flow can go through switch_to() from within a region of code with SR_SUM enabled and come back with SR_SUM still enabled. This patch addresses the problem allowing future work to enable full use of unsafe_get/put_XXX() macros without needing to take a CSR bit flip cost on every access. Make switch_to() save and restore SR_SUM.
--- arch/riscv/include/asm/processor.h | 1 + arch/riscv/kernel/asm-offsets.c | 5 +++++ arch/riscv/kernel/entry.S | 9 +++++++++ 3 files changed, 15 insertions(+)
arch/riscv/include/asm/processor.h +1 -0
@@ -39,6 +39,7 @@ struct thread_struct {unsigned long s[12 ];/* s[0]: frame pointer */ struct __riscv_d_ext_state fstate;unsigned long bad_cause; +unsigned long status; };/* Whitelist the fstate from the task_struct for hardened usercopy */
arch/riscv/kernel/asm-offsets.c +5 -0
@@ -33,6 +33,7 @@ void asm_offsets(void)OFFSET (TASK_THREAD_S10 , task_struct, thread.s[10 ]);OFFSET (TASK_THREAD_S11 , task_struct, thread.s[11 ]);OFFSET (TASK_TI_FLAGS , task_struct, thread_info.flags); +OFFSET (TASK_THREAD_STATUS , task_struct, thread.status);OFFSET (TASK_TI_PREEMPT_COUNT , task_struct, thread_info.preempt_count);OFFSET (TASK_TI_KERNEL_SP , task_struct, thread_info.kernel_sp);OFFSET (TASK_TI_USER_SP , task_struct, thread_info.user_sp);
@@ -331,6 +332,10 @@ void asm_offsets(void) offsetof(struct task_struct, thread.s[11]) - offsetof(struct task_struct, thread.ra) ); +DEFINE (TASK_THREAD_STATUS_RA , + offsetof(struct task_struct, thread.status) + - offsetof(struct task_struct, thread.ra) + );DEFINE (TASK_THREAD_F0_F0 , offsetof(struct task_struct, thread.fstate.f[0])
arch/riscv/kernel/entry.S +9 -0
@@ -502,7 +502,16 @@ ENTRY(__switch_to) REG_S s9, TASK_THREAD_S9_RA(a3) REG_S s10, TASK_THREAD_S10_RA(a3) REG_S s11, TASK_THREAD_S11_RA(a3) + + /* save the user space access flag */ + csrr s0, CSR_STATUS + REG_S s0, TASK_THREAD_STATUS_RA(a3) + /* Restore context from next->thread */ + REG_L s0, TASK_THREAD_STATUS_RA(a4) + li s1, SR_SUM + and s0, s0, s1 + csrs CSR_STATUS, s0 REG_L ra, TASK_THREAD_RA_RA(a4) REG_L sp, TASK_THREAD_SP_RA(a4) REG_L s0, TASK_THREAD_S0_RA(a4)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 803/1887 net: dsa: b53: do not enable EEE on bcm63xx
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <[email protected]>
[ Upstream commit 1237c2d4a8db79dfd4369bff6930b0e385ed7d5c ]
BCM63xx internal switches do not support EEE, but provide multiple RGMII ports where external PHYs may be connected. If one of these PHYs are EEE capable, we may try to enable EEE for the MACs, which then hangs the system on access of the (non-existent) EEE registers.
Fix this by checking if the switch actually supports EEE before attempting to configure it.
--- drivers/net/dsa/b53/b53_common.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/net/dsa/b53/b53_common.c +6 -2
@@ -2237,8 +2237,12 @@ EXPORT_SYMBOL(b53_eee_enable_set);*/ int b53_eee_init (struct dsa_switch *ds,int port,struct phy_device *phy) { +struct b53_device *dev = ds->priv;int ret; +if (is5325 (dev) ||is5365 (dev) ||is63xx (dev)) +return 0 ; + ret =phy_init_eee (phy, false);if (ret)return 0 ;
@@ -2255,7 +2259,7 @@ int b53_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)struct ethtool_eee *p = &dev->ports[port].eee;u16 reg; -if (is5325 (dev) ||is5365 (dev)) +if (is5325 (dev) ||is5365 (dev) ||is63xx (dev))return -EOPNOTSUPP ;b53_read16 (dev,B53_EEE_PAGE ,B53_EEE_LPI_INDICATE , ®);
@@ -2271,7 +2275,7 @@ int b53_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)struct b53_device *dev = ds->priv;struct ethtool_eee *p = &dev->ports[port].eee; -if (is5325 (dev) ||is5365 (dev)) +if (is5325 (dev) ||is5365 (dev) ||is63xx (dev))return -EOPNOTSUPP ; p->eee_enabled = e->eee_enabled;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 804/1887 hisi_acc_vfio_pci: bugfix live migration function without VF device driver
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Longfang Liu <[email protected]>
[ Upstream commit 2777a40998deb36f96b6afc48bd397cf58a4edf0 ]
If the VF device driver is not loaded in the Guest OS and we attempt to perform device data migration, the address of the migrated data will be NULL.
The live migration recovery operation on the destination side will access a null address value, which will cause access errors.
Therefore, live migration of VMs without added VF device drivers does not require device data migration.
In addition, when the queue address data obtained by the destination is empty, device queue recovery processing will not be performed.
--- .../vfio/pci/hisilicon/hisi_acc_vfio_pci.c | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-)
drivers/vfio/pci/hisilicon/hisi_acc_vfio_pci.c +15 -7
@@ -426,13 +426,6 @@ static int vf_qm_check_match(struct hisi_acc_vf_core_device *hisi_acc_vdev,return -EINVAL ; } - ret =qm_write_regs (vf_qm,QM_VF_STATE , &vf_data->vf_qm_state,1 ); -if (ret) { -dev_err (dev,"failed to write QM_VF_STATE\n" ); -return ret; - } - - hisi_acc_vdev->vf_qm_state = vf_data->vf_qm_state;return 0 ; }
@@ -497,6 +490,20 @@ static int vf_qm_load_data(struct hisi_acc_vf_core_device *hisi_acc_vdev,if (migf->total_length <sizeof (struct acc_vf_data ))return -EINVAL ; +if (!vf_data->eqe_dma || !vf_data->aeqe_dma || + !vf_data->sqc_dma || !vf_data->cqc_dma) { +dev_info (dev,"resume dma addr is NULL!\n" ); + hisi_acc_vdev->vf_qm_state =QM_NOT_READY ; +return 0 ; + } + + ret =qm_write_regs (qm,QM_VF_STATE , &vf_data->vf_qm_state,1 ); +if (ret) { +dev_err (dev,"failed to write QM_VF_STATE\n" ); +return -EINVAL ; + } + hisi_acc_vdev->vf_qm_state = vf_data->vf_qm_state; + qm->eqe_dma = vf_data->eqe_dma; qm->aeqe_dma = vf_data->aeqe_dma; qm->sqc_dma = vf_data->sqc_dma;
@@ -1269,6 +1276,7 @@ static int hisi_acc_vfio_pci_migrn_init_dev(struct vfio_device *core_vdev) hisi_acc_vdev->vf_id =pci_iov_vf_id (pdev) +1 ; hisi_acc_vdev->pf_qm = pf_qm; hisi_acc_vdev->vf_dev = pdev; + hisi_acc_vdev->vf_qm_state =QM_NOT_READY ;mutex_init (&hisi_acc_vdev->state_mutex); core_vdev->migration_flags =VFIO_MIGRATION_STOP_COPY ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 805/1887 s390/mm: Fix in_atomic() handling in do_secure_storage_access()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Carstens <[email protected]>
[ Upstream commit 11709abccf93b08adde95ef313c300b0d4bc28f1 ]
Kernel user spaces accesses to not exported pages in atomic context incorrectly try to resolve the page fault.
With debug options enabled call traces like this can be seen:
BUG: sleeping function called from invalid context at kernel/locking/rwsem.c:1523
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 419074, name: qemu-system-s39preempt_count: 1, expected: 0
RCU nest depth: 0, expected: 0
INFO: lockdep is turned off.
Preemption disabled at:
[<00000383ea47cfa2>] copy_page_from_iter_atomic+0xa2/0x8a0 CPU: 12 UID: 0 PID: 419074 Comm: qemu-system-s39 Tainted: G W 6.16.0-20250531.rc0.git0.69b3a602feac.63.fc42.s390x+debug #1 PREEMPT Tainted: [W]=WARN Hardware name: IBM 3931 A01 703 (LPAR) Call Trace: [<00000383e990d282>] dump_stack_lvl+0xa2/0xe8 [<00000383e99bf152>] __might_resched+0x292/0x2d0 [<00000383eaa7c374>] down_read+0x34/0x2d0 [<00000383e99432f8>] do_secure_storage_access+0x108/0x360 [<00000383eaa724b0>] __do_pgm_check+0x130/0x220 [<00000383eaa842e4>] pgm_check_handler+0x114/0x160 [<00000383ea47d028>] copy_page_from_iter_atomic+0x128/0x8a0 ([<00000383ea47d016>] copy_page_from_iter_atomic+0x116/0x8a0) [<00000383e9c45eae>] generic_perform_write+0x16e/0x310 [<00000383e9eb87f4>] ext4_buffered_write_iter+0x84/0x160 [<00000383e9da0de4>] vfs_write+0x1c4/0x460 [<00000383e9da123c>] ksys_write+0x7c/0x100 [<00000383eaa7284e>] __do_syscall+0x15e/0x280 [<00000383eaa8417e>] system_call+0x6e/0x90
INFO: lockdep is turned off.
It is not allowed to take the mmap_lock while in atomic context. Therefore handle such a secure storage access fault as if the accessed page is not
mapped: the uaccess function will return -EFAULT, and the caller has to deal with this. Usually this means that the access is retried in process context, which allows to resolve the page fault (or in this case export the page).
--- arch/s390/mm/fault.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/s390/mm/fault.c +4 -0
@@ -818,6 +818,8 @@ void do_secure_storage_access(struct pt_regs *regs)switch (get_fault_type (regs)) {case GMAP_FAULT : +if (faulthandler_disabled ()) +return do_fault_error (regs,VM_FAULT_BADMAP ); mm = current->mm; gmap = (struct gmap *)S390_lowcore.gmap;mmap_read_lock (mm);
@@ -829,6 +831,8 @@ void do_secure_storage_access(struct pt_regs *regs) } fallthrough;case USER_FAULT : +if (faulthandler_disabled ()) +return do_fault_error (regs,VM_FAULT_BADMAP ); mm = current->mm;mmap_read_lock (mm); vma =find_vma (mm, addr);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 806/1887 bus: mhi: ep: Update read pointer only after buffer is written
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sumit Kumar <[email protected]>
[ Upstream commit 6f18d174b73d0ceeaa341f46c0986436b3aefc9a ]
Inside mhi_ep_ring_add_element, the read pointer (rd_offset) is updated before the buffer is written, potentially causing race conditions where the host sees an updated read pointer before the buffer is actually written. Updating rd_offset prematurely can lead to the host accessing an uninitialized or incomplete element, resulting in data corruption.
Invoke the buffer write before updating rd_offset to ensure the element is fully written before signaling its availability.
--- drivers/bus/mhi/ep/ring.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/bus/mhi/ep/ring.c +6 -6
@@ -125,19 +125,19 @@ int mhi_ep_ring_add_element(struct mhi_ep_ring *ring, struct mhi_ring_element *e } old_offset = ring->rd_offset; -mhi_ep_ring_inc_index (ring);dev_dbg (dev,"Adding an element to ring at offset (%zu)\n" , ring->rd_offset); - -/* Update rp in ring context */ - rp =cpu_to_le64 (ring->rd_offset *sizeof (*el) + ring->rbase); -memcpy_toio ((void __iomem *) &ring->ring_ctx->generic.rp, &rp,sizeof (u64)); - ret = mhi_cntrl->write_to_host (mhi_cntrl, el, ring->rbase + (old_offset *sizeof (*el)),sizeof (*el));if (ret <0 )return ret; +mhi_ep_ring_inc_index (ring); + +/* Update rp in ring context */ + rp =cpu_to_le64 (ring->rd_offset *sizeof (*el) + ring->rbase); +memcpy_toio ((void __iomem *) &ring->ring_ctx->generic.rp, &rp,sizeof (u64)); +return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 807/1887 HID: nintendo: avoid bluetooth suspend/resume stalls
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel J. Ogorchock <[email protected]>
[ Upstream commit 4a0381080397e77792a5168069f174d3e56175ff ]
Ensure we don't stall or panic the kernel when using bluetooth-connected controllers. This was reported as an issue on android devices using kernel 6.6 due to the resume hook which had been added for usb joycons.
First, set a new state value to JOYCON_CTLR_STATE_SUSPENDED in a newly-added nintendo_hid_suspend. This makes sure we will not stall out the kernel waiting for input reports during led classdev suspend. The stalls could happen if connectivity is unreliable or lost to the controller prior to suspend.
Second, since we lose connectivity during suspend, do not try joycon_init() for bluetooth controllers in the nintendo_hid_resume path.
Tested via multiple suspend/resume flows when using the controller both in USB and bluetooth modes.
--- drivers/hid/hid-nintendo.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-)
drivers/hid/hid-nintendo.c +36 -2
@@ -301,6 +301,7 @@ enum joycon_ctlr_state {JOYCON_CTLR_STATE_INIT ,JOYCON_CTLR_STATE_READ ,JOYCON_CTLR_STATE_REMOVED , + JOYCON_CTLR_STATE_SUSPENDED, };/* Controller type received as part of device info */
@@ -2341,14 +2342,46 @@ static void nintendo_hid_remove(struct hid_device *hdev)static int nintendo_hid_resume (struct hid_device *hdev) { -int ret =joycon_init (hdev); +struct joycon_ctlr *ctlr =hid_get_drvdata (hdev); +int ret; + +hid_dbg (hdev,"resume\n" ); +if (hdev->bus !=BUS_USB ) { +hid_dbg (hdev,"no-op resume for bt ctlr\n" ); + ctlr->ctlr_state =JOYCON_CTLR_STATE_READ ; +return 0 ; + } + ret =joycon_init (hdev);if (ret) -hid_err (hdev,"Failed to restore controller after resume" ); +hid_err (hdev, +"Failed to restore controller after resume: %d\n" , + ret); +else + ctlr->ctlr_state =JOYCON_CTLR_STATE_READ ;return ret; } +static int nintendo_hid_suspend (struct hid_device *hdev,pm_message_t message) +{ +struct joycon_ctlr *ctlr =hid_get_drvdata (hdev); + +hid_dbg (hdev,"suspend: %d\n" , message.event); +/* +* Avoid any blocking loops in suspend/resume transitions. +* +* joycon_enforce_subcmd_rate() can result in repeated retries if for +* whatever reason the controller stops providing input reports. +* +* This has been observed with bluetooth controllers which lose +* connectivity prior to suspend (but not long enough to result in +* complete disconnection). +*/ + ctlr->ctlr_state =JOYCON_CTLR_STATE_SUSPENDED ; +return 0 ; +} +#endif static const struct hid_device_id nintendo_hid_devices[] = {
@@ -2375,6 +2408,7 @@ static struct hid_driver nintendo_hid_driver = {#ifdef CONFIG_PM .resume = nintendo_hid_resume, + .suspend = nintendo_hid_suspend,#endif };module_hid_driver (nintendo_hid_driver);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 808/1887 rxrpc: Fix recv-recv race of completed call
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
[ Upstream commit 962fb1f651c2cf2083e0c3ef53ba69e3b96d3fbc ]
If a call receives an event (such as incoming data), the call gets placed on the socket's queue and a thread in recvmsg can be awakened to go and process it. Once the thread has picked up the call off of the queue, further events will cause it to be requeued, and once the socket lock is dropped (recvmsg uses call->user_mutex to allow the socket to be used in parallel), a second thread can come in and its recvmsg can pop the call off the socket queue again.
In such a case, the first thread will be receiving stuff from the call and the second thread will be blocked on call->user_mutex. The first thread can, at this point, process both the event that it picked call for and the event that the second thread picked the call for and may see the call terminate - in which case the call will be "released", decoupling the call from the user call ID assigned to it (RXRPC_USER_CALL_ID in the control message).
The first thread will return okay, but then the second thread will wake up holding the user_mutex and, if it sees that the call has been released by the first thread, it will BUG thusly:
kernel BUG at net/rxrpc/recvmsg.c:474!
Fix this by just dequeuing the call and ignoring it if it is seen to be already released. We can't tell userspace about it anyway as the user call ID has become stale.
--- net/rxrpc/recvmsg.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
net/rxrpc/recvmsg.c +14 -2
@@ -546,6 +546,15 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,write_lock_bh (&rx->recvmsg_lock); l = rx->recvmsg_q.next; call = list_entry(l, struct rxrpc_call, recvmsg_link); + +if (test_bit (RXRPC_CALL_RELEASED , &call->flags)) { +list_del_init (&call->recvmsg_link); +write_unlock_bh (&rx->recvmsg_lock); +release_sock (&rx->sk); +rxrpc_put_call (call, rxrpc_call_put); + goto try_again; + } +if (!(flags &MSG_PEEK ))list_del_init (&call->recvmsg_link);else
@@ -568,8 +577,11 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,release_sock (&rx->sk); -if (test_bit (RXRPC_CALL_RELEASED , &call->flags)) -BUG (); +if (test_bit (RXRPC_CALL_RELEASED , &call->flags)) { +mutex_unlock (&call->user_mutex); +rxrpc_put_call (call, rxrpc_call_put); + goto try_again; + }if (test_bit (RXRPC_CALL_HAS_USERID , &call->flags)) {if (flags &MSG_CMSG_COMPAT ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 809/1887 iio: st_sensors: core and lsm9ds0 switch to devm_regulator_bulk_get_enable()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonathan Cameron <[email protected]>
[ Upstream commit 9e855d77b1ec57704d23e25761a97e6e64abed66 ]
These drivers only turns the power on at probe and off via a custom devm_add_action_or_reset() callback. The two regulators were handled separately so also switch to bulk registration.
The new devm_regulator_bulk_get_enable() replaces all this boilerplate code.
Stable-dep-of: 9f92e93e257b ("iio: common: st_sensors: Fix use of uninitialize device structs")
--- .../iio/common/st_sensors/st_sensors_core.c | 39 ++--------- drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c | 65 ++----------------- include/linux/iio/common/st_sensors.h | 4 -- 3 files changed, 14 insertions(+), 94 deletions(-)
drivers/iio/common/st_sensors/st_sensors_core.c +7 -32
@@ -219,47 +219,22 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable) }EXPORT_SYMBOL_NS (st_sensors_set_axis_enable,IIO_ST_SENSORS ); -static void st_reg_disable (void *reg) -{ -regulator_disable (reg); -}int st_sensors_power_enable (struct iio_dev *indio_dev) { -struct st_sensor_data *pdata =iio_priv (indio_dev); +static const char *const regulator_names[] = {"vdd" ,"vddio" };struct device *parent = indio_dev->dev.parent;int err;/* Regulators not mandatory, but if requested we should enable them. */ - pdata->vdd =devm_regulator_get (parent,"vdd" ); -if (IS_ERR (pdata->vdd)) -return dev_err_probe (&indio_dev->dev,PTR_ERR (pdata->vdd), -"unable to get Vdd supply\n" ); - - err =regulator_enable (pdata->vdd); -if (err !=0 ) { -dev_warn (&indio_dev->dev, -"Failed to enable specified Vdd supply\n" ); -return err; - } - - err =devm_add_action_or_reset (parent, st_reg_disable, pdata->vdd); + err =devm_regulator_bulk_get_enable (parent, +ARRAY_SIZE (regulator_names), + regulator_names);if (err) -return err; +return dev_err_probe (&indio_dev->dev, err, +"unable to enable supplies\n" ); - pdata->vdd_io =devm_regulator_get (parent,"vddio" ); -if (IS_ERR (pdata->vdd_io)) -return dev_err_probe (&indio_dev->dev,PTR_ERR (pdata->vdd_io), -"unable to get Vdd_IO supply\n" ); - - err =regulator_enable (pdata->vdd_io); -if (err !=0 ) { -dev_warn (&indio_dev->dev, -"Failed to enable specified Vdd_IO supply\n" ); -return err; - } - -return devm_add_action_or_reset (parent, st_reg_disable, pdata->vdd_io); +return 0 ; }EXPORT_SYMBOL_NS (st_sensors_power_enable,IIO_ST_SENSORS );
drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c +7 -58
92 lines not on this page · raw message
include/linux/iio/common/st_sensors.h +0 -4
@@ -224,8 +224,6 @@ struct st_sensor_settings {* @mount_matrix: The mounting matrix of the sensor. * @sensor_settings: Pointer to the specific sensor settings in use. * @current_fullscale: Maximum range of measure by the sensor. -* @vdd: Pointer to sensor's Vdd power supply -* @vdd_io: Pointer to sensor's Vdd-IO power supply * @regmap: Pointer to specific sensor regmap configuration. * @enabled: Status of the sensor (false->off, true->on). * @odr: Output data rate of the sensor [Hz].
@@ -244,8 +242,6 @@ struct st_sensor_data {struct iio_mount_matrix mount_matrix;struct st_sensor_settings *sensor_settings;struct st_sensor_fullscale_avl *current_fullscale; -struct regulator *vdd; -struct regulator *vdd_io;struct regmap *regmap;bool enabled;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 810/1887 iio: st_sensors: relax WhoAmI check in st_sensors_verify_id()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kaustabh Chakraborty <[email protected]>
[ Upstream commit a3c2c5c937ed7562b6d120670f2743e979c05881 ]
Hard matching against the WhoAmI values isn't ideal for using devices which are compatible with existing ones. Instead of raising an error, issue a warning instead, thus allowing the driver to continue probing.
Stable-dep-of: 9f92e93e257b ("iio: common: st_sensors: Fix use of uninitialize device structs")
--- drivers/iio/common/st_sensors/st_sensors_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/iio/common/st_sensors/st_sensors_core.c +1 -2
@@ -617,10 +617,9 @@ int st_sensors_verify_id(struct iio_dev *indio_dev) }if (sdata->sensor_settings->wai != wai) { -dev_err (&indio_dev->dev, +dev_warn (&indio_dev->dev,"%s: WhoAmI mismatch (0x%x).\n" , indio_dev->name, wai); -return -EINVAL ; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 811/1887 iio: common: st_sensors: Fix use of uninitialize device structs
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maud Spierings <[email protected]>
[ Upstream commit 9f92e93e257b33e73622640a9205f8642ec16ddd ]
Throughout the various probe functions &indio_dev->dev is used before it is initialized. This caused a kernel panic in st_sensors_power_enable() when the call to devm_regulator_bulk_get_enable() fails and then calls dev_err_probe() with the uninitialized device.
This seems to only cause a panic with dev_err_probe(), dev_err(), dev_warn() and dev_info() don't seem to cause a panic, but are fixed as well.
The issue is reported and traced here: [1]
--- drivers/iio/accel/st_accel_core.c | 10 +++--- .../iio/common/st_sensors/st_sensors_core.c | 36 +++++++++---------- .../common/st_sensors/st_sensors_trigger.c | 20 +++++------ 3 files changed, 31 insertions(+), 35 deletions(-)
drivers/iio/accel/st_accel_core.c +5 -5
@@ -1269,6 +1269,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev)union acpi_object *ont;union acpi_object *elements;acpi_status status; +struct device *parent = indio_dev->dev.parent;int ret = -EINVAL ;unsigned int val;int i, j;
@@ -1287,7 +1288,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) }; - adev =ACPI_COMPANION (indio_dev->dev.parent); + adev =ACPI_COMPANION (parent);if (!adev)return -ENXIO ;
@@ -1296,8 +1297,7 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev)if (status ==AE_NOT_FOUND ) {return -ENXIO ; }else if (ACPI_FAILURE (status)) { -dev_warn (&indio_dev->dev,"failed to execute _ONT: %d\n" , - status); +dev_warn (parent,"failed to execute _ONT: %d\n" , status);return status; }
@@ -1373,12 +1373,12 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) } ret =0 ; -dev_info (&indio_dev->dev,"computed mount matrix from ACPI\n" ); +dev_info (parent,"computed mount matrix from ACPI\n" ); out:kfree (buffer.pointer);if (ret) -dev_dbg (&indio_dev->dev, +dev_dbg (parent,"failed to apply ACPI orientation data: %d\n" , ret);return ret;
drivers/iio/common/st_sensors/st_sensors_core.c +17 -19
@@ -154,7 +154,7 @@ static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)return err; st_accel_set_fullscale_error: -dev_err (&indio_dev->dev,"failed to set new fullscale.\n" ); +dev_err (indio_dev->dev.parent,"failed to set new fullscale.\n" );return err; }
@@ -231,8 +231,7 @@ int st_sensors_power_enable(struct iio_dev *indio_dev)ARRAY_SIZE (regulator_names), regulator_names);if (err) -return dev_err_probe (&indio_dev->dev, err, -"unable to enable supplies\n" ); +return dev_err_probe (parent, err,"unable to enable supplies\n" );return 0 ; }
@@ -241,13 +240,14 @@ EXPORT_SYMBOL_NS(st_sensors_power_enable, IIO_ST_SENSORS);static int st_sensors_set_drdy_int_pin (struct iio_dev *indio_dev,struct st_sensors_platform_data *pdata) { +struct device *parent = indio_dev->dev.parent;struct st_sensor_data *sdata =iio_priv (indio_dev);/* Sensor does not support interrupts */ if (!sdata->sensor_settings->drdy_irq.int1.addr && !sdata->sensor_settings->drdy_irq.int2.addr) {if (pdata->drdy_int_pin) -dev_info (&indio_dev->dev, +dev_info (parent,"DRDY on pin INT%d specified, but sensor does not support interrupts\n" , pdata->drdy_int_pin);return 0 ;
@@ -256,29 +256,27 @@ static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,switch (pdata->drdy_int_pin) {case 1 :if (!sdata->sensor_settings->drdy_irq.int1.mask) { -dev_err (&indio_dev->dev, -"DRDY on INT1 not available.\n" ); +dev_err (parent,"DRDY on INT1 not available.\n" );return -EINVAL ; } sdata->drdy_int_pin =1 ;break ;case 2 :if (!sdata->sensor_settings->drdy_irq.int2.mask) { -dev_err (&indio_dev->dev, -"DRDY on INT2 not available.\n" ); +dev_err (parent,"DRDY on INT2 not available.\n" );return -EINVAL ; } sdata->drdy_int_pin =2 ;break ;default : -dev_err (&indio_dev->dev,"DRDY on pdata not valid.\n" ); +dev_err (parent,"DRDY on pdata not valid.\n" );return -EINVAL ; }if (pdata->open_drain) {if (!sdata->sensor_settings->drdy_irq.int1.addr_od && !sdata->sensor_settings->drdy_irq.int2.addr_od) -dev_err (&indio_dev->dev, +dev_err (parent,"open drain requested but unsupported.\n" );else sdata->int_pin_open_drain = true;
@@ -336,6 +334,7 @@ EXPORT_SYMBOL_NS(st_sensors_dev_name_probe, IIO_ST_SENSORS);int st_sensors_init_sensor (struct iio_dev *indio_dev,struct st_sensors_platform_data *pdata) { +struct device *parent = indio_dev->dev.parent;struct st_sensor_data *sdata =iio_priv (indio_dev);struct st_sensors_platform_data *of_pdata;int err =0 ;
@@ -343,7 +342,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,mutex_init (&sdata->odr_lock);/* If OF/DT pdata exists, it will take precedence of anything else */ - of_pdata =st_sensors_dev_probe (indio_dev->dev.parent, pdata); + of_pdata =st_sensors_dev_probe (parent, pdata);if (IS_ERR (of_pdata))return PTR_ERR (of_pdata);if (of_pdata)
@@ -370,7 +369,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,if (err <0 )return err; }else -dev_info (&indio_dev->dev,"Full-scale not possible\n" ); +dev_info (parent,"Full-scale not possible\n" ); err =st_sensors_set_odr (indio_dev, sdata->odr);if (err <0 )
@@ -405,7 +404,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev, mask = sdata->sensor_settings->drdy_irq.int2.mask_od; } -dev_info (&indio_dev->dev, +dev_info (parent,"set interrupt line to open drain mode on pin %d\n" , sdata->drdy_int_pin); err = st_sensors_write_data_with_mask(indio_dev, addr,
@@ -605,21 +604,20 @@ EXPORT_SYMBOL_NS(st_sensors_get_settings_index, IIO_ST_SENSORS);int st_sensors_verify_id (struct iio_dev *indio_dev) {struct st_sensor_data *sdata =iio_priv (indio_dev); +struct device *parent = indio_dev->dev.parent;int wai, err;if (sdata->sensor_settings->wai_addr) { err =regmap_read (sdata->regmap, sdata->sensor_settings->wai_addr, &wai);if (err <0 ) { -dev_err (&indio_dev->dev, -"failed to read Who-Am-I register.\n" ); -return err; +return dev_err_probe (parent, err, +"failed to read Who-Am-I register.\n" ); }if (sdata->sensor_settings->wai != wai) { -dev_warn (&indio_dev->dev, -"%s: WhoAmI mismatch (0x%x).\n" , - indio_dev->name, wai); +dev_warn (parent,"%s: WhoAmI mismatch (0x%x).\n" , + indio_dev->name, wai); } }
drivers/iio/common/st_sensors/st_sensors_trigger.c +9 -11
@@ -127,7 +127,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->trig =devm_iio_trigger_alloc (parent,"%s-trigger" , indio_dev->name);if (sdata->trig ==NULL ) { -dev_err (&indio_dev->dev,"failed to allocate iio trigger.\n" ); +dev_err (parent,"failed to allocate iio trigger.\n" );return -ENOMEM ; }
@@ -143,7 +143,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,case IRQF_TRIGGER_FALLING :case IRQF_TRIGGER_LOW :if (!sdata->sensor_settings->drdy_irq.addr_ihl) { -dev_err (&indio_dev->dev, +dev_err (parent,"falling/low specified for IRQ but hardware supports only rising/high: will request rising/high\n" );if (irq_trig ==IRQF_TRIGGER_FALLING ) irq_trig =IRQF_TRIGGER_RISING ;
@@ -156,21 +156,19 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->sensor_settings->drdy_irq.mask_ihl, 1);if (err <0 )return err; -dev_info (&indio_dev->dev, +dev_info (parent,"interrupts on the falling edge or active low level\n" ); }break ;case IRQF_TRIGGER_RISING : -dev_info (&indio_dev->dev, -"interrupts on the rising edge\n" ); +dev_info (parent,"interrupts on the rising edge\n" );break ;case IRQF_TRIGGER_HIGH : -dev_info (&indio_dev->dev, -"interrupts active high level\n" ); +dev_info (parent,"interrupts active high level\n" );break ;default :/* This is the most preferred mode, if possible */ -dev_err (&indio_dev->dev, +dev_err (parent,"unsupported IRQ trigger specified (%lx), enforce rising edge\n" , irq_trig); irq_trig =IRQF_TRIGGER_RISING ; }
@@ -179,7 +177,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,if (irq_trig ==IRQF_TRIGGER_FALLING || irq_trig ==IRQF_TRIGGER_RISING ) {if (!sdata->sensor_settings->drdy_irq.stat_drdy.addr) { -dev_err (&indio_dev->dev, +dev_err (parent,"edge IRQ not supported w/o stat register.\n" );return -EOPNOTSUPP ; }
@@ -214,13 +212,13 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev, sdata->trig->name, sdata->trig);if (err) { -dev_err (&indio_dev->dev,"failed to request trigger IRQ.\n" ); +dev_err (parent,"failed to request trigger IRQ.\n" );return err; } err =devm_iio_trigger_register (parent, sdata->trig);if (err <0 ) { -dev_err (&indio_dev->dev,"failed to register iio trigger.\n" ); +dev_err (parent,"failed to register iio trigger.\n" );return err; } indio_dev->trig =iio_trigger_get (sdata->trig);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 812/1887 rxrpc: Fix bug due to prealloc collision
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
[ Upstream commit 69e4186773c6445b258fb45b6e1df18df831ec45 ]
When userspace is using AF_RXRPC to provide a server, it has to preallocate incoming calls and assign to them call IDs that will be used to thread related recvmsg() and sendmsg() together. The preallocated call IDs will automatically be attached to calls as they come in until the pool is empty.
To the kernel, the call IDs are just arbitrary numbers, but userspace can use the call ID to hold a pointer to prepared structs. In any case, the user isn't permitted to create two calls with the same call ID (call IDs become available again when the call ends) and EBADSLT should result from sendmsg() if an attempt is made to preallocate a call with an in-use call ID.
However, the cleanup in the error handling will trigger both assertions in rxrpc_cleanup_call() because the call isn't marked complete and isn't marked as having been released.
Fix this by setting the call state in rxrpc_service_prealloc_one() and then marking it as being released before calling the cleanup function.
--- net/rxrpc/call_accept.c | 5 +++++ 1 file changed, 5 insertions(+)
net/rxrpc/call_accept.c +5 -0
@@ -151,6 +151,11 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx, id_in_use:write_unlock (&rx->call_lock); + call->abort_code =RX_CALL_DEAD ; + call->error = -EBADSLT ; + call->completion =RXRPC_CALL_LOCAL_ERROR ; + call->state =RXRPC_CALL_COMPLETE ; +set_bit (RXRPC_CALL_RELEASED , &call->flags);rxrpc_cleanup_call (call);_leave (" = -EBADSLT" );return -EBADSLT ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 813/1887 RDMA/hns: Fix double destruction of rsv_qp
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: wenglianfa <[email protected]>
[ Upstream commit c6957b95ecc5b63c5a4bb4ecc28af326cf8f6dc8 ]
rsv_qp may be double destroyed in error flow, first in free_mr_init(), and then in hns_roce_exit(). Fix it by moving the free_mr_init() call into hns_roce_v2_init().
list_del corruption, ffff589732eb9b50->next is LIST_POISON1 (dead000000000100)
WARNING: CPU: 8 PID: 1047115 at lib/list_debug.c:53 __list_del_entry_valid+0x148/0x240 ... Call trace: __list_del_entry_valid+0x148/0x240 hns_roce_qp_remove+0x4c/0x3f0 [hns_roce_hw_v2] hns_roce_v2_destroy_qp_common+0x1dc/0x5f4 [hns_roce_hw_v2] hns_roce_v2_destroy_qp+0x22c/0x46c [hns_roce_hw_v2] free_mr_exit+0x6c/0x120 [hns_roce_hw_v2] hns_roce_v2_exit+0x170/0x200 [hns_roce_hw_v2] hns_roce_exit+0x118/0x350 [hns_roce_hw_v2] __hns_roce_hw_v2_init_instance+0x1c8/0x304 [hns_roce_hw_v2] hns_roce_hw_v2_reset_notify_init+0x170/0x21c [hns_roce_hw_v2] hns_roce_hw_v2_reset_notify+0x6c/0x190 [hns_roce_hw_v2] hclge_notify_roce_client+0x6c/0x160 [hclge] hclge_reset_rebuild+0x150/0x5c0 [hclge] hclge_reset+0x10c/0x140 [hclge] hclge_reset_subtask+0x80/0x104 [hclge] hclge_reset_service_task+0x168/0x3ac [hclge] hclge_service_task+0x50/0x100 [hclge] process_one_work+0x250/0x9a0 worker_thread+0x324/0x990 kthread+0x190/0x210 ret_from_fork+0x10/0x18
--- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 25 +++++++++++----------- drivers/infiniband/hw/hns/hns_roce_main.c | 5 +++-- 2 files changed, 16 insertions(+), 14 deletions(-)
drivers/infiniband/hw/hns/hns_roce_hw_v2.c +13 -12
@@ -3013,14 +3013,22 @@ static int hns_roce_v2_init(struct hns_roce_dev *hr_dev) {int ret; +if (hr_dev->pci_dev->revision ==PCI_REVISION_ID_HIP08 ) { + ret =free_mr_init (hr_dev); +if (ret) { +dev_err (hr_dev->dev,"failed to init free mr!\n" ); +return ret; + } + } +/* The hns ROCEE requires the extdb info to be cleared before using */ ret =hns_roce_clear_extdb_list_info (hr_dev);if (ret) -return ret; + goto err_clear_extdb_failed; ret =get_hem_table (hr_dev);if (ret) -return ret; + goto err_clear_extdb_failed;if (hr_dev->is_vf)return 0 ;
@@ -3035,6 +3043,9 @@ static int hns_roce_v2_init(struct hns_roce_dev *hr_dev) err_llm_init_failed:put_hem_table (hr_dev); +err_clear_extdb_failed: +if (hr_dev->pci_dev->revision ==PCI_REVISION_ID_HIP08 ) +free_mr_exit (hr_dev);return ret; }
@@ -6939,21 +6950,11 @@ static int __hns_roce_hw_v2_init_instance(struct hnae3_handle *handle) goto error_failed_roce_init; } -if (hr_dev->pci_dev->revision ==PCI_REVISION_ID_HIP08 ) { - ret =free_mr_init (hr_dev); -if (ret) { -dev_err (hr_dev->dev,"failed to init free mr!\n" ); - goto error_failed_free_mr_init; - } - } handle->priv = hr_dev;return 0 ; -error_failed_free_mr_init: -hns_roce_exit (hr_dev); - error_failed_roce_init:kfree (hr_dev->priv);
drivers/infiniband/hw/hns/hns_roce_main.c +3 -2
@@ -835,6 +835,9 @@ static int hns_roce_setup_hca(struct hns_roce_dev *hr_dev)spin_lock_init (&hr_dev->sm_lock); +INIT_LIST_HEAD (&hr_dev->qp_list); +spin_lock_init (&hr_dev->qp_list_lock); +if (hr_dev->caps.flags &HNS_ROCE_CAP_FLAG_CQ_RECORD_DB || hr_dev->caps.flags &HNS_ROCE_CAP_FLAG_QP_RECORD_DB ) {INIT_LIST_HEAD (&hr_dev->pgdir_list);
@@ -979,8 +982,6 @@ int hns_roce_init(struct hns_roce_dev *hr_dev) } } -INIT_LIST_HEAD (&hr_dev->qp_list); -spin_lock_init (&hr_dev->qp_list_lock);INIT_LIST_HEAD (&hr_dev->dip_list);spin_lock_init (&hr_dev->dip_list_lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 814/1887 net/mlx5e: Provide intermediate pointer to access IPsec struct
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit 7bddb659bd0fc4e9022d3a3a2260540c01856e68 ]
Improve readability by providing direct pointer to struct mlx5e_ipsec.
Stable-dep-of: 6d19c44b5c6d ("net/mlx5e: Remove skb secpath if xfrm state is not found")
--- .../mellanox/mlx5/core/en_accel/ipsec_rxtx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c +6 -6
@@ -314,23 +314,23 @@ void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, struct mlx5_cqe64 *cqe) {u32 ipsec_meta_data =be32_to_cpu (cqe->ft_metadata); -struct mlx5e_priv *priv; +struct mlx5e_priv *priv =netdev_priv (netdev); +struct mlx5e_ipsec *ipsec = priv->ipsec;struct xfrm_offload *xo;struct xfrm_state *xs;struct sec_path *sp;u32 sa_handle; sa_handle =MLX5_IPSEC_METADATA_HANDLE (ipsec_meta_data); - priv =netdev_priv (netdev); sp =secpath_set (skb);if (unlikely (!sp)) { -atomic64_inc (&priv->ipsec->sw_stats.ipsec_rx_drop_sp_alloc); +atomic64_inc (&ipsec->sw_stats.ipsec_rx_drop_sp_alloc);return ; } - xs =mlx5e_ipsec_sadb_rx_lookup (priv->ipsec, sa_handle); + xs =mlx5e_ipsec_sadb_rx_lookup (ipsec, sa_handle);if (unlikely (!xs)) { -atomic64_inc (&priv->ipsec->sw_stats.ipsec_rx_drop_sadb_miss); +atomic64_inc (&ipsec->sw_stats.ipsec_rx_drop_sadb_miss);return ; }
@@ -351,6 +351,6 @@ void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, xo->status =CRYPTO_INVALID_PACKET_SYNTAX ;break ;default : -atomic64_inc (&priv->ipsec->sw_stats.ipsec_rx_drop_syndrome); +atomic64_inc (&ipsec->sw_stats.ipsec_rx_drop_syndrome); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 815/1887 net/mlx5e: Remove skb secpath if xfrm state is not found
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jianbo Liu <[email protected]>
[ Upstream commit 6d19c44b5c6dd72f9a357d0399604ec16a77de3c ]
Hardware returns a unique identifier for a decrypted packet's xfrm state, this state is looked up in an xarray. However, the state might have been freed by the time of this lookup.
Currently, if the state is not found, only a counter is incremented. The secpath (sp) extension on the skb is not removed, resulting in sp->len becoming 0.
Subsequently, functions like __xfrm_policy_check() attempt to access fields such as xfrm_input_state(skb)->xso.type (which dereferences sp->xvec[sp->len - 1]) without first validating sp->len. This leads to a crash when dereferencing an invalid state pointer.
This patch prevents the crash by explicitly removing the secpath extension from the skb if the xfrm state is not found after hardware decryption. This ensures downstream functions do not operate on a zero-length secpath.
BUG: unable to handle page fault for address: ffffffff000002c8 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 282e067 P4D 282e067 PUD 0 Oops: Oops: 0000 [#1] SMP CPU: 12 UID: 0 PID: 0 Comm: swapper/12 Not tainted 6.15.0-rc7_for_upstream_min_debug_2025_05_27_22_44 #1 NONE Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 RIP: 0010:__xfrm_policy_check+0x61a/0xa30 Code: b6 77 7f 83 e6 02 74 14 4d 8b af d8 00 00 00 41 0f b6 45 05 c1 e0 03 48 98 49 01 c5 41 8b 45 00 83 e8 01 48 98 49 8b 44 c5 10 <0f> b6 80 c8 02 00 00 83 e0 0c 3c 04 0f 84 0c 02 00 00 31 ff 80 fa RSP: 0018:ffff88885fb04918 EFLAGS: 00010297 RAX: ffffffff00000000 RBX: 0000000000000002 RCX: 0000000000000000 RDX: 0000000000000002 RSI: 0000000000000002 RDI: 0000000000000000 RBP: ffffffff8311af80 R08: 0000000000000020 R09: 00000000c2eda353 R10: ffff88812be2bbc8 R11: 000000001faab533 R12: ffff88885fb049c8 R13: ffff88812be2bbc8 R14: 0000000000000000 R15: ffff88811896ae00 FS: 0000000000000000(0000) GS:ffff8888dca82000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffff000002c8 CR3: 0000000243050002 CR4: 0000000000372eb0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <IRQ> ? try_to_wake_up+0x108/0x4c0 ? udp4_lib_lookup2+0xbe/0x150 ? udp_lib_lport_inuse+0x100/0x100 ? __udp4_lib_lookup+0x2b0/0x410 __xfrm_policy_check2.constprop.0+0x11e/0x130 udp_queue_rcv_one_skb+0x1d/0x530 udp_unicast_rcv_skb+0x76/0x90 __udp4_lib_rcv+0xa64/0xe90 ip_protocol_deliver_rcu+0x20/0x130 ip_local_deliver_finish+0x75/0xa0 ip_local_deliver+0xc1/0xd0 ? ip_protocol_deliver_rcu+0x130/0x130 ip_sublist_rcv+0x1f9/0x240 ? ip_rcv_finish_core+0x430/0x430 ip_list_rcv+0xfc/0x130 __netif_receive_skb_list_core+0x181/0x1e0 netif_receive_skb_list_internal+0x200/0x360 ? mlx5e_build_rx_skb+0x1bc/0xda0 [mlx5_core] gro_receive_skb+0xfd/0x210 mlx5e_handle_rx_cqe_mpwrq+0x141/0x280 [mlx5_core] mlx5e_poll_rx_cq+0xcc/0x8e0 [mlx5_core] ? mlx5e_handle_rx_dim+0x91/0xd0 [mlx5_core] mlx5e_napi_poll+0x114/0xab0 [mlx5_core] __napi_poll+0x25/0x170 net_rx_action+0x32d/0x3a0 ? mlx5_eq_comp_int+0x8d/0x280 [mlx5_core] ? notifier_call_chain+0x33/0xa0 handle_softirqs+0xda/0x250 irq_exit_rcu+0x6d/0xc0 common_interrupt+0x81/0xa0 </IRQ>
--- drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c +4 -0
@@ -331,6 +331,10 @@ void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, xs =mlx5e_ipsec_sadb_rx_lookup (ipsec, sa_handle);if (unlikely (!xs)) {atomic64_inc (&ipsec->sw_stats.ipsec_rx_drop_sadb_miss); +/* Clear secpath to prevent invalid dereference +* in downstream XFRM policy checks. +*/ +secpath_reset (skb);return ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 816/1887 xen: fix UAF in dmabuf_exp_from_pages()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit 532c8b51b3a8676cbf533a291f8156774f30ea87 ]
[dma_buf_fd() fixes; no preferences regarding the tree it goes through - up to xen folks]
As soon as we'd inserted a file reference into descriptor table, another thread could close it. That's fine for the case when all we are doing is returning that descriptor to userland (it's a race, but it's a userland race and there's nothing the kernel can do about it). However, if we follow fd_install() with any kind of access to objects that would be destroyed on close (be it the struct file itself or anything destroyed by its ->release()), we have a UAF.
dma_buf_fd() is a combination of reserving a descriptor and fd_install(). gntdev dmabuf_exp_from_pages() calls it and then proceeds to access the objects destroyed on close - starting with gntdev_dmabuf itself.
Fix that by doing reserving descriptor before anything else and do fd_install() only when everything had been set up.
Message-ID: <20250712050916.GY1880847@ZenIV>
--- drivers/xen/gntdev-dmabuf.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-)
drivers/xen/gntdev-dmabuf.c +13 -18
@@ -357,8 +357,12 @@ struct gntdev_dmabuf_export_args {static int dmabuf_exp_from_pages (struct gntdev_dmabuf_export_args *args) {DEFINE_DMA_BUF_EXPORT_INFO (exp_info); -struct gntdev_dmabuf *gntdev_dmabuf; -int ret; + struct gntdev_dmabuf *gntdev_dmabuf __free(kfree) = NULL; +CLASS (get_unused_fd, ret)(O_CLOEXEC ); +int fd; + +if (ret <0 ) +return ret; gntdev_dmabuf =kzalloc (sizeof (*gntdev_dmabuf),GFP_KERNEL );if (!gntdev_dmabuf)
@@ -383,32 +387,23 @@ static int dmabuf_exp_from_pages(struct gntdev_dmabuf_export_args *args) exp_info.priv = gntdev_dmabuf; gntdev_dmabuf->dmabuf =dma_buf_export (&exp_info); -if (IS_ERR (gntdev_dmabuf->dmabuf)) { - ret =PTR_ERR (gntdev_dmabuf->dmabuf); - gntdev_dmabuf->dmabuf =NULL ; - goto fail; - } - - ret =dma_buf_fd (gntdev_dmabuf->dmabuf,O_CLOEXEC ); -if (ret <0 ) - goto fail; +if (IS_ERR (gntdev_dmabuf->dmabuf)) +return PTR_ERR (gntdev_dmabuf->dmabuf); gntdev_dmabuf->fd = ret; args->fd = ret;pr_debug ("Exporting DMA buffer with fd %d\n" , ret); +get_file (gntdev_dmabuf->priv->filp);mutex_lock (&args->dmabuf_priv->lock);list_add (&gntdev_dmabuf->next, &args->dmabuf_priv->exp_list);mutex_unlock (&args->dmabuf_priv->lock); -get_file (gntdev_dmabuf->priv->filp); -return 0 ; -fail: -if (gntdev_dmabuf->dmabuf) -dma_buf_put (gntdev_dmabuf->dmabuf); -kfree (gntdev_dmabuf); -return ret; + fd = ret; + ret = -EBADF ; +fd_install (fd,no_free_ptr (gntdev_dmabuf)->dmabuf->file); +return 0 ; } static struct gntdev_grant_map *
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 817/1887 drm/rockchip: vop2: fail cleanly if missing a primary plane for a video-port
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Stuebner <[email protected]>
[ Upstream commit f9f68bf1d0efeadb6c427c9dbb30f307a7def19b ]
Each window of a vop2 is usable by a specific set of video ports, so while binding the vop2, we look through the list of available windows trying to find one designated as primary-plane and usable by that specific port.
The code later wants to use drm_crtc_init_with_planes with that found primary plane, but nothing has checked so far if a primary plane was actually found.
For whatever reason, the rk3576 vp2 does not have a usable primary window (if vp0 is also in use) which brought the issue to light and ended in a null-pointer dereference further down.
As we expect a primary-plane to exist for a video-port, add a check at the end of the window-iteration and fail probing if none was found.
--- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +4 -0
@@ -2409,6 +2409,10 @@ static int vop2_create_crtc(struct vop2 *vop2)if (!vp->crtc.port)continue ; +if (!vp->primary_plane) +return dev_err_probe (drm->dev, -ENOENT , +"no primary plane for vp %d\n" , i); + plane = &vp->primary_plane->base; ret = drm_crtc_init_with_planes(drm, &vp->crtc, plane, NULL,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 818/1887 fs/ntfs3: cancle set bad inode after removing name fails
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <[email protected]>
[ Upstream commit d99208b91933fd2a58ed9ed321af07dacd06ddc3 ]
The reproducer uses a file0 on a ntfs3 file system with a corrupted i_link. When renaming, the file0's inode is marked as a bad inode because the file name cannot be deleted.
The underlying bug is that make_bad_inode() is called on a live inode. In some cases it's "icache lookup finds a normal inode, d_splice_alias() is called to attach it to dentry, while another thread decides to call make_bad_inode() on it - that would evict it from icache, but we'd already found it there earlier".
In some it's outright "we have an inode attached to dentry - that's how we got it in the first place; let's call make_bad_inode() on it just for shits and giggles".
--- fs/ntfs3/frecord.c | 7 +++---- fs/ntfs3/namei.c | 10 +++------- fs/ntfs3/ntfs_fs.h | 3 +-- 3 files changed, 7 insertions(+), 13 deletions(-)
fs/ntfs3/frecord.c +3 -4
@@ -3170,8 +3170,7 @@ int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni,* ni_rename - Remove one name and insert new name. */ int ni_rename (struct ntfs_inode *dir_ni,struct ntfs_inode *new_dir_ni, -struct ntfs_inode *ni,struct NTFS_DE *de,struct NTFS_DE *new_de, -bool *is_bad) +struct ntfs_inode *ni,struct NTFS_DE *de,struct NTFS_DE *new_de) {int err;struct NTFS_DE *de2 =NULL ;
@@ -3194,8 +3193,8 @@ int ni_rename(struct ntfs_inode *dir_ni, struct ntfs_inode *new_dir_ni, err =ni_add_name (new_dir_ni, ni, new_de);if (!err) { err =ni_remove_name (dir_ni, ni, de, &de2, &undo); -if (err &&ni_remove_name (new_dir_ni, ni, new_de, &de2, &undo)) - *is_bad = true; +WARN_ON (err &&ni_remove_name (new_dir_ni, ni, new_de, &de2, + &undo)); }/*
fs/ntfs3/namei.c +3 -7
@@ -250,7 +250,7 @@ static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *dir,struct ntfs_inode *ni =ntfs_i (inode);struct inode *new_inode =d_inode (new_dentry);struct NTFS_DE *de, *new_de; -bool is_same, is_bad; +bool is_same;/* * de - memory of PATH_MAX bytes: * [0-1024) - original name (dentry->d_name)
@@ -314,12 +314,8 @@ static int ntfs_rename(struct user_namespace *mnt_userns, struct inode *dir,ni_lock_dir (dir_ni);ni_lock (ni); - is_bad = false; - err =ni_rename (dir_ni, new_dir_ni, ni, de, new_de, &is_bad); -if (is_bad) { -/* Restore after failed rename failed too. */ -_ntfs_bad_inode (inode); - }else if (!err) { + err =ni_rename (dir_ni, new_dir_ni, ni, de, new_de); +if (!err) { inode->i_ctime = dir->i_ctime = dir->i_mtime =current_time (dir);mark_inode_dirty (inode);
fs/ntfs3/ntfs_fs.h +1 -2
@@ -573,8 +573,7 @@ int ni_add_name(struct ntfs_inode *dir_ni, struct ntfs_inode *ni, struct NTFS_DE *de);int ni_rename (struct ntfs_inode *dir_ni,struct ntfs_inode *new_dir_ni, -struct ntfs_inode *ni,struct NTFS_DE *de,struct NTFS_DE *new_de, -bool *is_bad); +struct ntfs_inode *ni,struct NTFS_DE *de,struct NTFS_DE *new_de);bool ni_is_dirty (struct inode *inode);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 819/1887 Use strings in da monitors tracepoints
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriele Monaco <[email protected]>
[ Upstream commit 7f904ff6e58d398c4336f3c19c42b338324451f7 ]
Using DA monitors tracepoints with KASAN enabled triggers the following warning:
BUG: KASAN: global-out-of-bounds in do_trace_event_raw_event_event_da_monitor+0xd6/0x1a0 Read of size 32 at addr ffffffffaada8980 by task ... Call Trace: <TASK> [...] do_trace_event_raw_event_event_da_monitor+0xd6/0x1a0 ? __pfx_do_trace_event_raw_event_event_da_monitor+0x10/0x10 ? trace_event_sncid+0x83/0x200 trace_event_sncid+0x163/0x200 [...] The buggy address belongs to the variable: automaton_snep+0x4e0/0x5e0
This is caused by the tracepoints reading 32 bytes __array instead of __string from the automata definition. Such strings are literals and reading 32 bytes ends up in out of bound memory accesses (e.g. the next automaton's data in this case).
The error is harmless as, while printing the string, we stop at the null terminator, but it should still be fixed.
Use the __string facilities while defining the tracepoints to avoid reading out of bound memory.
--- include/trace/events/rv.h | 76 +++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-)
include/trace/events/rv.h +38 -38
@@ -16,23 +16,23 @@ DECLARE_EVENT_CLASS(event_da_monitor, TP_ARGS(state, event, next_state, final_state),TP_STRUCT__entry ( -__array (char ,state ,MAX_DA_NAME_LEN ) -__array ( char, event,MAX_DA_NAME_LEN ) -__array ( char, next_state,MAX_DA_NAME_LEN ) -__field ( bool, final_state ) +__string (state ,state ) +__string ( event, event ) +__string ( next_state, next_state ) +__field ( bool, final_state ) ),TP_fast_assign ( - memcpy(__entry->state, state, MAX_DA_NAME_LEN); -memcpy (__entry->event, event,MAX_DA_NAME_LEN ); -memcpy (__entry->next_state, next_state,MAX_DA_NAME_LEN ); - __entry->final_state = final_state; + __assign_str(state, state); +__assign_str (event, event); +__assign_str (next_state, next_state); + __entry->final_state = final_state; ),TP_printk ("%s x %s -> %s %s" , - __entry->state, - __entry->event, - __entry->next_state, +__get_str (state), +__get_str (event), +__get_str (next_state), __entry->final_state ?"(final)" :"" ) );
@@ -43,18 +43,18 @@ DECLARE_EVENT_CLASS(error_da_monitor,TP_ARGS (state, event),TP_STRUCT__entry ( - __array( char, state, MAX_DA_NAME_LEN ) -__array ( char, event,MAX_DA_NAME_LEN ) + __string( state, state ) +__string ( event, event ) ),TP_fast_assign ( - memcpy(__entry->state, state, MAX_DA_NAME_LEN); -memcpy (__entry->event, event,MAX_DA_NAME_LEN ); + __assign_str(state, state); +__assign_str (event, event); ),TP_printk ("event %s not expected in the state %s" , - __entry->event, - __entry->state) +__get_str (event), +__get_str (state)) );#ifdef CONFIG_RV_MON_WIP
@@ -76,26 +76,26 @@ DECLARE_EVENT_CLASS(event_da_monitor_id, TP_ARGS(id, state, event, next_state, final_state),TP_STRUCT__entry ( -__field (int ,id ) -__array ( char, state,MAX_DA_NAME_LEN ) -__array ( char, event,MAX_DA_NAME_LEN ) -__array ( char, next_state,MAX_DA_NAME_LEN ) -__field ( bool, final_state ) +__field (int ,id ) +__string ( state, state ) +__string ( event, event ) +__string ( next_state, next_state ) +__field ( bool, final_state ) ),TP_fast_assign ( - memcpy(__entry->state, state, MAX_DA_NAME_LEN); -memcpy (__entry->event, event,MAX_DA_NAME_LEN ); -memcpy (__entry->next_state, next_state,MAX_DA_NAME_LEN ); - __entry->id = id; - __entry->final_state = final_state; + __assign_str(state, state); +__assign_str (event, event); +__assign_str (next_state, next_state); + __entry->id = id; + __entry->final_state = final_state; ),TP_printk ("%d: %s x %s -> %s %s" , __entry->id, - __entry->state, - __entry->event, - __entry->next_state, +__get_str (state), +__get_str (event), +__get_str (next_state), __entry->final_state ?"(final)" :"" ) );
@@ -106,21 +106,21 @@ DECLARE_EVENT_CLASS(error_da_monitor_id, TP_ARGS(id, state, event),TP_STRUCT__entry ( -__field (int ,id ) -__array ( char, state,MAX_DA_NAME_LEN ) -__array ( char, event,MAX_DA_NAME_LEN ) +__field (int ,id ) +__string ( state, state ) +__string ( event, event ) ),TP_fast_assign ( - memcpy(__entry->state, state, MAX_DA_NAME_LEN); -memcpy (__entry->event, event,MAX_DA_NAME_LEN ); - __entry->id = id; + __assign_str(state, state); +__assign_str (event, event); + __entry->id = id; ),TP_printk ("%d: event %s not expected in the state %s" , __entry->id, - __entry->event, - __entry->state) +__get_str (event), +__get_str (state)) );#ifdef CONFIG_RV_MON_WWNR
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 820/1887 exfat: remove unnecessary arguments from exfat_find_dir_entry()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuezhang Mo <[email protected]>
[ Upstream commit 72880cb5f157514d797d5f6ab3184bbde671a18a ]
This commit removes argument 'num_entries' and 'type' from exfat_find_dir_entry().
Code refinement, no functional changes.
Stable-dep-of: 99f9a97dce39 ("exfat: add cluster chain loop check for dir")
--- fs/exfat/dir.c | 12 +++++++----- fs/exfat/exfat_fs.h | 3 +-- fs/exfat/namei.c | 10 ++-------- 3 files changed, 10 insertions(+), 15 deletions(-)
fs/exfat/dir.c +7 -5
@@ -931,7 +931,7 @@ enum {*/ int exfat_find_dir_entry (struct super_block *sb,struct exfat_inode_info *ei,struct exfat_chain *p_dir,struct exfat_uni_name *p_uniname, -int num_entries,unsigned int type,struct exfat_hint *hint_opt) +struct exfat_hint *hint_opt) {int i, rewind =0 , dentry =0 , end_eidx =0 , num_ext =0 , len;int order, step, name_len =0 ;
@@ -942,6 +942,10 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,struct exfat_hint *hint_stat = &ei->hint_stat;struct exfat_hint_femp candi_empty;struct exfat_sb_info *sbi =EXFAT_SB (sb); +int num_entries =exfat_calc_num_entries (p_uniname); + +if (num_entries <0 ) +return num_entries; dentries_per_clu = sbi->dentries_per_clu;
@@ -1010,10 +1014,8 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, step =DIRENT_STEP_FILE ; hint_opt->clu = clu.dir; hint_opt->eidx = i; -if (type ==TYPE_ALL || type == entry_type) { - num_ext = ep->dentry.file.num_ext; - step =DIRENT_STEP_STRM ; - } + num_ext = ep->dentry.file.num_ext; + step =DIRENT_STEP_STRM ;brelse (bh);continue ; }
fs/exfat/exfat_fs.h +1 -2
@@ -62,7 +62,6 @@ enum {#define TYPE_PADDING 0x0402#define TYPE_ACLTAB 0x0403#define TYPE_BENIGN_SEC 0x0800 -#define TYPE_ALL 0x0FFF#define MAX_CHARSET_SIZE 6/* max size of multi-byte character */ #define MAX_NAME_LENGTH 255/* max len of file name excluding NULL */
@@ -467,7 +466,7 @@ void exfat_update_dir_chksum_with_entry_set(struct exfat_entry_set_cache *es);int exfat_calc_num_entries (struct exfat_uni_name *p_uniname);int exfat_find_dir_entry (struct super_block *sb,struct exfat_inode_info *ei,struct exfat_chain *p_dir,struct exfat_uni_name *p_uniname, -int num_entries,unsigned int type,struct exfat_hint *hint_opt); +struct exfat_hint *hint_opt);int exfat_alloc_new_dir (struct inode *inode,struct exfat_chain *clu);struct exfat_dentry *exfat_get_dentry (struct super_block *sb,struct exfat_chain *p_dir,int entry,struct buffer_head **bh);
fs/exfat/namei.c +2 -8
@@ -600,7 +600,7 @@ static int exfat_create(struct user_namespace *mnt_userns, struct inode *dir,static int exfat_find (struct inode *dir,struct qstr *qname,struct exfat_dir_entry *info) { -int ret, dentry, num_entries, count; +int ret, dentry, count;struct exfat_chain cdir;struct exfat_uni_name uni_name;struct super_block *sb = dir->i_sb;
@@ -619,10 +619,6 @@ static int exfat_find(struct inode *dir, struct qstr *qname,if (ret)return ret; - num_entries =exfat_calc_num_entries (&uni_name); -if (num_entries <0 ) -return num_entries; -/* check the validation of hint_stat and initialize it if required */ if (ei->version != (inode_peek_iversion_raw (dir) &0xffffffff )) { ei->hint_stat.clu = cdir.dir;
@@ -632,9 +628,7 @@ static int exfat_find(struct inode *dir, struct qstr *qname, }/* search the file name for directories */ - dentry =exfat_find_dir_entry (sb, ei, &cdir, &uni_name, - num_entries,TYPE_ALL , &hint_opt); - + dentry =exfat_find_dir_entry (sb, ei, &cdir, &uni_name, &hint_opt);if (dentry <0 )return dentry;/* -error value */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 821/1887 exfat: add cluster chain loop check for dir
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuezhang Mo <[email protected]>
[ Upstream commit 99f9a97dce39ad413c39b92c90393bbd6778f3fd ]
An infinite loop may occur if the following conditions occur due to file system corruption.
(1) Condition for exfat_count_dir_entries() to loop infinitely.
- The cluster chain includes a loop.
- There is no UNUSED entry in the cluster chain.
(2) Condition for exfat_create_upcase_table() to loop infinitely.
- The cluster chain of the root directory includes a loop.
- There are no UNUSED entry and up-case table entry in the cluster chain of the root directory.
(3) Condition for exfat_load_bitmap() to loop infinitely.
- The cluster chain of the root directory includes a loop.
- There are no UNUSED entry and bitmap entry in the cluster chain of the root directory.
(4) Condition for exfat_find_dir_entry() to loop infinitely.
- The cluster chain includes a loop.
- The unused directory entries were exhausted by some operation.
(5) Condition for exfat_check_dir_empty() to loop infinitely.
- The cluster chain includes a loop.
- The unused directory entries were exhausted by some operation.
- All files and sub-directories under the directory are deleted.
This commit adds checks to break the above infinite loop.
--- fs/exfat/dir.c | 12 ++++++++++++ fs/exfat/fatent.c | 10 ++++++++++ fs/exfat/namei.c | 5 +++++ fs/exfat/super.c | 32 +++++++++++++++++++++----------- 4 files changed, 48 insertions(+), 11 deletions(-)
fs/exfat/dir.c +12 -0
@@ -943,6 +943,7 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei,struct exfat_hint_femp candi_empty;struct exfat_sb_info *sbi =EXFAT_SB (sb);int num_entries =exfat_calc_num_entries (p_uniname); +unsigned int clu_count =0 ;if (num_entries <0 )return num_entries;
@@ -1100,6 +1101,10 @@ int exfat_find_dir_entry(struct super_block *sb, struct exfat_inode_info *ei, }else {if (exfat_get_next_cluster (sb, &clu.dir))return -EIO ; + +/* break if the cluster chain includes a loop */ +if (unlikely (++clu_count >EXFAT_DATA_CLUSTER_COUNT (sbi))) + goto not_found; } }
@@ -1178,6 +1183,7 @@ int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir)int i, count =0 ;int dentries_per_clu;unsigned int entry_type; +unsigned int clu_count =0 ;struct exfat_chain clu;struct exfat_dentry *ep;struct exfat_sb_info *sbi =EXFAT_SB (sb);
@@ -1210,6 +1216,12 @@ int exfat_count_dir_entries(struct super_block *sb, struct exfat_chain *p_dir) }else {if (exfat_get_next_cluster (sb, &(clu.dir)))return -EIO ; + +if (unlikely (++clu_count > sbi->used_clusters)) { +exfat_fs_error (sb,"FAT or bitmap is corrupted" ); +return -EIO ; + } + } }
fs/exfat/fatent.c +10 -0
@@ -470,5 +470,15 @@ int exfat_count_num_clusters(struct super_block *sb, } *ret_count = count; + +/* +* since exfat_count_used_clusters() is not called, sbi->used_clusters +* cannot be used here. +*/ +if (unlikely (i == sbi->num_clusters && clu !=EXFAT_EOF_CLUSTER )) { +exfat_fs_error (sb,"The cluster chain has a loop" ); +return -EIO ; + } +return 0 ; }
fs/exfat/namei.c +5 -0
@@ -892,6 +892,7 @@ static int exfat_check_dir_empty(struct super_block *sb, {int i, dentries_per_clu;unsigned int type; +unsigned int clu_count =0 ;struct exfat_chain clu;struct exfat_dentry *ep;struct exfat_sb_info *sbi =EXFAT_SB (sb);
@@ -928,6 +929,10 @@ static int exfat_check_dir_empty(struct super_block *sb, }else {if (exfat_get_next_cluster (sb, &(clu.dir)))return -EIO ; + +/* break if the cluster chain includes a loop */ +if (unlikely (++clu_count >EXFAT_DATA_CLUSTER_COUNT (sbi))) +break ; } }
fs/exfat/super.c +21 -11
@@ -336,13 +336,12 @@ static void exfat_hash_init(struct super_block *sb)INIT_HLIST_HEAD (&sbi->inode_hashtable[i]); } -static int exfat_read_root (struct inode *inode) +static int exfat_read_root (struct inode *inode,struct exfat_chain *root_clu) {struct super_block *sb = inode->i_sb;struct exfat_sb_info *sbi =EXFAT_SB (sb);struct exfat_inode_info *ei =EXFAT_I (inode); -struct exfat_chain cdir; -int num_subdirs, num_clu =0 ; +int num_subdirs;exfat_chain_set (&ei->dir, sbi->root_dir,0 ,ALLOC_FAT_CHAIN ); ei->entry =-1 ;
@@ -355,12 +354,9 @@ static int exfat_read_root(struct inode *inode) ei->hint_stat.clu = sbi->root_dir; ei->hint_femp.eidx =EXFAT_HINT_NONE ; -exfat_chain_set (&cdir, sbi->root_dir,0 ,ALLOC_FAT_CHAIN ); -if (exfat_count_num_clusters (sb, &cdir, &num_clu)) -return -EIO ; -i_size_write (inode, num_clu << sbi->cluster_size_bits); +i_size_write (inode,EXFAT_CLU_TO_B (root_clu->size, sbi)); - num_subdirs =exfat_count_dir_entries (sb, &cdir); + num_subdirs =exfat_count_dir_entries (sb, root_clu);if (num_subdirs <0 )return -EIO ;set_nlink (inode, num_subdirs +EXFAT_MIN_SUBDIR );
@@ -580,7 +576,8 @@ static int exfat_verify_boot_region(struct super_block *sb) }/* mount the file system volume */ -static int __exfat_fill_super (struct super_block *sb) +static int __exfat_fill_super (struct super_block *sb, +struct exfat_chain *root_clu) {int ret;struct exfat_sb_info *sbi =EXFAT_SB (sb);
@@ -597,6 +594,18 @@ static int __exfat_fill_super(struct super_block *sb) goto free_bh; } +/* +* Call exfat_count_num_cluster() before searching for up-case and +* bitmap directory entries to avoid infinite loop if they are missing +* and the cluster chain includes a loop. +*/ +exfat_chain_set (root_clu, sbi->root_dir,0 ,ALLOC_FAT_CHAIN ); + ret =exfat_count_num_clusters (sb, root_clu, &root_clu->size); +if (ret) { +exfat_err (sb,"failed to count the number of clusters in root" ); + goto free_bh; + } + ret =exfat_create_upcase_table (sb);if (ret) {exfat_err (sb,"failed to load upcase table" );
@@ -631,6 +640,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc)struct exfat_sb_info *sbi = sb->s_fs_info;struct exfat_mount_options *opts = &sbi->options;struct inode *root_inode; +struct exfat_chain root_clu;int err;if (opts->allow_utime == (unsigned short )-1 )
@@ -649,7 +659,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_time_min =EXFAT_MIN_TIMESTAMP_SECS ; sb->s_time_max =EXFAT_MAX_TIMESTAMP_SECS ; - err =__exfat_fill_super (sb); + err =__exfat_fill_super (sb, &root_clu);if (err) {exfat_err (sb,"failed to recognize exfat type" ); goto check_nls_io;
@@ -684,7 +694,7 @@ static int exfat_fill_super(struct super_block *sb, struct fs_context *fc) root_inode->i_ino =EXFAT_ROOT_INO ;inode_set_iversion (root_inode,1 ); - err =exfat_read_root (root_inode); + err =exfat_read_root (root_inode, &root_clu);if (err) {exfat_err (sb,"failed to initialize root inode" ); goto put_inode;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 822/1887 drm/amd/pm: fix null pointer access
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Umio Yasuno <[email protected]>
[ Upstream commit d524d40e3a6152a3ea1125af729f8cd8ca65efde ]
Writing a string without delimiters (' ', '\n', '\0') to the under gpu_od/fan_ctrl sysfs or pp_power_profile_mode for the CUSTOM profile will result in a null pointer dereference.
--- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/amd/pm/amdgpu_pm.c +2 -0
@@ -1436,6 +1436,8 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev,if (ret)return -EINVAL ; parameter_size++; +if (!tmp_str) +break ;while (isspace (*tmp_str)) tmp_str++; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 823/1887 loop: Avoid updating block size under exclusive owner
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
[ Upstream commit 7e49538288e523427beedd26993d446afef1a6fb ]
Syzbot came up with a reproducer where a loop device block size is changed underneath a mounted filesystem. This causes a mismatch between the block device block size and the block size stored in the superblock causing confusion in various places such as fs/buffer.c. The particular issue triggered by syzbot was a warning in __getblk_slow() due to requested buffer size not matching block device block size.
Fix the problem by getting exclusive hold of the loop device to change its block size. This fails if somebody (such as filesystem) has already an exclusive ownership of the block device and thus prevents modifying the loop device under some exclusive owner which doesn't expect it.
--- drivers/block/loop.c | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-)
drivers/block/loop.c +31 -9
@@ -1472,19 +1472,36 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg)return error; } -static int loop_set_block_size (struct loop_device *lo,unsigned long arg) +static int loop_set_block_size (struct loop_device *lo,fmode_t mode, +struct block_device *bdev,unsigned long arg) {int err =0 ; -if (lo->lo_state != Lo_bound) -return -ENXIO ; +/* +* If we don't hold exclusive handle for the device, upgrade to it +* here to avoid changing device under exclusive owner. +*/ +if (!(mode &FMODE_EXCL )) { + err =bd_prepare_to_claim (bdev, loop_set_block_size); +if (err) +return err; + } + + err =mutex_lock_killable (&lo->lo_mutex); +if (err) + goto abort_claim; + +if (lo->lo_state != Lo_bound) { + err = -ENXIO ; + goto unlock; + } err =blk_validate_block_size (arg);if (err) -return err; + goto unlock;if (lo->lo_queue->limits.logical_block_size == arg) -return 0 ; + goto unlock;sync_blockdev (lo->lo_device);invalidate_bdev (lo->lo_device);
@@ -1496,6 +1513,11 @@ static int loop_set_block_size(struct loop_device *lo, unsigned long arg)loop_update_dio (lo);blk_mq_unfreeze_queue (lo->lo_queue); +unlock: +mutex_unlock (&lo->lo_mutex); +abort_claim: +if (!(mode &FMODE_EXCL )) +bd_abort_claiming (bdev, loop_set_block_size);return err; }
@@ -1514,9 +1536,6 @@ static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd,case LOOP_SET_DIRECT_IO : err =loop_set_dio (lo, arg);break ; -case LOOP_SET_BLOCK_SIZE : - err =loop_set_block_size (lo, arg); -break ;default : err = -EINVAL ; }
@@ -1573,9 +1592,12 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,break ;case LOOP_GET_STATUS64 :return loop_get_status64 (lo, argp); +case LOOP_SET_BLOCK_SIZE : +if (!(mode &FMODE_WRITE ) && !capable (CAP_SYS_ADMIN )) +return -EPERM ; +return loop_set_block_size (lo, mode, bdev, arg);case LOOP_SET_CAPACITY :case LOOP_SET_DIRECT_IO : -case LOOP_SET_BLOCK_SIZE :if (!(mode &FMODE_WRITE ) && !capable (CAP_SYS_ADMIN ))return -EPERM ; fallthrough;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 824/1887 pagemap: add filemap_grab_folio()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vishal Moola (Oracle) <[email protected]>
[ Upstream commit ee7a5906ff08e435ed95ec9fe7c7eed2c11015d2 ]
Patch series "Convert to filemap_get_folios_tag()", v5.
This patch series replaces find_get_pages_range_tag() with filemap_get_folios_tag(). This also allows the removal of multiple calls to compound_head() throughout.
It also makes a good chunk of the straightforward conversions to folios, and takes the opportunity to introduce a function that grabs a folio from the pagecache.
This patch (of 23):
Add function filemap_grab_folio() to grab a folio from the page cache. This function is meant to serve as a folio replacement for grab_cache_page, and is used to facilitate the removal of find_get_pages_range_tag().
Stable-dep-of: 736a0516a162 ("hfs: fix general protection fault in hfs_find_init()")
--- include/linux/pagemap.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
include/linux/pagemap.h +20 -0
@@ -610,6 +610,26 @@ static inline struct folio *filemap_lock_folio(struct address_space *mapping,return __filemap_get_folio (mapping, index,FGP_LOCK ,0 ); } +/** +* filemap_grab_folio - grab a folio from the page cache +* @mapping: The address space to search +* @index: The page index +* +* Looks up the page cache entry at @mapping & @index. If no folio is found, +* a new folio is created. The folio is locked, marked as accessed, and +* returned. +* +* Return: A found or created folio. NULL if no folio is found and failed to +* create a folio. +*/ +static inline struct folio *filemap_grab_folio (struct address_space *mapping, +pgoff_t index) +{ +return __filemap_get_folio (mapping, index, +FGP_LOCK |FGP_ACCESSED |FGP_CREAT , +mapping_gfp_mask (mapping)); +} +/** * find_get_page - find and get a page reference * @mapping: the address_space to search
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 825/1887 highmem: add memcpy_to_folio() and memcpy_from_folio()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
[ Upstream commit b23d03ef7af567929bcd3fca7eea6f4f347387d3 ]
Patch series "More filesystem folio conversions for 6.6".
Remove the only spots in affs which actually use a struct page; there are a few places where one is mentioned, but it's part of the interface.
The rest of this is removing the remaining calls to set_bh_page(), and then removing the function before any new users show up.
This patch (of 7):
These are the folio equivalent of memcpy_to_page() and memcpy_from_page().
Stable-dep-of: 736a0516a162 ("hfs: fix general protection fault in hfs_find_init()")
--- include/linux/highmem.h | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
include/linux/highmem.h +44 -0
@@ -415,6 +415,50 @@ static inline void memzero_page(struct page *page, size_t offset, size_t len)kunmap_local (addr); } +static inline void memcpy_from_folio (char *to,struct folio *folio, +size_t offset,size_t len) +{ +VM_BUG_ON (offset + len >folio_size (folio)); + +do { +const char *from =kmap_local_folio (folio, offset); +size_t chunk = len; + +if (folio_test_highmem (folio) && + chunk >PAGE_SIZE -offset_in_page (offset)) + chunk =PAGE_SIZE -offset_in_page (offset); +memcpy (to, from, chunk); +kunmap_local (from); + + from += chunk; + offset += chunk; + len -= chunk; + }while (len >0 ); +} + +static inline void memcpy_to_folio (struct folio *folio,size_t offset, +const char *from,size_t len) +{ +VM_BUG_ON (offset + len >folio_size (folio)); + +do { +char *to =kmap_local_folio (folio, offset); +size_t chunk = len; + +if (folio_test_highmem (folio) && + chunk >PAGE_SIZE -offset_in_page (offset)) + chunk =PAGE_SIZE -offset_in_page (offset); +memcpy (to, from, chunk); +kunmap_local (to); + + from += chunk; + offset += chunk; + len -= chunk; + }while (len >0 ); + +flush_dcache_folio (folio); +} +/** * folio_zero_segments() - Zero two byte ranges in a folio. * @folio: The folio to write to.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 826/1887 hfs: fix general protection fault in hfs_find_init()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Viacheslav Dubeyko <[email protected]>
[ Upstream commit 736a0516a16268995f4898eded49bfef077af709 ]
The hfs_find_init() method can trigger the crash
if tree pointer is NULL:
[ 45.746290][ T9787] Oops: general protection fault, probably for non-canonical address 0xdffffc0000000008: 0000 [#1] SMP KAI [ 45.747287][ T9787] KASAN: null-ptr-deref in range [0x0000000000000040-0x0000000000000047] [ 45.748716][ T9787] CPU: 2 UID: 0 PID: 9787 Comm: repro Not tainted 6.16.0-rc3 #10 PREEMPT(full) [ 45.750250][ T9787] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 45.751983][ T9787] RIP: 0010:hfs_find_init+0x86/0x230 [ 45.752834][ T9787] Code: c1 ea 03 80 3c 02 00 0f 85 9a 01 00 00 4c 8d 6b 40 48 c7 45 18 00 00 00 00 48 b8 00 00 00 00 00 fc [ 45.755574][ T9787] RSP: 0018:ffffc90015157668 EFLAGS: 00010202 [ 45.756432][ T9787] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff819a4d09 [ 45.757457][ T9787] RDX: 0000000000000008 RSI: ffffffff819acd3a RDI: ffffc900151576e8 [ 45.758282][ T9787] RBP: ffffc900151576d0 R08: 0000000000000005 R09: 0000000000000000 [ 45.758943][ T9787] R10: 0000000080000000 R11: 0000000000000001 R12: 0000000000000004 [ 45.759619][ T9787] R13: 0000000000000040 R14: ffff88802c50814a R15: 0000000000000000 [ 45.760293][ T9787] FS: 00007ffb72734540(0000) GS:ffff8880cec64000(0000) knlGS:0000000000000000 [ 45.761050][ T9787] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 45.761606][ T9787] CR2: 00007f9bd8225000 CR3: 000000010979a000 CR4: 00000000000006f0 [ 45.762286][ T9787] Call Trace: [ 45.762570][ T9787] <TASK> [ 45.762824][ T9787] hfs_ext_read_extent+0x190/0x9d0 [ 45.763269][ T9787] ? submit_bio_noacct_nocheck+0x2dd/0xce0 [ 45.763766][ T9787] ? __pfx_hfs_ext_read_extent+0x10/0x10 [ 45.764250][ T9787] hfs_get_block+0x55f/0x830 [ 45.764646][ T9787] block_read_full_folio+0x36d/0x850 [ 45.765105][ T9787] ? __pfx_hfs_get_block+0x10/0x10 [ 45.765541][ T9787] ? const_folio_flags+0x5b/0x100 [ 45.765972][ T9787] ? __pfx_hfs_read_folio+0x10/0x10 [ 45.766415][ T9787] filemap_read_folio+0xbe/0x290 [ 45.766840][ T9787] ? __pfx_filemap_read_folio+0x10/0x10 [ 45.767325][ T9787] ? __filemap_get_folio+0x32b/0xbf0 [ 45.767780][ T9787] do_read_cache_folio+0x263/0x5c0 [ 45.768223][ T9787] ? __pfx_hfs_read_folio+0x10/0x10 [ 45.768666][ T9787] read_cache_page+0x5b/0x160 [ 45.769070][ T9787] hfs_btree_open+0x491/0x1740 [ 45.769481][ T9787] hfs_mdb_get+0x15e2/0x1fb0 [ 45.769877][ T9787] ? __pfx_hfs_mdb_get+0x10/0x10 [ 45.770316][ T9787] ? find_held_lock+0x2b/0x80 [ 45.770731][ T9787] ? lockdep_init_map_type+0x5c/0x280 [ 45.771200][ T9787] ? lockdep_init_map_type+0x5c/0x280 [ 45.771674][ T9787] hfs_fill_super+0x38e/0x720 [ 45.772092][ T9787] ? __pfx_hfs_fill_super+0x10/0x10 [ 45.772549][ T9787] ? snprintf+0xbe/0x100 [ 45.772931][ T9787] ? __pfx_snprintf+0x10/0x10 [ 45.773350][ T9787] ? do_raw_spin_lock+0x129/0x2b0 [ 45.773796][ T9787] ? find_held_lock+0x2b/0x80 [ 45.774215][ T9787] ? set_blocksize+0x40a/0x510 [ 45.774636][ T9787] ? sb_set_blocksize+0x176/0x1d0 [ 45.775087][ T9787] ? setup_bdev_super+0x369/0x730 [ 45.775533][ T9787] get_tree_bdev_flags+0x384/0x620 [ 45.775985][ T9787] ? __pfx_hfs_fill_super+0x10/0x10 [ 45.776453][ T9787] ? __pfx_get_tree_bdev_flags+0x10/0x10 [ 45.776950][ T9787] ? bpf_lsm_capable+0x9/0x10 [ 45.777365][ T9787] ? security_capable+0x80/0x260 [ 45.777803][ T9787] vfs_get_tree+0x8e/0x340 [ 45.778203][ T9787] path_mount+0x13de/0x2010 [ 45.778604][ T9787] ? kmem_cache_free+0x2b0/0x4c0 [ 45.779052][ T9787] ? __pfx_path_mount+0x10/0x10 [ 45.779480][ T9787] ? getname_flags.part.0+0x1c5/0x550 [ 45.779954][ T9787] ? putname+0x154/0x1a0 [ 45.780335][ T9787] __x64_sys_mount+0x27b/0x300 [ 45.780758][ T9787] ? __pfx___x64_sys_mount+0x10/0x10 [ 45.781232][ T9787] do_syscall_64+0xc9/0x480 [ 45.781631][ T9787] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 45.782149][ T9787] RIP: 0033:0x7ffb7265b6ca [ 45.782539][ T9787] Code: 48 8b 0d c9 17 0d 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 [ 45.784212][ T9787] RSP: 002b:00007ffc0c10cfb8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a5 [ 45.784935][ T9787] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007ffb7265b6ca [ 45.785626][ T9787] RDX: 0000200000000240 RSI: 0000200000000280 RDI: 00007ffc0c10d100 [ 45.786316][ T9787] RBP: 00007ffc0c10d190 R08: 00007ffc0c10d000 R09: 0000000000000000 [ 45.787011][ T9787] R10: 0000000000000048 R11: 0000000000000206 R12: 0000560246733250 [ 45.787697][ T9787] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 [ 45.788393][ T9787] </TASK> [ 45.788665][ T9787] Modules linked in: [ 45.789058][ T9787] ---[ end trace 0000000000000000 ]--- [ 45.789554][ T9787] RIP: 0010:hfs_find_init+0x86/0x230 [ 45.790028][ T9787] Code: c1 ea 03 80 3c 02 00 0f 85 9a 01 00 00 4c 8d 6b 40 48 c7 45 18 00 00 00 00 48 b8 00 00 00 00 00 fc [ 45.792364][ T9787] RSP: 0018:ffffc90015157668 EFLAGS: 00010202 [ 45.793155][ T9787] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff819a4d09 [ 45.794123][ T9787] RDX: 0000000000000008 RSI: ffffffff819acd3a RDI: ffffc900151576e8 [ 45.795105][ T9787] RBP: ffffc900151576d0 R08: 0000000000000005 R09: 0000000000000000 [ 45.796135][ T9787] R10: 0000000080000000 R11: 0000000000000001 R12: 0000000000000004 [ 45.797114][ T9787] R13: 0000000000000040 R14: ffff88802c50814a R15: 0000000000000000 [ 45.798024][ T9787] FS: 00007ffb72734540(0000) GS:ffff8880cec64000(0000) knlGS:0000000000000000 [ 45.799019][ T9787] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 45.799822][ T9787] CR2: 00007f9bd8225000 CR3: 000000010979a000 CR4: 00000000000006f0 [ 45.800747][ T9787] Kernel panic - not syncing: Fatal exception
The hfs_fill_super() calls hfs_mdb_get() method that tries to construct Extents Tree and Catalog Tree:
HFS_SB(sb)->ext_tree = hfs_btree_open(sb, HFS_EXT_CNID, hfs_ext_keycmp);
if (!HFS_SB(sb)->ext_tree) {
pr_err("unable to open extent tree\n");
goto out;
}
HFS_SB(sb)->cat_tree = hfs_btree_open(sb, HFS_CAT_CNID, hfs_cat_keycmp);
if (!HFS_SB(sb)->cat_tree) {
pr_err("unable to open catalog tree\n");
goto out;
}However, hfs_btree_open() calls read_mapping_page() that calls hfs_get_block(). And this method calls hfs_ext_read_extent():
static int hfs_ext_read_extent(struct inode *inode, u16 block)
{
struct hfs_find_data fd;
int res;
if (block >= HFS_I(inode)->cached_start &&
block < HFS_I(inode)->cached_start + HFS_I(inode)->cached_blocks)
return 0;
res = hfs_find_init(HFS_SB(inode->i_sb)->ext_tree, &fd);
if (!res) {
res = __hfs_ext_cache_extent(&fd, inode, block);
hfs_find_exit(&fd);
}
return res;
}The problem here that hfs_find_init() is trying to use HFS_SB(inode->i_sb)->ext_tree that is not initialized yet. It will be initailized when hfs_btree_open() finishes the execution.
The patch adds checking of tree pointer in hfs_find_init() and it reworks the logic of hfs_btree_open() by reading the b-tree's header directly from the volume. The read_mapping_page() is exchanged on filemap_grab_folio() that grab the folio from mapping. Then, sb_bread() extracts the b-tree's header content and copy it into the folio.
--- fs/hfs/bfind.c | 3 +++ fs/hfs/btree.c | 57 +++++++++++++++++++++++++++++++++++++++---------- fs/hfs/extent.c | 2 +- fs/hfs/hfs_fs.h | 1 + 4 files changed, 51 insertions(+), 12 deletions(-)
fs/hfs/bfind.c +3 -0
@@ -16,6 +16,9 @@ int hfs_find_init(struct hfs_btree *tree, struct hfs_find_data *fd) {void *ptr; +if (!tree || !fd) +return -EINVAL ; + fd->tree = tree; fd->bnode =NULL ; ptr =kzalloc (tree->max_key_len *2 +4 ,GFP_KERNEL );
fs/hfs/btree.c +46 -11
100 lines not on this page · raw message
fs/hfs/extent.c +1 -1
@@ -71,7 +71,7 @@ int hfs_ext_keycmp(const btree_key *key1, const btree_key *key2)* * Find a block within an extent record */ -static u16 hfs_ext_find_block (struct hfs_extent *ext,u16 off) +u16 hfs_ext_find_block (struct hfs_extent *ext,u16 off) {int i;u16 count;
fs/hfs/hfs_fs.h +1 -0
@@ -193,6 +193,7 @@ extern const struct inode_operations hfs_dir_inode_operations;/* extent.c */ extern int hfs_ext_keycmp (const btree_key *key1,const btree_key *key2); +extern u16 hfs_ext_find_block (struct hfs_extent *ext,u16 off);extern int hfs_free_fork (struct super_block *sb,struct hfs_cat_file *file,int type);extern int hfs_ext_write_extent (struct inode *inode);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 827/1887 habanalabs: remove support to export dmabuf from handle
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ohad Sharabi <[email protected]>
[ Upstream commit 303dad15ed8ccbb1702f3476642d8a43680f97b5 ]
The API to the user which allows exporting DMA buffer from handle is deprecated here. It was never used as it is relevant only for Gaudi2, and the user stack has yet to add support for dmabuf in Gaudi2.
Looking forward, a modified API to export DMA buffer for ASICs that supports virtual memory will be added.
Until the new API will be ready- exporting DMA buffer will not be supported for ASICs with virtual memory.
Stable-dep-of: 33927f3d0ecd ("habanalabs: fix UAF in export_dmabuf()")
--- drivers/misc/habanalabs/common/habanalabs.h | 5 - drivers/misc/habanalabs/common/memory.c | 143 ++------------------ 2 files changed, 9 insertions(+), 139 deletions(-)
drivers/misc/habanalabs/common/habanalabs.h +0 -5
@@ -1732,8 +1732,6 @@ struct hl_cs_counters_atomic {* struct hl_dmabuf_priv - a dma-buf private object. * @dmabuf: pointer to dma-buf object. * @ctx: pointer to the dma-buf owner's context. -* @phys_pg_pack: pointer to physical page pack if the dma-buf was exported for -* memory allocation handle. * @device_address: physical address of the device's memory. Relevant only * if phys_pg_pack is NULL (dma-buf was exported from address). * The total size can be taken from the dmabuf object.
@@ -1741,7 +1739,6 @@ struct hl_cs_counters_atomic {struct hl_dmabuf_priv {struct dma_buf *dmabuf;struct hl_ctx *ctx; -struct hl_vm_phys_pg_pack *phys_pg_pack;uint64_t device_address; };
@@ -2105,7 +2102,6 @@ struct hl_vm_hw_block_list_node {* @node: used to attach to deletion list that is used when all the allocations are cleared * at the teardown of the context. * @mapping_cnt: number of shared mappings. -* @exporting_cnt: number of dma-buf exporting. * @asid: the context related to this list. * @page_size: size of each page in the pack. * @flags: HL_MEM_* flags related to this list.
@@ -2121,7 +2117,6 @@ struct hl_vm_phys_pg_pack {u64 total_size;struct list_head node;atomic_t mapping_cnt; -u32 exporting_cnt;u32 asid;u32 page_size;u32 flags;
drivers/misc/habanalabs/common/memory.c +9 -134
205 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 828/1887 habanalabs: helper function to validate export params
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ohad Sharabi <[email protected]>
[ Upstream commit 54fde5505c1311d45a96d7ad8fb8809581d38f22 ]
Validate export parameters in a dedicated function instead of in the main export flow.
This will be useful later when support to export dmabuf for devices with virtual memory will be added.
Stable-dep-of: 33927f3d0ecd ("habanalabs: fix UAF in export_dmabuf()")
--- drivers/misc/habanalabs/common/memory.c | 79 ++++++++++++++----------- 1 file changed, 44 insertions(+), 35 deletions(-)
drivers/misc/habanalabs/common/memory.c +44 -35
@@ -1797,36 +1797,10 @@ static int export_dmabuf(struct hl_ctx *ctx,return rc; } -/** -* export_dmabuf_from_addr() - export a dma-buf object for the given memory -* address and size. -* @ctx: pointer to the context structure. -* @device_addr: device memory physical address. -* @size: size of device memory. -* @flags: DMA-BUF file/FD flags. -* @dmabuf_fd: pointer to result FD that represents the dma-buf object. -* -* Create and export a dma-buf object for an existing memory allocation inside -* the device memory, and return a FD which is associated with the dma-buf -* object. -* -* Return: 0 on success, non-zero for failure. -*/ -static int export_dmabuf_from_addr (struct hl_ctx *ctx,u64 device_addr, -u64 size,int flags,int *dmabuf_fd) +static int validate_export_params (struct hl_device *hdev,u64 device_addr,u64 size) { -struct hl_dmabuf_priv *hl_dmabuf; -struct hl_device *hdev = ctx->hdev; -struct asic_fixed_properties *prop; +struct asic_fixed_properties *prop = &hdev->asic_prop;u64 bar_address; -int rc; - - prop = &hdev->asic_prop; - -if (prop->dram_supports_virtual_memory) { -dev_dbg (hdev->dev,"Export not supported for devices with virtual memory\n" ); -return -EOPNOTSUPP ; - }if (!IS_ALIGNED (device_addr,PAGE_SIZE )) { dev_dbg(hdev->dev,
@@ -1843,26 +1817,61 @@ static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 device_addr, }if (device_addr < prop->dram_user_base_address || - device_addr + size > prop->dram_end_address || - device_addr + size < device_addr) { + (device_addr + size) > prop->dram_end_address || + (device_addr + size) < device_addr) {dev_dbg (hdev->dev,"DRAM memory range 0x%llx (+0x%llx) is outside of DRAM boundaries\n" , device_addr, size);return -EINVAL ; } - bar_address = hdev->dram_pci_bar_start + - (device_addr - prop->dram_base_address); + bar_address = hdev->dram_pci_bar_start + (device_addr - prop->dram_base_address); -if (bar_address + size > - hdev->dram_pci_bar_start + prop->dram_pci_bar_size || - bar_address + size < bar_address) { +if ((bar_address + size) > (hdev->dram_pci_bar_start + prop->dram_pci_bar_size) || + (bar_address + size) < bar_address) {dev_dbg (hdev->dev,"DRAM memory range 0x%llx (+0x%llx) is outside of PCI BAR boundaries\n" , device_addr, size);return -EINVAL ; } +return 0 ; +} + +/** +* export_dmabuf_from_addr() - export a dma-buf object for the given memory +* address and size. +* @ctx: pointer to the context structure. +* @device_addr: device memory physical address. +* @size: size of device memory. +* @flags: DMA-BUF file/FD flags. +* @dmabuf_fd: pointer to result FD that represents the dma-buf object. +* +* Create and export a dma-buf object for an existing memory allocation inside +* the device memory, and return a FD which is associated with the dma-buf +* object. +* +* Return: 0 on success, non-zero for failure. +*/ +static int export_dmabuf_from_addr (struct hl_ctx *ctx,u64 device_addr, +u64 size,int flags,int *dmabuf_fd) +{ +struct hl_dmabuf_priv *hl_dmabuf; +struct hl_device *hdev = ctx->hdev; +struct asic_fixed_properties *prop; +int rc; + + prop = &hdev->asic_prop; + +if (prop->dram_supports_virtual_memory) { +dev_dbg (hdev->dev,"Export not supported for devices with virtual memory\n" ); +return -EOPNOTSUPP ; + } + + rc =validate_export_params (hdev, device_addr, size); +if (rc) +return rc; + hl_dmabuf =kzalloc (sizeof (*hl_dmabuf),GFP_KERNEL );if (!hl_dmabuf)return -ENOMEM ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 829/1887 habanalabs: fix dma-buf release handling if dma_buf_fd() fails
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomer Tayar <[email protected]>
[ Upstream commit 9b3d9f917f81aed559d19377c11d6fac3db89fd7 ]
The dma-buf private object is freed if a call to dma_buf_fd() fails, and because a file was already associated with the dma-buf in dma_buf_export(), the release op will be called and will use this object.
Mark the 'priv' field as NULL in this case, and avoid accessing it from the release op.
Stable-dep-of: 33927f3d0ecd ("habanalabs: fix UAF in export_dmabuf()")
--- drivers/misc/habanalabs/common/memory.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/misc/habanalabs/common/memory.c +5 -1
@@ -1748,6 +1748,9 @@ static void hl_release_dmabuf(struct dma_buf *dmabuf) {struct hl_dmabuf_priv *hl_dmabuf = dmabuf->priv; +if (!hl_dmabuf) +return ; +hl_ctx_put (hl_dmabuf->ctx);kfree (hl_dmabuf); }
@@ -1780,7 +1783,7 @@ static int export_dmabuf(struct hl_ctx *ctx, fd =dma_buf_fd (hl_dmabuf->dmabuf, flags);if (fd <0 ) { -dev_err (hdev->dev,"failed to get a file descriptor for a dma-buf\n" ); +dev_err (hdev->dev,"failed to get a file descriptor for a dma-buf, %d\n" , fd); rc = fd; goto err_dma_buf_put; }
@@ -1793,6 +1796,7 @@ static int export_dmabuf(struct hl_ctx *ctx,return 0 ; err_dma_buf_put: + hl_dmabuf->dmabuf->priv =NULL ;dma_buf_put (hl_dmabuf->dmabuf);return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 830/1887 habanalabs: fix UAF in export_dmabuf()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit 33927f3d0ecdcff06326d6e4edb6166aed42811c ]
As soon as we'd inserted a file reference into descriptor table, another thread could close it. That's fine for the case when all we are doing is returning that descriptor to userland (it's a race, but it's a userland race and there's nothing the kernel can do about it). However, if we follow fd_install() with any kind of access to objects that would be destroyed on close (be it the struct file itself or anything destroyed by its ->release()), we have a UAF.
dma_buf_fd() is a combination of reserving a descriptor and fd_install(). habanalabs export_dmabuf() calls it and then proceeds to access the objects destroyed on close. In particular, it grabs an extra reference to another struct file that will be dropped as part of ->release() for ours; that "will be" is actually "might have already been".
Fix that by reserving descriptor before anything else and do fd_install() only when everything had been set up. As a side benefit, we no longer have the failure exit with file already created, but reference to underlying file (as well as ->dmabuf_export_cnt, etc.) not grabbed yet; unlike dma_buf_fd(), fd_install() can't fail.
--- drivers/misc/habanalabs/common/memory.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-)
drivers/misc/habanalabs/common/memory.c +8 -16
@@ -1748,9 +1748,6 @@ static void hl_release_dmabuf(struct dma_buf *dmabuf) {struct hl_dmabuf_priv *hl_dmabuf = dmabuf->priv; -if (!hl_dmabuf) -return ; -hl_ctx_put (hl_dmabuf->ctx);kfree (hl_dmabuf); }
@@ -1768,7 +1765,12 @@ static int export_dmabuf(struct hl_ctx *ctx, {DEFINE_DMA_BUF_EXPORT_INFO (exp_info);struct hl_device *hdev = ctx->hdev; -int rc, fd; +CLASS (get_unused_fd, fd)(flags); + +if (fd <0 ) { +dev_err (hdev->dev,"failed to get a file descriptor for a dma-buf, %d\n" , fd); +return fd; + } exp_info.ops = &habanalabs_dmabuf_ops; exp_info.size = total_size;
@@ -1781,24 +1783,14 @@ static int export_dmabuf(struct hl_ctx *ctx,return PTR_ERR (hl_dmabuf->dmabuf); } - fd =dma_buf_fd (hl_dmabuf->dmabuf, flags); -if (fd <0 ) { -dev_err (hdev->dev,"failed to get a file descriptor for a dma-buf, %d\n" , fd); - rc = fd; - goto err_dma_buf_put; - } - hl_dmabuf->ctx = ctx;hl_ctx_get (hl_dmabuf->ctx); *dmabuf_fd = fd; +fd_install (fd, hl_dmabuf->dmabuf->file); + fd = -EBADF ;return 0 ; - -err_dma_buf_put: - hl_dmabuf->dmabuf->priv =NULL ; -dma_buf_put (hl_dmabuf->dmabuf); -return rc; }static int validate_export_params (struct hl_device *hdev,u64 device_addr,u64 size)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 831/1887 net/smc: fix UAF on smcsk after smc_listen_out()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: D. Wythe <[email protected]>
[ Upstream commit d9cef55ed49117bd63695446fb84b4b91815c0b4 ]
BPF CI testing report a UAF issue:
[ 16.446633] BUG: kernel NULL pointer dereference, address: 000000000000003 0 [ 16.447134] #PF: supervisor read access in kernel mod e [ 16.447516] #PF: error_code(0x0000) - not-present pag e [ 16.447878] PGD 0 P4D 0 [ 16.448063] Oops: Oops: 0000 [#1] PREEMPT SMP NOPT I [ 16.448409] CPU: 0 UID: 0 PID: 9 Comm: kworker/0:1 Tainted: G OE 6.13.0-rc3-g89e8a75fda73-dirty #4 2 [ 16.449124] Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODUL E [ 16.449502] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/201 4 [ 16.450201] Workqueue: smc_hs_wq smc_listen_wor k [ 16.450531] RIP: 0010:smc_listen_work+0xc02/0x159 0 [ 16.452158] RSP: 0018:ffffb5ab40053d98 EFLAGS: 0001024 6 [ 16.452526] RAX: 0000000000000001 RBX: 0000000000000002 RCX: 000000000000030 0 [ 16.452994] RDX: 0000000000000280 RSI: 00003513840053f0 RDI: 000000000000000 0 [ 16.453492] RBP: ffffa097808e3800 R08: ffffa09782dba1e0 R09: 000000000000000 5 [ 16.453987] R10: 0000000000000000 R11: 0000000000000000 R12: ffffa0978274640 0 [ 16.454497] R13: 0000000000000000 R14: 0000000000000000 R15: ffffa09782d4092 0 [ 16.454996] FS: 0000000000000000(0000) GS:ffffa097bbc00000(0000) knlGS:000000000000000 0 [ 16.455557] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003 3 [ 16.455961] CR2: 0000000000000030 CR3: 0000000102788004 CR4: 0000000000770ef 0 [ 16.456459] PKRU: 5555555 4 [ 16.456654] Call Trace : [ 16.456832] <TASK > [ 16.456989] ? __die+0x23/0x7 0 [ 16.457215] ? page_fault_oops+0x180/0x4c 0 [ 16.457508] ? __lock_acquire+0x3e6/0x249 0 [ 16.457801] ? exc_page_fault+0x68/0x20 0 [ 16.458080] ? asm_exc_page_fault+0x26/0x3 0 [ 16.458389] ? smc_listen_work+0xc02/0x159 0 [ 16.458689] ? smc_listen_work+0xc02/0x159 0 [ 16.458987] ? lock_is_held_type+0x8f/0x10 0 [ 16.459284] process_one_work+0x1ea/0x6d 0 [ 16.459570] worker_thread+0x1c3/0x38 0 [ 16.459839] ? __pfx_worker_thread+0x10/0x1 0 [ 16.460144] kthread+0xe0/0x11 0 [ 16.460372] ? __pfx_kthread+0x10/0x1 0 [ 16.460640] ret_from_fork+0x31/0x5 0 [ 16.460896] ? __pfx_kthread+0x10/0x1 0 [ 16.461166] ret_from_fork_asm+0x1a/0x3 0 [ 16.461453] </TASK > [ 16.461616] Modules linked in: bpf_testmod(OE) [last unloaded: bpf_testmod(OE) ] [ 16.462134] CR2: 000000000000003 0 [ 16.462380] ---[ end trace 0000000000000000 ]--- [ 16.462710] RIP: 0010:smc_listen_work+0xc02/0x1590
The direct cause of this issue is that after smc_listen_out_connected(), newclcsock->sk may be NULL since it will releases the smcsk. Therefore, if the application closes the socket immediately after accept, newclcsock->sk can be NULL. A possible execution order could be as follows:
smc_listen_work | userspace
-----------------------------------------------------------------
lock_sock(sk) |
smc_listen_out_connected() |
| \- smc_listen_out |
| | \- release_sock |
| |- sk->sk_data_ready() |
| fd = accept();
| close(fd);
| \- socket->sk = NULL;/* newclcsock->sk is NULL now */
SMC_STAT_SERV_SUCC_INC(sock_net(newclcsock->sk))
Since smc_listen_out_connected() will not fail, simply swapping the order of the code can easily fix this issue.
--- net/smc/af_smc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/smc/af_smc.c +2 -1
@@ -2468,8 +2468,9 @@ static void smc_listen_work(struct work_struct *work)mutex_unlock (&smc_server_lgr_pending); }smc_conn_save_peer_info (new_smc, cclc); -smc_listen_out_connected (new_smc);SMC_STAT_SERV_SUCC_INC (sock_net (newclcsock->sk), ini); +/* smc_listen_out() will release smcsk */ +smc_listen_out_connected (new_smc); goto out_free; out_unlock:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 832/1887 net/sched: Fix backlog accounting in qdisc_dequeue_internal
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: William Liu <[email protected]>
[ Upstream commit 52bf272636bda69587952b35ae97690b8dc89941 ]
This issue applies for the following qdiscs: hhf, fq, fq_codel, and fq_pie, and occurs in their change handlers when adjusting to the new limit. The problem is the following in the values passed to the subsequent qdisc_tree_reduce_backlog call given a tbf parent:
When the tbf parent runs out of tokens, skbs of these qdiscs will be placed in gso_skb. Their peek handlers are qdisc_peek_dequeued, which accounts for both qlen and backlog. However, in the case of qdisc_dequeue_internal, ONLY qlen is accounted for when pulling from gso_skb. This means that these qdiscs are missing a qdisc_qstats_backlog_dec when dropping packets to satisfy the new limit in their change handlers.
One can observe this issue with the following (with tc patched to support a limit of 0):
export TARGET=fq
tc qdisc del dev lo root
tc qdisc add dev lo root handle 1: tbf rate 8bit burst 100b latency 1ms tc qdisc replace dev lo handle 3: parent 1:1 $TARGET limit 1000 echo ''; echo 'add child'; tc -s -d qdisc show dev lo
ping -I lo -f -c2 -s32 -W0.001 127.0.0.1 2>&1 >/dev/null echo ''; echo 'after ping'; tc -s -d qdisc show dev lo
tc qdisc change dev lo handle 3: parent 1:1 $TARGET limit 0 echo ''; echo 'after limit drop'; tc -s -d qdisc show dev lo tc qdisc replace dev lo handle 2: parent 1:1 sfq
echo ''; echo 'post graft'; tc -s -d qdisc show dev lo
The second to last show command shows 0 packets but a positive number (74) of backlog bytes. The problem becomes clearer in the last show command, where qdisc_purge_queue triggers qdisc_tree_reduce_backlog with the positive backlog and causes an underflow in the tbf parent's backlog (4096 Mb instead of 0).
To fix this issue, the codepath for all clients of qdisc_dequeue_internal has been simplified: codel, pie, hhf, fq, fq_pie, and fq_codel. qdisc_dequeue_internal handles the backlog adjustments for all cases that do not directly use the dequeue handler.
The old fq_codel_change limit adjustment loop accumulated the arguments to the subsequent qdisc_tree_reduce_backlog call through the cstats field. However, this is confusing and error prone as fq_codel_dequeue could also potentially mutate this field (which qdisc_dequeue_internal calls in the non gso_skb case), so we have unified the code here with other qdiscs.
--- include/net/sch_generic.h | 11 ++++++++--- net/sched/sch_codel.c | 12 +++++++----- net/sched/sch_fq.c | 12 +++++++----- net/sched/sch_fq_codel.c | 12 +++++++----- net/sched/sch_fq_pie.c | 12 +++++++----- net/sched/sch_hhf.c | 12 +++++++----- net/sched/sch_pie.c | 12 +++++++----- 7 files changed, 50 insertions(+), 33 deletions(-)
include/net/sch_generic.h +8 -3
@@ -1048,12 +1048,17 @@ static inline struct sk_buff *qdisc_dequeue_internal(struct Qdisc *sch, bool dir skb =__skb_dequeue (&sch->gso_skb);if (skb) { sch->q.qlen--; +qdisc_qstats_backlog_dec (sch, skb);return skb; } -if (direct) -return __qdisc_dequeue_head (&sch->q); -else +if (direct) { + skb =__qdisc_dequeue_head (&sch->q); +if (skb) +qdisc_qstats_backlog_dec (sch, skb); +return skb; + }else {return sch->dequeue (sch); + } }static inline struct sk_buff *qdisc_dequeue_head (struct Qdisc *sch)
net/sched/sch_codel.c +7 -5
@@ -168,9 +168,9 @@ static const struct nla_policy codel_policy[TCA_CODEL_MAX + 1] = {static int codel_change (struct Qdisc *sch,struct nlattr *opt,struct netlink_ext_ack *extack) { +unsigned int dropped_pkts =0 , dropped_bytes =0 ;struct codel_sched_data *q =qdisc_priv (sch);struct nlattr *tb[TCA_CODEL_MAX +1 ]; -unsigned int qlen, dropped =0 ;int err; err = nla_parse_nested_deprecated(tb, TCA_CODEL_MAX, opt,
@@ -204,15 +204,17 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt,if (tb[TCA_CODEL_ECN ]) q->params.ecn = !!nla_get_u32 (tb[TCA_CODEL_ECN ]); - qlen = sch->q.qlen;while (sch->q.qlen > sch->limit) {struct sk_buff *skb =qdisc_dequeue_internal (sch, true); - dropped +=qdisc_pkt_len (skb); -qdisc_qstats_backlog_dec (sch, skb); +if (!skb) +break ; + + dropped_pkts++; + dropped_bytes +=qdisc_pkt_len (skb);rtnl_qdisc_drop (skb, sch); } -qdisc_tree_reduce_backlog (sch, qlen - sch->q.qlen, dropped); +qdisc_tree_reduce_backlog (sch, dropped_pkts, dropped_bytes);sch_tree_unlock (sch);return 0 ;
net/sched/sch_fq.c +7 -5
@@ -806,11 +806,11 @@ static const struct nla_policy fq_policy[TCA_FQ_MAX + 1] = {static int fq_change (struct Qdisc *sch,struct nlattr *opt,struct netlink_ext_ack *extack) { +unsigned int dropped_pkts =0 , dropped_bytes =0 ;struct fq_sched_data *q =qdisc_priv (sch);struct nlattr *tb[TCA_FQ_MAX +1 ]; -int err, drop_count =0 ; -unsigned drop_len =0 ;u32 fq_log; +int err; err =nla_parse_nested_deprecated (tb,TCA_FQ_MAX , opt, fq_policy,NULL );
@@ -900,16 +900,18 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt, err =fq_resize (sch, fq_log);sch_tree_lock (sch); } +while (sch->q.qlen > sch->limit) {struct sk_buff *skb =qdisc_dequeue_internal (sch, false);if (!skb)break ; - drop_len +=qdisc_pkt_len (skb); + + dropped_pkts++; + dropped_bytes +=qdisc_pkt_len (skb);rtnl_kfree_skbs (skb, skb); - drop_count++; } -qdisc_tree_reduce_backlog (sch, drop_count, drop_len); +qdisc_tree_reduce_backlog (sch, dropped_pkts, dropped_bytes);sch_tree_unlock (sch);return err;
net/sched/sch_fq_codel.c +7 -5
@@ -402,6 +402,7 @@ static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = {static int fq_codel_change (struct Qdisc *sch,struct nlattr *opt,struct netlink_ext_ack *extack) { +unsigned int dropped_pkts =0 , dropped_bytes =0 ;struct fq_codel_sched_data *q =qdisc_priv (sch);struct nlattr *tb[TCA_FQ_CODEL_MAX +1 ];u32 quantum =0 ;
@@ -470,13 +471,14 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt, q->memory_usage > q->memory_limit) {struct sk_buff *skb =qdisc_dequeue_internal (sch, false); - q->cstats.drop_len +=qdisc_pkt_len (skb); +if (!skb) +break ; + + dropped_pkts++; + dropped_bytes +=qdisc_pkt_len (skb);rtnl_kfree_skbs (skb, skb); - q->cstats.drop_count++; } -qdisc_tree_reduce_backlog (sch, q->cstats.drop_count, q->cstats.drop_len); - q->cstats.drop_count =0 ; - q->cstats.drop_len =0 ; +qdisc_tree_reduce_backlog (sch, dropped_pkts, dropped_bytes);sch_tree_unlock (sch);return 0 ;
net/sched/sch_fq_pie.c +7 -5
@@ -284,10 +284,9 @@ static struct sk_buff *fq_pie_qdisc_dequeue(struct Qdisc *sch)static int fq_pie_change (struct Qdisc *sch,struct nlattr *opt,struct netlink_ext_ack *extack) { +unsigned int dropped_pkts =0 , dropped_bytes =0 ;struct fq_pie_sched_data *q =qdisc_priv (sch);struct nlattr *tb[TCA_FQ_PIE_MAX +1 ]; -unsigned int len_dropped =0 ; -unsigned int num_dropped =0 ;int err; err =nla_parse_nested (tb,TCA_FQ_PIE_MAX , opt, fq_pie_policy, extack);
@@ -366,11 +365,14 @@ static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt,while (sch->q.qlen > sch->limit) {struct sk_buff *skb =qdisc_dequeue_internal (sch, false); - len_dropped +=qdisc_pkt_len (skb); - num_dropped +=1 ; +if (!skb) +break ; + + dropped_pkts++; + dropped_bytes +=qdisc_pkt_len (skb);rtnl_kfree_skbs (skb, skb); } -qdisc_tree_reduce_backlog (sch, num_dropped, len_dropped); +qdisc_tree_reduce_backlog (sch, dropped_pkts, dropped_bytes);sch_tree_unlock (sch);return 0 ;
net/sched/sch_hhf.c +7 -5
@@ -536,9 +536,9 @@ static const struct nla_policy hhf_policy[TCA_HHF_MAX + 1] = {static int hhf_change (struct Qdisc *sch,struct nlattr *opt,struct netlink_ext_ack *extack) { +unsigned int dropped_pkts =0 , dropped_bytes =0 ;struct hhf_sched_data *q =qdisc_priv (sch);struct nlattr *tb[TCA_HHF_MAX +1 ]; -unsigned int qlen, prev_backlog;int err;u64 non_hh_quantum;u32 new_quantum = q->quantum;
@@ -585,15 +585,17 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt, q->hhf_evict_timeout =usecs_to_jiffies (us); } - qlen = sch->q.qlen; - prev_backlog = sch->qstats.backlog;while (sch->q.qlen > sch->limit) {struct sk_buff *skb =qdisc_dequeue_internal (sch, false); +if (!skb) +break ; + + dropped_pkts++; + dropped_bytes +=qdisc_pkt_len (skb);rtnl_kfree_skbs (skb, skb); } -qdisc_tree_reduce_backlog (sch, qlen - sch->q.qlen, - prev_backlog - sch->qstats.backlog); +qdisc_tree_reduce_backlog (sch, dropped_pkts, dropped_bytes);sch_tree_unlock (sch);return 0 ;
net/sched/sch_pie.c +7 -5
@@ -138,9 +138,9 @@ static const struct nla_policy pie_policy[TCA_PIE_MAX + 1] = {static int pie_change (struct Qdisc *sch,struct nlattr *opt,struct netlink_ext_ack *extack) { +unsigned int dropped_pkts =0 , dropped_bytes =0 ;struct pie_sched_data *q =qdisc_priv (sch);struct nlattr *tb[TCA_PIE_MAX +1 ]; -unsigned int qlen, dropped =0 ;int err; err = nla_parse_nested_deprecated(tb, TCA_PIE_MAX, opt, pie_policy,
@@ -188,15 +188,17 @@ static int pie_change(struct Qdisc *sch, struct nlattr *opt,nla_get_u32 (tb[TCA_PIE_DQ_RATE_ESTIMATOR ]);/* Drop excess packets if new limit is lower */ - qlen = sch->q.qlen;while (sch->q.qlen > sch->limit) {struct sk_buff *skb =qdisc_dequeue_internal (sch, true); - dropped +=qdisc_pkt_len (skb); -qdisc_qstats_backlog_dec (sch, skb); +if (!skb) +break ; + + dropped_pkts++; + dropped_bytes +=qdisc_pkt_len (skb);rtnl_qdisc_drop (skb, sch); } -qdisc_tree_reduce_backlog (sch, qlen - sch->q.qlen, dropped); +qdisc_tree_reduce_backlog (sch, dropped_pkts, dropped_bytes);sch_tree_unlock (sch);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 833/1887 drm/amd/display: fix a Null pointer dereference vulnerability
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Siyang Liu <[email protected]>
[ Upstream commit 1bcf63a44381691d6192872801f830ce3250e367 ]
[Why]
A null pointer dereference vulnerability exists in the AMD display driver's (DC module) cleanup function dc_destruct().
When display control context (dc->ctx) construction fails
(due to memory allocation failure), this pointer remains NULL. During subsequent error handling when dc_destruct() is called, there's no NULL check before dereferencing the perf_trace member (dc->ctx->perf_trace), causing a kernel null pointer dereference crash.
[How]
Check if dc->ctx is non-NULL before dereferencing.
(Updated commit text and removed unnecessary error message)
--- drivers/gpu/drm/amd/display/dc/core/dc.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/gpu/drm/amd/display/dc/core/dc.c +9 -7
@@ -831,16 +831,18 @@ static void dc_destruct(struct dc *dc)dc_destroy_resource_pool (dc); -if (dc->ctx->gpio_service) -dal_gpio_service_destroy (&dc->ctx->gpio_service); +if (dc->ctx) { +if (dc->ctx->gpio_service) +dal_gpio_service_destroy (&dc->ctx->gpio_service); -if (dc->ctx->created_bios) -dal_bios_parser_destroy (&dc->ctx->dc_bios); +if (dc->ctx->created_bios) +dal_bios_parser_destroy (&dc->ctx->dc_bios); -dc_perf_trace_destroy (&dc->ctx->perf_trace); +dc_perf_trace_destroy (&dc->ctx->perf_trace); -kfree (dc->ctx); - dc->ctx =NULL ; +kfree (dc->ctx); + dc->ctx =NULL ; + }kfree (dc->bw_vbios); dc->bw_vbios =NULL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 834/1887 ksmbd: fix refcount leak causing resource not released
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ziyan Xu <[email protected]>
[ Upstream commit 89bb430f621124af39bb31763c4a8b504c9651e2 ]
When ksmbd_conn_releasing(opinfo->conn) returns true,the refcount was not decremented properly, causing a refcount leak that prevents the count from reaching zero and the memory from being released.
--- fs/smb/server/oplock.c | 3 +++ 1 file changed, 3 insertions(+)
fs/smb/server/oplock.c +3 -0
@@ -1142,6 +1142,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,atomic_inc (&opinfo->conn->r_count);if (ksmbd_conn_releasing (opinfo->conn)) {atomic_dec (&opinfo->conn->r_count); +opinfo_put (opinfo);continue ; }
@@ -1184,6 +1185,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)atomic_inc (&opinfo->conn->r_count);if (ksmbd_conn_releasing (opinfo->conn)) {atomic_dec (&opinfo->conn->r_count); +opinfo_put (opinfo);continue ; }read_unlock (&p_ci->m_lock);
@@ -1390,6 +1392,7 @@ void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,atomic_inc (&brk_op->conn->r_count);if (ksmbd_conn_releasing (brk_op->conn)) {atomic_dec (&brk_op->conn->r_count); +opinfo_put (brk_op);continue ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 835/1887 s390/ism: Introduce struct ism_dmb
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Raspl <[email protected]>
[ Upstream commit 1baedb13f1d50ae8c7852134fdf934b4463e9baa ]
Conceptually, a DMB is a structure that belongs to ISM devices. However, SMC currently 'owns' this structure. So future exploiters of ISM devices would be forced to include SMC headers to work - which is just weird. Therefore, we switch ISM to struct ism_dmb, introduce a new public header with the definition (will be populated with further API calls later on), and, add a thin wrapper to please SMC. Since structs smcd_dmb and ism_dmb are identical, we can simply convert between the two for now.
Stable-dep-of: 897e8601b9cf ("s390/ism: fix concurrency management in ism_cmd()")
--- drivers/s390/net/ism.h | 1 + drivers/s390/net/ism_drv.c | 22 ++++++++++++++++------ include/linux/ism.h | 23 +++++++++++++++++++++++ 3 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 include/linux/ism.h
drivers/s390/net/ism.h +1 -0
@@ -5,6 +5,7 @@#include <linux/spinlock.h> #include <linux/types.h> #include <linux/pci.h> +#include <linux/ism.h> #include <net/smc.h> #include <asm/pci_insn.h>
drivers/s390/net/ism_drv.c +16 -6
@@ -215,14 +215,14 @@ static int ism_query_rgid(struct smcd_dev *smcd, u64 rgid, u32 vid_valid,return ism_cmd (ism, &cmd); } -static void ism_free_dmb (struct ism_dev *ism,struct smcd_dmb *dmb) +static void ism_free_dmb (struct ism_dev *ism,struct ism_dmb *dmb) {clear_bit (dmb->sba_idx, ism->sba_bitmap);dma_free_coherent (&ism->pdev->dev, dmb->dmb_len, dmb->cpu_addr, dmb->dma_addr); } -static int ism_alloc_dmb (struct ism_dev *ism,struct smcd_dmb *dmb) +static int ism_alloc_dmb (struct ism_dev *ism,struct ism_dmb *dmb) {unsigned long bit;
@@ -250,7 +250,7 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct smcd_dmb *dmb)return dmb->cpu_addr ?0 : -ENOMEM ; } -static int ism_register_dmb (struct smcd_dev *smcd,struct smcd_dmb *dmb) +static int ism_register_dmb (struct smcd_dev *smcd,struct ism_dmb *dmb) {struct ism_dev *ism = smcd->priv;union ism_reg_dmb cmd;
@@ -281,7 +281,12 @@ static int ism_register_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb)return ret; } -static int ism_unregister_dmb (struct smcd_dev *smcd,struct smcd_dmb *dmb) +static int smcd_register_dmb (struct smcd_dev *smcd,struct smcd_dmb *dmb) +{ +return ism_register_dmb (smcd, (struct ism_dmb *)dmb); +} + +static int ism_unregister_dmb (struct smcd_dev *smcd,struct ism_dmb *dmb) {struct ism_dev *ism = smcd->priv;union ism_unreg_dmb cmd;
@@ -302,6 +307,11 @@ static int ism_unregister_dmb(struct smcd_dev *smcd, struct smcd_dmb *dmb)return ret; } +static int smcd_unregister_dmb (struct smcd_dev *smcd,struct smcd_dmb *dmb) +{ +return ism_unregister_dmb (smcd, (struct ism_dmb *)dmb); +} +static int ism_add_vlan_id (struct smcd_dev *smcd,u64 vlan_id) {struct ism_dev *ism = smcd->priv;
@@ -474,8 +484,8 @@ static irqreturn_t ism_handle_irq(int irq, void *data)static const struct smcd_ops ism_ops = { .query_remote_gid = ism_query_rgid, - .register_dmb = ism_register_dmb, - .unregister_dmb = ism_unregister_dmb, + .register_dmb = smcd_register_dmb, + .unregister_dmb = smcd_unregister_dmb, .add_vlan_id = ism_add_vlan_id, .del_vlan_id = ism_del_vlan_id, .set_vlan_required = ism_set_vlan_required,
include/linux/ism.h new file +23 -0
@@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* +* Internal Shared Memory +* +* Definitions for the ISM module +* +* Copyright IBM Corp. 2022 +*/ +#ifndef _ISM_H +#define _ISM_H + +struct ism_dmb { +u64 dmb_tok; +u64 rgid; +u32 dmb_len; +u32 sba_idx; +u32 vlan_valid; +u32 vlan_id; +void *cpu_addr; +dma_addr_t dma_addr; +}; + +#endif /* _ISM_H */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 836/1887 s390/ism: fix concurrency management in ism_cmd()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Halil Pasic <[email protected]>
[ Upstream commit 897e8601b9cff1d054cdd53047f568b0e1995726 ]
The s390x ISM device data sheet clearly states that only one request-response sequence is allowable per ISM function at any point in time. Unfortunately as of today the s390/ism driver in Linux does not honor that requirement. This patch aims to rectify that.
This problem was discovered based on Aliaksei's bug report which states that for certain workloads the ISM functions end up entering error state (with PEC 2 as seen from the logs) after a while and as a consequence connections handled by the respective function break, and for future connection requests the ISM device is not considered -- given it is in a dysfunctional state. During further debugging PEC 3A was observed as well.
A kernel message like
[ 1211.244319] zpci: 061a:00:00.0: Event 0x2 reports an error for PCI function 0x61a is a reliable indicator of the stated function entering error state with PEC 2. Let me also point out that a kernel message like [ 1211.244325] zpci: 061a:00:00.0: The ism driver bound to the device does not support error recovery
is a reliable indicator that the ISM function won't be auto-recovered because the ISM driver currently lacks support for it.
On a technical level, without this synchronization, commands (inputs to the FW) may be partially or fully overwritten (corrupted) by another CPU trying to issue commands on the same function. There is hard evidence that this can lead to DMB token values being used as DMB IOVAs, leading to PEC 2 PCI events indicating invalid DMA. But this is only one of the failure modes imaginable. In theory even completely losing one command and executing another one twice and then trying to interpret the outputs as if the command we intended to execute was actually executed and not the other one is also possible. Frankly, I don't feel confident about providing an exhaustive list of possible consequences.
--- drivers/s390/net/ism.h | 1 + drivers/s390/net/ism_drv.c | 3 +++ 2 files changed, 4 insertions(+)
drivers/s390/net/ism.h +1 -0
@@ -192,6 +192,7 @@ struct ism_sba {struct ism_dev {spinlock_t lock; +spinlock_t cmd_lock;/* serializes cmds */ struct pci_dev *pdev;struct smcd_dev *smcd;
drivers/s390/net/ism_drv.c +3 -0
@@ -40,6 +40,7 @@ static int ism_cmd(struct ism_dev *ism, void *cmd)struct ism_req_hdr *req = cmd;struct ism_resp_hdr *resp = cmd; +spin_lock (&ism->cmd_lock);__ism_write_cmd (ism, req +1 ,sizeof (*req), req->len -sizeof (*req));__ism_write_cmd (ism, req,0 ,sizeof (*req));
@@ -53,6 +54,7 @@ static int ism_cmd(struct ism_dev *ism, void *cmd) }__ism_read_cmd (ism, resp +1 ,sizeof (*resp), resp->len -sizeof (*resp)); out: +spin_unlock (&ism->cmd_lock);return resp->ret; }
@@ -555,6 +557,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id)return -ENOMEM ;spin_lock_init (&ism->lock); +spin_lock_init (&ism->cmd_lock);dev_set_drvdata (&pdev->dev, ism); ism->pdev = pdev;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 837/1887 rcu: Fix rcu_read_unlock() deadloop due to IRQ work
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joel Fernandes <[email protected]>
[ Upstream commit b41642c87716bbd09797b1e4ea7d904f06c39b7b ]
During rcu_read_unlock_special(), if this happens during irq_exit(), we can lockup if an IPI is issued. This is because the IPI itself triggers the irq_exit() path causing a recursive lock up.
This is precisely what Xiongfeng found when invoking a BPF program on the trace_tick_stop() tracepoint As shown in the trace below. Fix by managing the irq_work state correctly.
irq_exit()
__irq_exit_rcu()
/* in_hardirq() returns false after this */
preempt_count_sub(HARDIRQ_OFFSET)
tick_irq_exit()
tick_nohz_irq_exit()
tick_nohz_stop_sched_tick()
trace_tick_stop() /* a bpf prog is hooked on this trace point */
__bpf_trace_tick_stop()
bpf_trace_run2()
rcu_read_unlock_special()
/* will send a IPI to itself */
irq_work_queue_on(&rdp->defer_qs_iw, rdp->cpu);A simple reproducer can also be obtained by doing the following in tick_irq_exit(). It will hang on boot without the patch:
static inline void tick_irq_exit(void)
{
+ rcu_read_lock();
+ WRITE_ONCE(current->rcu_read_unlock_special.b.need_qs, true);
+ rcu_read_unlock();
+
--- kernel/rcu/tree.h | 13 ++++++++++++- kernel/rcu/tree_plugin.h | 37 ++++++++++++++++++++++++++----------- 2 files changed, 38 insertions(+), 12 deletions(-)
kernel/rcu/tree.h +12 -1
@@ -158,6 +158,17 @@ union rcu_noqs {u16 s;/* Set of bits, aggregate OR here. */ }; +/* +* An IRQ work (deferred_qs_iw) is used by RCU to get the scheduler's attention. +* to report quiescent states at the soonest possible time. +* The request can be in one of the following states: +* - DEFER_QS_IDLE: An IRQ work is yet to be scheduled. +* - DEFER_QS_PENDING: An IRQ work was scheduled but either not yet run, or it +* ran and we still haven't reported a quiescent state. +*/ +#define DEFER_QS_IDLE 0 +#define DEFER_QS_PENDING 1 +/* Per-CPU data for read-copy update. */ struct rcu_data {/* 1) quiescent-state and grace-period handling : */
@@ -175,7 +186,7 @@ struct rcu_data {/* during and after the last grace */ /* period it is aware of. */ struct irq_work defer_qs_iw;/* Obtain later scheduler attention. */ -bool defer_qs_iw_pending;/* Scheduler attention pending? */ +int defer_qs_iw_pending;/* Scheduler attention pending? */ struct work_struct strict_work;/* Schedule readers for strict GPs. */ /* 2) batch handling */
kernel/rcu/tree_plugin.h +26 -11
@@ -474,13 +474,16 @@ rcu_preempt_deferred_qs_irqrestore(struct task_struct *t, unsigned long flags)struct rcu_node *rnp;union rcu_special special; + rdp =this_cpu_ptr (&rcu_data); +if (rdp->defer_qs_iw_pending ==DEFER_QS_PENDING ) + rdp->defer_qs_iw_pending =DEFER_QS_IDLE ; +/* * If RCU core is waiting for this CPU to exit its critical section, * report the fact that it has exited. Because irqs are disabled, * t->rcu_read_unlock_special cannot change. */ special = t->rcu_read_unlock_special; - rdp =this_cpu_ptr (&rcu_data);if (!special.s && !rdp->cpu_no_qs.b.exp) {local_irq_restore (flags);return ;
@@ -617,7 +620,23 @@ static void rcu_preempt_deferred_qs_handler(struct irq_work *iwp) rdp = container_of(iwp, struct rcu_data, defer_qs_iw);local_irq_save (flags); - rdp->defer_qs_iw_pending = false; + +/* +* If the IRQ work handler happens to run in the middle of RCU read-side +* critical section, it could be ineffective in getting the scheduler's +* attention to report a deferred quiescent state (the whole point of the +* IRQ work). For this reason, requeue the IRQ work. +* +* Basically, we want to avoid following situation: +* 1. rcu_read_unlock() queues IRQ work (state -> DEFER_QS_PENDING) +* 2. CPU enters new rcu_read_lock() +* 3. IRQ work runs but cannot report QS due to rcu_preempt_depth() > 0 +* 4. rcu_read_unlock() does not re-queue work (state still PENDING) +* 5. Deferred QS reporting does not happen. +*/ +if (rcu_preempt_depth () >0 ) +WRITE_ONCE (rdp->defer_qs_iw_pending,DEFER_QS_IDLE ); +local_irq_restore (flags); }
@@ -664,17 +683,13 @@ static void rcu_read_unlock_special(struct task_struct *t)set_tsk_need_resched (current);set_preempt_need_resched ();if (IS_ENABLED (CONFIG_IRQ_WORK ) && irqs_were_disabled && - expboost && !rdp->defer_qs_iw_pending &&cpu_online (rdp->cpu)) { + expboost && rdp->defer_qs_iw_pending !=DEFER_QS_PENDING && +cpu_online (rdp->cpu)) {// Get scheduler to re-evaluate and call hooks. // If !IRQ_WORK, FQS scan will eventually IPI. -if (IS_ENABLED (CONFIG_RCU_STRICT_GRACE_PERIOD ) && -IS_ENABLED (CONFIG_PREEMPT_RT )) - rdp->defer_qs_iw =IRQ_WORK_INIT_HARD ( - rcu_preempt_deferred_qs_handler); -else -init_irq_work (&rdp->defer_qs_iw, - rcu_preempt_deferred_qs_handler); - rdp->defer_qs_iw_pending = true; + rdp->defer_qs_iw = +IRQ_WORK_INIT_HARD (rcu_preempt_deferred_qs_handler); + rdp->defer_qs_iw_pending =DEFER_QS_PENDING ;irq_work_queue_on (&rdp->defer_qs_iw, rdp->cpu); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 838/1887 mm/smaps: fix race between smaps_hugetlb_range and migration
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinjiang Tu <[email protected]>
[ Upstream commit 45d19b4b6c2d422771c29b83462d84afcbb33f01 ]
smaps_hugetlb_range() handles the pte without holdling ptl, and may be concurrenct with migration, leaing to BUG_ON in pfn_swap_entry_to_page(). The race is as follows.
smaps_hugetlb_range migrate_pages
huge_ptep_get
remove_migration_ptes folio_unlock
pfn_swap_entry_folio
BUG_ON
To fix it, hold ptl lock in smaps_hugetlb_range().
--- fs/proc/task_mmu.c | 3 +++ 1 file changed, 3 insertions(+)
fs/proc/task_mmu.c +3 -0
@@ -727,7 +727,9 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask,struct mem_size_stats *mss = walk->private;struct vm_area_struct *vma = walk->vma;struct page *page =NULL ; +spinlock_t *ptl; + ptl =huge_pte_lock (hstate_vma (vma), walk->mm, pte);if (pte_present (*pte)) { page =vm_normal_page (vma, addr, *pte); }else if (is_swap_pte (*pte)) {
@@ -742,6 +744,7 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask, else mss->private_hugetlb += huge_page_size(hstate_vma(vma)); } +spin_unlock (ptl);return 0 ; }#else
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 839/1887 LoongArch: Optimize module load time by optimizing PLT/GOT counting
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kanglong Wang <[email protected]>
[ Upstream commit 63dbd8fb2af3a89466538599a9acb2d11ef65c06 ]
When enabling CONFIG_KASAN, CONFIG_PREEMPT_VOLUNTARY_BUILD and CONFIG_PREEMPT_VOLUNTARY at the same time, there will be soft deadlock, the relevant logs are as follows:
rcu: INFO: rcu_sched self-detected stall on CPU ... Call Trace: [<900000000024f9e4>] show_stack+0x5c/0x180 [<90000000002482f4>] dump_stack_lvl+0x94/0xbc [<9000000000224544>] rcu_dump_cpu_stacks+0x1fc/0x280 [<900000000037ac80>] rcu_sched_clock_irq+0x720/0xf88 [<9000000000396c34>] update_process_times+0xb4/0x150 [<90000000003b2474>] tick_nohz_handler+0xf4/0x250 [<9000000000397e28>] __hrtimer_run_queues+0x1d0/0x428 [<9000000000399b2c>] hrtimer_interrupt+0x214/0x538 [<9000000000253634>] constant_timer_interrupt+0x64/0x80 [<9000000000349938>] __handle_irq_event_percpu+0x78/0x1a0 [<9000000000349a78>] handle_irq_event_percpu+0x18/0x88 [<9000000000354c00>] handle_percpu_irq+0x90/0xf0 [<9000000000348c74>] handle_irq_desc+0x94/0xb8 [<9000000001012b28>] handle_cpu_irq+0x68/0xa0 [<9000000001def8c0>] handle_loongarch_irq+0x30/0x48 [<9000000001def958>] do_vint+0x80/0xd0 [<9000000000268a0c>] kasan_mem_to_shadow.part.0+0x2c/0x2a0 [<90000000006344f4>] __asan_load8+0x4c/0x120 [<900000000025c0d0>] module_frob_arch_sections+0x5c8/0x6b8 [<90000000003895f0>] load_module+0x9e0/0x2958 [<900000000038b770>] __do_sys_init_module+0x208/0x2d0 [<9000000001df0c34>] do_syscall+0x94/0x190 [<900000000024d6fc>] handle_syscall+0xbc/0x158
After analysis, this is because the slow speed of loading the amdgpu module leads to the long time occupation of the cpu and then the soft deadlock.
When loading a module, module_frob_arch_sections() tries to figure out the number of PLTs/GOTs that will be needed to handle all the RELAs. It will call the count_max_entries() to find in an out-of-order date which counting algorithm has O(n^2) complexity.
To make it faster, we sort the relocation list by info and addend. That way, to check for a duplicate relocation, it just needs to compare with the previous entry. This reduces the complexity of the algorithm to O(n
log n), as done in commit d4e0340919fb ("arm64/module: Optimize module
load time by optimizing PLT counting"). This gives sinificant reduction in module load time for modules with large number of relocations.
After applying this patch, the soft deadlock problem has been solved, and the kernel starts normally without "Call Trace".
Using the default configuration to test some modules, the results are as follows:
Module Size ip_tables 36K fat 143K radeon 2.5MB amdgpu 16MB
Without this patch:
Module Module load time (ms) Count(PLTs/GOTs) ip_tables 18 59/6 fat 0 162/14 radeon 54 1221/84 amdgpu 1411 4525/1098
With this patch:
Module Module load time (ms) Count(PLTs/GOTs) ip_tables 18 59/6 fat 0 162/14 radeon 22 1221/84 amdgpu 45 4525/1098
--- arch/loongarch/kernel/module-sections.c | 36 ++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-)
arch/loongarch/kernel/module-sections.c +18 -18
@@ -6,6 +6,7 @@#include <linux/elf.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/sort.h> Elf_Addr module_emit_got_entry (struct module *mod,Elf_Addr val) {
@@ -59,39 +60,38 @@ Elf_Addr module_emit_plt_entry(struct module *mod, Elf_Addr val)return (Elf_Addr)&plt[nr]; } -static int is_rela_equal (const Elf_Rela *x,const Elf_Rela *y) -{ -return x->r_info == y->r_info && x->r_addend == y->r_addend; -} +#define cmp_3way (a, b) ((a) < (b) ? -1 : (a) > (b)) -static bool duplicate_rela (const Elf_Rela *rela,int idx) +static int compare_rela (const void *x,const void *y) { -int i; +int ret; +const Elf_Rela *rela_x = x, *rela_y = y; -for (i =0 ; i < idx; i++) { -if (is_rela_equal (&rela[i], &rela[idx])) -return true; - } + ret =cmp_3way (rela_x->r_info, rela_y->r_info); +if (ret ==0 ) + ret =cmp_3way (rela_x->r_addend, rela_y->r_addend); -return false; +return ret; }static void count_max_entries (Elf_Rela *relas,int num,unsigned int *plts,unsigned int *gots) { -unsigned int i, type; +unsigned int i; + +sort (relas, num,sizeof (Elf_Rela), compare_rela,NULL );for (i =0 ; i < num; i++) { - type =ELF_R_TYPE (relas[i].r_info); -switch (type) { +if (i && !compare_rela (&relas[i-1 ], &relas[i])) +continue ; + +switch (ELF_R_TYPE (relas[i].r_info)) {case R_LARCH_SOP_PUSH_PLT_PCREL :case R_LARCH_B26 : -if (!duplicate_rela (relas, i)) - (*plts)++; + (*plts)++;break ;case R_LARCH_GOT_PC_HI20 : -if (!duplicate_rela (relas, i)) - (*gots)++; + (*gots)++;break ;default :break ;/* Do nothing. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 840/1887 xfrm: Duplicate SPI Handling
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aakash Kumar S <[email protected]>
[ Upstream commit 94f39804d891cffe4ce17737d295f3b195bc7299 ]
The issue originates when Strongswan initiates an XFRM_MSG_ALLOCSPI Netlink message, which triggers the kernel function xfrm_alloc_spi(). This function is expected to ensure uniqueness of the Security Parameter Index (SPI) for inbound Security Associations (SAs). However, it can return success even when the requested SPI is already in use, leading to duplicate SPIs assigned to multiple inbound SAs, differentiated only by their destination addresses.
This behavior causes inconsistencies during SPI lookups for inbound packets. Since the lookup may return an arbitrary SA among those with the same SPI, packet processing can fail, resulting in packet drops.
According to RFC 4301 section 4.4.2 , for inbound processing a unicast SA is uniquely identified by the SPI and optionally protocol.
Reproducing the Issue Reliably:
To consistently reproduce the problem, restrict the available SPI range in charon.conf : spi_min = 0x10000000 spi_max = 0x10000002
This limits the system to only 2 usable SPI values.
Next, create more than 2 Child SA. each using unique pair of src/dst address. As soon as the 3rd Child SA is initiated, it will be assigned a duplicate SPI, since the SPI pool is already exhausted.
With a narrow SPI range, the issue is consistently reproducible. With a broader/default range, it becomes rare and unpredictable.
Current implementation:xfrm_spi_hash() lookup function computes hash using daddr, proto, and family. So if two SAs have the same SPI but different destination addresses, then they will:
a. Hash into different buckets
b. Be stored in different linked lists (byspi + h)
c. Not be seen in the same hlist_for_each_entry_rcu() iteration.
As a result, the lookup will result in NULL and kernel allows that Duplicate SPI
Proposed Change:xfrm_state_lookup_spi_proto() does a truly global search - across all states, regardless of hash bucket and matches SPI and proto.
--- net/xfrm/xfrm_state.c | 67 ++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 26 deletions(-)
net/xfrm/xfrm_state.c +41 -26
@@ -1304,6 +1304,26 @@ struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi, }EXPORT_SYMBOL (xfrm_state_lookup_byspi); +static struct xfrm_state *xfrm_state_lookup_spi_proto (struct net *net,__be32 spi,u8 proto) +{ +struct xfrm_state *x; +unsigned int i; + +rcu_read_lock (); +for (i =0 ; i <= net->xfrm.state_hmask; i++) { +hlist_for_each_entry_rcu (x, &net->xfrm.state_byspi[i], byspi) { +if (x->id.spi == spi && x->id.proto == proto) { +if (!xfrm_state_hold_rcu (x)) +continue ; +rcu_read_unlock (); +return x; + } + } + } +rcu_read_unlock (); +return NULL ; +} +static void __xfrm_state_insert (struct xfrm_state *x) {struct net *net =xs_net (x);
@@ -2091,10 +2111,8 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high)unsigned int h;struct xfrm_state *x0;int err = -ENOENT ; -__be32 minspi =htonl (low); -__be32 maxspi =htonl (high); +u32 range = high - low +1 ;__be32 newspi =0 ; -u32 mark = x->mark.v & x->mark.m;spin_lock_bh (&x->lock);if (x->km.state ==XFRM_STATE_DEAD )
@@ -2106,33 +2124,30 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high) err = -ENOENT ; -if (minspi == maxspi) { - x0 =xfrm_state_lookup (net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family); -if (x0) { -xfrm_state_put (x0); +for (h =0 ; h < range; h++) { +u32 spi = (low == high) ? low : low +prandom_u32_max (high - low +1 ); + newspi =htonl (spi); + +spin_lock_bh (&net->xfrm.xfrm_state_lock); + x0 =xfrm_state_lookup_spi_proto (net, newspi, x->id.proto); +if (!x0) { + x->id.spi = newspi; + h =xfrm_spi_hash (net, &x->id.daddr, newspi, x->id.proto, x->props.family); +hlist_add_head_rcu (&x->byspi, net->xfrm.state_byspi + h); +spin_unlock_bh (&net->xfrm.xfrm_state_lock); + err =0 ; goto unlock; } - newspi = minspi; - }else { -u32 spi =0 ; -for (h =0 ; h < high-low+1 ; h++) { - spi = low +prandom_u32_max (high - low +1 ); - x0 =xfrm_state_lookup (net, mark, &x->id.daddr,htonl (spi), x->id.proto, x->props.family); -if (x0 ==NULL ) { - newspi =htonl (spi); -break ; - } -xfrm_state_put (x0); - } - } -if (newspi) { -spin_lock_bh (&net->xfrm.xfrm_state_lock); - x->id.spi = newspi; - h =xfrm_spi_hash (net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family); -hlist_add_head_rcu (&x->byspi, net->xfrm.state_byspi + h); +xfrm_state_put (x0);spin_unlock_bh (&net->xfrm.xfrm_state_lock); - err =0 ; +if (signal_pending (current)) { + err = -ERESTARTSYS ; + goto unlock; + } + +if (low == high) +break ; } unlock:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 841/1887 bnxt_en: Fix memory corruption when FW resources change during ifdown
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sreekanth Reddy <[email protected]>
[ Upstream commit 2747328ba2714f1a7454208dbbc1dc0631990b4a ]
bnxt_set_dflt_rings() assumes that it is always called before any TC has been created. So it doesn't take bp->num_tc into account and assumes that it is always 0 or 1.
In the FW resource or capability change scenario, the FW will return flags in bnxt_hwrm_if_change() that will cause the driver to reinitialize and call bnxt_cancel_reservations(). This will lead to bnxt_init_dflt_ring_mode() calling bnxt_set_dflt_rings() and bp->num_tc may be greater than 1. This will cause bp->tx_ring[] to be sized too small and cause memory corruption in bnxt_alloc_cp_rings().
Fix it by properly scaling the TX rings by bp->num_tc in the code paths mentioned above. Add 2 helper functions to determine bp->tx_nr_rings and bp->tx_nr_rings_per_tc.
--- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 24 ++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +19 -5
@@ -10520,6 +10520,20 @@ static int bnxt_reinit_after_abort(struct bnxt *bp)return rc; } +static int bnxt_tx_nr_rings (struct bnxt *bp) +{ +int tcs =netdev_get_num_tc (bp->dev); + +return tcs ? bp->tx_nr_rings_per_tc * tcs : bp->tx_nr_rings_per_tc; +} + +static int bnxt_tx_nr_rings_per_tc (struct bnxt *bp) +{ +int tcs =netdev_get_num_tc (bp->dev); + +return tcs ? bp->tx_nr_rings / tcs : bp->tx_nr_rings; +} +static int __bnxt_open_nic (struct bnxt *bp,bool irq_re_init,bool link_re_init) {int rc =0 ;
@@ -13471,7 +13485,7 @@ static void bnxt_trim_dflt_sh_rings(struct bnxt *bp) bp->cp_nr_rings =min_t (int, bp->tx_nr_rings_per_tc, bp->rx_nr_rings); bp->rx_nr_rings = bp->cp_nr_rings; bp->tx_nr_rings_per_tc = bp->cp_nr_rings; - bp->tx_nr_rings = bp->tx_nr_rings_per_tc; + bp->tx_nr_rings =bnxt_tx_nr_rings (bp); }static int bnxt_set_dflt_rings (struct bnxt *bp,bool sh)
@@ -13502,12 +13516,12 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh)bnxt_trim_dflt_sh_rings (bp); else bp->cp_nr_rings = bp->tx_nr_rings_per_tc + bp->rx_nr_rings; - bp->tx_nr_rings = bp->tx_nr_rings_per_tc; + bp->tx_nr_rings =bnxt_tx_nr_rings (bp); rc =__bnxt_reserve_rings (bp);if (rc && rc != -ENODEV )netdev_warn (bp->dev,"Unable to reserve tx rings\n" ); - bp->tx_nr_rings_per_tc = bp->tx_nr_rings; + bp->tx_nr_rings_per_tc =bnxt_tx_nr_rings_per_tc (bp);if (sh)bnxt_trim_dflt_sh_rings (bp);
@@ -13516,7 +13530,7 @@ static int bnxt_set_dflt_rings(struct bnxt *bp, bool sh) rc =__bnxt_reserve_rings (bp);if (rc && rc != -ENODEV )netdev_warn (bp->dev,"2nd rings reservation failed.\n" ); - bp->tx_nr_rings_per_tc = bp->tx_nr_rings; + bp->tx_nr_rings_per_tc =bnxt_tx_nr_rings_per_tc (bp); }if (BNXT_CHIP_TYPE_NITRO_A0 (bp)) { bp->rx_nr_rings++;
@@ -13550,7 +13564,7 @@ static int bnxt_init_dflt_ring_mode(struct bnxt *bp)if (rc) goto init_dflt_ring_err; - bp->tx_nr_rings_per_tc = bp->tx_nr_rings; + bp->tx_nr_rings_per_tc =bnxt_tx_nr_rings_per_tc (bp);bnxt_set_dflt_rfs (bp);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 842/1887 trace/fgraph: Fix the warning caused by missing unregister notifier
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ye Weihua <[email protected]>
[ Upstream commit edede7a6dcd7435395cf757d053974aaab6ab1c2 ]
This warning was triggered during testing on v6.16:
notifier callback ftrace_suspend_notifier_call already registered
WARNING: CPU: 2 PID: 86 at kernel/notifier.c:23 notifier_chain_register+0x44/0xb0 ... Call Trace: <TASK> blocking_notifier_chain_register+0x34/0x60 register_ftrace_graph+0x330/0x410 ftrace_profile_write+0x1e9/0x340 vfs_write+0xf8/0x420 ? filp_flush+0x8a/0xa0 ? filp_close+0x1f/0x30 ? do_dup2+0xaf/0x160 ksys_write+0x65/0xe0 do_syscall_64+0xa4/0x260 entry_SYSCALL_64_after_hwframe+0x77/0x7f
When writing to the function_profile_enabled interface, the notifier was not unregistered after start_graph_tracing failed, causing a warning the next time function_profile_enabled was written.
Fixed by adding unregister_pm_notifier in the exception path.
--- kernel/trace/fgraph.c | 1 + 1 file changed, 1 insertion(+)
kernel/trace/fgraph.c +1 -0
@@ -623,6 +623,7 @@ int register_ftrace_graph(struct fgraph_ops *gops) ret =start_graph_tracing ();if (ret) { ftrace_graph_active--; +unregister_pm_notifier (&ftrace_suspend_notifier); goto out; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 843/1887 vxlan: Fix NPD in {arp,neigh}_reduce() when using nexthop objects
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit 1f5d2fd1ca04a23c18b1bde9a43ce2fa2ffa1bce ]
When the "proxy" option is enabled on a VXLAN device, the device will suppress ARP requests and IPv6 Neighbor Solicitation messages if it is able to reply on behalf of the remote host. That is, if a matching and valid neighbor entry is configured on the VXLAN device whose MAC address is not behind the "any" remote (0.0.0.0 / ::).
The code currently assumes that the FDB entry for the neighbor's MAC address points to a valid remote destination, but this is incorrect if the entry is associated with an FDB nexthop group. This can result in a NPD [1][3] which can be reproduced using [2][4].
Fix by checking that the remote destination exists before dereferencing it.
[1]
BUG: kernel NULL pointer dereference, address: 0000000000000000 [...] CPU: 4 UID: 0 PID: 365 Comm: arping Not tainted 6.17.0-rc2-virtme-g2a89cb21162c #2 PREEMPT(voluntary) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-4.fc41 04/01/2014 RIP: 0010:vxlan_xmit+0xb58/0x15f0 [...] Call Trace: <TASK> dev_hard_start_xmit+0x5d/0x1c0 __dev_queue_xmit+0x246/0xfd0 packet_sendmsg+0x113a/0x1850 __sock_sendmsg+0x38/0x70 __sys_sendto+0x126/0x180 __x64_sys_sendto+0x24/0x30 do_syscall_64+0xa4/0x260 entry_SYSCALL_64_after_hwframe+0x4b/0x53
[2]
#!/bin/bash
ip address add 192.0.2.1/32 dev lo
ip nexthop add id 1 via 192.0.2.2 fdb
ip nexthop add id 10 group 1 fdb
ip link add name vx0 up type vxlan id 10010 local 192.0.2.1 dstport 4789 proxy
ip neigh add 192.0.2.3 lladdr 00:11:22:33:44:55 nud perm dev vx0
bridge fdb add 00:11:22:33:44:55 dev vx0 self static nhid 10
arping -b -c 1 -s 192.0.2.1 -I vx0 192.0.2.3
[3]
BUG: kernel NULL pointer dereference, address: 0000000000000000 [...] CPU: 13 UID: 0 PID: 372 Comm: ndisc6 Not tainted 6.17.0-rc2-virtmne-g6ee90cb26014 #3 PREEMPT(voluntary) Hardware name: QEMU Standard PC (i440FX + PIIX, 1v996), BIOS 1.17.0-4.fc41 04/01/2x014 RIP: 0010:vxlan_xmit+0x803/0x1600 [...] Call Trace: <TASK> dev_hard_start_xmit+0x5d/0x1c0 __dev_queue_xmit+0x246/0xfd0 ip6_finish_output2+0x210/0x6c0 ip6_finish_output+0x1af/0x2b0 ip6_mr_output+0x92/0x3e0 ip6_send_skb+0x30/0x90 rawv6_sendmsg+0xe6e/0x12e0 __sock_sendmsg+0x38/0x70 __sys_sendto+0x126/0x180 __x64_sys_sendto+0x24/0x30 do_syscall_64+0xa4/0x260 entry_SYSCALL_64_after_hwframe+0x4b/0x53 RIP: 0033:0x7f383422ec77
[4]
#!/bin/bash
ip address add 2001:db8:1::1/128 dev lo
ip nexthop add id 1 via 2001:db8:1::1 fdb
ip nexthop add id 10 group 1 fdb
ip link add name vx0 up type vxlan id 10010 local 2001:db8:1::1 dstport 4789 proxy
ip neigh add 2001:db8:1::3 lladdr 00:11:22:33:44:55 nud perm dev vx0
bridge fdb add 00:11:22:33:44:55 dev vx0 self static nhid 10
ndisc6 -r 1 -s 2001:db8:1::1 -w 1 2001:db8:1::3 vx0
--- drivers/net/vxlan/vxlan_core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/net/vxlan/vxlan_core.c +8 -2
@@ -1943,6 +1943,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) n =neigh_lookup (&arp_tbl, &tip, dev);if (n) { +struct vxlan_rdst *rdst =NULL ;struct vxlan_fdb *f;struct sk_buff *reply;
@@ -1952,7 +1953,9 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) } f =vxlan_find_mac (vxlan, n->ha, vni); -if (f &&vxlan_addr_any (&(first_remote_rcu (f)->remote_ip))) { +if (f) + rdst =first_remote_rcu (f); +if (rdst &&vxlan_addr_any (&rdst->remote_ip)) {/* bridge-local neighbor */ neigh_release (n); goto out;
@@ -2111,6 +2114,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) n =neigh_lookup (ipv6_stub->nd_tbl, &msg->target, dev);if (n) { +struct vxlan_rdst *rdst =NULL ;struct vxlan_fdb *f;struct sk_buff *reply;
@@ -2120,7 +2124,9 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) } f =vxlan_find_mac (vxlan, n->ha, vni); -if (f &&vxlan_addr_any (&(first_remote_rcu (f)->remote_ip))) { +if (f) + rdst =first_remote_rcu (f); +if (rdst &&vxlan_addr_any (&rdst->remote_ip)) {/* bridge-local neighbor */ neigh_release (n); goto out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 844/1887 vxlan: Fix NPD when refreshing an FDB entry with a nexthop object
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit 6ead38147ebb813f08be6ea8ef547a0e4c09559a ]
VXLAN FDB entries can point to either a remote destination or an FDB nexthop group. The latter is usually used in EVPN deployments where learning is disabled.
However, when learning is enabled, an incoming packet might try to refresh an FDB entry that points to an FDB nexthop group and therefore does not have a remote. Such packets should be dropped, but they are only dropped after dereferencing the non-existent remote, resulting in a NPD [1] which can be reproduced using [2].
Fix by dropping such packets earlier. Remove the misleading comment from first_remote_rcu().
[1]
BUG: kernel NULL pointer dereference, address: 0000000000000000 [...] CPU: 13 UID: 0 PID: 361 Comm: mausezahn Not tainted 6.17.0-rc1-virtme-g9f6b606b6b37 #1 PREEMPT(voluntary) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-4.fc41 04/01/2014 RIP: 0010:vxlan_snoop+0x98/0x1e0 [...] Call Trace: <TASK> vxlan_encap_bypass+0x209/0x240 encap_bypass_if_local+0xb1/0x100 vxlan_xmit_one+0x1375/0x17e0 vxlan_xmit+0x6b4/0x15f0 dev_hard_start_xmit+0x5d/0x1c0 __dev_queue_xmit+0x246/0xfd0 packet_sendmsg+0x113a/0x1850 __sock_sendmsg+0x38/0x70 __sys_sendto+0x126/0x180 __x64_sys_sendto+0x24/0x30 do_syscall_64+0xa4/0x260 entry_SYSCALL_64_after_hwframe+0x4b/0x53
[2]
#!/bin/bash
ip address add 192.0.2.1/32 dev lo
ip address add 192.0.2.2/32 dev lo
ip nexthop add id 1 via 192.0.2.3 fdb
ip nexthop add id 10 group 1 fdb
ip link add name vx0 up type vxlan id 10010 local 192.0.2.1 dstport 12345 localbypass ip link add name vx1 up type vxlan id 10020 local 192.0.2.2 dstport 54321 learning
bridge fdb add 00:11:22:33:44:55 dev vx0 self static dst 192.0.2.2 port 54321 vni 10020 bridge fdb add 00:aa:bb:cc:dd:ee dev vx1 self static nhid 10
mausezahn vx0 -a 00:aa:bb:cc:dd:ee -b 00:11:22:33:44:55 -c 1 -q
--- drivers/net/vxlan/vxlan_core.c | 8 ++++---- drivers/net/vxlan/vxlan_private.h | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-)
drivers/net/vxlan/vxlan_core.c +4 -4
@@ -1522,6 +1522,10 @@ static bool vxlan_snoop(struct net_device *dev,if (likely (f)) {struct vxlan_rdst *rdst =first_remote_rcu (f); +/* Don't override an fdb with nexthop with a learnt entry */ +if (rcu_access_pointer (f->nh)) +return true; +if (likely (vxlan_addr_equal (&rdst->remote_ip, src_ip) && rdst->remote_ifindex == ifindex))return false;
@@ -1530,10 +1534,6 @@ static bool vxlan_snoop(struct net_device *dev,if (f->state & (NUD_PERMANENT |NUD_NOARP ))return true; -/* Don't override an fdb with nexthop with a learnt entry */ -if (rcu_access_pointer (f->nh)) -return true; -if (net_ratelimit ()) netdev_info(dev, "%pM migrated from %pIS to %pIS\n",
drivers/net/vxlan/vxlan_private.h +1 -3
@@ -56,9 +56,7 @@ static inline struct hlist_head *vs_head(struct net *net, __be16 port)return &vn->sock_list[hash_32 (ntohs (port),PORT_HASH_BITS )]; } -/* First remote destination for a forwarding entry. -* Guaranteed to be non-NULL because remotes are never deleted. -*/ +/* First remote destination for a forwarding entry. */ static inline struct vxlan_rdst *first_remote_rcu (struct vxlan_fdb *fdb) {if (rcu_access_pointer (fdb->nh))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 845/1887 ptp: ocp: fix use-after-free bugs causing by ptp_ocp_watchdog
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Duoming Zhou <[email protected]>
[ Upstream commit 8bf935cf789872350b04c1a6468b0a509f67afb2 ]
The ptp_ocp_detach() only shuts down the watchdog timer if it is pending. However, if the timer handler is already running, the timer_delete_sync() is not called. This leads to race conditions where the devlink that contains the ptp_ocp is deallocated while the timer handler is still accessing it, resulting in use-after-free bugs. The following details one of the race scenarios.
(thread 1) | (thread 2)
ptp_ocp_remove() |
ptp_ocp_detach() | ptp_ocp_watchdog()
if (timer_pending(&bp->watchdog))| bp = timer_container_of()
timer_delete_sync() |
|
devlink_free(devlink) //free |
| bp-> //useResolve this by unconditionally calling timer_delete_sync() to ensure the timer is reliably deactivated, preventing any access after free.
--- drivers/ptp/ptp_ocp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/ptp/ptp_ocp.c +1 -2
@@ -3673,8 +3673,7 @@ ptp_ocp_detach(struct ptp_ocp *bp)ptp_ocp_debugfs_remove_device (bp);ptp_ocp_detach_sysfs (bp);ptp_ocp_attr_group_del (bp); -if (timer_pending (&bp->watchdog)) -del_timer_sync (&bp->watchdog); +del_timer_sync (&bp->watchdog);if (bp->ts0)ptp_ocp_unregister_ext (bp->ts0);if (bp->ts1)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 846/1887 mm/vmalloc, mm/kasan: respect gfp mask in kasan_populate_vmalloc()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uladzislau Rezki (Sony) <[email protected]>
[ Upstream commit 79357cd06d41d0f5a11b17d7c86176e395d10ef2 ]
kasan_populate_vmalloc() and its helpers ignore the caller's gfp_mask and always allocate memory using the hardcoded GFP_KERNEL flag. This makes them inconsistent with vmalloc(), which was recently extended to support GFP_NOFS and GFP_NOIO allocations.
Page table allocations performed during shadow population also ignore the external gfp_mask. To preserve the intended semantics of GFP_NOFS and GFP_NOIO, wrap the apply_to_page_range() calls into the appropriate memalloc scope.
xfs calls vmalloc with GFP_NOFS, so this bug could lead to deadlock.
There was a report here
https://lkml.kernel.org/r/[email protected]
This patch:
- Extends kasan_populate_vmalloc() and helpers to take gfp_mask;
- Passes gfp_mask down to alloc_pages_bulk() and __get_free_page();
- Enforces GFP_NOFS/NOIO semantics with memalloc_*_save()/restore() around apply_to_page_range();
- Updates vmalloc.c and percpu allocator call sites accordingly.
--- include/linux/kasan.h | 6 +++--- mm/kasan/shadow.c | 31 ++++++++++++++++++++++++------- mm/vmalloc.c | 4 ++-- 3 files changed, 29 insertions(+), 12 deletions(-)
include/linux/kasan.h +3 -3
@@ -387,7 +387,7 @@ static inline void kasan_init_hw_tags(void) { }#if defined(CONFIG_KASAN_GENERIC ) || defined(CONFIG_KASAN_SW_TAGS )void kasan_populate_early_vm_area_shadow (void *start,unsigned long size); -int kasan_populate_vmalloc (unsigned long addr,unsigned long size); +int kasan_populate_vmalloc (unsigned long addr,unsigned long size,gfp_t gfp_mask);void kasan_release_vmalloc (unsigned long start,unsigned long end,unsigned long free_region_start,unsigned long free_region_end);
@@ -398,7 +398,7 @@ static inline void kasan_populate_early_vm_area_shadow(void *start, unsigned long size) { }static inline int kasan_populate_vmalloc (unsigned long start, -unsigned long size) +unsigned long size,gfp_t gfp_mask) {return 0 ; }
@@ -443,7 +443,7 @@ kasan_unpoison_vmap_areas(struct vm_struct **vms, int nr_vms,static inline void kasan_populate_early_vm_area_shadow (void *start,unsigned long size) { }static inline int kasan_populate_vmalloc (unsigned long start, -unsigned long size) +unsigned long size,gfp_t gfp_mask) {return 0 ; }
mm/kasan/shadow.c +24 -7
@@ -302,13 +302,13 @@ static void ___free_pages_bulk(struct page **pages, int nr_pages) } } -static int ___alloc_pages_bulk (struct page **pages,int nr_pages) +static int ___alloc_pages_bulk (struct page **pages,int nr_pages,gfp_t gfp_mask) {unsigned long nr_populated, nr_total = nr_pages;struct page **page_array = pages;while (nr_pages) { - nr_populated =alloc_pages_bulk_array (GFP_KERNEL , nr_pages, pages); + nr_populated =alloc_pages_bulk_array (gfp_mask, nr_pages, pages);if (!nr_populated) {___free_pages_bulk (page_array, nr_total - nr_pages);return -ENOMEM ;
@@ -320,25 +320,42 @@ static int ___alloc_pages_bulk(struct page **pages, int nr_pages)return 0 ; } -static int __kasan_populate_vmalloc (unsigned long start,unsigned long end) +static int __kasan_populate_vmalloc (unsigned long start,unsigned long end,gfp_t gfp_mask) {unsigned long nr_pages, nr_total =PFN_UP (end - start);struct vmalloc_populate_data data; +unsigned int flags;int ret =0 ; - data.pages = (struct page **)__get_free_page (GFP_KERNEL | __GFP_ZERO); + data.pages = (struct page **)__get_free_page (gfp_mask | __GFP_ZERO);if (!data.pages)return -ENOMEM ;while (nr_total) { nr_pages =min (nr_total,PAGE_SIZE /sizeof (data.pages[0 ])); - ret =___alloc_pages_bulk (data.pages, nr_pages); + ret =___alloc_pages_bulk (data.pages, nr_pages, gfp_mask);if (ret)break ; data.start = start; + +/* +* page tables allocations ignore external gfp mask, enforce it +* by the scope API +*/ +if ((gfp_mask & (__GFP_FS | __GFP_IO)) == __GFP_IO) + flags =memalloc_nofs_save (); +else if ((gfp_mask & (__GFP_FS | __GFP_IO)) ==0 ) + flags =memalloc_noio_save (); + ret =apply_to_page_range (&init_mm, start, nr_pages *PAGE_SIZE , kasan_populate_vmalloc_pte, &data); + +if ((gfp_mask & (__GFP_FS | __GFP_IO)) == __GFP_IO) +memalloc_nofs_restore (flags); +else if ((gfp_mask & (__GFP_FS | __GFP_IO)) ==0 ) +memalloc_noio_restore (flags); +___free_pages_bulk (data.pages, nr_pages);if (ret)break ;
@@ -352,7 +369,7 @@ static int __kasan_populate_vmalloc(unsigned long start, unsigned long end)return ret; } -int kasan_populate_vmalloc (unsigned long addr,unsigned long size) +int kasan_populate_vmalloc (unsigned long addr,unsigned long size,gfp_t gfp_mask) {unsigned long shadow_start, shadow_end;int ret;
@@ -381,7 +398,7 @@ int kasan_populate_vmalloc(unsigned long addr, unsigned long size) shadow_start =PAGE_ALIGN_DOWN (shadow_start); shadow_end =PAGE_ALIGN (shadow_end); - ret =__kasan_populate_vmalloc (shadow_start, shadow_end); + ret =__kasan_populate_vmalloc (shadow_start, shadow_end, gfp_mask);if (ret)return ret;
mm/vmalloc.c +2 -2
@@ -1708,7 +1708,7 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,BUG_ON (va->va_start < vstart);BUG_ON (va->va_end > vend); - ret =kasan_populate_vmalloc (addr, size); + ret =kasan_populate_vmalloc (addr, size, gfp_mask);if (ret) {free_vmap_area (va);return ERR_PTR (ret);
@@ -3997,7 +3997,7 @@ struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,/* populate the kasan shadow space */ for (area =0 ; area < nr_vms; area++) { -if (kasan_populate_vmalloc (vas[area]->va_start, sizes[area])) +if (kasan_populate_vmalloc (vas[area]->va_start, sizes[area],GFP_KERNEL )) goto err_free_shadow; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 847/1887 smb: client: let smbd_destroy() call disable_work_sync(&info->post_send_credits_work)
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Metzmacher <[email protected]>
[ Upstream commit d9dcbbcf9145b68aa85c40947311a6907277e097 ]
In smbd_destroy() we may destroy the memory so we better wait until post_send_credits_work is no longer pending and will never be started again.
I actually just hit the case using rxe:
WARNING: CPU: 0 PID: 138 at drivers/infiniband/sw/rxe/rxe_verbs.c:1032 rxe_post_recv+0x1ee/0x480 [rdma_rxe] ... [ 5305.686979] [ T138] smbd_post_recv+0x445/0xc10 [cifs] [ 5305.687135] [ T138] ? srso_alias_return_thunk+0x5/0xfbef5 [ 5305.687149] [ T138] ? __kasan_check_write+0x14/0x30 [ 5305.687185] [ T138] ? __pfx_smbd_post_recv+0x10/0x10 [cifs] [ 5305.687329] [ T138] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 5305.687356] [ T138] ? srso_alias_return_thunk+0x5/0xfbef5 [ 5305.687368] [ T138] ? srso_alias_return_thunk+0x5/0xfbef5 [ 5305.687378] [ T138] ? _raw_spin_unlock_irqrestore+0x11/0x60 [ 5305.687389] [ T138] ? srso_alias_return_thunk+0x5/0xfbef5 [ 5305.687399] [ T138] ? get_receive_buffer+0x168/0x210 [cifs] [ 5305.687555] [ T138] smbd_post_send_credits+0x382/0x4b0 [cifs] [ 5305.687701] [ T138] ? __pfx_smbd_post_send_credits+0x10/0x10 [cifs] [ 5305.687855] [ T138] ? __pfx___schedule+0x10/0x10 [ 5305.687865] [ T138] ? __pfx__raw_spin_lock_irq+0x10/0x10 [ 5305.687875] [ T138] ? queue_delayed_work_on+0x8e/0xa0 [ 5305.687889] [ T138] process_one_work+0x629/0xf80 [ 5305.687908] [ T138] ? srso_alias_return_thunk+0x5/0xfbef5 [ 5305.687917] [ T138] ? __kasan_check_write+0x14/0x30 [ 5305.687933] [ T138] worker_thread+0x87f/0x1570
...
It means rxe_post_recv was called after rdma_destroy_qp(). This happened because put_receive_buffer() was triggered by ib_drain_qp() and called:queue_work(info->workqueue, &info->post_send_credits_work);
--- fs/smb/client/smbdirect.c | 3 +++ 1 file changed, 3 insertions(+)
fs/smb/client/smbdirect.c +3 -0
@@ -1358,6 +1358,9 @@ void smbd_destroy(struct TCP_Server_Info *server) info->transport_status == SMBD_DISCONNECTED); } +log_rdma_event (INFO ,"cancelling post_send_credits_work\n" ); +cancel_work_sync (&info->post_send_credits_work); +log_rdma_event (INFO ,"destroying qp\n" );ib_drain_qp (info->id->qp);rdma_destroy_qp (info->id);
Signature · 1 line
2.53.0
Re: [PATCH 6.1 0847/1887] smb: client: let smbd_destroy() call disable_work_sync(&info->post_send_credits_work)
Hi Greg, Sasha
please see below on what may be potentially improved in managing these huge amounts of backports, many of which come with adaptations to old stable kernels.
Quoted 61 lines · Greg Kroah-Hartman
6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Metzmacher <[email protected]>
[ Upstream commit
d9dcbbcf9145b68aa85c40947311a6907277e097]In
smbd_destroy()we may destroy the memory so we better wait untilpost_send_credits_workis no longer pending and will never be started again.I actually just hit the case using rxe:
WARNING: CPU: 0 PID: 138 at drivers/infiniband/sw/rxe/rxe_verbs.c:1032 rxe_post_recv+0x1ee/0x480 [rdma_rxe] ... [ 5305.686979] [ T138] smbd_post_recv+0x445/0xc10 [cifs] [ 5305.687135] [ T138] ? srso_alias_return_thunk+0x5/0xfbef5 [ 5305.687149] [ T138] ? __kasan_check_write+0x14/0x30 [ 5305.687185] [ T138] ? __pfx_smbd_post_recv+0x10/0x10 [cifs] [ 5305.687329] [ T138] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 5305.687356] [ T138] ? srso_alias_return_thunk+0x5/0xfbef5 [ 5305.687368] [ T138] ? srso_alias_return_thunk+0x5/0xfbef5 [ 5305.687378] [ T138] ? _raw_spin_unlock_irqrestore+0x11/0x60 [ 5305.687389] [ T138] ? srso_alias_return_thunk+0x5/0xfbef5 [ 5305.687399] [ T138] ? get_receive_buffer+0x168/0x210 [cifs] [ 5305.687555] [ T138] smbd_post_send_credits+0x382/0x4b0 [cifs] [ 5305.687701] [ T138] ? __pfx_smbd_post_send_credits+0x10/0x10 [cifs] [ 5305.687855] [ T138] ? __pfx___schedule+0x10/0x10 [ 5305.687865] [ T138] ? __pfx__raw_spin_lock_irq+0x10/0x10 [ 5305.687875] [ T138] ? queue_delayed_work_on+0x8e/0xa0 [ 5305.687889] [ T138] process_one_work+0x629/0xf80 [ 5305.687908] [ T138] ? srso_alias_return_thunk+0x5/0xfbef5 [ 5305.687917] [ T138] ? __kasan_check_write+0x14/0x30 [ 5305.687933] [ T138] worker_thread+0x87f/0x1570...
It means
rxe_post_recvwas called afterrdma_destroy_qp(). This happened becauseput_receive_buffer()was triggered byib_drain_qp()and called:queue_work(info->workqueue, &info->post_send_credits_work);Cc Steve French <[email protected]>Cc Tom Talpey <[email protected]>Cc Long Li <[email protected]>Cc Namjae Jeon <[email protected]>Fixes f198186aa9bb ("CIFS: SMBD: Establish SMB Direct connection")Signed-off-by Stefan Metzmacher <[email protected]>Signed-off-by Steve French <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- fs/smb/client/smbdirect.c | 3 +++ 1 file changed, 3 insertions(+)fs/smb/client/smbdirect.c +0
-0
fs/smb/client/smbdirect.c void smbd_destroy(struct TCP_Server_Info *server) · line 1366
Quoted 9 lines
fs/smb/client/smbdirect.c +3
-0@@ -1358,6 +1358,9 @@ void smbd_destroy(struct TCP_Server_Info *server) info->transport_status == SMBD_DISCONNECTED); } +log_rdma_event (INFO ,"cancelling post_send_credits_work\n" ); +cancel_work_sync (&info->post_send_credits_work); +log_rdma_event (INFO ,"destroying qp\n" );ib_drain_qp (info->id->qp);rdma_destroy_qp (info->id);
It would be good to see a small backporter's comment, you know, on the reasons behind the performed backport adaptation. Upstream commit adds a call to disable_work_sync(), while the backport only does cancel_work_sync() - and doesn't look to solve the problem completely. The commit's message says the work can be queued again during ib_drain_qp() processing a few lines below. So canceling is not enough.
However, there is no info on why cancel_work_sync() was chosen still: to reduce the existing race window as best effort, or maybe just calling cancel_work_sync() is actually fine on 6.1 and fixes the bug properly?
I guess that adding a brief backporter's comment explaining the rationale behind the adaptation won't be too resource-consuming on your side, especially if major part is already done with AI stuff. But it will make things clearer on whether the backport fix is correct and complete.
--
Fedor
Greg Kroah-Hartman
maintainerPATCH 848/1887 smb: client: let recv_done verify data_offset, data_length and remaining_data_length
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Metzmacher <[email protected]>
[ Upstream commit f57e53ea252363234f86674db475839e5b87102e ]
This is inspired by the related server fixes.
--- fs/smb/client/smbdirect.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
fs/smb/client/smbdirect.c +18 -1
@@ -461,7 +461,9 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)struct smbd_response *response = container_of(wc->wr_cqe, struct smbd_response, cqe);struct smbd_connection *info = response->info; -int data_length =0 ; +u32 data_offset =0 ; +u32 data_length =0 ; +u32 remaining_data_length =0 ; log_rdma_recv(INFO, "response=0x%p type=%d wc status=%d wc opcode %d byte_len=%d pkey_index=%u\n", response, response->type, wc->status, wc->opcode,
@@ -493,7 +495,22 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)/* SMBD data transfer packet */ case SMBD_TRANSFER_DATA : data_transfer =smbd_response_payload (response); + +if (wc->byte_len < + offsetof(struct smbd_data_transfer , padding)) + goto error; + + remaining_data_length =le32_to_cpu (data_transfer->remaining_data_length); + data_offset =le32_to_cpu (data_transfer->data_offset); data_length =le32_to_cpu (data_transfer->data_length); +if (wc->byte_len < data_offset || + (u64 )wc->byte_len < (u64 )data_offset + data_length) + goto error; + +if (remaining_data_length > info->max_fragmented_recv_size || + data_length > info->max_fragmented_recv_size || + (u64 )remaining_data_length + (u64 )data_length > (u64 )info->max_fragmented_recv_size) + goto error;/* * If this is a packet with data playload place the data in
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 849/1887 wifi: wilc1000: avoid buffer overflow in WID string configuration
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: [email protected] <[email protected]>
[ Upstream commit fe9e4d0c39311d0f97b024147a0d155333f388b5 ]
Fix the following copy overflow warning identified by Smatch checker.
drivers/net/wireless/microchip/wilc1000/wlan_cfg.c:184 wilc_wlan_parse_response_frame()
error: '__memcpy()' 'cfg->s[i]->str' copy overflow (512 vs 65537)
This patch introduces size check before accessing the memory buffer. The checks are base on the WID type of received data from the firmware. For WID string configuration, the size limit is determined by individual element size in 'struct wilc_cfg_str_vals' that is maintained in 'len' field of 'struct wilc_cfg_str'.
--- .../wireless/microchip/wilc1000/wlan_cfg.c | 37 ++++++++++++++----- .../wireless/microchip/wilc1000/wlan_cfg.h | 5 ++- 2 files changed, 30 insertions(+), 12 deletions(-)
drivers/net/wireless/microchip/wilc1000/wlan_cfg.c +27 -10
@@ -41,10 +41,10 @@ static const struct wilc_cfg_word g_cfg_word[] = { };static const struct wilc_cfg_str g_cfg_str[] = { - {WID_FIRMWARE_VERSION ,NULL }, - {WID_MAC_ADDR ,NULL }, - {WID_ASSOC_RES_INFO ,NULL }, - {WID_NIL ,NULL } + {WID_FIRMWARE_VERSION ,0 ,NULL }, + {WID_MAC_ADDR ,0 ,NULL }, + {WID_ASSOC_RES_INFO ,0 ,NULL }, + {WID_NIL ,0 ,NULL } };#define WILC_RESP_MSG_TYPE_CONFIG_REPLY 'R'
@@ -147,44 +147,58 @@ static void wilc_wlan_parse_response_frame(struct wilc *wl, u8 *info, int size)switch (FIELD_GET (WILC_WID_TYPE , wid)) {case WID_CHAR : + len =3 ; +if (len +2 > size) +return ; +while (cfg->b[i].id !=WID_NIL && cfg->b[i].id != wid) i++;if (cfg->b[i].id == wid) cfg->b[i].val = info[4 ]; - len =3 ;break ;case WID_SHORT : + len =4 ; +if (len +2 > size) +return ; +while (cfg->hw[i].id !=WID_NIL && cfg->hw[i].id != wid) i++;if (cfg->hw[i].id == wid) cfg->hw[i].val =get_unaligned_le16 (&info[4 ]); - len =4 ;break ;case WID_INT : + len =6 ; +if (len +2 > size) +return ; +while (cfg->w[i].id !=WID_NIL && cfg->w[i].id != wid) i++;if (cfg->w[i].id == wid) cfg->w[i].val =get_unaligned_le32 (&info[4 ]); - len =6 ;break ;case WID_STR : + len =2 +get_unaligned_le16 (&info[2 ]); +while (cfg->s[i].id !=WID_NIL && cfg->s[i].id != wid) i++; -if (cfg->s[i].id == wid) +if (cfg->s[i].id == wid) { +if (len > cfg->s[i].len || (len +2 > size)) +return ; +memcpy (cfg->s[i].str, &info[2 ], -get_unaligned_le16 (&info[2 ]) +2 ); + len); + } - len =2 +get_unaligned_le16 (&info[2 ]);break ;default :
@@ -384,12 +398,15 @@ int wilc_wlan_cfg_init(struct wilc *wl)/* store the string cfg parameters */ wl->cfg.s[i].id =WID_FIRMWARE_VERSION ; wl->cfg.s[i].str = str_vals->firmware_version; + wl->cfg.s[i].len =sizeof (str_vals->firmware_version); i++; wl->cfg.s[i].id =WID_MAC_ADDR ; wl->cfg.s[i].str = str_vals->mac_address; + wl->cfg.s[i].len =sizeof (str_vals->mac_address); i++; wl->cfg.s[i].id =WID_ASSOC_RES_INFO ; wl->cfg.s[i].str = str_vals->assoc_rsp; + wl->cfg.s[i].len =sizeof (str_vals->assoc_rsp); i++; wl->cfg.s[i].id =WID_NIL ; wl->cfg.s[i].str =NULL ;
drivers/net/wireless/microchip/wilc1000/wlan_cfg.h +3 -2
@@ -24,12 +24,13 @@ struct wilc_cfg_word {struct wilc_cfg_str {u16 id; +u16 len;u8 *str; };struct wilc_cfg_str_vals { -u8 mac_address[7 ]; -u8 firmware_version[129 ]; +u8 mac_address[8 ]; +u8 firmware_version[130 ];u8 assoc_rsp[256 ]; };
Signature · 1 line
2.53.0