inet: fix request sock refcounting
While testing last patch series, I found req sock refcounting was wrong.
We must set skc_refcnt to 1 for all request socks added in hashes,
but also on request sockets created by FastOpen or syncookies.
It is tricky because we need to defer this initialization so that
future RCU lookups do not try to take a refcount on a not yet
fully initialized request socket.
Also get rid of ireq_refcnt alias.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Fixes: 13854e5a60
("inet: add proper refcounting to request sock")
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
e3d95ad7da
commit
0470c8ca1d
@@ -227,11 +227,12 @@ static struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
|
||||
struct sock *child;
|
||||
|
||||
child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst);
|
||||
if (child)
|
||||
if (child) {
|
||||
atomic_set(&req->rsk_refcnt, 1);
|
||||
inet_csk_reqsk_queue_add(sk, req, child);
|
||||
else
|
||||
} else {
|
||||
reqsk_free(req);
|
||||
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
@@ -356,7 +357,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
|
||||
ireq->opt = tcp_v4_save_options(skb);
|
||||
|
||||
if (security_inet_conn_request(sk, skb, req)) {
|
||||
reqsk_put(req);
|
||||
reqsk_free(req);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -377,7 +378,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
|
||||
security_req_classify_flow(req, flowi4_to_flowi(&fl4));
|
||||
rt = ip_route_output_key(sock_net(sk), &fl4);
|
||||
if (IS_ERR(rt)) {
|
||||
reqsk_put(req);
|
||||
reqsk_free(req);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@@ -169,6 +169,7 @@ static bool tcp_fastopen_create_child(struct sock *sk,
|
||||
inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS,
|
||||
TCP_TIMEOUT_INIT, TCP_RTO_MAX);
|
||||
|
||||
atomic_set(&req->rsk_refcnt, 1);
|
||||
/* Add the child socket directly into the accept queue */
|
||||
inet_csk_reqsk_queue_add(sk, req, child);
|
||||
|
||||
|
@@ -5981,10 +5981,6 @@ struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,
|
||||
ireq->ireq_state = TCP_NEW_SYN_RECV;
|
||||
write_pnet(&ireq->ireq_net, sock_net(sk_listener));
|
||||
|
||||
/* Following is temporary. It is coupled with debugging
|
||||
* helpers in reqsk_put() & reqsk_free()
|
||||
*/
|
||||
atomic_set(&ireq->ireq_refcnt, 0);
|
||||
}
|
||||
|
||||
return req;
|
||||
|
@@ -49,11 +49,12 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
|
||||
struct sock *child;
|
||||
|
||||
child = icsk->icsk_af_ops->syn_recv_sock(sk, skb, req, dst);
|
||||
if (child)
|
||||
if (child) {
|
||||
atomic_set(&req->rsk_refcnt, 1);
|
||||
inet_csk_reqsk_queue_add(sk, req, child);
|
||||
else
|
||||
} else {
|
||||
reqsk_free(req);
|
||||
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user