]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Sep 2019 16:29:52 +0000 (18:29 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Sep 2019 16:29:52 +0000 (18:29 +0200)
added patches:
ipv4-icmp-fix-rt-dst-dev-null-pointer-dereference.patch
ipv6-addrconf-allow-adding-multicast-addr-if-ifa_f_mcautojoin-is-set.patch
ipv6-default-fib6_type-to-rtn_unicast-when-not-set.patch
net-smc-make-sure-epollout-is-raised.patch
net-tls-fix-sk_write_space-null-write-when-tx-disabled.patch
net-tls-fixed-return-value-when-tls_complete_pending_work-fails.patch
net-tls-swap-sk_write_space-on-close.patch
tcp-make-sure-epollout-wont-be-missed.patch

queue-4.19/ipv4-icmp-fix-rt-dst-dev-null-pointer-dereference.patch [new file with mode: 0644]
queue-4.19/ipv6-addrconf-allow-adding-multicast-addr-if-ifa_f_mcautojoin-is-set.patch [new file with mode: 0644]
queue-4.19/ipv6-default-fib6_type-to-rtn_unicast-when-not-set.patch [new file with mode: 0644]
queue-4.19/net-smc-make-sure-epollout-is-raised.patch [new file with mode: 0644]
queue-4.19/net-tls-fix-sk_write_space-null-write-when-tx-disabled.patch [new file with mode: 0644]
queue-4.19/net-tls-fixed-return-value-when-tls_complete_pending_work-fails.patch [new file with mode: 0644]
queue-4.19/net-tls-swap-sk_write_space-on-close.patch [new file with mode: 0644]
queue-4.19/series
queue-4.19/tcp-make-sure-epollout-wont-be-missed.patch [new file with mode: 0644]

diff --git a/queue-4.19/ipv4-icmp-fix-rt-dst-dev-null-pointer-dereference.patch b/queue-4.19/ipv4-icmp-fix-rt-dst-dev-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..45c5b31
--- /dev/null
@@ -0,0 +1,61 @@
+From foo@baz Mon 02 Sep 2019 06:29:26 PM CEST
+From: Hangbin Liu <liuhangbin@gmail.com>
+Date: Thu, 22 Aug 2019 22:19:48 +0800
+Subject: ipv4/icmp: fix rt dst dev null pointer dereference
+
+From: Hangbin Liu <liuhangbin@gmail.com>
+
+[ Upstream commit e2c693934194fd3b4e795635934883354c06ebc9 ]
+
+In __icmp_send() there is a possibility that the rt->dst.dev is NULL,
+e,g, with tunnel collect_md mode, which will cause kernel crash.
+Here is what the code path looks like, for GRE:
+
+- ip6gre_tunnel_xmit
+  - ip6gre_xmit_ipv4
+    - __gre6_xmit
+      - ip6_tnl_xmit
+        - if skb->len - t->tun_hlen - eth_hlen > mtu; return -EMSGSIZE
+    - icmp_send
+      - net = dev_net(rt->dst.dev); <-- here
+
+The reason is __metadata_dst_init() init dst->dev to NULL by default.
+We could not fix it in __metadata_dst_init() as there is no dev supplied.
+On the other hand, the reason we need rt->dst.dev is to get the net.
+So we can just try get it from skb->dev when rt->dst.dev is NULL.
+
+v4: Julian Anastasov remind skb->dev also could be NULL. We'd better
+still use dst.dev and do a check to avoid crash.
+
+v3: No changes.
+
+v2: fix the issue in __icmp_send() instead of updating shared dst dev
+in {ip_md, ip6}_tunnel_xmit.
+
+Fixes: c8b34e680a09 ("ip_tunnel: Add tnl_update_pmtu in ip_md_tunnel_xmit")
+Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
+Reviewed-by: Julian Anastasov <ja@ssi.bg>
+Acked-by: Jonathan Lemon <jonathan.lemon@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/icmp.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/net/ipv4/icmp.c
++++ b/net/ipv4/icmp.c
+@@ -587,7 +587,13 @@ void __icmp_send(struct sk_buff *skb_in,
+       if (!rt)
+               goto out;
+-      net = dev_net(rt->dst.dev);
++
++      if (rt->dst.dev)
++              net = dev_net(rt->dst.dev);
++      else if (skb_in->dev)
++              net = dev_net(skb_in->dev);
++      else
++              goto out;
+       /*
+        *      Find the original header. It is expected to be valid, of course.
diff --git a/queue-4.19/ipv6-addrconf-allow-adding-multicast-addr-if-ifa_f_mcautojoin-is-set.patch b/queue-4.19/ipv6-addrconf-allow-adding-multicast-addr-if-ifa_f_mcautojoin-is-set.patch
new file mode 100644 (file)
index 0000000..244a8c3
--- /dev/null
@@ -0,0 +1,59 @@
+From foo@baz Mon 02 Sep 2019 06:29:26 PM CEST
+From: Hangbin Liu <liuhangbin@gmail.com>
+Date: Tue, 20 Aug 2019 10:19:47 +0800
+Subject: ipv6/addrconf: allow adding multicast addr if IFA_F_MCAUTOJOIN is set
+
+From: Hangbin Liu <liuhangbin@gmail.com>
+
+[ Upstream commit f17f7648a49aa6728649ddf79bdbcac4f1970ce4 ]
+
+In commit 93a714d6b53d ("multicast: Extend ip address command to enable
+multicast group join/leave on") we added a new flag IFA_F_MCAUTOJOIN
+to make user able to add multicast address on ethernet interface.
+
+This works for IPv4, but not for IPv6. See the inet6_addr_add code.
+
+static int inet6_addr_add()
+{
+       ...
+       if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
+               ipv6_mc_config(net->ipv6.mc_autojoin_sk, true...)
+       }
+
+       ifp = ipv6_add_addr(idev, cfg, true, extack); <- always fail with maddr
+       if (!IS_ERR(ifp)) {
+               ...
+       } else if (cfg->ifa_flags & IFA_F_MCAUTOJOIN) {
+               ipv6_mc_config(net->ipv6.mc_autojoin_sk, false...)
+       }
+}
+
+But in ipv6_add_addr() it will check the address type and reject multicast
+address directly. So this feature is never worked for IPv6.
+
+We should not remove the multicast address check totally in ipv6_add_addr(),
+but could accept multicast address only when IFA_F_MCAUTOJOIN flag supplied.
+
+v2: update commit description
+
+Fixes: 93a714d6b53d ("multicast: Extend ip address command to enable multicast group join/leave on")
+Reported-by: Jianlin Shi <jishi@redhat.com>
+Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/addrconf.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -995,7 +995,8 @@ ipv6_add_addr(struct inet6_dev *idev, st
+       int err = 0;
+       if (addr_type == IPV6_ADDR_ANY ||
+-          addr_type & IPV6_ADDR_MULTICAST ||
++          (addr_type & IPV6_ADDR_MULTICAST &&
++           !(cfg->ifa_flags & IFA_F_MCAUTOJOIN)) ||
+           (!(idev->dev->flags & IFF_LOOPBACK) &&
+            addr_type & IPV6_ADDR_LOOPBACK))
+               return ERR_PTR(-EADDRNOTAVAIL);
diff --git a/queue-4.19/ipv6-default-fib6_type-to-rtn_unicast-when-not-set.patch b/queue-4.19/ipv6-default-fib6_type-to-rtn_unicast-when-not-set.patch
new file mode 100644 (file)
index 0000000..1352dda
--- /dev/null
@@ -0,0 +1,35 @@
+From foo@baz Mon 02 Sep 2019 06:29:26 PM CEST
+From: David Ahern <dsahern@gmail.com>
+Date: Wed, 19 Jun 2019 10:50:24 -0700
+Subject: ipv6: Default fib6_type to RTN_UNICAST when not set
+
+From: David Ahern <dsahern@gmail.com>
+
+[ Upstream commit c7036d97acd2527cef145b5ef9ad1a37ed21bbe6 ]
+
+A user reported that routes are getting installed with type 0 (RTN_UNSPEC)
+where before the routes were RTN_UNICAST. One example is from accel-ppp
+which apparently still uses the ioctl interface and does not set
+rtmsg_type. Another is the netlink interface where ipv6 does not require
+rtm_type to be set (v4 does). Prior to the commit in the Fixes tag the
+ipv6 stack converted type 0 to RTN_UNICAST, so restore that behavior.
+
+Fixes: e8478e80e5a7 ("net/ipv6: Save route type in rt6_info")
+Signed-off-by: David Ahern <dsahern@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/route.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -3109,7 +3109,7 @@ static struct fib6_info *ip6_route_info_
+       rt->fib6_metric = cfg->fc_metric;
+       rt->fib6_nh.nh_weight = 1;
+-      rt->fib6_type = cfg->fc_type;
++      rt->fib6_type = cfg->fc_type ? : RTN_UNICAST;
+       /* We cannot add true routes via loopback here,
+          they would result in kernel looping; promote them to reject routes
diff --git a/queue-4.19/net-smc-make-sure-epollout-is-raised.patch b/queue-4.19/net-smc-make-sure-epollout-is-raised.patch
new file mode 100644 (file)
index 0000000..3948809
--- /dev/null
@@ -0,0 +1,53 @@
+From foo@baz Mon 02 Sep 2019 06:29:26 PM CEST
+From: Jason Baron <jbaron@akamai.com>
+Date: Mon, 19 Aug 2019 14:36:01 -0400
+Subject: net/smc: make sure EPOLLOUT is raised
+
+From: Jason Baron <jbaron@akamai.com>
+
+[ Upstream commit 4651d1802f7063e4d8c0bcad957f46ece0c04024 ]
+
+Currently, we are only explicitly setting SOCK_NOSPACE on a write timeout
+for non-blocking sockets. Epoll() edge-trigger mode relies on SOCK_NOSPACE
+being set when -EAGAIN is returned to ensure that EPOLLOUT is raised.
+Expand the setting of SOCK_NOSPACE to non-blocking sockets as well that can
+use SO_SNDTIMEO to adjust their write timeout. This mirrors the behavior
+that Eric Dumazet introduced for tcp sockets.
+
+Signed-off-by: Jason Baron <jbaron@akamai.com>
+Cc: Eric Dumazet <edumazet@google.com>
+Cc: Ursula Braun <ubraun@linux.ibm.com>
+Cc: Karsten Graul <kgraul@linux.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/smc/smc_tx.c |    6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/net/smc/smc_tx.c
++++ b/net/smc/smc_tx.c
+@@ -75,13 +75,11 @@ static int smc_tx_wait(struct smc_sock *
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
+       struct smc_connection *conn = &smc->conn;
+       struct sock *sk = &smc->sk;
+-      bool noblock;
+       long timeo;
+       int rc = 0;
+       /* similar to sk_stream_wait_memory */
+       timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
+-      noblock = timeo ? false : true;
+       add_wait_queue(sk_sleep(sk), &wait);
+       while (1) {
+               sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
+@@ -96,8 +94,8 @@ static int smc_tx_wait(struct smc_sock *
+                       break;
+               }
+               if (!timeo) {
+-                      if (noblock)
+-                              set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
++                      /* ensure EPOLLOUT is subsequently generated */
++                      set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+                       rc = -EAGAIN;
+                       break;
+               }
diff --git a/queue-4.19/net-tls-fix-sk_write_space-null-write-when-tx-disabled.patch b/queue-4.19/net-tls-fix-sk_write_space-null-write-when-tx-disabled.patch
new file mode 100644 (file)
index 0000000..25173d7
--- /dev/null
@@ -0,0 +1,41 @@
+From foo@baz Mon 02 Sep 2019 06:29:26 PM CEST
+From: John Fastabend <john.fastabend@gmail.com>
+Date: Wed, 14 Aug 2019 05:31:54 +0000
+Subject: net: tls, fix sk_write_space NULL write when tx disabled
+
+From: John Fastabend <john.fastabend@gmail.com>
+
+[ Upstream commit d85f01775850a35eae47a0090839baf510c1ef12 ]
+
+The ctx->sk_write_space pointer is only set when TLS tx mode is enabled.
+When running without TX mode its a null pointer but we still set the
+sk sk_write_space pointer on close().
+
+Fix the close path to only overwrite sk->sk_write_space when the current
+pointer is to the tls_write_space function indicating the tls module should
+clean it up properly as well.
+
+Reported-by: Hillf Danton <hdanton@sina.com>
+Cc: Ying Xue <ying.xue@windriver.com>
+Cc: Andrey Konovalov <andreyknvl@google.com>
+Fixes: 57c722e932cfb ("net/tls: swap sk_write_space on close")
+Signed-off-by: John Fastabend <john.fastabend@gmail.com>
+Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/tls/tls_main.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/tls/tls_main.c
++++ b/net/tls/tls_main.c
+@@ -301,7 +301,8 @@ static void tls_sk_proto_close(struct so
+ #else
+       {
+ #endif
+-              sk->sk_write_space = ctx->sk_write_space;
++              if (sk->sk_write_space == tls_write_space)
++                      sk->sk_write_space = ctx->sk_write_space;
+               tls_ctx_free(ctx);
+               ctx = NULL;
+       }
diff --git a/queue-4.19/net-tls-fixed-return-value-when-tls_complete_pending_work-fails.patch b/queue-4.19/net-tls-fixed-return-value-when-tls_complete_pending_work-fails.patch
new file mode 100644 (file)
index 0000000..44bf88c
--- /dev/null
@@ -0,0 +1,61 @@
+From foo@baz Mon 02 Sep 2019 06:29:26 PM CEST
+From: Vakul Garg <vakul.garg@nxp.com>
+Date: Mon, 10 Sep 2018 22:53:46 +0530
+Subject: net/tls: Fixed return value when tls_complete_pending_work() fails
+
+From: Vakul Garg <vakul.garg@nxp.com>
+
+[ Upstream commit 150085791afb8054e11d2e080d4b9cd755dd7f69 ]
+
+In tls_sw_sendmsg() and tls_sw_sendpage(), the variable 'ret' has
+been set to return value of tls_complete_pending_work(). This allows
+return of proper error code if tls_complete_pending_work() fails.
+
+Fixes: 3c4d7559159b ("tls: kernel TLS support")
+Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/tls/tls_sw.c |   10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -354,7 +354,7 @@ int tls_sw_sendmsg(struct sock *sk, stru
+ {
+       struct tls_context *tls_ctx = tls_get_ctx(sk);
+       struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
+-      int ret = 0;
++      int ret;
+       int required_size;
+       long timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
+       bool eor = !(msg->msg_flags & MSG_MORE);
+@@ -370,7 +370,8 @@ int tls_sw_sendmsg(struct sock *sk, stru
+       lock_sock(sk);
+-      if (tls_complete_pending_work(sk, tls_ctx, msg->msg_flags, &timeo))
++      ret = tls_complete_pending_work(sk, tls_ctx, msg->msg_flags, &timeo);
++      if (ret)
+               goto send_end;
+       if (unlikely(msg->msg_controllen)) {
+@@ -505,7 +506,7 @@ int tls_sw_sendpage(struct sock *sk, str
+ {
+       struct tls_context *tls_ctx = tls_get_ctx(sk);
+       struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
+-      int ret = 0;
++      int ret;
+       long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
+       bool eor;
+       size_t orig_size = size;
+@@ -525,7 +526,8 @@ int tls_sw_sendpage(struct sock *sk, str
+       sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
+-      if (tls_complete_pending_work(sk, tls_ctx, flags, &timeo))
++      ret = tls_complete_pending_work(sk, tls_ctx, flags, &timeo);
++      if (ret)
+               goto sendpage_end;
+       /* Call the sk_stream functions to manage the sndbuf mem. */
diff --git a/queue-4.19/net-tls-swap-sk_write_space-on-close.patch b/queue-4.19/net-tls-swap-sk_write_space-on-close.patch
new file mode 100644 (file)
index 0000000..58fd9c6
--- /dev/null
@@ -0,0 +1,33 @@
+From foo@baz Mon 02 Sep 2019 06:29:26 PM CEST
+From: Jakub Kicinski <jakub.kicinski@netronome.com>
+Date: Fri, 9 Aug 2019 18:36:23 -0700
+Subject: net/tls: swap sk_write_space on close
+
+From: Jakub Kicinski <jakub.kicinski@netronome.com>
+
+[ Upstream commit 57c722e932cfb82e9820bbaae1b1f7222ea97b52 ]
+
+Now that we swap the original proto and clear the ULP pointer
+on close we have to make sure no callback will try to access
+the freed state. sk_write_space is not part of sk_prot, remember
+to swap it.
+
+Reported-by: syzbot+dcdc9deefaec44785f32@syzkaller.appspotmail.com
+Fixes: 95fa145479fb ("bpf: sockmap/tls, close can race with map free")
+Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/tls/tls_main.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/tls/tls_main.c
++++ b/net/tls/tls_main.c
+@@ -301,6 +301,7 @@ static void tls_sk_proto_close(struct so
+ #else
+       {
+ #endif
++              sk->sk_write_space = ctx->sk_write_space;
+               tls_ctx_free(ctx);
+               ctx = NULL;
+       }
index f85466841b1772fbc1090e13798e0bdb48823493..947c5b4adf6b6b9b9e5f805fd4930cfed1259598 100644 (file)
@@ -28,3 +28,11 @@ watchdog-bcm2835_wdt-fix-module-autoload.patch
 drm-bridge-tfp410-fix-memleak-in-get_modes.patch
 scsi-ufs-fix-rx_termination_force_enable-define-valu.patch
 drm-tilcdc-register-cpufreq-notifier-after-we-have-i.patch
+net-tls-fixed-return-value-when-tls_complete_pending_work-fails.patch
+net-tls-swap-sk_write_space-on-close.patch
+net-tls-fix-sk_write_space-null-write-when-tx-disabled.patch
+ipv6-addrconf-allow-adding-multicast-addr-if-ifa_f_mcautojoin-is-set.patch
+ipv6-default-fib6_type-to-rtn_unicast-when-not-set.patch
+net-smc-make-sure-epollout-is-raised.patch
+tcp-make-sure-epollout-wont-be-missed.patch
+ipv4-icmp-fix-rt-dst-dev-null-pointer-dereference.patch
diff --git a/queue-4.19/tcp-make-sure-epollout-wont-be-missed.patch b/queue-4.19/tcp-make-sure-epollout-wont-be-missed.patch
new file mode 100644 (file)
index 0000000..e02a5f7
--- /dev/null
@@ -0,0 +1,82 @@
+From foo@baz Mon 02 Sep 2019 06:29:26 PM CEST
+From: Eric Dumazet <edumazet@google.com>
+Date: Fri, 16 Aug 2019 21:26:22 -0700
+Subject: tcp: make sure EPOLLOUT wont be missed
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit ef8d8ccdc216f797e66cb4a1372f5c4c285ce1e4 ]
+
+As Jason Baron explained in commit 790ba4566c1a ("tcp: set SOCK_NOSPACE
+under memory pressure"), it is crucial we properly set SOCK_NOSPACE
+when needed.
+
+However, Jason patch had a bug, because the 'nonblocking' status
+as far as sk_stream_wait_memory() is concerned is governed
+by MSG_DONTWAIT flag passed at sendmsg() time :
+
+    long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
+
+So it is very possible that tcp sendmsg() calls sk_stream_wait_memory(),
+and that sk_stream_wait_memory() returns -EAGAIN with SOCK_NOSPACE
+cleared, if sk->sk_sndtimeo has been set to a small (but not zero)
+value.
+
+This patch removes the 'noblock' variable since we must always
+set SOCK_NOSPACE if -EAGAIN is returned.
+
+It also renames the do_nonblock label since we might reach this
+code path even if we were in blocking mode.
+
+Fixes: 790ba4566c1a ("tcp: set SOCK_NOSPACE under memory pressure")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Jason Baron <jbaron@akamai.com>
+Reported-by: Vladimir Rutsky  <rutsky@google.com>
+Acked-by: Soheil Hassas Yeganeh <soheil@google.com>
+Acked-by: Neal Cardwell <ncardwell@google.com>
+Acked-by: Jason Baron <jbaron@akamai.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/stream.c |   16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+--- a/net/core/stream.c
++++ b/net/core/stream.c
+@@ -120,7 +120,6 @@ int sk_stream_wait_memory(struct sock *s
+       int err = 0;
+       long vm_wait = 0;
+       long current_timeo = *timeo_p;
+-      bool noblock = (*timeo_p ? false : true);
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
+       if (sk_stream_memory_free(sk))
+@@ -133,11 +132,8 @@ int sk_stream_wait_memory(struct sock *s
+               if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
+                       goto do_error;
+-              if (!*timeo_p) {
+-                      if (noblock)
+-                              set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+-                      goto do_nonblock;
+-              }
++              if (!*timeo_p)
++                      goto do_eagain;
+               if (signal_pending(current))
+                       goto do_interrupted;
+               sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
+@@ -169,7 +165,13 @@ out:
+ do_error:
+       err = -EPIPE;
+       goto out;
+-do_nonblock:
++do_eagain:
++      /* Make sure that whenever EAGAIN is returned, EPOLLOUT event can
++       * be generated later.
++       * When TCP receives ACK packets that make room, tcp_check_space()
++       * only calls tcp_new_space() if SOCK_NOSPACE is set.
++       */
++      set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+       err = -EAGAIN;
+       goto out;
+ do_interrupted: