[PATCH] drm/nouveau/gsp: validate sequencer command span
Pengpeng Hou <[email protected]> Wed, 22 Jul 2026 12:21:23 +0800
| Newsgroups | org.freedesktop.lists.nouveau,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
The GSP sequencer RPC contains a variable command stream. The handler currently walks commands using the stream header length without first proving that the stream, each command payload, or a register-save slot fits in the received RPC and its fixed save area. Validate the stream and each command against the RPC payload before walking it, and reject register-save indexes beyond the fixed save array. Signed-off-by: Pengpeng Hou <[email protected]> --- .../drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c index f544afa12b6b..00417bbccc12 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c @@ -1010,15 +1010,30 @@ r535_gsp_msg_run_cpu_sequencer(void *priv, u32 fn, void *repv, u32 repc) struct nvkm_subdev *subdev = &gsp->subdev; struct nvkm_device *device = subdev->device; rpc_run_cpu_sequencer_v17_00 *seq = repv; - int ptr = 0, ret; + u32 ptr = 0, payload; + int ret; + + if (repc < offsetof(rpc_run_cpu_sequencer_v17_00, commandBuffer) || + seq->cmdIndex > + (repc - offsetof(rpc_run_cpu_sequencer_v17_00, commandBuffer)) / + sizeof(seq->commandBuffer[0])) { + nvkm_error(subdev, "invalid sequencer command buffer size\n"); + return -EINVAL; + } nvkm_debug(subdev, "seq: %08x %08x\n", seq->bufferSizeDWord, seq->cmdIndex); while (ptr < seq->cmdIndex) { GSP_SEQUENCER_BUFFER_CMD *cmd = (void *)&seq->commandBuffer[ptr]; + payload = GSP_SEQUENCER_PAYLOAD_SIZE_DWORDS(cmd->opCode); + if (seq->cmdIndex - ptr < payload + 1) { + nvkm_error(subdev, "truncated sequencer command\n"); + return -EINVAL; + } + ptr += 1; - ptr += GSP_SEQUENCER_PAYLOAD_SIZE_DWORDS(cmd->opCode); + ptr += payload; switch (cmd->opCode) { case GSP_SEQ_BUF_OPCODE_REG_WRITE: { @@ -1064,6 +1079,9 @@ r535_gsp_msg_run_cpu_sequencer(void *priv, u32 fn, void *repv, u32 repc) u32 addr = cmd->payload.regStore.addr; u32 slot = cmd->payload.regStore.index; + if (slot >= ARRAY_SIZE(seq->regSaveArea)) + return -EINVAL; + seq->regSaveArea[slot] = nvkm_rd32(device, addr); nvkm_trace(subdev, "seq save %08x -> %d: %08x\n", addr, slot, seq->regSaveArea[slot]); -- 2.43.0