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

comedi: me_daq: Fix potential overrun of firmware buffer



`me2600_xilinx_download()` loads the firmware that was requested by
`request_firmware()`.  It is possible for it to overrun the source
buffer because it blindly trusts the file format.  It reads a data
stream length from the first 4 bytes into variable `file_length` and
reads the data stream contents of length `file_length` from offset 16
onwards.  Although it checks that the supplied firmware is at least 16
bytes long, it does not check that it is long enough to contain the data
stream.

Add a test to ensure that the supplied firmware is long enough to
contain the header and the data stream.  On failure, log an error and
return `-EINVAL`.

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


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 3fb43a7a
Loading
Loading
Loading
Loading
+19 −16
Original line number Diff line number Diff line
@@ -344,19 +344,6 @@ static int me2600_xilinx_download(struct comedi_device *dev,
	unsigned int file_length;
	unsigned int i;

	/* disable irq's on PLX */
	writel(0x00, devpriv->plx_regbase + PLX9052_INTCSR);

	/* First, make a dummy read to reset xilinx */
	value = readw(dev->mmio + XILINX_DOWNLOAD_RESET);

	/* Wait until reset is over */
	sleep(1);

	/* Write a dummy value to Xilinx */
	writeb(0x00, dev->mmio + 0x0);
	sleep(1);

	/*
	 * Format of the firmware
	 * Build longs from the byte-wise coded header
@@ -365,13 +352,29 @@ static int me2600_xilinx_download(struct comedi_device *dev,
	 * Byte 8-11:  date
	 * Byte 12-15: reserved
	 */
	if (size < 16)
		return -EINVAL;

	if (size >= 4) {
		file_length = (((unsigned int)data[0] & 0xff) << 24) +
			      (((unsigned int)data[1] & 0xff) << 16) +
			      (((unsigned int)data[2] & 0xff) << 8) +
			      ((unsigned int)data[3] & 0xff);
	}
	if (size < 16 || file_length > size - 16) {
		dev_err(dev->class_dev, "Firmware length inconsistency\n");
		return -EINVAL;
	}

	/* disable irq's on PLX */
	writel(0x00, devpriv->plx_regbase + PLX9052_INTCSR);

	/* First, make a dummy read to reset xilinx */
	value = readw(dev->mmio + XILINX_DOWNLOAD_RESET);

	/* Wait until reset is over */
	sleep(1);

	/* Write a dummy value to Xilinx */
	writeb(0x00, dev->mmio + 0x0);
	sleep(1);

	/*
	 * Loop for writing firmware byte by byte to xilinx