aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Frederic Sowa <hannes@stressinduktion.org>2017-03-12 19:00:26 -0400
committerDavid S. Miller <davem@davemloft.net>2017-03-14 01:00:17 -0400
commitb20e2d54789c6acbf6bd0efdbec2cf5fa4d90ef1 (patch)
treeb8b44fcb6c183d7cfb9f08e83bf80f30a774618e
parent45caeaa5ac0b4b11784ac6f932c0ad4c6b67cda0 (diff)
tun: fix premature POLLOUT notification on tun devices
aszlig observed failing ssh tunnels (-w) during initialization since commit cc9da6cc4f56e0 ("ipv6: addrconf: use stable address generator for ARPHRD_NONE"). We already had reports that the mentioned commit breaks Juniper VPN connections. I can't clearly say that the Juniper VPN client has the same problem, but it is worth a try to hint to this patch. Because of the early generation of link local addresses, the kernel now can start asking for routers on the local subnet much earlier than usual. Those router solicitation packets arrive inside the ssh channels and should be transmitted to the tun fd before the configuration scripts might have upped the interface and made it ready for transmission. ssh polls on the interface and receives back a POLL_OUT. It tries to send the earily router solicitation packet to the tun interface. Unfortunately it hasn't been up'ed yet by config scripts, thus failing with -EIO. ssh doesn't retry again and considers the tun interface broken forever. Link: https://bugzilla.kernel.org/show_bug.cgi?id=121131 Fixes: cc9da6cc4f56 ("ipv6: addrconf: use stable address generator for ARPHRD_NONE") Cc: Bjørn Mork <bjorn@mork.no> Reported-by: Valdis Kletnieks <Valdis.Kletnieks@vt.edu> Cc: Valdis Kletnieks <Valdis.Kletnieks@vt.edu> Reported-by: Jonas Lippuner <jonas@lippuner.ca> Cc: Jonas Lippuner <jonas@lippuner.ca> Reported-by: aszlig <aszlig@redmoonstudios.org> Cc: aszlig <aszlig@redmoonstudios.org> Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/tun.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index f58b7d850114..34cc3c590aa5 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -822,7 +822,18 @@ static void tun_net_uninit(struct net_device *dev)
822/* Net device open. */ 822/* Net device open. */
823static int tun_net_open(struct net_device *dev) 823static int tun_net_open(struct net_device *dev)
824{ 824{
825 struct tun_struct *tun = netdev_priv(dev);
826 int i;
827
825 netif_tx_start_all_queues(dev); 828 netif_tx_start_all_queues(dev);
829
830 for (i = 0; i < tun->numqueues; i++) {
831 struct tun_file *tfile;
832
833 tfile = rtnl_dereference(tun->tfiles[i]);
834 tfile->socket.sk->sk_write_space(tfile->socket.sk);
835 }
836
826 return 0; 837 return 0;
827} 838}
828 839
@@ -1103,9 +1114,10 @@ static unsigned int tun_chr_poll(struct file *file, poll_table *wait)
1103 if (!skb_array_empty(&tfile->tx_array)) 1114 if (!skb_array_empty(&tfile->tx_array))
1104 mask |= POLLIN | POLLRDNORM; 1115 mask |= POLLIN | POLLRDNORM;
1105 1116
1106 if (sock_writeable(sk) || 1117 if (tun->dev->flags & IFF_UP &&
1107 (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) && 1118 (sock_writeable(sk) ||
1108 sock_writeable(sk))) 1119 (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
1120 sock_writeable(sk))))
1109 mask |= POLLOUT | POLLWRNORM; 1121 mask |= POLLOUT | POLLWRNORM;
1110 1122
1111 if (tun->dev->reg_state != NETREG_REGISTERED) 1123 if (tun->dev->reg_state != NETREG_REGISTERED)