Author: markj
Date: Tue Dec  1 03:07:26 2020
New Revision: 368202
URL: https://svnweb.freebsd.org/changeset/base/368202

Log:
  MFC r367114 (by melifaro):
  Fix use-after-free in icmp6_notify_error().

Modified:
  stable/11/sys/netinet6/icmp6.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/netinet6/icmp6.c
==============================================================================
--- stable/11/sys/netinet6/icmp6.c      Mon Nov 30 22:35:30 2020        
(r368201)
+++ stable/11/sys/netinet6/icmp6.c      Tue Dec  1 03:07:26 2020        
(r368202)
@@ -903,6 +903,7 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp
        }
 #endif
        eip6 = (struct ip6_hdr *)(icmp6 + 1);
+       bzero(&icmp6dst, sizeof(icmp6dst));
 
        /* Detect the upper level protocol */
        {
@@ -911,7 +912,6 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp
                int eoff = off + sizeof(struct icmp6_hdr) +
                    sizeof(struct ip6_hdr);
                struct ip6ctlparam ip6cp;
-               struct in6_addr *finaldst = NULL;
                int icmp6type = icmp6->icmp6_type;
                struct ip6_frag *fh;
                struct ip6_rthdr *rth;
@@ -994,7 +994,7 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp
                                        /* just ignore a bogus header */
                                        if ((rth0->ip6r0_len % 2) == 0 &&
                                            (hops = rth0->ip6r0_len/2))
-                                               finaldst = (struct in6_addr 
*)(rth0 + 1) + (hops - 1);
+                                               icmp6dst.sin6_addr = *((struct 
in6_addr *)(rth0 + 1) + (hops - 1));
                                }
                                eoff += rthlen;
                                nxt = rth->ip6r_nxt;
@@ -1059,13 +1059,10 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp
                 */
                eip6 = (struct ip6_hdr *)(icmp6 + 1);
 
-               bzero(&icmp6dst, sizeof(icmp6dst));
                icmp6dst.sin6_len = sizeof(struct sockaddr_in6);
                icmp6dst.sin6_family = AF_INET6;
-               if (finaldst == NULL)
+               if (IN6_IS_ADDR_UNSPECIFIED(&icmp6dst.sin6_addr))
                        icmp6dst.sin6_addr = eip6->ip6_dst;
-               else
-                       icmp6dst.sin6_addr = *finaldst;
                if (in6_setscope(&icmp6dst.sin6_addr, m->m_pkthdr.rcvif, NULL))
                        goto freeit;
                bzero(&icmp6src, sizeof(icmp6src));
@@ -1077,13 +1074,11 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp
                icmp6src.sin6_flowinfo =
                    (eip6->ip6_flow & IPV6_FLOWLABEL_MASK);
 
-               if (finaldst == NULL)
-                       finaldst = &eip6->ip6_dst;
                ip6cp.ip6c_m = m;
                ip6cp.ip6c_icmp6 = icmp6;
                ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
                ip6cp.ip6c_off = eoff;
-               ip6cp.ip6c_finaldst = finaldst;
+               ip6cp.ip6c_finaldst = &icmp6dst.sin6_addr;
                ip6cp.ip6c_src = &icmp6src;
                ip6cp.ip6c_nxt = nxt;
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to