Commit 0a67d3ef authored by Hannes Frederic Sowa's avatar Hannes Frederic Sowa Committed by David S. Miller

ipv6: compare sernum when walking fib for /proc/net/ipv6_route as safety net

This patch provides an additional safety net against NULL
pointer dereferences while walking the fib trie for the new
/proc/net/ipv6_route walkers. I never needed it myself and am unsure
if it is needed at all, but the same checks where introduced in
2bec5a36 ("ipv6: fib: fix crash when
changing large fib while dumping it") to fix NULL pointer bugs.

This patch is separated from the first patch to make it easier to revert
if we are sure we can drop this logic.

Cc: Ben Greear <greearb@candelatech.com>
Cc: Patrick McHardy <kaber@trash.net>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarHannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8d2ca1d7
...@@ -1771,6 +1771,7 @@ struct ipv6_route_iter { ...@@ -1771,6 +1771,7 @@ struct ipv6_route_iter {
struct fib6_walker_t w; struct fib6_walker_t w;
loff_t skip; loff_t skip;
struct fib6_table *tbl; struct fib6_table *tbl;
__u32 sernum;
}; };
static int ipv6_route_seq_show(struct seq_file *seq, void *v) static int ipv6_route_seq_show(struct seq_file *seq, void *v)
...@@ -1823,6 +1824,7 @@ static void ipv6_route_seq_setup_walk(struct ipv6_route_iter *iter) ...@@ -1823,6 +1824,7 @@ static void ipv6_route_seq_setup_walk(struct ipv6_route_iter *iter)
iter->w.state = FWS_INIT; iter->w.state = FWS_INIT;
iter->w.node = iter->w.root; iter->w.node = iter->w.root;
iter->w.args = iter; iter->w.args = iter;
iter->sernum = iter->w.root->fn_sernum;
INIT_LIST_HEAD(&iter->w.lh); INIT_LIST_HEAD(&iter->w.lh);
fib6_walker_link(&iter->w); fib6_walker_link(&iter->w);
} }
...@@ -1848,6 +1850,17 @@ static struct fib6_table *ipv6_route_seq_next_table(struct fib6_table *tbl, ...@@ -1848,6 +1850,17 @@ static struct fib6_table *ipv6_route_seq_next_table(struct fib6_table *tbl,
return hlist_entry_safe(node, struct fib6_table, tb6_hlist); return hlist_entry_safe(node, struct fib6_table, tb6_hlist);
} }
static void ipv6_route_check_sernum(struct ipv6_route_iter *iter)
{
if (iter->sernum != iter->w.root->fn_sernum) {
iter->sernum = iter->w.root->fn_sernum;
iter->w.state = FWS_INIT;
iter->w.node = iter->w.root;
WARN_ON(iter->w.skip);
iter->w.skip = iter->w.count;
}
}
static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ {
int r; int r;
...@@ -1865,6 +1878,7 @@ static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -1865,6 +1878,7 @@ static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos)
} }
iter_table: iter_table:
ipv6_route_check_sernum(iter);
read_lock(&iter->tbl->tb6_lock); read_lock(&iter->tbl->tb6_lock);
r = fib6_walk_continue(&iter->w); r = fib6_walk_continue(&iter->w);
read_unlock(&iter->tbl->tb6_lock); read_unlock(&iter->tbl->tb6_lock);
......
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