The pf code marks ICMP packets belonging to an TCP or UDP divert
authorbluhm <bluhm@openbsd.org>
Thu, 14 Dec 2017 14:26:50 +0000 (14:26 +0000)
committerbluhm <bluhm@openbsd.org>
Thu, 14 Dec 2017 14:26:50 +0000 (14:26 +0000)
state as diverted.  This is necessary for IP input to accept the
packet as ours.  But it must not be used to match the ICMP packet
to a raw socket.  Clear the PF_TAG_DIVERTED mbuf pf flag for the
special ICMP and ICMP6 packets in icmp_input_if() and icmp6_input().

The m_tag_delete_chain() caused an inconsistent PF_TAG_DIVERTED
mbuf pf flag and PACKET_TAG_PF_DIVERT mbuf tag which triggered an
assert in rip_input().  Deleting all mbuf tags can have undesired
side effects and is not necessary anymore since icmp_reflect() calls
m_resethdr().  Do not touch the mbuf tags and adjust the mbuf pf
flags for the correct behavior of rip_input() and rip6_input().

reported by Chris Eidem, James Turner, vicviq, Scott Vanderbilt
OK mpi@

sys/netinet/ip_icmp.c
sys/netinet6/icmp6.c

index f218b6f..b71e873 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ip_icmp.c,v 1.173 2017/10/18 17:01:14 bluhm Exp $     */
+/*     $OpenBSD: ip_icmp.c,v 1.174 2017/12/14 14:26:50 bluhm Exp $     */
 /*     $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $    */
 
 /*
@@ -378,6 +378,12 @@ icmp_input_if(struct ifnet *ifp, struct mbuf **mp, int *offp, int proto, int af)
 #if NPF > 0
        if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) {
                switch (icp->icmp_type) {
+                /*
+                 * As pf_icmp_mapping() considers redirects belonging to a
+                 * diverted connection, we must include it here.
+                 */
+               case ICMP_REDIRECT:
+                       /* FALLTHROUGH */
                /*
                 * These ICMP types map to other connections.  They must be
                 * delivered to pr_ctlinput() also for diverted connections.
@@ -386,12 +392,11 @@ icmp_input_if(struct ifnet *ifp, struct mbuf **mp, int *offp, int proto, int af)
                case ICMP_TIMXCEED:
                case ICMP_PARAMPROB:
                case ICMP_SOURCEQUENCH:
-                       break;
-                /*
-                 * Although pf_icmp_mapping() considers redirects belonging
-                 * to a diverted connection, we must process it here anyway.
-                 */
-               case ICMP_REDIRECT:
+                       /*
+                        * Do not use the divert-to property of the TCP or UDP
+                        * rule when doing the PCB lookup for the raw socket.
+                        */
+                       m->m_pkthdr.pf.flags &=~ PF_TAG_DIVERTED;
                        break;
                default:
                        goto raw;
@@ -454,10 +459,6 @@ icmp_input_if(struct ifnet *ifp, struct mbuf **mp, int *offp, int proto, int af)
                        goto badcode;
                code = PRC_QUENCH;
        deliver:
-               /* Free packet atttributes */
-               if (m->m_flags & M_PKTHDR)
-                       m_tag_delete_chain(m);
-
                /*
                 * Problem with datagram; advise higher level routines.
                 */
@@ -585,10 +586,6 @@ reflect:
                    &ip->ip_dst.s_addr, 1))
                        goto freeit;
 #endif
-               /* Free packet atttributes */
-               if (m->m_flags & M_PKTHDR)
-                       m_tag_delete_chain(m);
-
                icmpstat_inc(icps_reflect);
                icmpstat_inc(icps_outhist + icp->icmp_type);
                if (!icmp_reflect(m, &opts, NULL)) {
@@ -604,9 +601,6 @@ reflect:
                struct sockaddr_in ssrc;
                struct rtentry *newrt = NULL;
 
-               /* Free packet atttributes */
-               if (m->m_flags & M_PKTHDR)
-                       m_tag_delete_chain(m);
                if (icmp_rediraccept == 0 || ipforwarding == 1)
                        goto freeit;
                if (code > 3)
index 9567e5c..7db5b5c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: icmp6.c,v 1.220 2017/11/03 14:28:57 florian Exp $     */
+/*     $OpenBSD: icmp6.c,v 1.221 2017/12/14 14:26:50 bluhm Exp $       */
 /*     $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */
 
 /*
@@ -431,6 +431,11 @@ icmp6_input(struct mbuf **mp, int *offp, int proto, int af)
                case ICMP6_PACKET_TOO_BIG:
                case ICMP6_TIME_EXCEEDED:
                case ICMP6_PARAM_PROB:
+                       /*
+                        * Do not use the divert-to property of the TCP or UDP
+                        * rule when doing the PCB lookup for the raw socket.
+                        */
+                       m->m_pkthdr.pf.flags &=~ PF_TAG_DIVERTED;
                        break;
                default:
                        goto raw;