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



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