• Thomas Gleixner's avatar
    genirq: Make sparse_irq_lock protect what it should protect · 12ac1d0f
    Thomas Gleixner authored
    for_each_active_irq() iterates the sparse irq allocation bitmap. The caller
    must hold sparse_irq_lock. Several code pathes expect that an active bit in
    the sparse bitmap also has a valid interrupt descriptor.
    
    Unfortunately that's not true. The (de)allocation is a two step process,
    which holds the sparse_irq_lock only across the queue/remove from the radix
    tree and the set/clear in the allocation bitmap.
    
    If a iteration locks sparse_irq_lock between the two steps, then it might
    see an active bit but the corresponding irq descriptor is NULL. If that is
    dereferenced unconditionally, then the kernel oopses. Of course, all
    iterator sites could be audited and fixed, but....
    
    There is no reason why the sparse_irq_lock needs to be dropped between the
    two steps, in fact the code becomes simpler when the mutex is held across
    both and the semantics become more straight forward, so future problems of
    missing NULL pointer checks in the iteration are avoided and all existing
    sites are fixed in one go.
    
    Expand the lock held sections so both operations are covered and the bitmap
    and the radixtree are in sync.
    
    Fixes: a05a900a ("genirq: Make sparse_lock a mutex")
    Reported-and-tested-by: default avatarHuang Ying <ying.huang@intel.com>
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: stable@vger.kernel.org
    12ac1d0f
irqdesc.c 21.3 KB