Skip to content

Commit 9802f0a

Browse files
zhiwang-nvidiaDanilo Krummrich
authored andcommitted
drm/nouveau: fix a use-after-free in r535_gsp_rpc_push()
The RPC container is released after being passed to r535_gsp_rpc_send(). When sending the initial fragment of a large RPC and passing the caller's RPC container, the container will be freed prematurely. Subsequent attempts to send remaining fragments will therefore result in a use-after-free. Allocate a temporary RPC container for holding the initial fragment of a large RPC when sending. Free the caller's container when all fragments are successfully sent. Fixes: 176fdcb ("drm/nouveau/gsp/r535: add support for booting GSP-RM") Signed-off-by: Zhi Wang <[email protected]> Link: https://lore.kernel.org/r/[email protected] [ Rebase onto Blackwell changes. - Danilo ] Signed-off-by: Danilo Krummrich <[email protected]>
1 parent 80626ae commit 9802f0a

File tree

1 file changed

+12
-5
lines changed
  • drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535

1 file changed

+12
-5
lines changed

drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -637,12 +637,18 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload,
637637
if (payload_size > max_payload_size) {
638638
const u32 fn = rpc->function;
639639
u32 remain_payload_size = payload_size;
640+
void *next;
640641

641-
/* Adjust length, and send initial RPC. */
642-
rpc->length = sizeof(*rpc) + max_payload_size;
643-
msg->checksum = rpc->length;
642+
/* Send initial RPC. */
643+
next = r535_gsp_rpc_get(gsp, fn, max_payload_size);
644+
if (IS_ERR(next)) {
645+
repv = next;
646+
goto done;
647+
}
644648

645-
repv = r535_gsp_rpc_send(gsp, payload, NVKM_GSP_RPC_REPLY_NOWAIT, 0);
649+
memcpy(next, payload, max_payload_size);
650+
651+
repv = r535_gsp_rpc_send(gsp, next, NVKM_GSP_RPC_REPLY_NOWAIT, 0);
646652
if (IS_ERR(repv))
647653
goto done;
648654

@@ -653,7 +659,6 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload,
653659
while (remain_payload_size) {
654660
u32 size = min(remain_payload_size,
655661
max_payload_size);
656-
void *next;
657662

658663
next = r535_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD, size);
659664
if (IS_ERR(next)) {
@@ -674,6 +679,8 @@ r535_gsp_rpc_push(struct nvkm_gsp *gsp, void *payload,
674679
/* Wait for reply. */
675680
repv = r535_gsp_rpc_handle_reply(gsp, fn, policy, payload_size +
676681
sizeof(*rpc));
682+
if (!IS_ERR(repv))
683+
kvfree(msg);
677684
} else {
678685
repv = r535_gsp_rpc_send(gsp, payload, policy, gsp_rpc_len);
679686
}

0 commit comments

Comments
 (0)