| From c330fb1ddc0a922f044989492b7fcca77ee1db46 Mon Sep 17 00:00:00 2001 |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Tue, 25 Aug 2020 17:22:58 +0200 |
| Subject: XEN uses irqdesc::irq_data_common::handler_data to store a per interrupt XEN data pointer which contains XEN specific information. |
| |
| From: Thomas Gleixner <tglx@linutronix.de> |
| |
| commit c330fb1ddc0a922f044989492b7fcca77ee1db46 upstream. |
| |
| handler data is meant for interrupt handlers and not for storing irq chip |
| specific information as some devices require handler data to store internal |
| per interrupt information, e.g. pinctrl/GPIO chained interrupt handlers. |
| |
| This obviously creates a conflict of interests and crashes the machine |
| because the XEN pointer is overwritten by the driver pointer. |
| |
| As the XEN data is not handler specific it should be stored in |
| irqdesc::irq_data::chip_data instead. |
| |
| A simple sed s/irq_[sg]et_handler_data/irq_[sg]et_chip_data/ cures that. |
| |
| Cc: stable@vger.kernel.org |
| Reported-by: Roman Shaposhnik <roman@zededa.com> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Tested-by: Roman Shaposhnik <roman@zededa.com> |
| Reviewed-by: Juergen Gross <jgross@suse.com> |
| Link: https://lore.kernel.org/r/87lfi2yckt.fsf@nanos.tec.linutronix.de |
| Signed-off-by: Juergen Gross <jgross@suse.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/xen/events/events_base.c | 16 ++++++++-------- |
| 1 file changed, 8 insertions(+), 8 deletions(-) |
| |
| --- a/drivers/xen/events/events_base.c |
| +++ b/drivers/xen/events/events_base.c |
| @@ -155,7 +155,7 @@ int get_evtchn_to_irq(unsigned evtchn) |
| /* Get info for IRQ */ |
| struct irq_info *info_for_irq(unsigned irq) |
| { |
| - return irq_get_handler_data(irq); |
| + return irq_get_chip_data(irq); |
| } |
| |
| /* Constructors for packed IRQ information. */ |
| @@ -384,7 +384,7 @@ static void xen_irq_init(unsigned irq) |
| info->type = IRQT_UNBOUND; |
| info->refcnt = -1; |
| |
| - irq_set_handler_data(irq, info); |
| + irq_set_chip_data(irq, info); |
| |
| list_add_tail(&info->list, &xen_irq_list_head); |
| } |
| @@ -433,14 +433,14 @@ static int __must_check xen_allocate_irq |
| |
| static void xen_free_irq(unsigned irq) |
| { |
| - struct irq_info *info = irq_get_handler_data(irq); |
| + struct irq_info *info = irq_get_chip_data(irq); |
| |
| if (WARN_ON(!info)) |
| return; |
| |
| list_del(&info->list); |
| |
| - irq_set_handler_data(irq, NULL); |
| + irq_set_chip_data(irq, NULL); |
| |
| WARN_ON(info->refcnt > 0); |
| |
| @@ -610,7 +610,7 @@ EXPORT_SYMBOL_GPL(xen_irq_from_gsi); |
| static void __unbind_from_irq(unsigned int irq) |
| { |
| int evtchn = evtchn_from_irq(irq); |
| - struct irq_info *info = irq_get_handler_data(irq); |
| + struct irq_info *info = irq_get_chip_data(irq); |
| |
| if (info->refcnt > 0) { |
| info->refcnt--; |
| @@ -1114,7 +1114,7 @@ int bind_ipi_to_irqhandler(enum ipi_vect |
| |
| void unbind_from_irqhandler(unsigned int irq, void *dev_id) |
| { |
| - struct irq_info *info = irq_get_handler_data(irq); |
| + struct irq_info *info = irq_get_chip_data(irq); |
| |
| if (WARN_ON(!info)) |
| return; |
| @@ -1148,7 +1148,7 @@ int evtchn_make_refcounted(unsigned int |
| if (irq == -1) |
| return -ENOENT; |
| |
| - info = irq_get_handler_data(irq); |
| + info = irq_get_chip_data(irq); |
| |
| if (!info) |
| return -ENOENT; |
| @@ -1176,7 +1176,7 @@ int evtchn_get(unsigned int evtchn) |
| if (irq == -1) |
| goto done; |
| |
| - info = irq_get_handler_data(irq); |
| + info = irq_get_chip_data(irq); |
| |
| if (!info) |
| goto done; |