git: 5b9b55fbc432 - main - iommu_gas: avoid overflow in bounds check

From: Doug Moore <dougm_at_FreeBSD.org>
Date: Thu, 22 Dec 2022 20:34:17 UTC
The branch main has been updated by dougm:

URL: https://cgit.FreeBSD.org/src/commit/?id=5b9b55fbc43261fc1467caaf7f2b70b8f752e479

commit 5b9b55fbc43261fc1467caaf7f2b70b8f752e479
Author:     Doug Moore <dougm@FreeBSD.org>
AuthorDate: 2022-12-22 20:31:57 +0000
Commit:     Doug Moore <dougm@FreeBSD.org>
CommitDate: 2022-12-22 20:31:57 +0000

    iommu_gas: avoid overflow in bounds check
    
    Change the range test in iommu_gas_match_one from '< ubound' to '<=
    ubound', and pass a smaller-by-one ubound parameter to it, to avoid
    overflow in ubound calculation.
    
    Reported by:    andrew
    Reviewed by:    andrew (previous version)
    MFC after:      3 days
    Differential Revision:  https://reviews.freebsd.org/D37764
---
 sys/dev/iommu/iommu_gas.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/sys/dev/iommu/iommu_gas.c b/sys/dev/iommu/iommu_gas.c
index 5654bc7ed8de..86fc3bfa093c 100644
--- a/sys/dev/iommu/iommu_gas.c
+++ b/sys/dev/iommu/iommu_gas.c
@@ -309,7 +309,7 @@ struct iommu_gas_match_args {
 
 /*
  * The interval [beg, end) is a free interval between two iommu_map_entries.
- * Addresses can be allocated only in the range [lbound, ubound). Try to
+ * Addresses can be allocated only in the range [lbound, ubound]. Try to
  * allocate space in the free interval, subject to the conditions expressed by
  * a, and return 'true' if and only if the allocation attempt succeeds.
  */
@@ -332,10 +332,10 @@ iommu_gas_match_one(struct iommu_gas_match_args *a, iommu_gaddr_t beg,
 	start = roundup2(beg, a->common->alignment);
 	if (start < beg)
 		return (false);
-	end = MIN(end - IOMMU_PAGE_SIZE, ubound);
+	end = MIN(end - IOMMU_PAGE_SIZE - 1, ubound);
 	offset = a->offset;
 	size = a->size;
-	if (start + offset + size > end)
+	if (start + offset + size - 1 > end)
 		return (false);
 
 	/* Check for and try to skip past boundary crossing. */
@@ -349,7 +349,7 @@ iommu_gas_match_one(struct iommu_gas_match_args *a, iommu_gaddr_t beg,
 		beg = roundup2(start + offset + 1, a->common->boundary);
 		start = roundup2(beg, a->common->alignment);
 
-		if (start + offset + size > end ||
+		if (start + offset + size - 1 > end ||
 		    !vm_addr_bound_ok(start + offset, size,
 		    a->common->boundary)) {
 			/*
@@ -453,7 +453,7 @@ iommu_gas_find_space(struct iommu_domain *domain,
 	 * Walk the big-enough ranges tree until one satisfies alignment
 	 * requirements, or violates lowaddr address requirement.
 	 */
-	addr = a->common->lowaddr + 1;
+	addr = a->common->lowaddr;
 	for (curr = first; curr != NULL;
 	    curr = iommu_gas_next(curr, min_free)) {
 		if ((first = RB_LEFT(curr, rb_entry)) != NULL &&
@@ -464,7 +464,7 @@ iommu_gas_find_space(struct iommu_domain *domain,
 			return (0);
 		}
 		if (curr->end >= addr) {
-			/* All remaining ranges >= addr */
+			/* All remaining ranges > addr */
 			break;
 		}
 		if ((first = RB_RIGHT(curr, rb_entry)) != NULL &&
@@ -502,14 +502,14 @@ iommu_gas_find_space(struct iommu_domain *domain,
 	    curr = iommu_gas_next(curr, min_free)) {
 		if ((first = RB_LEFT(curr, rb_entry)) != NULL &&
 		    iommu_gas_match_one(a, first->last, curr->start,
-		    addr + 1, domain->end)) {
+		    addr + 1, domain->end - 1)) {
 			RB_INSERT_PREV(iommu_gas_entries_tree,
 			    &domain->rb_root, curr, a->entry);
 			return (0);
 		}
 		if ((first = RB_RIGHT(curr, rb_entry)) != NULL &&
 		    iommu_gas_match_one(a, curr->end, first->first,
-		    addr + 1, domain->end)) {
+		    addr + 1, domain->end - 1)) {
 			RB_INSERT_NEXT(iommu_gas_entries_tree,
 			    &domain->rb_root, curr, a->entry);
 			return (0);