Skip to content
  • Thomas Gleixner's avatar
    genirq: Prevent proc race against freeing of irq descriptors · c291ee62
    Thomas Gleixner authored
    Since the rework of the sparse interrupt code to actually free the
    unused interrupt descriptors there exists a race between the /proc
    interfaces to the irq subsystem and the code which frees the interrupt
    descriptor.
    
    CPU0				CPU1
    				show_interrupts()
    				  desc = irq_to_desc(X);
    free_desc(desc)
      remove_from_radix_tree();
      kfree(desc);
    				  raw_spinlock_irq(&desc->lock);
    
    /proc/interrupts is the only interface which can actively corrupt
    kernel memory via the lock access. /proc/stat can only read from freed
    memory. Extremly hard to trigger, but possible.
    
    The interfaces in /proc/irq/N/ are not affected by this because the
    removal of the proc file is serialized in procfs against concurrent
    readers/writers. The removal happens before the descriptor is freed.
    
    For architectures which have CONFIG_SPARSE_IRQ=n this is a non issue
    as the descriptor is never freed. It's merely cleared out with the irq
    descriptor lock held. So any concurrent proc access will either see
    the old correct value or the cleared out ones.
    
    Protect the lookup and access to the irq descriptor in
    show_interrupts() with the sparse_irq_lock.
    
    Provide kstat_irqs_usr() which is protecting the lookup and access
    with sparse_irq_lock and switch /proc/stat to use it.
    
    Document the existing kstat_irqs interfaces so it's clear that the
    caller needs to take care about protection. The users of these
    interfaces are either not affected due to SPARSE_IRQ=n or already
    protected against removal.
    
    Fixes: 1f5a5b87
    
     "genirq: Implement a sane sparse_irq allocator"
    Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
    Cc: stable@vger.kernel.org
    c291ee62