Author: bz
Date: Wed Oct 24 10:42:35 2018
New Revision: 339682
URL: https://svnweb.freebsd.org/changeset/base/339682

Log:
  rip6_input() inp validation after epoch(9)
  
  After r335924 rip6_input() needs inp validation to avoid
  working on FREED inps.
  
  Apply the relevant bits from r335497,r335501 (rip_input() change)
  to the IPv6 counterpart.
  
  PR:                   232194
  Reviewed by:          rgrimes, ae (,hps)
  MFC after:            3 days
  Differential Revision:        https://reviews.freebsd.org/D17594

Modified:
  head/sys/netinet6/raw_ip6.c

Modified: head/sys/netinet6/raw_ip6.c
==============================================================================
--- head/sys/netinet6/raw_ip6.c Wed Oct 24 08:45:33 2018        (r339681)
+++ head/sys/netinet6/raw_ip6.c Wed Oct 24 10:42:35 2018        (r339682)
@@ -187,6 +187,45 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
                if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
                    !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
                        continue;
+               if (last != NULL) {
+                       struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
+
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+                       /*
+                        * Check AH/ESP integrity.
+                        */
+                       if (IPSEC_ENABLED(ipv6)) {
+                               if (n != NULL &&
+                                   IPSEC_CHECK_POLICY(ipv6, n, last) != 0) {
+                                       m_freem(n);
+                                       /* Do not inject data into pcb. */
+                                       n = NULL;
+                               }
+                       }
+#endif /* IPSEC */
+                       if (n) {
+                               if (last->inp_flags & INP_CONTROLOPTS ||
+                                   last->inp_socket->so_options & SO_TIMESTAMP)
+                                       ip6_savecontrol(last, n, &opts);
+                               /* strip intermediate headers */
+                               m_adj(n, *offp);
+                               if (sbappendaddr(&last->inp_socket->so_rcv,
+                                               (struct sockaddr *)&fromsa,
+                                                n, opts) == 0) {
+                                       m_freem(n);
+                                       if (opts)
+                                               m_freem(opts);
+                                       RIP6STAT_INC(rip6s_fullsock);
+                               } else
+                                       sorwakeup(last->inp_socket);
+                               opts = NULL;
+                       }
+                       INP_RUNLOCK(last);
+                       last = NULL;
+               }
+               INP_RLOCK(in6p);
+               if (__predict_false(in6p->inp_flags2 & INP_FREED))
+                       goto skip_2;
                if (jailed_without_vnet(in6p->inp_cred)) {
                        /*
                         * Allow raw socket in jail to receive multicast;
@@ -196,16 +235,14 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
                        if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
                            prison_check_ip6(in6p->inp_cred,
                            &ip6->ip6_dst) != 0)
-                               continue;
+                               goto skip_2;
                }
-               INP_RLOCK(in6p);
                if (in6p->in6p_cksum != -1) {
                        RIP6STAT_INC(rip6s_isum);
                        if (in6_cksum(m, proto, *offp,
                            m->m_pkthdr.len - *offp)) {
-                               INP_RUNLOCK(in6p);
                                RIP6STAT_INC(rip6s_badsum);
-                               continue;
+                               goto skip_2;
                        }
                }
                /*
@@ -251,46 +288,13 @@ rip6_input(struct mbuf **mp, int *offp, int proto)
                        }
                        if (blocked != MCAST_PASS) {
                                IP6STAT_INC(ip6s_notmember);
-                               INP_RUNLOCK(in6p);
-                               continue;
+                               goto skip_2;
                        }
                }
-               if (last != NULL) {
-                       struct mbuf *n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
-
-#if defined(IPSEC) || defined(IPSEC_SUPPORT)
-                       /*
-                        * Check AH/ESP integrity.
-                        */
-                       if (IPSEC_ENABLED(ipv6)) {
-                               if (n != NULL &&
-                                   IPSEC_CHECK_POLICY(ipv6, n, last) != 0) {
-                                       m_freem(n);
-                                       /* Do not inject data into pcb. */
-                                       n = NULL;
-                               }
-                       }
-#endif /* IPSEC */
-                       if (n) {
-                               if (last->inp_flags & INP_CONTROLOPTS ||
-                                   last->inp_socket->so_options & SO_TIMESTAMP)
-                                       ip6_savecontrol(last, n, &opts);
-                               /* strip intermediate headers */
-                               m_adj(n, *offp);
-                               if (sbappendaddr(&last->inp_socket->so_rcv,
-                                               (struct sockaddr *)&fromsa,
-                                                n, opts) == 0) {
-                                       m_freem(n);
-                                       if (opts)
-                                               m_freem(opts);
-                                       RIP6STAT_INC(rip6s_fullsock);
-                               } else
-                                       sorwakeup(last->inp_socket);
-                               opts = NULL;
-                       }
-                       INP_RUNLOCK(last);
-               }
                last = in6p;
+               continue;
+skip_2:
+               INP_RUNLOCK(in6p);
        }
        INP_INFO_RUNLOCK_ET(&V_ripcbinfo, et);
 #if defined(IPSEC) || defined(IPSEC_SUPPORT)
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to