• Andrey Vagin's avatar
    ipv6: fix race between ipv6_del_addr and DAD timer · b2238566
    Andrey Vagin authored
    Consider the following scenario:
    
    ipv6_del_addr(ifp)
      ipv6_ifa_notify(RTM_DELADDR, ifp)
        ip6_del_rt(ifp->rt)
    
    after returning from the ipv6_ifa_notify and enabling BH-s
    back, but *before* calling the addrconf_del_timer the 
    ifp->timer fires and:
    
    addrconf_dad_timer(ifp)
      addrconf_dad_completed(ifp)
        ipv6_ifa_notify(RTM_NEWADDR, ifp)
          ip6_ins_rt(ifp->rt)
    
    then return back to the ipv6_del_addr and:
    
    in6_ifa_put(ifp)
      inet6_ifa_finish_destroy(ifp)
        dst_release(&ifp->rt->u.dst)
    
    After this we have an ifp->rt inserted into fib6 lists, but 
    queued for gc, which in turn can result in oopses in the
    fib6_run_gc. Maybe some other nasty things, but we caught 
    only the oops in gc so far.
    
    The solution is to disarm the ifp->timer before flushing the
    rt from it.
    Signed-off-by: default avatarAndrey Vagin <avagin@parallels.com>
    Signed-off-by: default avatarPavel Emelyanov <xemul@openvz.org>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    b2238566
addrconf.c 108 KB