Skip to content

Commit

Permalink
spi: spi-zynq-qspi: Fixed buffer overflow in zynq_qspi_exec_mem_op
Browse files Browse the repository at this point in the history
Const-incorrectness, inconsistent memory allocation policy and buffer
overflow in the zynq_qspi_exec_mem_op function of spi-zynq-qspi.c
causes op constant input structure fields to be overwritten. Variable
xqspi->txbuf is not allocated for address processing and re-uses the
buffer pointer from command processing.

As per the TRM Zynq QSPI only supports 3byte addressing mode. Driver
reports an invalid argument error if the address width is greater than
3bytes.

Signed-off-by: Ferenc Damo <ferenc.damo@ni.com>
Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
  • Loading branch information
damoferenc authored and Michal Simek committed Jan 6, 2022
1 parent 52fd7c2 commit 1a11726
Showing 1 changed file with 10 additions and 1 deletion.
11 changes: 10 additions & 1 deletion drivers/spi/spi-zynq-qspi.c
Expand Up @@ -118,6 +118,9 @@
/* Maximum number of chip selects */
#define ZYNQ_QSPI_MAX_NUM_CS 2

/* Maximum address width */
#define ZYNQ_QSPI_MAX_ADDR_WIDTH 3

/**
* struct zynq_qspi - Defines qspi driver instance
* @dev: Pointer to the this device's information
Expand Down Expand Up @@ -539,19 +542,24 @@ static irqreturn_t zynq_qspi_irq(int irq, void *dev_id)
*
* This function first selects the chip and starts the memory operation.
*
* Return: 0 in case of success, a negative error code otherwise.
* Return: 0 in case of success, -EINVAL if address size greater than
* ZYNQ_QSPI_MAX_ADDR_WIDTH.
*/
static int zynq_qspi_exec_mem_op(struct spi_mem *mem,
const struct spi_mem_op *op)
{
struct zynq_qspi *xqspi = spi_controller_get_devdata(mem->spi->master);
int err = 0, i;
u8 *tmpbuf;
u8 opaddr[ZYNQ_QSPI_MAX_ADDR_WIDTH];

dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n",
op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
op->dummy.buswidth, op->data.buswidth);

if (op->addr.nbytes > ZYNQ_QSPI_MAX_ADDR_WIDTH)
return -EINVAL;

zynq_qspi_chipselect(mem->spi, true);
zynq_qspi_config_op(xqspi, mem->spi);

Expand All @@ -570,6 +578,7 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem,
}

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

0 comments on commit 1a11726

Please sign in to comment.