Unverified Commit a2c5bedb authored by Quanyang Wang's avatar Quanyang Wang Committed by Mark Brown
Browse files

spi: spi-zynqmp-gqspi: fix use-after-free in zynqmp_qspi_exec_op



When handling op->addr, it is using the buffer "tmpbuf" which has been
freed. This will trigger a use-after-free KASAN warning. Let's use
temporary variables to store op->addr.val and op->cmd.opcode to fix
this issue.

Fixes: 1c26372e ("spi: spi-zynqmp-gqspi: Update driver to use spi-mem framework")
Signed-off-by: default avatarQuanyang Wang <quanyang.wang@windriver.com>
Link: https://lore.kernel.org/r/20210416004652.2975446-5-quanyang.wang@windriver.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 2530b3df
Loading
Loading
Loading
Loading
+4 −10
Original line number Diff line number Diff line
@@ -928,8 +928,9 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
	struct zynqmp_qspi *xqspi = spi_controller_get_devdata
				    (mem->spi->master);
	int err = 0, i;
	u8 *tmpbuf;
	u32 genfifoentry = 0;
	u16 opcode = op->cmd.opcode;
	u64 opaddr;

	dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n",
		op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
@@ -942,14 +943,8 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
	genfifoentry |= xqspi->genfifobus;

	if (op->cmd.opcode) {
		tmpbuf = kzalloc(op->cmd.nbytes, GFP_KERNEL | GFP_DMA);
		if (!tmpbuf) {
			mutex_unlock(&xqspi->op_lock);
			return -ENOMEM;
		}
		tmpbuf[0] = op->cmd.opcode;
		reinit_completion(&xqspi->data_completion);
		xqspi->txbuf = tmpbuf;
		xqspi->txbuf = &opcode;
		xqspi->rxbuf = NULL;
		xqspi->bytes_to_transfer = op->cmd.nbytes;
		xqspi->bytes_to_receive = 0;
@@ -963,13 +958,12 @@ static int zynqmp_qspi_exec_op(struct spi_mem *mem,
		if (!wait_for_completion_timeout
		    (&xqspi->data_completion, msecs_to_jiffies(1000))) {
			err = -ETIMEDOUT;
			kfree(tmpbuf);
			goto return_err;
		}
		kfree(tmpbuf);
	}

	if (op->addr.nbytes) {
		xqspi->txbuf = &opaddr;
		for (i = 0; i < op->addr.nbytes; i++) {
			*(((u8 *)xqspi->txbuf) + i) = op->addr.val >>
					(8 * (op->addr.nbytes - i - 1));