cmd: read: fix unsigned overflow bypassing range check
The bounds check in do_rw() was written as:
if (cnt + blk > limit)
with cnt and blk declared as uint (unsigned int) and limit as ulong.
C's usual arithmetic conversions are applied per binary operator, so
"cnt + blk" is evaluated entirely in unsigned int and wraps modulo
2^32 before the result is widened for the comparison against limit.
With cnt = 0xFFFFFFFF and blk = 1 the sum wraps to 0 and the guard
passes, allowing blk_dread()/blk_dwrite() to be issued with a 4 GiB
transfer count that runs past the partition (or, when no partition
is selected, the entire device).
Rewrite the check as two comparisons that do not overflow:
if (blk > limit || cnt > limit - blk)
The subtraction is performed in ulong (limit's type), so no truncation
occurs, and the two sub-conditions cover both "start block past end"
and "count would push us past end" failure modes.
Signed-off-by: Naveen Kumar Chaudhary <naveen.osdev@gmail.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
committed by
Tom Rini
parent
72d780b5cc
commit
1b8283bd32
+1
-1
@@ -46,7 +46,7 @@ do_rw(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
|
||||
limit = ~0;
|
||||
}
|
||||
|
||||
if (cnt + blk > limit) {
|
||||
if (blk > limit || cnt > limit - blk) {
|
||||
printf("%s out of range\n", cmdtp->name);
|
||||
unmap_sysmem(ptr);
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user