|
|
48f65f6 |
From patchwork Thu Oct 1 12:39:26 2015
|
|
|
48f65f6 |
Content-Type: text/plain; charset="utf-8"
|
|
|
48f65f6 |
MIME-Version: 1.0
|
|
|
48f65f6 |
Content-Transfer-Encoding: 7bit
|
|
|
48f65f6 |
Subject: [net] inet: fix race in reqsk_queue_unlink()
|
|
|
48f65f6 |
From: Eric Dumazet <eric.dumazet@gmail.com>
|
|
|
48f65f6 |
X-Patchwork-Id: 524966
|
|
|
48f65f6 |
Message-Id: <1443703166.32531.47.camel@edumazet-glaptop2.roam.corp.google.com>
|
|
|
48f65f6 |
To: David Miller <davem@davemloft.net>
|
|
|
48f65f6 |
Cc: netdev <netdev@vger.kernel.org>, Yuchung Cheng <ycheng@google.com>
|
|
|
48f65f6 |
Date: Thu, 01 Oct 2015 05:39:26 -0700
|
|
|
48f65f6 |
|
|
|
48f65f6 |
From: Eric Dumazet <edumazet@google.com>
|
|
|
48f65f6 |
|
|
|
48f65f6 |
reqsk_timer_handler() tests if icsk_accept_queue.listen_opt
|
|
|
48f65f6 |
is NULL at its beginning.
|
|
|
48f65f6 |
|
|
|
48f65f6 |
By the time it calls inet_csk_reqsk_queue_drop() and
|
|
|
48f65f6 |
reqsk_queue_unlink(), listener might have been closed and
|
|
|
48f65f6 |
inet_csk_listen_stop() had called reqsk_queue_yank_acceptq()
|
|
|
48f65f6 |
which sets icsk_accept_queue.listen_opt to NULL
|
|
|
48f65f6 |
|
|
|
48f65f6 |
We therefore need to correctly check listen_opt being NULL
|
|
|
48f65f6 |
after holding syn_wait_lock for proper synchronization.
|
|
|
48f65f6 |
|
|
|
48f65f6 |
Fixes: fa76ce7328b2 ("inet: get rid of central tcp/dccp listener timer")
|
|
|
48f65f6 |
Fixes: b357a364c57c ("inet: fix possible panic in reqsk_queue_unlink()")
|
|
|
48f65f6 |
Signed-off-by: Eric Dumazet <edumazet@google.com>
|
|
|
48f65f6 |
Cc: Yuchung Cheng <ycheng@google.com>
|
|
|
48f65f6 |
---
|
|
|
48f65f6 |
net/ipv4/inet_connection_sock.c | 19 ++++++++++---------
|
|
|
48f65f6 |
1 file changed, 10 insertions(+), 9 deletions(-)
|
|
|
48f65f6 |
|
|
|
48f65f6 |
|
|
|
48f65f6 |
|
|
|
48f65f6 |
--
|
|
|
48f65f6 |
To unsubscribe from this list: send the line "unsubscribe netdev" in
|
|
|
48f65f6 |
the body of a message to majordomo@vger.kernel.org
|
|
|
48f65f6 |
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
|
|
48f65f6 |
|
|
|
48f65f6 |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
|
|
|
48f65f6 |
index 7bb9c39e0a4d..61b45a17fc73 100644
|
|
|
48f65f6 |
--- a/net/ipv4/inet_connection_sock.c
|
|
|
48f65f6 |
+++ b/net/ipv4/inet_connection_sock.c
|
|
|
48f65f6 |
@@ -577,21 +577,22 @@ EXPORT_SYMBOL(inet_rtx_syn_ack);
|
|
|
48f65f6 |
static bool reqsk_queue_unlink(struct request_sock_queue *queue,
|
|
|
48f65f6 |
struct request_sock *req)
|
|
|
48f65f6 |
{
|
|
|
48f65f6 |
- struct listen_sock *lopt = queue->listen_opt;
|
|
|
48f65f6 |
struct request_sock **prev;
|
|
|
48f65f6 |
+ struct listen_sock *lopt;
|
|
|
48f65f6 |
bool found = false;
|
|
|
48f65f6 |
|
|
|
48f65f6 |
spin_lock(&queue->syn_wait_lock);
|
|
|
48f65f6 |
-
|
|
|
48f65f6 |
- for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL;
|
|
|
48f65f6 |
- prev = &(*prev)->dl_next) {
|
|
|
48f65f6 |
- if (*prev == req) {
|
|
|
48f65f6 |
- *prev = req->dl_next;
|
|
|
48f65f6 |
- found = true;
|
|
|
48f65f6 |
- break;
|
|
|
48f65f6 |
+ lopt = queue->listen_opt;
|
|
|
48f65f6 |
+ if (lopt) {
|
|
|
48f65f6 |
+ for (prev = &lopt->syn_table[req->rsk_hash]; *prev != NULL;
|
|
|
48f65f6 |
+ prev = &(*prev)->dl_next) {
|
|
|
48f65f6 |
+ if (*prev == req) {
|
|
|
48f65f6 |
+ *prev = req->dl_next;
|
|
|
48f65f6 |
+ found = true;
|
|
|
48f65f6 |
+ break;
|
|
|
48f65f6 |
+ }
|
|
|
48f65f6 |
}
|
|
|
48f65f6 |
}
|
|
|
48f65f6 |
-
|
|
|
48f65f6 |
spin_unlock(&queue->syn_wait_lock);
|
|
|
48f65f6 |
if (timer_pending(&req->rsk_timer) && del_timer_sync(&req->rsk_timer))
|
|
|
48f65f6 |
reqsk_put(req);
|