Skip to content

Commit ac9a48a

Browse files
walking-machineAlexei Starovoitov
authored andcommitted
xsk: always clear DMA mapping information when unmapping the pool
When the umem is shared, the DMA mapping is also shared between the xsk pools, therefore it should stay valid as long as at least 1 user remains. However, the pool also keeps the copies of DMA-related information that are initialized in the same way in xp_init_dma_info(), but cleared by xp_dma_unmap() only for the last remaining pool, this causes the problems below. The first one is that the commit adbf5a4 ("ice: remove af_xdp_zc_qps bitmap") relies on pool->dev to determine the presence of a ZC pool on a given queue, avoiding internal bookkeeping. This works perfectly fine if the UMEM is not shared, but reliably fails otherwise as stated in the linked report. The second one is pool->dma_pages which is dynamically allocated and only freed in xp_dma_unmap(), this leads to a small memory leak. kmemleak does not catch it, but by printing the allocation results after terminating the userspace program it is possible to see that all addresses except the one belonging to the last detached pool are still accessible through the kmemleak dump functionality. Always clear the DMA mapping information from the pool and free pool->dma_pages when unmapping the pool, so that the only difference between results of the last remaining user's call and the ones before would be the destruction of the DMA mapping. Fixes: adbf5a4 ("ice: remove af_xdp_zc_qps bitmap") Fixes: 921b686 ("xsk: Enable sharing of dma mappings") Reported-by: Alasdair McWilliam <[email protected]> Closes: https://lore.kernel.org/PA4P194MB10056F208AF221D043F57A3D86512@PA4P194MB1005.EURP194.PROD.OUTLOOK.COM Acked-by: Maciej Fijalkowski <[email protected]> Signed-off-by: Larysa Zaremba <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 7ca0884 commit ac9a48a

File tree

1 file changed

+2
-3
lines changed

1 file changed

+2
-3
lines changed

net/xdp/xsk_buff_pool.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -387,10 +387,9 @@ void xp_dma_unmap(struct xsk_buff_pool *pool, unsigned long attrs)
387387
return;
388388
}
389389

390-
if (!refcount_dec_and_test(&dma_map->users))
391-
return;
390+
if (refcount_dec_and_test(&dma_map->users))
391+
__xp_dma_unmap(dma_map, attrs);
392392

393-
__xp_dma_unmap(dma_map, attrs);
394393
kvfree(pool->dma_pages);
395394
pool->dma_pages = NULL;
396395
pool->dma_pages_cnt = 0;

0 commit comments

Comments
 (0)