• YueHaibing's avatar
    xfrm: policy: Fix doulbe free in xfrm_policy_timer · 4c59406e
    YueHaibing authored
    After xfrm_add_policy add a policy, its ref is 2, then
    
                                 xfrm_policy_timer
                                   read_lock
                                   xp->walk.dead is 0
                                   ....
                                   mod_timer()
    xfrm_policy_kill
      policy->walk.dead = 1
      ....
      del_timer(&policy->timer)
        xfrm_pol_put //ref is 1
      xfrm_pol_put  //ref is 0
        xfrm_policy_destroy
          call_rcu
                                     xfrm_pol_hold //ref is 1
                                   read_unlock
                                   xfrm_pol_put //ref is 0
                                     xfrm_policy_destroy
                                      call_rcu
    
    xfrm_policy_destroy is called twice, which may leads to
    double free.
    
    Call Trace:
    RIP: 0010:refcount_warn_saturate+0x161/0x210
    ...
     xfrm_policy_timer+0x522/0x600
     call_timer_fn+0x1b3/0x5e0
     ? __xfrm_decode_session+0x2990/0x2990
     ? msleep+0xb0/0xb0
     ? _raw_spin_unlock_irq+0x24/0x40
     ? __xfrm_decode_session+0x2990/0x2990
     ? __xfrm_decode_session+0x2990/0x2990
     run_timer_softirq+0x5c5/0x10e0
    
    Fix this by use write_lock_bh in xfrm_policy_kill.
    
    Fixes: ea2dea9d ("xfrm: remove policy lock when accessing policy->walk.dead")
    Signed-off-by: default avatarYueHaibing <yuehaibing@huawei.com>
    Acked-by: default avatarTimo Teräs <timo.teras@iki.fi>
    Acked-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
    Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
    4c59406e
xfrm_policy.c 106 KB