• Kumar Kartikeya Dwivedi's avatar
    bpf: Defer work in bpf_timer_cancel_and_free · a6fcd19d
    Kumar Kartikeya Dwivedi authored
    Currently, the same case as previous patch (two timer callbacks trying
    to cancel each other) can be invoked through bpf_map_update_elem as
    well, or more precisely, freeing map elements containing timers. Since
    this relies on hrtimer_cancel as well, it is prone to the same deadlock
    situation as the previous patch.
    
    It would be sufficient to use hrtimer_try_to_cancel to fix this problem,
    as the timer cannot be enqueued after async_cancel_and_free. Once
    async_cancel_and_free has been done, the timer must be reinitialized
    before it can be armed again. The callback running in parallel trying to
    arm the timer will fail, and freeing bpf_hrtimer without waiting is
    sufficient (given kfree_rcu), and bpf_timer_cb will return
    HRTIMER_NORESTART, preventing the timer from being rearmed again.
    
    However, there exists a UAF scenario where the callback arms the timer
    before entering this function, such that if cancellation fails (due to
    timer callback invoking this routine, or the target timer callback
    running concurrently). In such a case, if the timer expiration is
    significantly far in the future, the RCU grace period expiration
    happening before it will free the bpf_hrtimer state and along with it
    the struct hrtimer, that is enqueued.
    
    Hence, it is clear cancellation needs to occur after
    async_cancel_and_free, and yet it cannot be done inline due to deadlock
    issues. We thus modify bpf_timer_cancel_and_free to defer work to the
    global workqueue, adding a work_struct alongside rcu_head (both used at
    _different_ points of time, so can share space).
    
    Update existing code comments to reflect the new state of affairs.
    
    Fixes: b00628b1 ("bpf: Introduce bpf timers.")
    Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
    Link: https://lore.kernel.org/r/20240709185440.1104957-3-memxor@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
    a6fcd19d
helpers.c 78.3 KB