Commit 4b9a9a6d authored by Ian Abbott's avatar Ian Abbott Committed by Greg Kroah-Hartman
Browse files

comedi: Reinit dev->spinlock between attachments to low-level drivers



`struct comedi_device` is the main controlling structure for a COMEDI
device created by the COMEDI subsystem.  It contains a member `spinlock`
containing a spin-lock that is initialized by the COMEDI subsystem, but
is reserved for use by a low-level driver attached to the COMEDI device
(at least since commit 25436dc9 ("Staging: comedi: remove RT
code")).

Some COMEDI devices (those created on initialization of the COMEDI
subsystem when the "comedi.comedi_num_legacy_minors" parameter is
non-zero) can be attached to different low-level drivers over their
lifetime using the `COMEDI_DEVCONFIG` ioctl command.  This can result in
inconsistent lock states being reported when there is a mismatch in the
spin-lock locking levels used by each low-level driver to which the
COMEDI device has been attached.  Fix it by reinitializing
`dev->spinlock` before calling the low-level driver's `attach` function
pointer if `CONFIG_LOCKDEP` is enabled.

Reported-by: default avatar <syzbot+cc9f7f4a7df09f53c4a4@syzkaller.appspotmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=cc9f7f4a7df09f53c4a4


Fixes: ed9eccbe ("Staging: add comedi core")
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarIan Abbott <abbotti@mev.co.uk>
Link: https://patch.msgid.link/20260225132427.86578-1-abbotti@mev.co.uk


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cc797d48
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1063,6 +1063,14 @@ int comedi_device_attach(struct comedi_device *dev, struct comedi_devconfig *it)
		ret = -EIO;
		goto out;
	}
	if (IS_ENABLED(CONFIG_LOCKDEP)) {
		/*
		 * dev->spinlock is for private use by the attached low-level
		 * driver.  Reinitialize it to stop lock-dependency tracking
		 * between attachments to different low-level drivers.
		 */
		spin_lock_init(&dev->spinlock);
	}
	dev->driver = driv;
	dev->board_name = dev->board_ptr ? *(const char **)dev->board_ptr
					 : dev->driver->driver_name;