]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.20.17/tcp-handle-inet_csk_reqsk_queue_add-failures.patch
Linux 4.20.17
[thirdparty/kernel/stable-queue.git] / releases / 4.20.17 / tcp-handle-inet_csk_reqsk_queue_add-failures.patch
1 From foo@baz Thu Mar 14 23:20:15 PDT 2019
2 From: Guillaume Nault <gnault@redhat.com>
3 Date: Fri, 8 Mar 2019 22:09:47 +0100
4 Subject: tcp: handle inet_csk_reqsk_queue_add() failures
5
6 From: Guillaume Nault <gnault@redhat.com>
7
8 [ Upstream commit 9d3e1368bb45893a75a5dfb7cd21fdebfa6b47af ]
9
10 Commit 7716682cc58e ("tcp/dccp: fix another race at listener
11 dismantle") let inet_csk_reqsk_queue_add() fail, and adjusted
12 {tcp,dccp}_check_req() accordingly. However, TFO and syncookies
13 weren't modified, thus leaking allocated resources on error.
14
15 Contrary to tcp_check_req(), in both syncookies and TFO cases,
16 we need to drop the request socket. Also, since the child socket is
17 created with inet_csk_clone_lock(), we have to unlock it and drop an
18 extra reference (->sk_refcount is initially set to 2 and
19 inet_csk_reqsk_queue_add() drops only one ref).
20
21 For TFO, we also need to revert the work done by tcp_try_fastopen()
22 (with reqsk_fastopen_remove()).
23
24 Fixes: 7716682cc58e ("tcp/dccp: fix another race at listener dismantle")
25 Signed-off-by: Guillaume Nault <gnault@redhat.com>
26 Signed-off-by: Eric Dumazet <edumazet@google.com>
27 Signed-off-by: David S. Miller <davem@davemloft.net>
28 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
29 ---
30 net/ipv4/syncookies.c | 7 ++++++-
31 net/ipv4/tcp_input.c | 8 +++++++-
32 2 files changed, 13 insertions(+), 2 deletions(-)
33
34 --- a/net/ipv4/syncookies.c
35 +++ b/net/ipv4/syncookies.c
36 @@ -216,7 +216,12 @@ struct sock *tcp_get_cookie_sock(struct
37 refcount_set(&req->rsk_refcnt, 1);
38 tcp_sk(child)->tsoffset = tsoff;
39 sock_rps_save_rxhash(child, skb);
40 - inet_csk_reqsk_queue_add(sk, req, child);
41 + if (!inet_csk_reqsk_queue_add(sk, req, child)) {
42 + bh_unlock_sock(child);
43 + sock_put(child);
44 + child = NULL;
45 + reqsk_put(req);
46 + }
47 } else {
48 reqsk_free(req);
49 }
50 --- a/net/ipv4/tcp_input.c
51 +++ b/net/ipv4/tcp_input.c
52 @@ -6511,7 +6511,13 @@ int tcp_conn_request(struct request_sock
53 af_ops->send_synack(fastopen_sk, dst, &fl, req,
54 &foc, TCP_SYNACK_FASTOPEN);
55 /* Add the child socket directly into the accept queue */
56 - inet_csk_reqsk_queue_add(sk, req, fastopen_sk);
57 + if (!inet_csk_reqsk_queue_add(sk, req, fastopen_sk)) {
58 + reqsk_fastopen_remove(fastopen_sk, req, false);
59 + bh_unlock_sock(fastopen_sk);
60 + sock_put(fastopen_sk);
61 + reqsk_put(req);
62 + goto drop;
63 + }
64 sk->sk_data_ready(sk);
65 bh_unlock_sock(fastopen_sk);
66 sock_put(fastopen_sk);