xen/events: Check that IRQ value passed in is valid.
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Tue, 16 Apr 2013 14:55:18 +0000 (10:55 -0400)
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Tue, 16 Apr 2013 20:05:13 +0000 (16:05 -0400)
We naively assume that the IRQ value passed in is correct.
If it is not, then any dereference operation for the 'info'
structure will result in crash - so might as well guard ourselves
and sprinkle copious amounts of WARN_ON.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
drivers/xen/events.c

index bb65f75e40a540d316abc9f307768b9c06624329..94daed14d47489666a0c3effb80fb17f0f9a38f9 100644 (file)
@@ -515,6 +515,9 @@ static void xen_free_irq(unsigned irq)
 {
        struct irq_info *info = irq_get_handler_data(irq);
 
+       if (WARN_ON(!info))
+               return;
+
        list_del(&info->list);
 
        irq_set_handler_data(irq, NULL);
@@ -1003,6 +1006,9 @@ static void unbind_from_irq(unsigned int irq)
        int evtchn = evtchn_from_irq(irq);
        struct irq_info *info = irq_get_handler_data(irq);
 
+       if (WARN_ON(!info))
+               return;
+
        mutex_lock(&irq_mapping_update_lock);
 
        if (info->refcnt > 0) {
@@ -1130,6 +1136,10 @@ int bind_ipi_to_irqhandler(enum ipi_vector ipi,
 
 void unbind_from_irqhandler(unsigned int irq, void *dev_id)
 {
+       struct irq_info *info = irq_get_handler_data(irq);
+
+       if (WARN_ON(!info))
+               return;
        free_irq(irq, dev_id);
        unbind_from_irq(irq);
 }
@@ -1441,6 +1451,9 @@ void rebind_evtchn_irq(int evtchn, int irq)
 {
        struct irq_info *info = info_for_irq(irq);
 
+       if (WARN_ON(!info))
+               return;
+
        /* Make sure the irq is masked, since the new event channel
           will also be masked. */
        disable_irq(irq);
@@ -1714,7 +1727,12 @@ void xen_poll_irq(int irq)
 int xen_test_irq_shared(int irq)
 {
        struct irq_info *info = info_for_irq(irq);
-       struct physdev_irq_status_query irq_status = { .irq = info->u.pirq.pirq };
+       struct physdev_irq_status_query irq_status;
+
+       if (WARN_ON(!info))
+               return -ENOENT;
+
+       irq_status.irq = info->u.pirq.pirq;
 
        if (HYPERVISOR_physdev_op(PHYSDEVOP_irq_status_query, &irq_status))
                return 0;