NetBSD-Bugs archive

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

Re: kern/50766: panic in tcp_input.c on the banana pi (earm7hf) when trying to connect an ipv6 address through a gif ipv6 in ipv4 tunnel



The following reply was made to PR kern/50766; it has been noted by GNATS.

From: Masanobu SAITOH <msaitoh%execsw.org@localhost>
To: gnats-bugs%NetBSD.org@localhost, kern-bug-people%netbsd.org@localhost,
 gnats-admin%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost
Cc: msaitoh%execsw.org@localhost
Subject: Re: kern/50766: panic in tcp_input.c on the banana pi (earm7hf) when
 trying to connect an ipv6 address through a gif ipv6 in ipv4 tunnel
Date: Thu, 4 Feb 2016 15:38:09 +0900

 On 2016/02/04 8:40, zafer%aydogan.de@localhost wrote:
 >> Number:         50766
 >> Category:       kern
 >> Synopsis:       panic in tcp_input.c on the banana pi (earm7hf) when trying to connect an ipv6 address through a gif ipv6 in ipv4 tunnel
 >> Confidential:   no
 >> Severity:       non-critical
 >> Priority:       high
 >> Responsible:    kern-bug-people
 >> State:          open
 >> Class:          sw-bug
 >> Submitter-Id:   net
 >> Arrival-Date:   Wed Feb 03 23:40:00 +0000 2016
 >> Originator:     Zafer Aydogan
 >> Release:        7.0
 >> Organization:
 >> Environment:
 > NetBSD bpi 7.0.0_PATCH NetBSD 7.0.0_PATCH (BPI) #2: Wed Feb  3 22:33:20 UTC 2016  zafer@current:/data/objdir/sys/arch/evbarm/compile/BPI evbarm
 >> Description:
 > With a banana pi running NetBSD 7.0 following panic occurs when trying to connect to an ipv6 address through a gif ipv6 in ipv4 tunnel
 > 
 > panic: kernel diagnostic assertion "TCP_HDR_ALIGNED_P(th) failed: file /data/src/sys/netinet/tcp_input.c line 1344.
 > 
 > ping6 and traceroute6 on the other hand are working just fine. Panic happens only upon connect.
 > 
 > Also, I cross-checked this issue on amd64, where it does not appear.
 > You can connect just fine on amd64.
 
  One of possibility is that the Ethernet device driver passed unaligned mbuf.
 
 
 
 >> How-To-Repeat:
 > Please enable pseudo device gif in the BPI kernel first,
 > then create a tunnel to an ipv6 enabled server.
 > I am using this script:
 > 
 > #!/bin/sh
 > ifconfig gif0 create
 > ifconfig gif0 tunnel 192.168.0.216 104.207.131.231
 > ifconfig gif0 inet6 2001:19f0:6c00:9089:8487:979e:c000:2 2001:19f0:6c00:9089:8487:979e:c000:1 prefixlen 128
 > route -n add -inet6 default 2001:19f0:6c00:9089:8487:979e:c000:1
 > 
 > where c000:2 and c000:1 are endpoints. 1 is the ipv6 enabled server and 2 is the banana pi at home. both endpoints are running NetBSD 7.0. The server is amd64.
 > 
 > I have applied following patches that show that nothing was misaligned prior to IP6_EXTHDR_GET in tcp_input.c on line 1298
 > 
 > 
 > diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
 > index 61a09aa..a4ed39e 100644
 > --- a/sys/netinet/in_gif.c
 > +++ b/sys/netinet/in_gif.c
 > @@ -57,6 +57,10 @@ __KERNEL_RCSID(0, "$NetBSD: in_gif.c,v 1.64 2014/05/18 14:46:16 rmind Exp $");
 >   #include <netinet/in_var.h>
 >   #include <netinet/ip_encap.h>
 >   #include <netinet/ip_ecn.h>
 > +#include <netinet/ip_private.h>
 > +#include <netinet/tcp_private.h>
 > +#include <netinet/udp_private.h>
 > +#include <netinet6/ip6_private.h>
 >   
 >   #ifdef INET6
 >   #include <netinet/ip6.h>
 > @@ -211,6 +215,11 @@ in_gif_input(struct mbuf *m, ...)
 >          proto = va_arg(ap, int);
 >          va_end(ap);
 >   
 > +       KASSERT(IP_HDR_ALIGNED_P(mtod(m, void *)));
 > +       KASSERT(IP_HDR_ALIGNED_P(off));
 > +       KASSERT(IP6_HDR_ALIGNED_P(off));
 > +       KASSERT(TCP_HDR_ALIGNED_P(off));
 > +       KASSERT(UDP_HDR_ALIGNED_P(off));
 
  At least, avobe checks aren't correct what you intended.
 
 % grep _HDR_ALIGNED_P */*.h
 netinet/icmp_private.h:#define  ICMP_HDR_ALIGNED_P(ic)  1
 netinet/icmp_private.h:#define  ICMP_HDR_ALIGNED_P(ic)  ((((vaddr_t) (ic)) & 3) == 0)
 netinet/igmp_var.h:#define      IGMP_HDR_ALIGNED_P(ig)  1
 netinet/igmp_var.h:#define      IGMP_HDR_ALIGNED_P(ig)  ((((vaddr_t) (ig)) & 3) == 0)
 netinet/ip_private.h:#define    IP_HDR_ALIGNED_P(ip)    1
 netinet/ip_private.h:#define    IP_HDR_ALIGNED_P(ip)    ((((vaddr_t) (ip)) & 3) == 0)
 netinet/tcp_private.h:#define   TCP_HDR_ALIGNED_P(th)   1
 netinet/tcp_private.h:#define   TCP_HDR_ALIGNED_P(th)   ((((vaddr_t)(th)) & 3) == 0)
 netinet/udp_private.h:#define   UDP_HDR_ALIGNED_P(uh)   1
 netinet/udp_private.h:#define   UDP_HDR_ALIGNED_P(uh)   ((((vaddr_t) (uh)) & 3) == 0)
 netinet6/ip6_private.h:#define  IP6_HDR_ALIGNED_P(ip)   1
 netinet6/ip6_private.h:#define  IP6_HDR_ALIGNED_P(ip)   ((((vaddr_t) (ip)) & 3) == 0)
 
 Each *_HDR_ALIGNED_P()'s argument takes the head of each protocol header.
 
 >          ip = mtod(m, const struct ip *);
 >   
 >          gifp = (struct ifnet *)encap_getarg(m);
 > @@ -230,6 +239,7 @@ in_gif_input(struct mbuf *m, ...)
 >   
 >          otos = ip->ip_tos;
 >          m_adj(m, off);
 > +       KASSERT(IP_HDR_ALIGNED_P(mtod(m, void *)));
 >   
 >          switch (proto) {
 >   #ifdef INET
 > @@ -241,6 +251,7 @@ in_gif_input(struct mbuf *m, ...)
 >                          if ((m = m_pullup(m, sizeof(*xip))) == NULL)
 >                                  return;
 >                  }
 > +               KASSERT(IP_HDR_ALIGNED_P(mtod(m, void *)));
 >                  xip = mtod(m, struct ip *);
 >                  if (gifp->if_flags & IFF_LINK1)
 >                          ip_ecn_egress(ECN_ALLOWED, &otos, &xip->ip_tos);
 > @@ -259,6 +270,7 @@ in_gif_input(struct mbuf *m, ...)
 >                          if ((m = m_pullup(m, sizeof(*ip6))) == NULL)
 >                                  return;
 >                  }
 > +               KASSERT(IP6_HDR_ALIGNED_P(mtod(m, void *)));
 >                  ip6 = mtod(m, struct ip6_hdr *);
 >                  itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
 >                  if (gifp->if_flags & IFF_LINK1)
 > diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
 > index cb80d94..7295941 100644
 > --- a/sys/netinet/ip_input.c
 > +++ b/sys/netinet/ip_input.c
 > @@ -407,12 +407,14 @@ ip_input(struct mbuf *m)
 >                          return;
 >                  }
 >          }
 > +       KASSERT(IP_HDR_ALIGNED_P(mtod(m, void *)));
 >          ip = mtod(m, struct ip *);
 >          if (ip->ip_v != IPVERSION) {
 >                  IP_STATINC(IP_STAT_BADVERS);
 >                  goto bad;
 >          }
 >          hlen = ip->ip_hl << 2;
 > +       KASSERT(IP_HDR_ALIGNED_P(hlen));
 >          if (hlen < sizeof(struct ip)) { /* minimum header length */
 >                  IP_STATINC(IP_STAT_BADHLEN);
 >                  goto bad;
 > @@ -422,6 +424,7 @@ ip_input(struct mbuf *m)
 >                          IP_STATINC(IP_STAT_BADHLEN);
 >                          return;
 >                  }
 > +               KASSERT(IP_HDR_ALIGNED_P(mtod(m, void *)));
 >                  ip = mtod(m, struct ip *);
 >          }
 >   
 > @@ -526,8 +529,10 @@ ip_input(struct mbuf *m)
 >                  if (freed || m == NULL) {
 >                          return;
 >                  }
 > +               KASSERT(IP_HDR_ALIGNED_P(mtod(m, void *)));
 >                  ip = mtod(m, struct ip *);
 >                  hlen = ip->ip_hl << 2;
 > +               KASSERT(IP_HDR_ALIGNED_P(hlen));
 >   
 >                  /*
 >                   * XXX The setting of "srcrt" here is to prevent ip_forward()
 > @@ -736,8 +741,10 @@ ours:
 >                   * Reassembly is done, we have the final packet.
 >                   * Updated cached data in local variable(s).
 >                   */
 > +               KASSERT(IP_HDR_ALIGNED_P(mtod(m, void *)));
 >                  ip = mtod(m, struct ip *);
 >                  hlen = ip->ip_hl << 2;
 > +               KASSERT(IP_HDR_ALIGNED_P(hlen));
 >          }
 >   
 >   #ifdef IPSEC
 > @@ -768,6 +775,9 @@ ours:
 >   
 >          const int off = hlen, nh = ip->ip_p;
 >   
 > +       KASSERT(IP_HDR_ALIGNED_P(mtod(m, void *)));
 > +       KASSERT(IP_HDR_ALIGNED_P(off));
 > +
 >          SOFTNET_LOCK();
 >          (*inetsw[ip_protox[nh]].pr_input)(m, off, nh);
 >          SOFTNET_UNLOCK();
 > diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
 > index 4362c99..88857227 100644
 > --- a/sys/netinet/tcp_input.c
 > +++ b/sys/netinet/tcp_input.c
 > @@ -212,6 +212,7 @@ __KERNEL_RCSID(0, "$NetBSD: tcp_input.c,v 1.334.2.2 2015/07/24 07:30:40 martin E
 >   #include <netinet/tcp_timer.h>
 >   #include <netinet/tcp_var.h>
 >   #include <netinet/tcp_private.h>
 > +#include <netinet/ip_private.h>
 >   #include <netinet/tcpip.h>
 >   #include <netinet/tcp_congctl.h>
 >   #include <netinet/tcp_debug.h>
 > @@ -1237,6 +1238,11 @@ tcp_input(struct mbuf *m, ...)
 >          (void)va_arg(ap, int);          /* ignore value, advance ap */
 >          va_end(ap);
 >   
 > +       KASSERT(IP_HDR_ALIGNED_P(mtod(m, void *)));
 > +       KASSERT(IP_HDR_ALIGNED_P(toff));
 > +       KASSERT(TCP_HDR_ALIGNED_P(mtod(m, void *)));
 > +       KASSERT(TCP_HDR_ALIGNED_P(toff));
 > +
 >          TCP_STATINC(TCP_STAT_RCVTOTAL);
 >   
 >          memset(&opti, 0, sizeof(opti));
 > @@ -1267,6 +1273,7 @@ tcp_input(struct mbuf *m, ...)
 >           * Get IP and TCP header.
 >           * Note: IP leaves IP header in first mbuf.
 >           */
 > +       KASSERT(IP_HDR_ALIGNED_P(mtod(m, void *)));
 >          ip = mtod(m, struct ip *);
 >          switch (ip->ip_v) {
 >   #ifdef INET
 > @@ -1276,12 +1283,15 @@ tcp_input(struct mbuf *m, ...)
 >   #endif
 >                  af = AF_INET;
 >                  iphlen = sizeof(struct ip);
 > +               KASSERT(TCP_HDR_ALIGNED_P(mtod(m, void *)));
 > +               KASSERT(TCP_HDR_ALIGNED_P(toff));
 >                  IP6_EXTHDR_GET(th, struct tcphdr *, m, toff,
 >                          sizeof(struct tcphdr));
 >                  if (th == NULL) {
 >                          TCP_STATINC(TCP_STAT_RCVSHORT);
 >                          return;
 >                  }
 > +               KASSERT(TCP_HDR_ALIGNED_P(th));
 >                  /* We do the checksum after PCB lookup... */
 >                  len = ntohs(ip->ip_len);
 >                  tlen = len - toff;
 > @@ -1294,12 +1304,15 @@ tcp_input(struct mbuf *m, ...)
 >                  iphlen = sizeof(struct ip6_hdr);
 >                  af = AF_INET6;
 >                  ip6 = mtod(m, struct ip6_hdr *);
 > +               KASSERT(TCP_HDR_ALIGNED_P(mtod(m, void *)));
 > +               KASSERT(TCP_HDR_ALIGNED_P(toff));
 >                  IP6_EXTHDR_GET(th, struct tcphdr *, m, toff,
 >                          sizeof(struct tcphdr));
 >                  if (th == NULL) {
 >                          TCP_STATINC(TCP_STAT_RCVSHORT);
 >                          return;
 >                  }
 > +               KASSERT(TCP_HDR_ALIGNED_P(th));
 >   
 >                  /* Be proactive about malicious use of IPv4 mapped address */
 >                  if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) ||
 > 
 >   
 > 
 > 
 > 
 >> Fix:
 > 
 
 
 -- 
 -----------------------------------------------
                 SAITOH Masanobu (msaitoh%execsw.org@localhost
                                  msaitoh%netbsd.org@localhost)
 


Home | Main Index | Thread Index | Old Index