• Maxime Bizon's avatar
    net: dst: fix missing initialization of rt_uncached · 418a7307
    Maxime Bizon authored
    xfrm_alloc_dst() followed by xfrm4_dst_destroy(), without a
    xfrm4_fill_dst() call in between, causes the following BUG:
    
     BUG: spinlock bad magic on CPU#0, fbxhostapd/732
      lock: 0x890b7668, .magic: 890b7668, .owner: <none>/-1, .owner_cpu: 0
     CPU: 0 PID: 732 Comm: fbxhostapd Not tainted 6.3.0-rc6-next-20230414-00613-ge8de66369925-dirty #9
     Hardware name: Marvell Kirkwood (Flattened Device Tree)
      unwind_backtrace from show_stack+0x10/0x14
      show_stack from dump_stack_lvl+0x28/0x30
      dump_stack_lvl from do_raw_spin_lock+0x20/0x80
      do_raw_spin_lock from rt_del_uncached_list+0x30/0x64
      rt_del_uncached_list from xfrm4_dst_destroy+0x3c/0xbc
      xfrm4_dst_destroy from dst_destroy+0x5c/0xb0
      dst_destroy from rcu_process_callbacks+0xc4/0xec
      rcu_process_callbacks from __do_softirq+0xb4/0x22c
      __do_softirq from call_with_stack+0x1c/0x24
      call_with_stack from do_softirq+0x60/0x6c
      do_softirq from __local_bh_enable_ip+0xa0/0xcc
    
    Patch "net: dst: Prevent false sharing vs. dst_entry:: __refcnt" moved
    rt_uncached and rt_uncached_list fields from rtable struct to dst
    struct, so they are more zeroed by memset_after(xdst, 0, u.dst) in
    xfrm_alloc_dst().
    
    Note that rt_uncached (list_head) was never properly initialized at
    alloc time, but xfrm[46]_dst_destroy() is written in such a way that
    it was not an issue thanks to the memset:
    
    	if (xdst->u.rt.dst.rt_uncached_list)
    		rt_del_uncached_list(&xdst->u.rt);
    
    The route code does it the other way around: rt_uncached_list is
    assumed to be valid IIF rt_uncached list_head is not empty:
    
    void rt_del_uncached_list(struct rtable *rt)
    {
            if (!list_empty(&rt->dst.rt_uncached)) {
                    struct uncached_list *ul = rt->dst.rt_uncached_list;
    
                    spin_lock_bh(&ul->lock);
                    list_del_init(&rt->dst.rt_uncached);
                    spin_unlock_bh(&ul->lock);
            }
    }
    
    This patch adds mandatory rt_uncached list_head initialization in
    generic dst_init(), and adapt xfrm[46]_dst_destroy logic to match the
    rest of the code.
    
    Fixes: d288a162 ("net: dst: Prevent false sharing vs. dst_entry:: __refcnt")
    Reported-by: default avatarkernel test robot <oliver.sang@intel.com>
    Link: https://lore.kernel.org/oe-lkp/202304162125.18b7bcdd-oliver.sang@intel.comReviewed-by: default avatarDavid Ahern <dsahern@kernel.org>
    Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
    CC: Leon Romanovsky <leon@kernel.org>
    Signed-off-by: default avatarMaxime Bizon <mbizon@freebox.fr>
    Link: https://lore.kernel.org/r/20230420182508.2417582-1-mbizon@freebox.frSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
    418a7307
route.c 167 KB