Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 May 2019 23:12:22 +0000 (UTC)
From:      Gordon Tetlow <gordon@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org
Subject:   svn commit: r347593 - in releng: 11.2/sys/netpfil/pf 12.0/sys/netpfil/pf
Message-ID:  <201905142312.x4ENCMrM058466@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gordon
Date: Tue May 14 23:12:22 2019
New Revision: 347593
URL: https://svnweb.freebsd.org/changeset/base/347593

Log:
  Fix ICMP/ICMP6 packet filter bypass in pf.
  
  Approved by:	so
  Security:	FreeBSD-SA-19:06.pf
  Security:	CVE-2019-5598

Modified:
  releng/11.2/sys/netpfil/pf/pf.c
  releng/12.0/sys/netpfil/pf/pf.c

Modified: releng/11.2/sys/netpfil/pf/pf.c
==============================================================================
--- releng/11.2/sys/netpfil/pf/pf.c	Tue May 14 23:12:14 2019	(r347592)
+++ releng/11.2/sys/netpfil/pf/pf.c	Tue May 14 23:12:22 2019	(r347593)
@@ -4550,7 +4550,7 @@ pf_test_state_icmp(struct pf_state **state, int direct
 {
 	struct pf_addr  *saddr = pd->src, *daddr = pd->dst;
 	u_int16_t	 icmpid = 0, *icmpsum;
-	u_int8_t	 icmptype;
+	u_int8_t	 icmptype, icmpcode;
 	int		 state_icmp = 0;
 	struct pf_state_key_cmp key;
 
@@ -4559,6 +4559,7 @@ pf_test_state_icmp(struct pf_state **state, int direct
 #ifdef INET
 	case IPPROTO_ICMP:
 		icmptype = pd->hdr.icmp->icmp_type;
+		icmpcode = pd->hdr.icmp->icmp_code;
 		icmpid = pd->hdr.icmp->icmp_id;
 		icmpsum = &pd->hdr.icmp->icmp_cksum;
 
@@ -4573,6 +4574,7 @@ pf_test_state_icmp(struct pf_state **state, int direct
 #ifdef INET6
 	case IPPROTO_ICMPV6:
 		icmptype = pd->hdr.icmp6->icmp6_type;
+		icmpcode = pd->hdr.icmp6->icmp6_code;
 		icmpid = pd->hdr.icmp6->icmp6_id;
 		icmpsum = &pd->hdr.icmp6->icmp6_cksum;
 
@@ -4771,6 +4773,23 @@ pf_test_state_icmp(struct pf_state **state, int direct
 #endif /* INET6 */
 		}
 
+		if (PF_ANEQ(pd->dst, pd2.src, pd->af)) {
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
+				printf("pf: BAD ICMP %d:%d outer dst: ",
+				    icmptype, icmpcode);
+				pf_print_host(pd->src, 0, pd->af);
+				printf(" -> ");
+				pf_print_host(pd->dst, 0, pd->af);
+				printf(" inner src: ");
+				pf_print_host(pd2.src, 0, pd2.af);
+				printf(" -> ");
+				pf_print_host(pd2.dst, 0, pd2.af);
+				printf("\n");
+			}
+			REASON_SET(reason, PFRES_BADSTATE);
+			return (PF_DROP);
+		}
+
 		switch (pd2.proto) {
 		case IPPROTO_TCP: {
 			struct tcphdr		 th;
@@ -4827,7 +4846,7 @@ pf_test_state_icmp(struct pf_state **state, int direct
 			    !SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)))) {
 				if (V_pf_status.debug >= PF_DEBUG_MISC) {
 					printf("pf: BAD ICMP %d:%d ",
-					    icmptype, pd->hdr.icmp->icmp_code);
+					    icmptype, icmpcode);
 					pf_print_host(pd->src, 0, pd->af);
 					printf(" -> ");
 					pf_print_host(pd->dst, 0, pd->af);
@@ -4840,7 +4859,7 @@ pf_test_state_icmp(struct pf_state **state, int direct
 			} else {
 				if (V_pf_status.debug >= PF_DEBUG_MISC) {
 					printf("pf: OK ICMP %d:%d ",
-					    icmptype, pd->hdr.icmp->icmp_code);
+					    icmptype, icmpcode);
 					pf_print_host(pd->src, 0, pd->af);
 					printf(" -> ");
 					pf_print_host(pd->dst, 0, pd->af);

Modified: releng/12.0/sys/netpfil/pf/pf.c
==============================================================================
--- releng/12.0/sys/netpfil/pf/pf.c	Tue May 14 23:12:14 2019	(r347592)
+++ releng/12.0/sys/netpfil/pf/pf.c	Tue May 14 23:12:22 2019	(r347593)
@@ -4588,7 +4588,7 @@ pf_test_state_icmp(struct pf_state **state, int direct
 {
 	struct pf_addr  *saddr = pd->src, *daddr = pd->dst;
 	u_int16_t	 icmpid = 0, *icmpsum;
-	u_int8_t	 icmptype;
+	u_int8_t	 icmptype, icmpcode;
 	int		 state_icmp = 0;
 	struct pf_state_key_cmp key;
 
@@ -4597,6 +4597,7 @@ pf_test_state_icmp(struct pf_state **state, int direct
 #ifdef INET
 	case IPPROTO_ICMP:
 		icmptype = pd->hdr.icmp->icmp_type;
+		icmpcode = pd->hdr.icmp->icmp_code;
 		icmpid = pd->hdr.icmp->icmp_id;
 		icmpsum = &pd->hdr.icmp->icmp_cksum;
 
@@ -4611,6 +4612,7 @@ pf_test_state_icmp(struct pf_state **state, int direct
 #ifdef INET6
 	case IPPROTO_ICMPV6:
 		icmptype = pd->hdr.icmp6->icmp6_type;
+		icmpcode = pd->hdr.icmp6->icmp6_code;
 		icmpid = pd->hdr.icmp6->icmp6_id;
 		icmpsum = &pd->hdr.icmp6->icmp6_cksum;
 
@@ -4809,6 +4811,23 @@ pf_test_state_icmp(struct pf_state **state, int direct
 #endif /* INET6 */
 		}
 
+		if (PF_ANEQ(pd->dst, pd2.src, pd->af)) {
+			if (V_pf_status.debug >= PF_DEBUG_MISC) {
+				printf("pf: BAD ICMP %d:%d outer dst: ",
+				    icmptype, icmpcode);
+				pf_print_host(pd->src, 0, pd->af);
+				printf(" -> ");
+				pf_print_host(pd->dst, 0, pd->af);
+				printf(" inner src: ");
+				pf_print_host(pd2.src, 0, pd2.af);
+				printf(" -> ");
+				pf_print_host(pd2.dst, 0, pd2.af);
+				printf("\n");
+			}
+			REASON_SET(reason, PFRES_BADSTATE);
+			return (PF_DROP);
+		}
+
 		switch (pd2.proto) {
 		case IPPROTO_TCP: {
 			struct tcphdr		 th;
@@ -4865,7 +4884,7 @@ pf_test_state_icmp(struct pf_state **state, int direct
 			    !SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)))) {
 				if (V_pf_status.debug >= PF_DEBUG_MISC) {
 					printf("pf: BAD ICMP %d:%d ",
-					    icmptype, pd->hdr.icmp->icmp_code);
+					    icmptype, icmpcode);
 					pf_print_host(pd->src, 0, pd->af);
 					printf(" -> ");
 					pf_print_host(pd->dst, 0, pd->af);
@@ -4878,7 +4897,7 @@ pf_test_state_icmp(struct pf_state **state, int direct
 			} else {
 				if (V_pf_status.debug >= PF_DEBUG_MISC) {
 					printf("pf: OK ICMP %d:%d ",
-					    icmptype, pd->hdr.icmp->icmp_code);
+					    icmptype, icmpcode);
 					pf_print_host(pd->src, 0, pd->af);
 					printf(" -> ");
 					pf_print_host(pd->dst, 0, pd->af);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905142312.x4ENCMrM058466>