DragonFlyBSD Kernel Audit
DF-0705 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/net/ipfw3_basic/ip_fw3_sync.c b/sys/net/ipfw3_basic/ip_fw3_sync.c
--- a/sys/net/ipfw3_basic/ip_fw3_sync.c	2026-06-29 12:51:19.000000000 +0000
+++ b/sys/net/ipfw3_basic/ip_fw3_sync.c	2026-07-19 07:48:46.110916061 +0000
@@ -102,8 +102,15 @@
 	struct ipfw3_ioc_sync_context *tmp_sync_ctx;
 	int size;
 
+	/* DF-0705 #3: count is a signed int; reject negatives to avoid
+	 * (a) tiny `size` bypassing the sopt_valsize check, and
+	 * (b) huge size_t bcopy length wrap-around. */
+	if (fw3_sync_ctx.count < 0) {
+		bzero(sopt->sopt_val, sopt->sopt_valsize);
+		return EINVAL;
+	}
 	size = 3 * sizeof(int) + fw3_sync_ctx.count * LEN_SYNC_EDGE;
-	if (sopt->sopt_valsize < size) {
+	if (sopt->sopt_valsize < (size_t)size) {
 		/* sopt_val is not big enough */
 		bzero(sopt->sopt_val, sopt->sopt_valsize);
 		return 0;
@@ -140,6 +147,10 @@
 	int size;
 
 	ioc_centre = sopt->sopt_val;
+	/* DF-0705: validate count is non-negative and reasonably bounded */
+	if (ioc_centre->count < 0 || ioc_centre->count > MAX_EDGES) {
+		return EINVAL;
+	}
 	size = ioc_centre->count * LEN_SYNC_EDGE;
 	if (fw3_sync_ctx.count == 0) {
 		fw3_sync_ctx.edges = kmalloc(size, M_IPFW3_SYNC, M_NOWAIT | M_ZERO);
@@ -239,6 +250,11 @@
 	if (fw3_sync_ctx.running & 1) {
 		return 0;
 	}
+	/* DF-0705 #1: caller must have configured the edge socket first */
+	if (fw3_sync_ctx.edge_sock == NULL) {
+		kprintf("ipfw3sync edge not configured\n");
+		return EINVAL;
+	}
 	td = curthread->td_proc ? curthread : &thread0;
 	bzero(&sin, sizeof(struct sockaddr_in));
 	sin.sin_family = AF_INET;
@@ -260,7 +276,10 @@
 	error = kthread_create(ip_fw3_sync_edge_socket_handler, NULL,
 			&fw3_sync_ctx.edge_td, "sync_edge_thread");
 	if (error) {
-		panic("ip_fw3_sync_edge_socket_handler:error %d",error);
+		/* DF-0705 #2: don't panic; report error to caller */
+		kprintf("ipfw3sync edge kthread_create: %d\n", error);
+		fw3_sync_ctx.running &= ~1;
+		return error;
 	}
 	return 0;
 }