DragonFlyBSD Kernel Audit
DF-0053 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -707,7 +707,15 @@
 		kfree(freepath, M_TEMP);
 		if (count < 0)
 			goto end;
-		jlsused += count;
+		/* ksnprintf() returns the would-be length, not the bytes
+		   actually written.  Clamp the cursor so the invariant
+		   jlsused <= jlssize always holds; otherwise the unsigned
+		   "jlssize - jlsused" arithmetic below (and the SYSCTL_OUT
+		   length) can underflow/overflow the buffer. */
+		if (count >= (int)(jlssize - jlsused))
+			jlsused = jlssize;
+		else
+			jlsused += count;
 
 		/* Copy the IPS */
 		SLIST_FOREACH(jip, &pr->pr_ips, entries) {
@@ -730,7 +738,11 @@
 				break;
 			}
 
-			if ((jlssize - jlsused) < (strlen(oip) + 1)) {
+			/* Guard explicitly against jlsused >= jlssize so the
+			   unsigned "jlssize - jlsused" subtraction cannot
+			   underflow to ~UINT_MAX and bypass this check. */
+			if (jlsused >= jlssize ||
+			    (jlssize - jlsused) < (strlen(oip) + 1)) {
 				error = ERANGE;
 				goto end;
 			}
@@ -738,7 +750,12 @@
 					  " %s", oip);
 			if (count < 0)
 				goto end;
-			jlsused += count;
+			/* ksnprintf() returns the would-be length; clamp to
+			   preserve jlsused <= jlssize (see comment above). */
+			if (count >= (int)(jlssize - jlsused))
+				jlsused = jlssize;
+			else
+				jlsused += count;
 		}
 	}