genirq: Protect access to irq_desc->action in can_request_irq()
authorThomas Gleixner <tglx@linutronix.de>
Tue, 23 Mar 2010 21:40:53 +0000 (22:40 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Wed, 24 Mar 2010 13:38:23 +0000 (14:38 +0100)
can_request_irq() accesses and dereferences irq_desc->action w/o
holding irq_desc->lock. So action can be freed on another CPU before
it's dereferenced. Unlikely, but ...

Protect it with desc->lock.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
kernel/irq/manage.c

index 69a3d7b9414c3e7bdb74241d623ce21408c2a397..398fda155f6e26dd72dd1fa00805b1383c156a5d 100644 (file)
@@ -382,6 +382,7 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
 {
        struct irq_desc *desc = irq_to_desc(irq);
        struct irqaction *action;
+       unsigned long flags;
 
        if (!desc)
                return 0;
@@ -389,11 +390,14 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)
        if (desc->status & IRQ_NOREQUEST)
                return 0;
 
+       raw_spin_lock_irqsave(&desc->lock, flags);
        action = desc->action;
        if (action)
                if (irqflags & action->flags & IRQF_SHARED)
                        action = NULL;
 
+       raw_spin_unlock_irqrestore(&desc->lock, flags);
+
        return !action;
 }