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