DragonFlyBSD Kernel Audit
DF-0243 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/imgact_shell.c b/sys/kern/imgact_shell.c
--- a/sys/kern/imgact_shell.c
+++ b/sys/kern/imgact_shell.c
@@ -123,10 +123,25 @@
 	bcopy(imgp->args->begin_argv + length, imgp->args->begin_argv + offset,
 		imgp->args->endp - (imgp->args->begin_argv + length));
 
-	offset -= length;		/* calculate actual adjustment */
-	imgp->args->begin_envv += offset;
-	imgp->args->endp += offset;
-	imgp->args->space -= offset;
+	/*
+	 * Calculate the actual pointer/space adjustment without relying on
+	 * size_t modular wrap when offset < length (which happens whenever
+	 * argv[0] is longer than the interpreter tokens + fname).  Handle
+	 * the grow (offset >= length) and shrink (offset < length) cases
+	 * explicitly so the intent is obvious and unsigned underflow cannot
+	 * confuse readers or static analyzers.
+	 */
+	if (offset >= length) {
+		size_t grow = offset - length;
+		imgp->args->begin_envv += grow;
+		imgp->args->endp += grow;
+		imgp->args->space -= (int)grow;
+	} else {
+		size_t shrink = length - offset;
+		imgp->args->begin_envv -= shrink;
+		imgp->args->endp -= shrink;
+		imgp->args->space += (int)shrink;
+	}
 	/* decr argc remove old argv[0], incr argc for fname add, net 0 */
 
 	/*