DragonFlyBSD Kernel Audit
DF-0603 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/net/pf/pf_if.c b/sys/net/pf/pf_if.c
--- a/sys/net/pf/pf_if.c
+++ b/sys/net/pf/pf_if.c
@@ -772,10 +772,22 @@
 		if (pfi_skip_if(name, p))
 			continue;
 		if (*size > n++) {
+			struct pfi_kif	ucopy;
 			if (!p->pfik_tzero)
 				p->pfik_tzero = time_second;
 			pfi_kif_ref(p, PFI_KIF_REF_RULE);
-			if (copyout(p, buf++, sizeof(*buf))) {
+			/*
+			 * Never leak kernel pointers to userspace.  Copy the
+			 * kif to a stack scratch and explicitly zero every
+			 * pointer field (RB_ENTRY linkage, ifp/group, and the
+			 * dynaddr TAILQ_HEAD) before copyout().
+			 */
+			ucopy = *p;
+			bzero(&ucopy.pfik_tree, sizeof(ucopy.pfik_tree));
+			ucopy.pfik_ifp = NULL;
+			ucopy.pfik_group = NULL;
+			bzero(&ucopy.pfik_dynaddrs, sizeof(ucopy.pfik_dynaddrs));
+			if (copyout(&ucopy, buf++, sizeof(ucopy))) {
 				pfi_kif_unref(p, PFI_KIF_REF_RULE);
 				crit_exit();
 				return (EFAULT);