Commit 29c68526 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

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: fa76ce73 ("inet: get rid of central tcp/dccp listener timer")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Ying Cai <ycai@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ed2e9239
...@@ -685,20 +685,20 @@ void reqsk_queue_hash_req(struct request_sock_queue *queue, ...@@ -685,20 +685,20 @@ void reqsk_queue_hash_req(struct request_sock_queue *queue,
req->num_timeout = 0; req->num_timeout = 0;
req->sk = NULL; 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 /* before letting lookups find us, make sure all req fields
* are committed to memory and refcnt initialized. * are committed to memory and refcnt initialized.
*/ */
smp_wmb(); smp_wmb();
atomic_set(&req->rsk_refcnt, 2); 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); spin_lock(&queue->syn_wait_lock);
req->dl_next = lopt->syn_table[hash]; req->dl_next = lopt->syn_table[hash];
lopt->syn_table[hash] = req; lopt->syn_table[hash] = req;
spin_unlock(&queue->syn_wait_lock); spin_unlock(&queue->syn_wait_lock);
mod_timer_pinned(&req->rsk_timer, jiffies + timeout);
} }
EXPORT_SYMBOL(reqsk_queue_hash_req); EXPORT_SYMBOL(reqsk_queue_hash_req);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment