NetBSD-Bugs archive

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

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



>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.
>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));
        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:



Home | Main Index | Thread Index | Old Index