]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iommu/riscv: Remove overflows on the invalidation path
authorJason Gunthorpe <jgg@nvidia.com>
Fri, 27 Mar 2026 15:22:10 +0000 (12:22 -0300)
committerJoerg Roedel <joerg.roedel@amd.com>
Thu, 2 Apr 2026 07:35:49 +0000 (09:35 +0200)
Since RISC-V supports a sign extended page table it should support
a gather->end of ULONG_MAX, but if this happens it will infinite loop
because of the overflow.

Also avoid overflow computing the length by moving the +1 to the other
side of the <

Fixes: 488ffbf18171 ("iommu/riscv: Paging domain support")
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
drivers/iommu/riscv/iommu.c

index 6ac7e3edef8aaf7698287515a036a90f2f3fca22..3ec99c979d47361a652ac63777d890912fa15ed0 100644 (file)
@@ -931,8 +931,6 @@ static void riscv_iommu_iotlb_inval(struct riscv_iommu_domain *domain,
        struct riscv_iommu_bond *bond;
        struct riscv_iommu_device *iommu, *prev;
        struct riscv_iommu_command cmd;
-       unsigned long len = end - start + 1;
-       unsigned long iova;
 
        /*
         * For each IOMMU linked with this protection domain (via bonds->dev),
@@ -975,11 +973,14 @@ static void riscv_iommu_iotlb_inval(struct riscv_iommu_domain *domain,
 
                riscv_iommu_cmd_inval_vma(&cmd);
                riscv_iommu_cmd_inval_set_pscid(&cmd, domain->pscid);
-               if (len && len < RISCV_IOMMU_IOTLB_INVAL_LIMIT) {
-                       for (iova = start; iova < end; iova += PAGE_SIZE) {
+               if (end - start < RISCV_IOMMU_IOTLB_INVAL_LIMIT - 1) {
+                       unsigned long iova = start;
+
+                       do {
                                riscv_iommu_cmd_inval_set_addr(&cmd, iova);
                                riscv_iommu_cmd_send(iommu, &cmd);
-                       }
+                       } while (!check_add_overflow(iova, PAGE_SIZE, &iova) &&
+                                iova < end);
                } else {
                        riscv_iommu_cmd_send(iommu, &cmd);
                }