Message ID | 20180604204142.8941-1-dsahern@kernel.org |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Series | [net] net/ipv6: prevent use after free in ip6_route_mpath_notify | expand |
On 06/04/2018 01:41 PM, dsahern@kernel.org wrote: > From: David Ahern <dsahern@gmail.com> > > syzbot reported a use-after-free: > > BUG: KASAN: use-after-free in ip6_route_mpath_notify+0xe9/0x100 net/ipv6/route.c:4180 > Read of size 4 at addr ffff8801bf789cf0 by task syz-executor756/4555 > > Fix by not setting rt_last until the it is verified the insert succeeded. > > Fixes: 3b1137fe7482 ("net: ipv6: Change notifications for multipath add to RTA_MULTIPATH") > Cc: Eric Dumazet <edumazet@google.com> > Reported-by: syzbot <syzkaller@googlegroups.com> > Signed-off-by: David Ahern <dsahern@gmail.com> > --- Reviewed-by: Eric Dumazet <edumazet@google.com> Thanks David !
From: dsahern@kernel.org Date: Mon, 4 Jun 2018 13:41:42 -0700 > From: David Ahern <dsahern@gmail.com> > > syzbot reported a use-after-free: ... > The problem is that rt_last can point to a deleted route if the insert > fails. > > One reproducer is to insert a route and then add a multipath route that > has a duplicate nexthop.e.g,: > $ ip -6 ro add vrf red 2001:db8:101::/64 nexthop via 2001:db8:1::2 > $ ip -6 ro append vrf red 2001:db8:101::/64 nexthop via 2001:db8:1::4 nexthop via 2001:db8:1::2 > > Fix by not setting rt_last until the it is verified the insert succeeded. > > Fixes: 3b1137fe7482 ("net: ipv6: Change notifications for multipath add to RTA_MULTIPATH") > Cc: Eric Dumazet <edumazet@google.com> > Reported-by: syzbot <syzkaller@googlegroups.com> > Signed-off-by: David Ahern <dsahern@gmail.com> Applied and queued up for -stable, thanks David.
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index f4d61736c41a..c516f8556dbe 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -4263,11 +4263,15 @@ static int ip6_route_multipath_add(struct fib6_config *cfg, err_nh = NULL; list_for_each_entry(nh, &rt6_nh_list, next) { - rt_last = nh->rt6_info; err = __ip6_ins_rt(nh->rt6_info, info, &nh->mxc, extack); - /* save reference to first route for notification */ - if (!rt_notif && !err) - rt_notif = nh->rt6_info; + if (!err) { + /* save reference to last route successfully inserted */ + rt_last = nh->rt6_info; + + /* save reference to first route for notification */ + if (!rt_notif) + rt_notif = nh->rt6_info; + } /* nh->rt6_info is used or freed at this point, reset to NULL*/ nh->rt6_info = NULL;