• Nikolay Aleksandrov's avatar
    inet: frags: fix a race between inet_evict_bucket and inet_frag_kill · 65ba1f1e
    Nikolay Aleksandrov authored
    When the evictor is running it adds some chosen frags to a local list to
    be evicted once the chain lock has been released but at the same time
    the *frag_queue can be running for some of the same queues and it
    may call inet_frag_kill which will wait on the chain lock and
    will then delete the queue from the wrong list since it was added in the
    eviction one. The fix is simple - check if the queue has the evict flag
    set under the chain lock before deleting it, this is safe because the
    evict flag is set only under that lock and having the flag set also means
    that the queue has been detached from the chain list, so no need to delete
    it again.
    An important note to make is that we're safe w.r.t refcnt because
    inet_frag_kill and inet_evict_bucket will sync on the del_timer operation
    where only one of the two can succeed (or if the timer is executing -
    none of them), the cases are:
    1. inet_frag_kill succeeds in del_timer
     - then the timer ref is removed, but inet_evict_bucket will not add
       this queue to its expire list but will restart eviction in that chain
    2. inet_evict_bucket succeeds in del_timer
     - then the timer ref is kept until the evictor "expires" the queue, but
       inet_frag_kill will remove the initial ref and will set
       INET_FRAG_COMPLETE which will make the frag_expire fn just to remove
       its ref.
    In the end all of the queue users will do an inet_frag_put and the one
    that reaches 0 will free it. The refcount balance should be okay.
    
    CC: Florian Westphal <fw@strlen.de>
    CC: Eric Dumazet <eric.dumazet@gmail.com>
    CC: Patrick McLean <chutzpah@gentoo.org>
    
    Fixes: b13d3cbf ("inet: frag: move eviction of queues to work queue")
    Suggested-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
    Reported-by: default avatarPatrick McLean <chutzpah@gentoo.org>
    Tested-by: default avatarPatrick McLean <chutzpah@gentoo.org>
    Signed-off-by: default avatarNikolay Aleksandrov <nikolay@redhat.com>
    Reviewed-by: default avatarFlorian Westphal <fw@strlen.de>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    65ba1f1e
inet_fragment.c 11 KB