summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Frederic Sowa <hannes@stressinduktion.org>2017-03-13 00:00:26 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-03-22 12:57:02 +0100
commita79fa23c82a1b7ee3726ea348336fbe874130a7c (patch)
treeaf9a4ff58bdb87367c4652b4ee7c9804b4f91b0f
parentb34c9f7fe45e0f884f5b9c8093ec99a0a9a52002 (diff)
downloadlinux-stable-a79fa23c82a1b7ee3726ea348336fbe874130a7c.tar.gz
linux-stable-a79fa23c82a1b7ee3726ea348336fbe874130a7c.tar.bz2
linux-stable-a79fa23c82a1b7ee3726ea348336fbe874130a7c.zip
tun: fix premature POLLOUT notification on tun devices
[ Upstream commit b20e2d54789c6acbf6bd0efdbec2cf5fa4d90ef1 ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 bfabe180053e..cdf6339827e6 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -819,7 +819,18 @@ static void tun_net_uninit(struct net_device *dev)
/* Net device open. */
static int tun_net_open(struct net_device *dev)
{
+ struct tun_struct *tun = netdev_priv(dev);
+ int i;
+
netif_tx_start_all_queues(dev);
+
+ for (i = 0; i < tun->numqueues; i++) {
+ struct tun_file *tfile;
+
+ tfile = rtnl_dereference(tun->tfiles[i]);
+ tfile->socket.sk->sk_write_space(tfile->socket.sk);
+ }
+
return 0;
}
@@ -1101,9 +1112,10 @@ static unsigned int tun_chr_poll(struct file *file, poll_table *wait)
if (!skb_array_empty(&tfile->tx_array))
mask |= POLLIN | POLLRDNORM;
- if (sock_writeable(sk) ||
- (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
- sock_writeable(sk)))
+ if (tun->dev->flags & IFF_UP &&
+ (sock_writeable(sk) ||
+ (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
+ sock_writeable(sk))))
mask |= POLLOUT | POLLWRNORM;
if (tun->dev->reg_state != NETREG_REGISTERED)