Skip to content

Commit

Permalink
ipv6: check for ip6_null_entry in __ip6_del_rt_siblings()
Browse files Browse the repository at this point in the history
Andrey reported a NULL pointer deref bug in ipv6_route_ioctl()
-> ip6_route_del() -> __ip6_del_rt_siblings() code path. This is
because ip6_null_entry is returned in this path since ip6_null_entry
is kinda default for a ipv6 route table root node. Quote from
David Ahern:

 ip6_null_entry is the root of all ipv6 fib tables making it integrated
 into the table ...

We should ignore any attempt of trying to delete it, like we do in
__ip6_del_rt() path and several others.

Reported-by: Andrey Konovalov <[email protected]>
Fixes: 0ae8133 ("net: ipv6: Allow shorthand delete of all nexthops in multipath route")
Cc: David Ahern <[email protected]>
Cc: Eric Dumazet <[email protected]>
Signed-off-by: Cong Wang <[email protected]>
Acked-by: David Ahern <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
congwang authored and davem330 committed Mar 2, 2017
1 parent 48cac18 commit e333003
Showing 1 changed file with 9 additions and 5 deletions.
14 changes: 9 additions & 5 deletions net/ipv6/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -2169,10 +2169,13 @@ int ip6_del_rt(struct rt6_info *rt)
static int __ip6_del_rt_siblings(struct rt6_info *rt, struct fib6_config *cfg)
{
struct nl_info *info = &cfg->fc_nlinfo;
struct net *net = info->nl_net;
struct sk_buff *skb = NULL;
struct fib6_table *table;
int err;
int err = -ENOENT;

if (rt == net->ipv6.ip6_null_entry)
goto out_put;
table = rt->rt6i_table;
write_lock_bh(&table->tb6_lock);

Expand All @@ -2184,7 +2187,7 @@ static int __ip6_del_rt_siblings(struct rt6_info *rt, struct fib6_config *cfg)
if (skb) {
u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;

if (rt6_fill_node(info->nl_net, skb, rt,
if (rt6_fill_node(net, skb, rt,
NULL, NULL, 0, RTM_DELROUTE,
info->portid, seq, 0) < 0) {
kfree_skb(skb);
Expand All @@ -2198,17 +2201,18 @@ static int __ip6_del_rt_siblings(struct rt6_info *rt, struct fib6_config *cfg)
rt6i_siblings) {
err = fib6_del(sibling, info);
if (err)
goto out;
goto out_unlock;
}
}

err = fib6_del(rt, info);
out:
out_unlock:
write_unlock_bh(&table->tb6_lock);
out_put:
ip6_rt_put(rt);

if (skb) {
rtnl_notify(skb, info->nl_net, info->portid, RTNLGRP_IPV6_ROUTE,
rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE,
info->nlh, gfp_any());
}
return err;
Expand Down

0 comments on commit e333003

Please sign in to comment.