[PATCH] powerpc/iommu: Fix notifiers being shared by PCI and VIO buses
R Nageswara Sastry
rnsastry at linux.ibm.com
Wed Mar 22 23:49:36 AEDT 2023
On 22/03/23 9:23 am, Russell Currey wrote:
> fail_iommu_setup() registers the fail_iommu_bus_notifier struct to both
> PCI and VIO buses. struct notifier_block is a linked list node, so this
> causes any notifiers later registered to either bus type to also be
> registered to the other since they share the same node.
>
> This causes issues in (at least) the vgaarb code, which registers a
> notifier for PCI buses. pci_notify() ends up being called on a vio
> device, converted with to_pci_dev() even though it's not a PCI device,
> and finally makes a bad access in vga_arbiter_add_pci_device() as
> discovered with KASAN:
>
> BUG: KASAN: slab-out-of-bounds in vga_arbiter_add_pci_device+0x60/0xe00
> Read of size 4 at addr c000000264c26fdc by task swapper/0/1
>
> Call Trace:
> [c000000263607520] [c000000010f7023c] dump_stack_lvl+0x1bc/0x2b8 (unreliable)
> [c000000263607560] [c00000000f142a64] print_report+0x3f4/0xc60
> [c000000263607640] [c00000000f142144] kasan_report+0x244/0x698
> [c000000263607740] [c00000000f1460e8] __asan_load4+0xe8/0x250
> [c000000263607760] [c00000000ff4b850] vga_arbiter_add_pci_device+0x60/0xe00
> [c000000263607850] [c00000000ff4c678] pci_notify+0x88/0x444
> [c0000002636078b0] [c00000000e94dfc4] notifier_call_chain+0x104/0x320
> [c000000263607950] [c00000000e94f050] blocking_notifier_call_chain+0xa0/0x140
> [c000000263607990] [c0000000100cb3b8] device_add+0xac8/0x1d30
> [c000000263607aa0] [c0000000100ccd98] device_register+0x58/0x80
> [c000000263607ad0] [c00000000e84247c] vio_register_device_node+0x9ac/0xce0
> [c000000263607ba0] [c0000000126c95d8] vio_bus_scan_register_devices+0xc4/0x13c
> [c000000263607bd0] [c0000000126c96e4] __machine_initcall_pseries_vio_device_init+0x94/0xf0
> [c000000263607c00] [c00000000e69467c] do_one_initcall+0x12c/0xaa8
> [c000000263607cf0] [c00000001268b8a8] kernel_init_freeable+0xa48/0xba8
> [c000000263607dd0] [c00000000e695f24] kernel_init+0x64/0x400
> [c000000263607e50] [c00000000e68e0e4] ret_from_kernel_thread+0x5c/0x64
>
> Fix this by creating separate notifier_block structs for each bus type.
>
> Fixes: d6b9a81b2a45 ("powerpc: IOMMU fault injection")
> Reported-by: Nageswara R Sastry <rnsastry at linux.ibm.com>
> Signed-off-by: Russell Currey <ruscur at russell.cc>
Tested-by: Nageswara R Sastry <rnsastry at linux.ibm.com>
> ---
> arch/powerpc/kernel/iommu.c | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
> index ee95937bdaf1..6f1117fe3870 100644
> --- a/arch/powerpc/kernel/iommu.c
> +++ b/arch/powerpc/kernel/iommu.c
> @@ -171,17 +171,26 @@ static int fail_iommu_bus_notify(struct notifier_block *nb,
> return 0;
> }
>
> -static struct notifier_block fail_iommu_bus_notifier = {
> +/*
> + * PCI and VIO buses need separate notifier_block structs, since they're linked
> + * list nodes. Sharing a notifier_block would mean that any notifiers later
> + * registered for PCI buses would also get called by VIO buses and vice versa.
> + */
> +static struct notifier_block fail_iommu_pci_bus_notifier = {
> + .notifier_call = fail_iommu_bus_notify
> +};
> +
> +static struct notifier_block fail_iommu_vio_bus_notifier = {
> .notifier_call = fail_iommu_bus_notify
> };
>
> static int __init fail_iommu_setup(void)
> {
> #ifdef CONFIG_PCI
> - bus_register_notifier(&pci_bus_type, &fail_iommu_bus_notifier);
> + bus_register_notifier(&pci_bus_type, &fail_iommu_pci_bus_notifier);
> #endif
> #ifdef CONFIG_IBMVIO
> - bus_register_notifier(&vio_bus_type, &fail_iommu_bus_notifier);
> + bus_register_notifier(&vio_bus_type, &fail_iommu_vio_bus_notifier);
> #endif
>
> return 0;
--
Thanks and Regards
R.Nageswara Sastry
More information about the Linuxppc-dev
mailing list