]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/irdma: Prevent overflows in memory contiguity checks
authorAleksandrova Alyona <aga@itb.spb.ru>
Wed, 24 Jun 2026 14:48:46 +0000 (17:48 +0300)
committerLeon Romanovsky <leon@kernel.org>
Sun, 5 Jul 2026 11:02:35 +0000 (07:02 -0400)
irdma_check_mem_contiguous() and irdma_check_mr_contiguous() verify that
PBL entries describe physically contiguous memory ranges.

Both functions calculate byte offsets using 32-bit operands. For example,
with 4 KiB pages, pg_size * pg_idx overflows 32-bit arithmetic when
pg_idx reaches 1048576. In the level-2 check, PBLE_PER_PAGE is 512, so
i * pg_size * PBLE_PER_PAGE overflows when i reaches 2048.

These values are reachable in the driver. For MRs, palloc->total_cnt
comes from iwmr->page_cnt, which is calculated by
ib_umem_num_dma_blocks(). The MR size is limited by IRDMA_MAX_MR_SIZE,
so a 4 GiB MR with 4 KiB pages can reach page_cnt of 1048576. PBLE
resources do not exclude this value either: for gen3, the limit is based
on avail_sds * MAX_PBLE_PER_SD, and MAX_PBLE_PER_SD is 0x40000, so 4 SDs
are enough for 1048576 PBLEs.

Cast one operand to u64 before the multiplications so that the offset
calculations are performed in 64-bit arithmetic.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
Signed-off-by: Aleksandrova Alyona <aga@itb.spb.ru>
Link: https://patch.msgid.link/20260624144846.61242-1-aga@itb.spb.ru
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/hw/irdma/verbs.c

index be8c5cf12f7ff0e9adeed9116907d5e9763c086f..b7388b41ed958929460c32cb7d702d446e35f3c0 100644 (file)
@@ -2801,7 +2801,7 @@ static bool irdma_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size)
        u32 pg_idx;
 
        for (pg_idx = 0; pg_idx < npages; pg_idx++) {
-               if ((*arr + (pg_size * pg_idx)) != arr[pg_idx])
+               if ((*arr + ((u64)pg_size * pg_idx)) != arr[pg_idx])
                        return false;
        }
 
@@ -2834,7 +2834,7 @@ static bool irdma_check_mr_contiguous(struct irdma_pble_alloc *palloc,
 
        for (i = 0; i < lvl2->leaf_cnt; i++, leaf++) {
                arr = leaf->addr;
-               if ((*start_addr + (i * pg_size * PBLE_PER_PAGE)) != *arr)
+               if ((*start_addr + ((u64)i * pg_size * PBLE_PER_PAGE)) != *arr)
                        return false;
                ret = irdma_check_mem_contiguous(arr, leaf->cnt, pg_size);
                if (!ret)