Commit 1bde5ac4 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

tcp: fix listening_get_next()

Alexey Vlasov found /proc/net/tcp could sometime loop and display
millions of sockets in LISTEN state.

In 2.6.29, when we converted TCP hash tables to RCU, we left two
sk_next() calls in listening_get_next().

We must instead use sk_nulls_next() to properly detect an end of chain.
Reported-by: default avatarAlexey Vlasov <renton@renton.name>
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b7e03ec9
...@@ -2030,7 +2030,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) ...@@ -2030,7 +2030,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
get_req: get_req:
req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket]; req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];
} }
sk = sk_next(st->syn_wait_sk); sk = sk_nulls_next(st->syn_wait_sk);
st->state = TCP_SEQ_STATE_LISTENING; st->state = TCP_SEQ_STATE_LISTENING;
read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock); read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
} else { } else {
...@@ -2039,7 +2039,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur) ...@@ -2039,7 +2039,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
if (reqsk_queue_len(&icsk->icsk_accept_queue)) if (reqsk_queue_len(&icsk->icsk_accept_queue))
goto start_req; goto start_req;
read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock); read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
sk = sk_next(sk); sk = sk_nulls_next(sk);
} }
get_sk: get_sk:
sk_nulls_for_each_from(sk, node) { sk_nulls_for_each_from(sk, node) {
......
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