Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Setting `pm_state = DISABLE_STATE` actively suppresses the necessary hardware `GPI_EV_CMD_DEALLOC` command, leaking hardware state.
Pre-existing issues:
- [High] `ev_ring` is freed on the `gpi_ch_init()` error path without explicitly canceling the event tasklet, leading to a race condition and UAF.
- [High] `gpi_ch_init()` error path destroys hardware state and shared resources for an already-active channel, leaving the sibling channel silently broken.
- [High] `gpi_issue_pending()` writes to the channel doorbell register without verifying that the hardware `pm_state` is active.
--
--- Patch [1]: [PATCH v2] dmaengine: qcom: gpi: Fix channel cleanup in unwind path ---
commit 47c71a5c319e41aac4e85d0f59c76a1364b2c273
Author: Aniket Randive <[email protected]>
dmaengine: qcom: gpi: Fix channel cleanup in unwind path
This commit attempts to fix three bugs in the gpi_ch_init() error path.
It updates the unwind loops to properly reset and deallocate sibling
channels, restores pm_state to DISABLE_STATE, and frees ch_ring if
initialization fails.
> diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c
> index a5055a6273af6..c41bfac65ddf3 100644
> --- a/drivers/dma/qcom/gpi.c
> +++ b/drivers/dma/qcom/gpi.c
> @@ -1965,16 +1965,19 @@ static int gpi_ch_init(struct gchan *gchan)
> error_start_chan:
> for (i = i - 1; i >= 0; i--) {
> gpi_stop_chan(&gpii->gchan[i]);
> - gpi_send_cmd(gpii, gchan, GPI_CH_CMD_RESET);
> + gpi_send_cmd(gpii, &gpii->gchan[i], GPI_CH_CMD_RESET);
> }
> i = 2;
> error_alloc_chan:
> for (i = i - 1; i >= 0; i--)
> - gpi_reset_chan(gchan, GPI_CH_CMD_DE_ALLOC);
> + gpi_reset_chan(&gpii->gchan[i], GPI_CH_CMD_DE_ALLOC);
[Severity: High]
This is a pre-existing issue, but does this error path destroy hardware state
for an already-active channel?
gpi_ch_init() initializes both channels when the second channel is allocated.
If the second channel's initialization fails, this error path iterates
backwards, stopping and deallocating both channels and freeing the shared
ev_ring.
Since the first channel's client successfully completed
gpi_alloc_chan_resources() previously, could it remain unaware that its
hardware channel and event ring have just been destroyed?
[Severity: High]
This is also a pre-existing issue, but does this lead to a bus fault or
system stall if the first channel's client submits a transfer after the
sibling channel allocation fails?
If the first channel's client is unaware of the failure and calls
dma_issue_pending(), gpi_issue_pending() will execute:
drivers/dma/qcom/gpi.c:gpi_issue_pending() {
...
gpi_desc->db = ch_ring->wp;
gpi_write_ch_db(gchan, &gchan->ch_ring, gpi_desc->db);
...
}
Could this write directly to gchan->ch_cntxt_db_reg without checking if
REG_ACCESS_VALID(gpii->pm_state) is active, accessing unclocked or
deallocated hardware?
> error_alloc_ev_ring:
> gpi_disable_interrupts(gpii);
> error_config_int:
> gpi_free_ring(&gpii->ev_ring, gpii);
[Severity: High]
This is a pre-existing issue, but does this error path create a race condition
and use-after-free with the event tasklet?
If a channel fails gpi_ch_init(), gpi_disable_interrupts() frees the IRQ but
does not kill scheduled tasklets before gpi_free_ring() frees the memory.
If ev_task is already scheduled, it will bypass the state check because
pm_state remains ACTIVE_STATE during this time:
drivers/dma/qcom/gpi.c:gpi_ev_tasklet() {
...
if (!REG_ACCESS_VALID(gpii->pm_state)) {
...
}
Will the tasklet then process events using the freed and zeroed ev_ring?
> + write_lock_irq(&gpii->pm_lock);
> + gpii->pm_state = DISABLE_STATE;
> + write_unlock_irq(&gpii->pm_lock);
[Severity: High]
Does this regression actively prevent the necessary hardware GPI_EV_CMD_DEALLOC
command?
If the initialization fails, gpi_free_chan_resources() is called, but it
checks for ACTIVE_STATE before deallocating:
drivers/dma/qcom/gpi.c:gpi_free_chan_resources() {
...
if (cur_state == ACTIVE_STATE)
gpi_send_cmd(gpii, NULL, GPI_EV_CMD_DEALLOC);
...
}
Could this leak the hardware state because the hardware is never told to
release the event ring context?
--
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.