[PATCH v3 1/3] i3c: master: dw: Report actual GET CCC payload length on success

sashiko-bot at kernel.org sashiko-bot at kernel.org
Wed Jun 10 19:08:19 PDT 2026


Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Heap/stack buffer overflow when reading from the hardware RX FIFO.
- [High] Transfer queue stall and cascading timeouts after a single transfer timeout.
- [High] Spurious completion of new transfers due to unhandled late interrupts from previous timeouts.
--

commit 097603b8b0f1e852cd40f174d2e0bd01af652c87
Author: Adrian Ng Ho Yin <adrian.ho.yin.ng at altera.com>

i3c: master: dw: Report actual GET CCC payload length on success

On successful GET CCC transfers, set dests[0].payload.len from
RESPONSE_PORT_DATA_LEN so the I3C core receives the number of bytes
actually read. Core helpers such as i3c_master_getmrl_locked() use
dest.payload.len after the transfer to interpret the response.

> diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
> index a7593d6efac5a..e42cf3ddcec8f 100644
> --- a/drivers/i3c/master/dw-i3c-master.c
> +++ b/drivers/i3c/master/dw-i3c-master.c

[ ... ]

> @@ -780,7 +783,10 @@ static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
>  		dw_i3c_master_dequeue_xfer(master, xfer);

[Severity: High]
This is a pre-existing issue, but does dw_i3c_master_dequeue_xfer_locked()
properly restart the queue after a timeout?

When a transfer times out, dw_i3c_master_dequeue_xfer_locked() resets the
hardware and clears master->xferqueue.cur:

drivers/i3c/master/dw-i3c-master.c:dw_i3c_master_dequeue_xfer_locked() {
    ...
		master->xferqueue.cur = NULL;

		writel(RESET_CTRL_RX_FIFO | RESET_CTRL_TX_FIFO |
		       RESET_CTRL_RESP_QUEUE | RESET_CTRL_CMD_QUEUE,
		       master->regs + RESET_CTRL);
    ...
}

However, it doesn't seem to dequeue the next transfer from
master->xferqueue.list and start it.

Because cur is NULL and no code advances the queue, will all pending transfers
remain stranded and individually time out unless a new transfer is enqueued?

[Severity: High]
This is a pre-existing issue, but can unhandled late interrupts from a timeout
cause spurious completions for new transfers?

If a transfer times out, dw_i3c_master_dequeue_xfer_locked() resets the
hardware queues, dropping nresp to 0, but it does not clear latched interrupt
statuses like INTR_TRANSFER_ERR_STAT.

If a new transfer is enqueued before the delayed IRQ handler acquires the
lock, the ISR will fire based on the old interrupt.

drivers/i3c/master/dw-i3c-master.c:dw_i3c_master_end_xfer_locked() {
    ...
	nresp = readl(master->regs + QUEUE_STATUS_LEVEL);
	nresp = QUEUE_STATUS_LEVEL_RESP(nresp);

	for (i = 0; i < nresp; i++) {
		// ... skipped if nresp == 0
    ...
}

dw_i3c_master_end_xfer_locked() reads nresp = 0 and skips the error parsing
loop, leaving ret = 0.

Will this erroneously complete the newly enqueued transfer with a success
status without actually executing it on the bus?

>  
>  	ret = xfer->ret;
> -	if (xfer->cmds[0].error == RESPONSE_ERROR_IBA_NACK)
> +	cmd = &xfer->cmds[0];
> +	if (!ret)
> +		ccc->dests[0].payload.len = cmd->rx_len;

[Severity: Critical]
This is a pre-existing issue, but is there a risk of a buffer overflow when
reading from the hardware RX FIFO?

In dw_i3c_master_end_xfer_locked(), the driver reads the response length from
the hardware and directly overwrites cmd->rx_len:

drivers/i3c/master/dw-i3c-master.c:dw_i3c_master_end_xfer_locked() {
    ...
		cmd->rx_len = RESPONSE_PORT_DATA_LEN(resp);
		cmd->error = RESPONSE_PORT_ERR_STATUS(resp);
		if (cmd->rx_len && !cmd->error)
			dw_i3c_master_read_rx_fifo(master, cmd->rx_buf,
						   cmd->rx_len);
    ...
}

The length from the hardware is not validated against the originally requested
buffer size.

If a peripheral sends more data than requested, could this directly overflow
the cmd->rx_buf into adjacent memory?

It seems the payload length validation introduced in subsequent patches of this
series only checks the length after the buffer has already been overwritten.

> +	if (cmd->error == RESPONSE_ERROR_IBA_NACK)
>  		ccc->err = I3C_ERROR_M2;
>  
>  	return ret;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1781142158.git.tze.yee.ng@altera.com?part=1



More information about the linux-i3c mailing list