Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dist/ipf/netinet Fix mbuf corruption when sending ICMP e...



details:   https://anonhg.NetBSD.org/src/rev/2b123541629a
branches:  trunk
changeset: 757557:2b123541629a
user:      mlelstv <mlelstv%NetBSD.org@localhost>
date:      Sun Sep 05 12:36:46 2010 +0000

description:
Fix mbuf corruption when sending ICMP errors for blocked IPv6
packets due to wrong buffer size computations. The corrupted
mbufs could lead to a panic.

Fix computation of link mtu where the link mtu itself is unspecified.

Limit ICMP error packets for IPv6 to MMTU as required by RFC4443. This
also avoids dropped errors when the length exceeds the link mtu.

diffstat:

 sys/dist/ipf/netinet/ip_fil_netbsd.c |  26 +++++++++++++++-----------
 1 files changed, 15 insertions(+), 11 deletions(-)

diffs (86 lines):

diff -r 733623e75fb4 -r 2b123541629a sys/dist/ipf/netinet/ip_fil_netbsd.c
--- a/sys/dist/ipf/netinet/ip_fil_netbsd.c      Sun Sep 05 06:52:53 2010 +0000
+++ b/sys/dist/ipf/netinet/ip_fil_netbsd.c      Sun Sep 05 12:36:46 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_fil_netbsd.c,v 1.55 2010/06/01 08:53:20 plunky Exp $        */
+/*     $NetBSD: ip_fil_netbsd.c,v 1.56 2010/09/05 12:36:46 mlelstv Exp $       */
 
 /*
  * Copyright (C) 1993-2003 by Darren Reed.
@@ -8,7 +8,7 @@
 #if !defined(lint)
 #if defined(__NetBSD__)
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_fil_netbsd.c,v 1.55 2010/06/01 08:53:20 plunky Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_fil_netbsd.c,v 1.56 2010/09/05 12:36:46 mlelstv Exp $");
 #else
 static const char sccsid[] = "@(#)ip_fil.c     2.41 6/5/96 (C) 1993-2000 Darren Reed";
 static const char rcsid[] = "@(#)Id: ip_fil_netbsd.c,v 2.55.2.67 2009/12/19 05:41:08 darrenr Exp";
@@ -1076,6 +1076,7 @@
 
                hlen = sizeof(ip_t);
                ohlen = fin->fin_hlen;
+               iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen;
                if (fin->fin_hlen < fin->fin_plen)
                        xtra = MIN(fin->fin_dlen, 8);
                else
@@ -1086,12 +1087,12 @@
        else if (fin->fin_v == 6) {
                hlen = sizeof(ip6_t);
                ohlen = sizeof(ip6_t);
+               iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen;
                type = icmptoicmp6types[type];
                if (type == ICMP6_DST_UNREACH)
                        code = icmptoicmp6unreach[code];
 
-               if (hlen + sizeof(*icmp) + max_linkhdr +
-                   fin->fin_plen > avail) {
+               if (iclen + max_linkhdr + fin->fin_plen > avail) {
                        MCLGET(m, M_DONTWAIT);
                        if (m == NULL)
                                return -1;
@@ -1102,7 +1103,14 @@
                        avail = MCLBYTES;
                }
                xtra = MIN(fin->fin_plen,
-                          avail - hlen - sizeof(*icmp) - max_linkhdr);
+                          avail - iclen - max_linkhdr);
+               /* RFC4443 asks for 'as much of invoking packet
+                * as possible without the ICMPv6 packet exceeding
+                * the minimum IPv6 MTU'
+                * fr_send_ip also drops packets larger than the
+                * link mtu
+                */
+               xtra = MIN(xtra, IPV6_MMTU - iclen);
                if (dst == 0) {
                        if (fr_ifpaddr(6, FRI_NORMAL, ifp,
                                       (struct in_addr *)&dst6, NULL) == -1) {
@@ -1118,7 +1126,6 @@
                return -1;
        }
 
-       iclen = hlen + sizeof(*icmp);
        avail -= (max_linkhdr + iclen);
        if (avail < 0) {
                FREE_MB_T(m);
@@ -1584,9 +1591,7 @@
 
        {
 # if (__NetBSD_Version__ >= 106010000)
-#  if (__NetBSD_Version__ >= 399001400)
-               struct in6_ifextra *ife;
-#  else
+#  if (__NetBSD_Version__ < 399001400)
                struct in6_addr finaldst = fin->fin_dst6;
                int frag;
 #  endif
@@ -1605,8 +1610,7 @@
                mtu = nd_ifinfo[ifp->if_index].linkmtu;
 # else
 #  if (__NetBSD_Version__ >= 399001400)
-               ife = (struct in6_ifextra *)(ifp)->if_afdata[AF_INET6];
-               mtu = ife->nd_ifinfo[ifp->if_index].linkmtu;
+               mtu = IN6_LINKMTU(ifp);
 #  else
                error = ip6_getpmtu(ro, ro, ifp, &finaldst, &mtu, &frag);
 #  endif



Home | Main Index | Thread Index | Old Index