From: Alexei Starovoitov When an sk_msg prog redirects data to the egress of another socket, the sender calls tcp_sendmsg_locked() on that socket. The sender holds a reference to the sock, but not to its file. Thus __tcp_close() can call sock_orphan() while the sender sleeps in sk_stream_wait_memory(). sock_orphan() sets SOCK_DEAD and sets sk_wq to NULL. After the sleep the loop continues and does not test SOCK_DEAD. The subsequent sk_set_bit() can dereference the NULL sk_wq. The tests of sk_err and sk_shutdown do not always stop the sender. sock_error() clears sk_err, and __tcp_close() can call tcp_disconnect(), which clears sk_shutdown. The sender then adds data to the write queue of the dead socket, and inet_sock_destruct() warns. Leave the loop with -EPIPE when the socket is dead after the sleep. The function already tests SOCK_DEAD before remove_wait_queue() for the same reason. A caller that has the socket open never sees SOCK_DEAD. Fixes: 4f738adba30a ("bpf: create tcp_bpf_ulp allowing BPF to monitor socket TX/RX data") Signed-off-by: Alexei Starovoitov --- net/core/stream.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/core/stream.c b/net/core/stream.c index cb255e2a3a5d..334124d683a7 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -150,7 +150,11 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) (sk_stream_memory_free(sk) && !vm_wait), &wait); sk->sk_write_pending--; - if (ret < 0) + /* + * A sender which sockmap has redirected to sk does not keep it + * open. A dead socket has no sk_wq. + */ + if (ret < 0 || sock_flag(sk, SOCK_DEAD)) goto do_error; if (vm_wait) { -- 2.55.0