mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-22 03:27:30 -04:00
RDMA/umem: Be careful about boundary conditions in ib_umem_find_best_pgsz()
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 Link: https://patch.msgid.link/r/2-v1-88303e9e509f+f7-ib_umem_types_jgg@nvidia.com Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user