diff options
| author | Paolo Abeni <[email protected]> | 2023-10-11 07:20:55 +0000 |
|---|---|---|
| committer | Jakub Kicinski <[email protected]> | 2023-10-13 23:49:32 +0000 |
| commit | 419ce133ab928ab5efd7b50b2ef36ddfd4eadbd2 (patch) | |
| tree | 8d934593e6eaf8f7ded2c7c32e8bd0db8effccd9 /net/ipv4/tcp_bpf.c | |
| parent | ice: fix over-shifted variable (diff) | |
| download | kernel-419ce133ab928ab5efd7b50b2ef36ddfd4eadbd2.tar.gz kernel-419ce133ab928ab5efd7b50b2ef36ddfd4eadbd2.zip | |
tcp: allow again tcp_disconnect() when threads are waiting
As reported by Tom, .NET and applications build on top of it rely
on connect(AF_UNSPEC) to async cancel pending I/O operations on TCP
socket.
The blamed commit below caused a regression, as such cancellation
can now fail.
As suggested by Eric, this change addresses the problem explicitly
causing blocking I/O operation to terminate immediately (with an error)
when a concurrent disconnect() is executed.
Instead of tracking the number of threads blocked on a given socket,
track the number of disconnect() issued on such socket. If such counter
changes after a blocking operation releasing and re-acquiring the socket
lock, error out the current operation.
Fixes: 4faeee0cf8a5 ("tcp: deny tcp_disconnect() when threads are waiting")
Reported-by: Tom Deseyn <[email protected]>
Closes: https://bugzilla.redhat.com/show_bug.cgi?id=1886305
Suggested-by: Eric Dumazet <[email protected]>
Signed-off-by: Paolo Abeni <[email protected]>
Reviewed-by: Eric Dumazet <[email protected]>
Link: https://lore.kernel.org/r/f3b95e47e3dbed840960548aebaa8d954372db41.1697008693.git.pabeni@redhat.com
Signed-off-by: Jakub Kicinski <[email protected]>
Diffstat (limited to 'net/ipv4/tcp_bpf.c')
| -rw-r--r-- | net/ipv4/tcp_bpf.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index 327268203001..ba2e92188124 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -307,6 +307,8 @@ msg_bytes_ready: } data = tcp_msg_wait_data(sk, psock, timeo); + if (data < 0) + return data; if (data && !sk_psock_queue_empty(psock)) goto msg_bytes_ready; copied = -EAGAIN; @@ -351,6 +353,8 @@ msg_bytes_ready: timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); data = tcp_msg_wait_data(sk, psock, timeo); + if (data < 0) + return data; if (data) { if (!sk_psock_queue_empty(psock)) goto msg_bytes_ready; |
