summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi RongQing <lirongqing@baidu.com>2026-02-06 08:08:36 +0300
committerJason Gunthorpe <jgg@nvidia.com>2026-04-28 17:15:49 +0300
commit76b48a70b16b4036814964b039cde413e0164416 (patch)
tree16a29e62d91df65f826edbb9c714aa4abd808ec9
parent254f49634ee16a731174d2ae34bc50bd5f45e731 (diff)
downloadlinux-76b48a70b16b4036814964b039cde413e0164416.tar.xz
IB/hfi1: Fix potential use-after-free in PIO and SDMA map teardown
The current teardown logic for dd->pio_map and dd->sdma_map frees the structures while they might still be accessed by RCU readers. Although the pointer is nulled under a spinlock, the memory is reclaimed before waiting for the grace period to end. This patch fixes the sequence by: 1. Extracting the pointer under the lock. 2. Clearing the RCU-protected pointer. 3. Waiting for readers to finish with synchronize_rcu(). 4. Finally freeing the memory. Fixes: 7724105686e7 ("IB/hfi1: add driver files") Link: https://patch.msgid.link/r/20260206050836.5890-1-lirongqing@baidu.com Signed-off-by: Li RongQing <lirongqing@baidu.com> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
-rw-r--r--drivers/infiniband/hw/hfi1/pio.c5
-rw-r--r--drivers/infiniband/hw/hfi1/sdma.c4
2 files changed, 7 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c
index 51afaac88c72..9121d83bf88a 100644
--- a/drivers/infiniband/hw/hfi1/pio.c
+++ b/drivers/infiniband/hw/hfi1/pio.c
@@ -1942,13 +1942,16 @@ bail:
void free_pio_map(struct hfi1_devdata *dd)
{
+ struct pio_vl_map *map;
+
/* Free PIO map if allocated */
if (rcu_access_pointer(dd->pio_map)) {
spin_lock_irq(&dd->pio_map_lock);
- pio_map_free(rcu_access_pointer(dd->pio_map));
+ map = rcu_access_pointer(dd->pio_map);
RCU_INIT_POINTER(dd->pio_map, NULL);
spin_unlock_irq(&dd->pio_map_lock);
synchronize_rcu();
+ pio_map_free(map);
}
kfree(dd->kernel_send_context);
dd->kernel_send_context = NULL;
diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c
index e5f442938177..cfd9dd0f7e81 100644
--- a/drivers/infiniband/hw/hfi1/sdma.c
+++ b/drivers/infiniband/hw/hfi1/sdma.c
@@ -1255,6 +1255,7 @@ void sdma_clean(struct hfi1_devdata *dd, size_t num_engines)
{
size_t i;
struct sdma_engine *sde;
+ struct sdma_vl_map *map;
if (dd->sdma_pad_dma) {
dma_free_coherent(&dd->pcidev->dev, SDMA_PAD,
@@ -1291,10 +1292,11 @@ void sdma_clean(struct hfi1_devdata *dd, size_t num_engines)
}
if (rcu_access_pointer(dd->sdma_map)) {
spin_lock_irq(&dd->sde_map_lock);
- sdma_map_free(rcu_access_pointer(dd->sdma_map));
+ map = rcu_access_pointer(dd->sdma_map);
RCU_INIT_POINTER(dd->sdma_map, NULL);
spin_unlock_irq(&dd->sde_map_lock);
synchronize_rcu();
+ sdma_map_free(map);
}
kfree(dd->per_sdma);
dd->per_sdma = NULL;