summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeon Romanovsky <leonro@nvidia.com>2026-08-30 14:16:19 +0300
committerBjorn Helgaas <bhelgaas@google.com>2026-09-11 15:23:30 -0500
commitaed1ebc4d8a25436938b50d93d964500185d205c (patch)
tree29021b11b4348c480f0a31cda027f590e03cb6a6
parent78a60dd7afb54ed9422247efb57c7a9a6011f2d7 (diff)
downloadlinux-next-aed1ebc4d8a25436938b50d93d964500185d205c.tar.gz
linux-next-aed1ebc4d8a25436938b50d93d964500185d205c.zip
PCI/P2PDMA: Do not tear down the allocate attribute on registration failure
pci_p2pdma_add_resource() installs pci_p2pdma_unmap_mappings() as a devres action with the devres allocated p2p_pgmap as its data, and only then adds the range to the pool: error = devm_add_action_or_reset(&pdev->dev, pci_p2pdma_unmap_mappings, p2p_pgmap); if (error) goto pages_free; p2pdma = rcu_dereference_protected(pdev->p2pdma, 1); error = gen_pool_add_owner(p2pdma->pool, ...); if (error) goto pages_free; The action removes the allocate attribute for the whole device, which tears down existing userspace mappings of every BAR already registered on it. Both failures here get that wrong, in opposite ways. devm_add_action_or_reset() runs the action when it cannot allocate its devres node, so an -ENOMEM while registering a second BAR unmaps the first one. Use devm_add_action() and let the error path unwind only what this call created. gen_pool_add_owner() allocates a chunk and can also fail with -ENOMEM. There the action is registered, and the error path frees p2p_pgmap with devm_kfree() while leaving the action pointing at it. On unbind devres runs the action and pci_p2pdma_unmap_mappings() dereferences p2p_pgmap->mem->owner->kobj, which is freed memory. Give that failure its own label and drop the action with devm_remove_action(), which removes it without running it. Fixes: 7e9c7ef83d78 ("PCI/P2PDMA: Allow userspace VMA allocations through sysfs") Fixes: f58ef9d1d135 ("PCI/P2PDMA: Separate the mmap() support from the core logic") Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Tested-by: Tushar Dave <tdave@nvidia.com> Reviewed-by: Logan Gunthorpe <logang@deltatee.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Link: https://patch.msgid.link/20260830-batch-p2p-fixes-v1-1-5044e8dfbe2e@nvidia.com
-rw-r--r--drivers/pci/p2pdma.c8
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 9fbbf1692f0e..ff9f2cc7bf8d 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -440,8 +440,8 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
goto pgmap_free;
}
- error = devm_add_action_or_reset(&pdev->dev, pci_p2pdma_unmap_mappings,
- p2p_pgmap);
+ error = devm_add_action(&pdev->dev, pci_p2pdma_unmap_mappings,
+ p2p_pgmap);
if (error)
goto pages_free;
@@ -451,13 +451,15 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size,
range_len(&pgmap->range), dev_to_node(&pdev->dev),
&pgmap->ref);
if (error)
- goto pages_free;
+ goto mappings_remove;
pci_info(pdev, "added peer-to-peer DMA memory %#llx-%#llx\n",
pgmap->range.start, pgmap->range.end);
return 0;
+mappings_remove:
+ devm_remove_action(&pdev->dev, pci_p2pdma_unmap_mappings, p2p_pgmap);
pages_free:
devm_memunmap_pages(&pdev->dev, pgmap);
pgmap_free: