summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgordon <gordon@FreeBSD.org>2019-05-14 23:12:22 +0000
committergordon <gordon@FreeBSD.org>2019-05-14 23:12:22 +0000
commit0e01c3bb0b9c163317d5a53c8f768356ad9304dd (patch)
tree1838884b0d04eefd61c2bbe687f61c49a2893fea
parentf4d79a1222c4f4c9ae1941f72ee3ba12ec7cc812 (diff)
downloadFreeBSD-src-0e01c3bb0b9c163317d5a53c8f768356ad9304dd.zip
FreeBSD-src-0e01c3bb0b9c163317d5a53c8f768356ad9304dd.tar.gz
Fix ICMP/ICMP6 packet filter bypass in pf.
Approved by: so Security: FreeBSD-SA-19:06.pf Security: CVE-2019-5598
-rw-r--r--sys/netpfil/pf/pf.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index eeb06d2..096b9a4 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -4550,7 +4550,7 @@ pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
{
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 direction, struct pfi_kif *kif,
#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 direction, struct pfi_kif *kif,
#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 direction, struct pfi_kif *kif,
#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 direction, struct pfi_kif *kif,
!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 direction, struct pfi_kif *kif,
} 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);
OpenPOWER on IntegriCloud