• Hou Tao's avatar
    bpf: Check map->usercnt after timer->timer is assigned · fd381ce6
    Hou Tao authored
    When there are concurrent uref release and bpf timer init operations,
    the following sequence diagram is possible. It will break the guarantee
    provided by bpf_timer: bpf_timer will still be alive after userspace
    application releases or unpins the map. It also will lead to kmemleak
    for old kernel version which doesn't release bpf_timer when map is
    released.
    
    bpf program X:
    
    bpf_timer_init()
      lock timer->lock
        read timer->timer as NULL
        read map->usercnt != 0
    
                    process Y:
    
                    close(map_fd)
                      // put last uref
                      bpf_map_put_uref()
                        atomic_dec_and_test(map->usercnt)
                          array_map_free_timers()
                            bpf_timer_cancel_and_free()
                              // just return
                              read timer->timer is NULL
    
        t = bpf_map_kmalloc_node()
        timer->timer = t
      unlock timer->lock
    
    Fix the problem by checking map->usercnt after timer->timer is assigned,
    so when there are concurrent uref release and bpf timer init, either
    bpf_timer_cancel_and_free() from uref release reads a no-NULL timer
    or the newly-added atomic64_read() returns a zero usercnt.
    
    Because atomic_dec_and_test(map->usercnt) and READ_ONCE(timer->timer)
    in bpf_timer_cancel_and_free() are not protected by a lock, so add
    a memory barrier to guarantee the order between map->usercnt and
    timer->timer. Also use WRITE_ONCE(timer->timer, x) to match the lockless
    read of timer->timer in bpf_timer_cancel_and_free().
    Reported-by: default avatarHsin-Wei Hung <hsinweih@uci.edu>
    Closes: https://lore.kernel.org/bpf/CABcoxUaT2k9hWsS1tNgXyoU3E-=PuOgMn737qK984fbFmfYixQ@mail.gmail.com
    Fixes: b00628b1 ("bpf: Introduce bpf timers.")
    Signed-off-by: default avatarHou Tao <houtao1@huawei.com>
    Link: https://lore.kernel.org/r/20231030063616.1653024-1-houtao@huaweicloud.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    fd381ce6
helpers.c 69.2 KB