Commit 847b4237 authored by Ido Schimmel's avatar Ido Schimmel Committed by Greg Kroah-Hartman

ipv6: Unlink sibling route in case of failure

[ Upstream commit 54851aa9 ]

When a route needs to be appended to an existing multipath route,
fib6_add_rt2node() first appends it to the siblings list and increments
the number of sibling routes on each sibling.

Later, the function notifies the route via call_fib6_entry_notifiers().
In case the notification is vetoed, the route is not unlinked from the
siblings list, which can result in a use-after-free.

Fix this by unlinking the route from the siblings list before returning
an error.

Audited the rest of the call sites from which the FIB notification chain
is called and could not find more problems.

Fixes: 2233000c ("net/ipv6: Move call_fib6_entry_notifiers up for route adds")
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Reported-by: default avatarAlexander Petrovskiy <alexpe@mellanox.com>
Reviewed-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f2acb290
......@@ -1113,9 +1113,25 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
err = call_fib6_entry_notifiers(info->nl_net,
FIB_EVENT_ENTRY_ADD,
rt, extack);
if (err)
if (err) {
struct fib6_info *sibling, *next_sibling;
/* If the route has siblings, then it first
* needs to be unlinked from them.
*/
if (!rt->fib6_nsiblings)
return err;
list_for_each_entry_safe(sibling, next_sibling,
&rt->fib6_siblings,
fib6_siblings)
sibling->fib6_nsiblings--;
rt->fib6_nsiblings = 0;
list_del_init(&rt->fib6_siblings);
rt6_multipath_rebalance(next_sibling);
return err;
}
rcu_assign_pointer(rt->fib6_next, iter);
atomic_inc(&rt->fib6_ref);
rcu_assign_pointer(rt->fib6_node, fn);
......
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