* [PATCH 1/3] RDMA/umem: Fix truncation for block sizes >= 4G
2026-06-01 16:52 [PATCH 0/3] Fix typing issues in the umem code Jason Gunthorpe
@ 2026-06-01 16:52 ` Jason Gunthorpe
2026-06-01 16:52 ` [PATCH 2/3] RDMA/umem: Be careful about boundary conditions in ib_umem_find_best_pgsz() Jason Gunthorpe
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Jason Gunthorpe @ 2026-06-01 16:52 UTC (permalink / raw)
To: Leon Romanovsky, linux-rdma; +Cc: patches, Shiraz Saleem, stable
When the iommu is used the linearization of the mapping can give a single
block that is very large split across multiple SG entries.
When __rdma_block_iter_next() reassembles the split SG entries it is
overflowing the 32 bit stack values and computed the wrong DMA addresses
for blocks after the truncation.
Use the right types to hold DMA addresses.
Cc: stable@vger.kernel.org
Fixes: a808273a495c ("RDMA/verbs: Add a DMA iterator to return aligned contiguous memory blocks")
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/infiniband/core/iter.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/infiniband/core/iter.c b/drivers/infiniband/core/iter.c
index 8e543d100657ee..3ed351e8fcf6c9 100644
--- a/drivers/infiniband/core/iter.c
+++ b/drivers/infiniband/core/iter.c
@@ -19,8 +19,8 @@ EXPORT_SYMBOL(__rdma_block_iter_start);
bool __rdma_block_iter_next(struct ib_block_iter *biter)
{
- unsigned int block_offset;
- unsigned int delta;
+ dma_addr_t block_offset;
+ dma_addr_t delta;
if (!biter->__sg_nents || !biter->__sg)
return false;
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/3] RDMA/umem: Be careful about boundary conditions in ib_umem_find_best_pgsz()
2026-06-01 16:52 [PATCH 0/3] Fix typing issues in the umem code Jason Gunthorpe
2026-06-01 16:52 ` [PATCH 1/3] RDMA/umem: Fix truncation for block sizes >= 4G Jason Gunthorpe
@ 2026-06-01 16:52 ` Jason Gunthorpe
2026-06-01 16:52 ` [PATCH 3/3] RDMA/umem: Make ib_umem_is_contiguous() safe on 32 bit Jason Gunthorpe
2026-06-03 12:41 ` [PATCH 0/3] Fix typing issues in the umem code Jason Gunthorpe
3 siblings, 0 replies; 5+ messages in thread
From: Jason Gunthorpe @ 2026-06-01 16:52 UTC (permalink / raw)
To: Leon Romanovsky, linux-rdma; +Cc: patches, Shiraz Saleem, stable
Several corner cases, especially important on 32 bits:
- umem->iova is u64, the function argument should pass in u64 or
iova will be truncated
- Check that the length is not too large for the iova
- Check that lengths > 4G don't overflow the GENMASK
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/infiniband/core/umem.c | 18 ++++++++++++------
include/rdma/ib_umem.h | 4 ++--
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c
index e424a9de66c177..fd8f3888da5227 100644
--- a/drivers/infiniband/core/umem.c
+++ b/drivers/infiniband/core/umem.c
@@ -84,14 +84,17 @@ static void __ib_umem_release(struct ib_device *dev, struct ib_umem *umem, int d
*/
unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
unsigned long pgsz_bitmap,
- unsigned long virt)
+ u64 virt)
{
unsigned long curr_len = 0;
dma_addr_t curr_base = ~0;
- unsigned long va, pgoff;
+ unsigned long pgoff;
struct scatterlist *sg;
- dma_addr_t mask;
+ unsigned long mask = 0;
+ unsigned int bits;
dma_addr_t end;
+ u64 last_va;
+ u64 va;
int i;
umem->iova = va = virt;
@@ -109,9 +112,12 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
* number of required pages. Compute the largest page size that could
* work based on VA address bits that don't change.
*/
- mask = pgsz_bitmap &
- GENMASK(BITS_PER_LONG - 1,
- bits_per((umem->length - 1 + virt) ^ virt));
+ if (check_add_overflow(umem->length - 1, virt, &last_va))
+ return 0;
+ bits = bits_per(virt ^ last_va);
+ if (bits < BITS_PER_LONG)
+ mask = pgsz_bitmap & GENMASK(BITS_PER_LONG - 1, bits);
+
/* offset into first SGL */
pgoff = umem->address & ~PAGE_MASK;
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index bc1e6ed73b3f49..4c8f433ba246f3 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -109,7 +109,7 @@ int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offset,
size_t length);
unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
unsigned long pgsz_bitmap,
- unsigned long virt);
+ u64 virt);
/**
* ib_umem_find_best_pgoff - Find best HW page size
@@ -234,7 +234,7 @@ static inline int ib_umem_copy_from(void *dst, struct ib_umem *umem, size_t offs
}
static inline unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,
unsigned long pgsz_bitmap,
- unsigned long virt)
+ u64 virt)
{
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 3/3] RDMA/umem: Make ib_umem_is_contiguous() safe on 32 bit
2026-06-01 16:52 [PATCH 0/3] Fix typing issues in the umem code Jason Gunthorpe
2026-06-01 16:52 ` [PATCH 1/3] RDMA/umem: Fix truncation for block sizes >= 4G Jason Gunthorpe
2026-06-01 16:52 ` [PATCH 2/3] RDMA/umem: Be careful about boundary conditions in ib_umem_find_best_pgsz() Jason Gunthorpe
@ 2026-06-01 16:52 ` Jason Gunthorpe
2026-06-03 12:41 ` [PATCH 0/3] Fix typing issues in the umem code Jason Gunthorpe
3 siblings, 0 replies; 5+ messages in thread
From: Jason Gunthorpe @ 2026-06-01 16:52 UTC (permalink / raw)
To: Leon Romanovsky, linux-rdma; +Cc: patches, Shiraz Saleem, stable
Sashiko points out the roundup_pow_of_two() only uses unsigned long but
dma_addr_t can be u64.
Change this algorithm to be simpler, compute the page size, if any page
size is found and it results in a single block then it is contiguous.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
include/rdma/ib_umem.h | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index 4c8f433ba246f3..bb4005a9c69066 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -145,16 +145,11 @@ static inline unsigned long ib_umem_find_best_pgoff(struct ib_umem *umem,
static inline bool ib_umem_is_contiguous(struct ib_umem *umem)
{
- dma_addr_t dma_addr;
unsigned long pgsz;
- /*
- * Select the smallest aligned page that can contain the whole umem if
- * it was contiguous.
- */
- dma_addr = ib_umem_start_dma_addr(umem);
- pgsz = roundup_pow_of_two((dma_addr ^ (umem->length - 1 + dma_addr)) + 1);
- return !!ib_umem_find_best_pgoff(umem, pgsz, U64_MAX);
+ pgsz = ib_umem_find_best_pgsz(umem, ULONG_MAX,
+ ib_umem_start_dma_addr(umem));
+ return pgsz && ib_umem_num_dma_blocks(umem, pgsz) == 1;
}
struct ib_umem_dmabuf *ib_umem_dmabuf_get(struct ib_device *device,
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH 0/3] Fix typing issues in the umem code
2026-06-01 16:52 [PATCH 0/3] Fix typing issues in the umem code Jason Gunthorpe
` (2 preceding siblings ...)
2026-06-01 16:52 ` [PATCH 3/3] RDMA/umem: Make ib_umem_is_contiguous() safe on 32 bit Jason Gunthorpe
@ 2026-06-03 12:41 ` Jason Gunthorpe
3 siblings, 0 replies; 5+ messages in thread
From: Jason Gunthorpe @ 2026-06-03 12:41 UTC (permalink / raw)
To: Leon Romanovsky, linux-rdma; +Cc: patches, Shiraz Saleem, stable
On Mon, Jun 01, 2026 at 01:52:30PM -0300, Jason Gunthorpe wrote:
> The types are tricky here as we have a mixture of u64, dma_addr_t and
> unsigned long used purposefully for different things:
> - The on-the-wire IOVA address of the MR is u64
> - The dma address is dma_addr_t which can be u32 or u64
> - unsigned long is used for pgsize, mostly because a bunch of bit math
> helper functions are used and they are obnoxious to use u64
>
> Fix various silent truncations, issues on 32 bit compiles and
> understandability.
>
> Jason Gunthorpe (3):
> RDMA/umem: Fix truncation for block sizes >= 4G
> RDMA/umem: Be careful about boundary conditions in
> ib_umem_find_best_pgsz()
> RDMA/umem: Make ib_umem_is_contiguous() safe on 32 bit
I picked up t he first patch to -rc
Jason
^ permalink raw reply [flat|nested] 5+ messages in thread