]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
comedi: comedi_parport: deal with premature interrupt
authorIan Abbott <abbotti@mev.co.uk>
Wed, 27 May 2026 12:51:03 +0000 (13:51 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 17 Jul 2026 12:50:35 +0000 (14:50 +0200)
Syzbot reported a general protection fault in
`comedi_get_is_subdevice_running()`, which was called from the interrupt
handler `parport_interrupt()` in the "comedi_parport" driver, but it
does not currently have a C reproducer for the problem.  It's
probably due to a premature interrupt for one of two reasons:

1. The driver sets up the interrupt handler before the comedi subdevices
   used by the interrupt handler have been allocated, but does not
   disable the interrupt in the parallel port's CTRL register first.
2. The driver uses a user-supplied I/O port base address which Syzbot
   would have supplied, but it might not be backed by real parallel port
   hardware.

Change the initialization order in the driver's comedi "attach" handler
(`parport_attach()`) so that the hardware registers are initialized
before the interrupt handler is requested.  This should prevent
premature interrupts occurring for real hardware.

Also add a test to the interrupt handler to ensure the comedi device is
fully attached and return early if it isn't.

Fixes: 241ab6ad7108e ("Staging: comedi: add comedi_parport driver")
Reported-by: syzbot+f24c3d5d316011bacc70@syzkaller.appspotmail.com
Cc: stable <stable@kernel.org>
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Link: https://patch.msgid.link/20260527125104.96596-1-abbotti@mev.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/comedi/drivers/comedi_parport.c

index 2604680d86c4a380c2141aff06e6a1bd0451a7f6..57ee3f9dfba2634f5274343356cdebff8fc96443 100644 (file)
@@ -211,6 +211,13 @@ static irqreturn_t parport_interrupt(int irq, void *d)
        unsigned int ctrl;
        unsigned short val = 0;
 
+       /*
+        * Check device is fully attached.  Device interrupts should have
+        * been disabled, but do this in case of bad hardware.
+        */
+       if (!dev->attached)
+               return IRQ_NONE;
+
        ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
        if (!(ctrl & PARPORT_CTRL_IRQ_ENA))
                return IRQ_NONE;
@@ -233,6 +240,9 @@ static int parport_attach(struct comedi_device *dev,
        if (ret)
                return ret;
 
+       outb(0, dev->iobase + PARPORT_DATA_REG);
+       outb(0, dev->iobase + PARPORT_CTRL_REG);
+
        if (it->options[1]) {
                ret = request_irq(it->options[1], parport_interrupt, 0,
                                  dev->board_name, dev);
@@ -288,9 +298,6 @@ static int parport_attach(struct comedi_device *dev,
                s->cancel       = parport_intr_cancel;
        }
 
-       outb(0, dev->iobase + PARPORT_DATA_REG);
-       outb(0, dev->iobase + PARPORT_CTRL_REG);
-
        return 0;
 }