Latest working kernel version: None known -- appears to be a historic bug Earliest failing kernel version: All Distribution: Hardware Environment: Software Environment: Problem Description: Steps to reproduce: Open a tun device as type TUN, set the TUN_NO_PI flag, and try sending an IPv6 packet. The packet appears at the interface under tcpdumps, but propagates no further. This is because the default protocol info used for tun devices where the TUN_NO_PI flag is set assumes IPv4 as can be seen by the initialization at the top of the tun_get_user function in drivers/net/tun.c file given by struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) }; This can easily be fixed by adding a quick check at the top of tun_get_user. Basically the code that used to read if (!(tun->flags & TUN_NO_PI)) { if ((len -= sizeof(pi)) > count) return -EINVAL; if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi))) return -EFAULT; } when changed to read if (!(tun->flags & TUN_NO_PI)) { if ((len -= sizeof(pi)) > count) return -EINVAL; if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi))) return -EFAULT; } else { /* Fixup default pi if IPv6 rather than IPv4 */ if (((tun->flags & TUN_TYPE_MASK) == TUN_TUN_DEV) && (*(char *)(iv->iov_base) == 0x60)) { pi.proto = __constant_htons(ETH_P_IPV6); } } fixes the problem. How do we get this in as part of the maintained codebase?? Thanks Steve
Reply-To: akpm@linux-foundation.org On Mon, 4 Feb 2008 13:46:13 -0800 (PST) bugme-daemon@bugzilla.kernel.org wrote: > http://bugzilla.kernel.org/show_bug.cgi?id=9888 > > Summary: tun device without protocol info header fails under IPv6 > Product: Networking > Version: 2.5 > KernelVersion: >=2.6.23 > Platform: All > OS/Version: Linux > Tree: Mainline > Status: NEW > Severity: low > Priority: P1 > Component: IPV6 > AssignedTo: yoshfuji@linux-ipv6.org > ReportedBy: steve.zabele@baesystems.com > > > Latest working kernel version: None known -- appears to be a historic bug > Earliest failing kernel version: All > Distribution: > Hardware Environment: > Software Environment: > Problem Description: > > Steps to reproduce: > > Open a tun device as type TUN, set the TUN_NO_PI flag, and try sending an > IPv6 > packet. The packet appears at the interface under tcpdumps, but propagates no > further. This is because the default protocol info used for tun devices where > the TUN_NO_PI flag is set assumes IPv4 as can be seen by the initialization > at > the top of the tun_get_user function in drivers/net/tun.c file given by > > struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) }; > > This can easily be fixed by adding a quick check at the top of tun_get_user. > Basically the code that used to read > > if (!(tun->flags & TUN_NO_PI)) { > if ((len -= sizeof(pi)) > count) > return -EINVAL; > > if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi))) > return -EFAULT; > } > > when changed to read > > if (!(tun->flags & TUN_NO_PI)) { > if ((len -= sizeof(pi)) > count) > return -EINVAL; > > if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi))) > return -EFAULT; > } > else { > /* Fixup default pi if IPv6 rather than IPv4 */ > if (((tun->flags & TUN_TYPE_MASK) == TUN_TUN_DEV) && > (*(char *)(iv->iov_base) == 0x60)) { > pi.proto = __constant_htons(ETH_P_IPV6); > } > } > > fixes the problem. > > How do we get this in as part of the maintained codebase?? > Please email a tested patch prepared as described in Documentation/SubmittingPatches Documentation/SubmitChecklist http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt to Maxim Krasnyansky <maxk@qualcomm.com> "David S. Miller" <davem@davemloft.net> Andrew Morton <akpm@linux-foundation.org> netdev@vger.kernel.org thanks.
Reply-To: maxk@qualcomm.com Andrew Morton wrote: > On Mon, 4 Feb 2008 13:46:13 -0800 (PST) > bugme-daemon@bugzilla.kernel.org wrote: >> >> Open a tun device as type TUN, set the TUN_NO_PI flag, and try sending an >> IPv6 >> packet. The packet appears at the interface under tcpdumps, but propagates >> no >> further. This is because the default protocol info used for tun devices >> where >> the TUN_NO_PI flag is set assumes IPv4 as can be seen by the initialization >> at >> the top of the tun_get_user function in drivers/net/tun.c file given by >> >> struct tun_pi pi = { 0, __constant_htons(ETH_P_IP) }; >> >> This can easily be fixed by adding a quick check at the top of tun_get_user. >> Basically the code that used to read >> >> if (!(tun->flags & TUN_NO_PI)) { >> if ((len -= sizeof(pi)) > count) >> return -EINVAL; >> >> if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi))) >> return -EFAULT; >> } >> >> when changed to read >> >> if (!(tun->flags & TUN_NO_PI)) { >> if ((len -= sizeof(pi)) > count) >> return -EINVAL; >> >> if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi))) >> return -EFAULT; >> } >> else { >> /* Fixup default pi if IPv6 rather than IPv4 */ >> if (((tun->flags & TUN_TYPE_MASK) == TUN_TUN_DEV) && >> (*(char *)(iv->iov_base) == 0x60)) { >> pi.proto = __constant_htons(ETH_P_IPV6); >> } >> } >> >> fixes the problem. >> >> How do we get this in as part of the maintained codebase?? >> > > Please email a tested patch prepared as described in > > Documentation/SubmittingPatches > Documentation/SubmitChecklist > http://www.zip.com.au/~akpm/linux/patches/stuff/tpp.txt > > to > > Maxim Krasnyansky <maxk@qualcomm.com> > "David S. Miller" <davem@davemloft.net> > Andrew Morton <akpm@linux-foundation.org> > netdev@vger.kernel.org btw I'd be ok with this fix. But I guess the questions is why not use struct tun_pi in the apps instead ? Max
Created attachment 14747 [details] TUN_NO_PI and IPv6 fix
Created attachment 15333 [details] TUN_NO_PI and IPv6 update The memcpy_fromiovec used in the previous patch advances the iovec internal pointer and decrements the packet length, such that subsequent attempts to pull the packet from the user space buffer finds that the buffer is now too short -- generating an -EFAULT. The enclosed patch instead users copy_from_user and correctly leaves the iovec unmodified
Steve, Can you please submit the patch to LKML and to Maxim (maxk@qualcomm.com) via email (if you haven't already)?