aboutsummaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2016-04-01 11:52:16 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-04 22:11:19 -0400
commit3a5d1c0e7cb5ba91aabbd7e28626e3cc925f8093 (patch)
tree14db12b0567eaaa34d3d9850645daf8b54e8689f /include/net
parent2d331915a04144dad738e725769d8fac06ef6155 (diff)
inet: reqsk_alloc() needs to take care of dead listeners
We'll soon no longer take a refcount on listeners, so reqsk_alloc() can not assume a listener refcount is not zero. We need to use atomic_inc_not_zero() Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/request_sock.h31
1 files changed, 15 insertions, 16 deletions
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index f49759decb28..6ebe13eb1c4c 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -85,24 +85,23 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
85 struct request_sock *req; 85 struct request_sock *req;
86 86
87 req = kmem_cache_alloc(ops->slab, GFP_ATOMIC | __GFP_NOWARN); 87 req = kmem_cache_alloc(ops->slab, GFP_ATOMIC | __GFP_NOWARN);
88 88 if (!req)
89 if (req) { 89 return NULL;
90 req->rsk_ops = ops; 90 req->rsk_listener = NULL;
91 if (attach_listener) { 91 if (attach_listener) {
92 sock_hold(sk_listener); 92 if (unlikely(!atomic_inc_not_zero(&sk_listener->sk_refcnt))) {
93 req->rsk_listener = sk_listener; 93 kmem_cache_free(ops->slab, req);
94 } else { 94 return NULL;
95 req->rsk_listener = NULL;
96 } 95 }
97 req_to_sk(req)->sk_prot = sk_listener->sk_prot; 96 req->rsk_listener = sk_listener;
98 sk_node_init(&req_to_sk(req)->sk_node);
99 sk_tx_queue_clear(req_to_sk(req));
100 req->saved_syn = NULL;
101 /* Following is temporary. It is coupled with debugging
102 * helpers in reqsk_put() & reqsk_free()
103 */
104 atomic_set(&req->rsk_refcnt, 0);
105 } 97 }
98 req->rsk_ops = ops;
99 req_to_sk(req)->sk_prot = sk_listener->sk_prot;
100 sk_node_init(&req_to_sk(req)->sk_node);
101 sk_tx_queue_clear(req_to_sk(req));
102 req->saved_syn = NULL;
103 atomic_set(&req->rsk_refcnt, 0);
104
106 return req; 105 return req;
107} 106}
108 107