DragonFlyBSD Kernel Audit
DF-0362 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/net/pf/pf_table.c b/sys/net/pf/pf_table.c
--- a/sys/net/pf/pf_table.c
+++ b/sys/net/pf/pf_table.c
@@ -1742,14 +1742,26 @@
 	size_t siz = MAXPATHLEN;
 	int i;
 
+	/* anchor must be NUL-terminated within siz bytes, otherwise the
+	   slash-stripping loop below could read past the array (the byte
+	   immediately after pfrt_anchor is pfrt_name, also attacker-controlled),
+	   making 'off' exceed 'siz' and causing siz - off to wrap as size_t
+	   in the subsequent bcopy(). */
+	if (anchor[siz - 1] != '\0')
+		return (-1);
 	if (anchor[0] == '/') {
 		char *path;
 		int off;
 
 		path = anchor;
 		off = 1;
-		while (*++path == '/')
+		while (off < siz && *++path == '/')
 			off++;
+		/* off == siz cannot happen now (anchor[siz-1] == 0 was checked
+		   above, so the loop stops at the NUL at the latest), but keep
+		   the guard as defense-in-depth. */
+		if (off >= siz)
+			return (-1);
 		bcopy(path, anchor, siz - off);
 		memset(anchor + siz - off, 0, off);
 	}