summaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp.c
diff options
context:
space:
mode:
authorJason Baron2018-08-03 23:24:53 +0200
committerDavid S. Miller2018-08-04 01:44:19 +0200
commit51f7e95187f127d5eadf50541943813ff57f12ba (patch)
treebc23c743b9cf6bed86cd611cdc16e31b4bb4fb70 /net/ipv4/tcp.c
parentppp: mppe: Remove VLA usage (diff)
downloadkernel-qcow2-linux-51f7e95187f127d5eadf50541943813ff57f12ba.tar.gz
kernel-qcow2-linux-51f7e95187f127d5eadf50541943813ff57f12ba.tar.xz
kernel-qcow2-linux-51f7e95187f127d5eadf50541943813ff57f12ba.zip
af_unix: ensure POLLOUT on remote close() for connected dgram socket
Applications use -ECONNREFUSED as returned from write() in order to determine that a socket should be closed. However, when using connected dgram unix sockets in a poll/write loop, a final POLLOUT event can be missed when the remote end closes. Thus, the poll is stuck forever: thread 1 (client) thread 2 (server) connect() to server write() returns -EAGAIN unix_dgram_poll() -> unix_recvq_full() is true close() ->unix_release_sock() ->wake_up_interruptible_all() unix_dgram_poll() (due to the wake_up_interruptible_all) -> unix_recvq_full() still is true ->free all skbs Now thread 1 is stuck and will not receive anymore wakeups. In this case, when thread 1 gets the -EAGAIN, it has not queued any skbs otherwise the 'free all skbs' step would in fact cause a wakeup and a POLLOUT return. So the race here is probably fairly rare because it means there are no skbs that thread 1 queued and that thread 1 schedules before the 'free all skbs' step. This issue was reported as a hang when /dev/log is closed. The fix is to signal POLLOUT if the socket is marked as SOCK_DEAD, which means a subsequent write() will get -ECONNREFUSED. Reported-by: Ian Lance Taylor <iant@golang.org> Cc: David Rientjes <rientjes@google.com> Cc: Rainer Weikusat <rweikusat@mobileactivedefense.com> Cc: Eric Dumazet <edumazet@google.com> Signed-off-by: Jason Baron <jbaron@akamai.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp.c')
0 files changed, 0 insertions, 0 deletions