inet: fix races in reqsk_queue_hash_req()
Before allowing lockless LISTEN processing, we need to make
sure to arm the SYN_RECV timer before the req socket is visible
in hash tables.
Also, req->rsk_hash should be written before we set rsk_refcnt
to a non zero value.
Fixes: fa76ce7328
("inet: get rid of central tcp/dccp listener timer")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ying Cai <ycai@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ed2e923945
commit
29c6852602
|
@ -685,20 +685,20 @@ void reqsk_queue_hash_req(struct request_sock_queue *queue,
|
|||
req->num_timeout = 0;
|
||||
req->sk = NULL;
|
||||
|
||||
setup_timer(&req->rsk_timer, reqsk_timer_handler, (unsigned long)req);
|
||||
mod_timer_pinned(&req->rsk_timer, jiffies + timeout);
|
||||
req->rsk_hash = hash;
|
||||
|
||||
/* before letting lookups find us, make sure all req fields
|
||||
* are committed to memory and refcnt initialized.
|
||||
*/
|
||||
smp_wmb();
|
||||
atomic_set(&req->rsk_refcnt, 2);
|
||||
setup_timer(&req->rsk_timer, reqsk_timer_handler, (unsigned long)req);
|
||||
req->rsk_hash = hash;
|
||||
|
||||
spin_lock(&queue->syn_wait_lock);
|
||||
req->dl_next = lopt->syn_table[hash];
|
||||
lopt->syn_table[hash] = req;
|
||||
spin_unlock(&queue->syn_wait_lock);
|
||||
|
||||
mod_timer_pinned(&req->rsk_timer, jiffies + timeout);
|
||||
}
|
||||
EXPORT_SYMBOL(reqsk_queue_hash_req);
|
||||
|
||||
|
|
Loading…
Reference in New Issue