Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Jul 2024 14:52:35 GMT
From:      Mitchell Horne <mhorne@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 558c1b37334c - main - busdma: avoid buflen underflow
Message-ID:  <202407081452.468EqZWf046714@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by mhorne:

URL: https://cgit.FreeBSD.org/src/commit/?id=558c1b37334c4dcc9913b7c157a491f9d244e335

commit 558c1b37334c4dcc9913b7c157a491f9d244e335
Author:     Mitchell Horne <mhorne@FreeBSD.org>
AuthorDate: 2024-07-08 14:51:31 +0000
Commit:     Mitchell Horne <mhorne@FreeBSD.org>
CommitDate: 2024-07-08 14:51:31 +0000

    busdma: avoid buflen underflow
    
    The loop condition in the dmamap_load_buffer() method is 'buflen > 0',
    and buflen is an unsigned type (bus_size_t).
    
    A recent change made it possible for sgsize to exceed the remaining
    buflen, when the tag has a large alignment requirement. The result is
    that we would not break out of the loop at the correct time. Fix this by
    avoiding underflow in the subtraction at the end of the loop.
    
    PR:             279383
    Reported by:    Robert Morris <rtm@lcs.mit.edu>
    Reviewed by:    jhibbits
    Fixes:          a77e1f0f81df ("busdma: better handling of small segment bouncing")
    Differential Revision:  https://reviews.freebsd.org/D45732
---
 sys/arm/arm/busdma_machdep.c         | 2 +-
 sys/arm64/arm64/busdma_bounce.c      | 2 +-
 sys/powerpc/powerpc/busdma_machdep.c | 2 +-
 sys/riscv/riscv/busdma_bounce.c      | 2 +-
 sys/x86/x86/busdma_bounce.c          | 4 ++--
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/sys/arm/arm/busdma_machdep.c b/sys/arm/arm/busdma_machdep.c
index 13af7eb682d6..99a72c9e79d0 100644
--- a/sys/arm/arm/busdma_machdep.c
+++ b/sys/arm/arm/busdma_machdep.c
@@ -1035,7 +1035,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
 		    segp))
 			break;
 		vaddr += sgsize;
-		buflen -= sgsize;
+		buflen -= MIN(sgsize, buflen); /* avoid underflow */
 	}
 
 cleanup:
diff --git a/sys/arm64/arm64/busdma_bounce.c b/sys/arm64/arm64/busdma_bounce.c
index f218bc062642..3836f8c74b45 100644
--- a/sys/arm64/arm64/busdma_bounce.c
+++ b/sys/arm64/arm64/busdma_bounce.c
@@ -898,7 +898,7 @@ bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
 		    segp))
 			break;
 		vaddr += sgsize;
-		buflen -= sgsize;
+		buflen -= MIN(sgsize, buflen); /* avoid underflow */
 	}
 
 	/*
diff --git a/sys/powerpc/powerpc/busdma_machdep.c b/sys/powerpc/powerpc/busdma_machdep.c
index b023e7f353b9..5f7f88041a67 100644
--- a/sys/powerpc/powerpc/busdma_machdep.c
+++ b/sys/powerpc/powerpc/busdma_machdep.c
@@ -656,7 +656,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dmat,
 		    segp))
 			break;
 		vaddr += sgsize;
-		buflen -= sgsize;
+		buflen -= MIN(sgsize, buflen); /* avoid underflow */
 	}
 
 	/*
diff --git a/sys/riscv/riscv/busdma_bounce.c b/sys/riscv/riscv/busdma_bounce.c
index e1c217f1d12e..68525bb742bc 100644
--- a/sys/riscv/riscv/busdma_bounce.c
+++ b/sys/riscv/riscv/busdma_bounce.c
@@ -705,7 +705,7 @@ bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
 		    segp))
 			break;
 		vaddr += sgsize;
-		buflen -= sgsize;
+		buflen -= MIN(sgsize, buflen); /* avoid underflow */
 	}
 
 cleanup:
diff --git a/sys/x86/x86/busdma_bounce.c b/sys/x86/x86/busdma_bounce.c
index 5aa4ffcff3cc..656b76159250 100644
--- a/sys/x86/x86/busdma_bounce.c
+++ b/sys/x86/x86/busdma_bounce.c
@@ -733,7 +733,7 @@ bounce_bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
 		    segp))
 			break;
 		vaddr += sgsize;
-		buflen -= sgsize;
+		buflen -= MIN(sgsize, buflen); /* avoid underflow */
 	}
 
 	/*
@@ -808,7 +808,7 @@ bounce_bus_dmamap_load_ma(bus_dma_tag_t dmat, bus_dmamap_t map,
 			break;
 		KASSERT(buflen >= sgsize,
 		    ("Segment length overruns original buffer"));
-		buflen -= sgsize;
+		buflen -= MIN(sgsize, buflen); /* avoid underflow */
 		if (((ma_offs + sgsize) & ~PAGE_MASK) != 0)
 			page_index++;
 		ma_offs = (ma_offs + sgsize) & PAGE_MASK;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202407081452.468EqZWf046714>