Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: 176fdcbddfd2 ("drm/nouveau/gsp/r535: add support for booting GSP-RM")
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
Link: https://lore.kernel.org/r/20250527163712.3444-1-zhiw@nvidia.com
[ Rebase onto Blackwell changes. - Danilo ]
Signed-off-by: Danilo Krummrich <dakr@kernel.org>

authored by

Zhi Wang and committed by
Danilo Krummrich
9802f0a6 80626ae6

+12 -5
+12 -5
drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/rpc.c
··· 637 637 if (payload_size > max_payload_size) { 638 638 const u32 fn = rpc->function; 639 639 u32 remain_payload_size = payload_size; 640 + void *next; 640 641 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 + } 644 648 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); 646 652 if (IS_ERR(repv)) 647 653 goto done; 648 654 ··· 659 653 while (remain_payload_size) { 660 654 u32 size = min(remain_payload_size, 661 655 max_payload_size); 662 - void *next; 663 656 664 657 next = r535_gsp_rpc_get(gsp, NV_VGPU_MSG_FUNCTION_CONTINUATION_RECORD, size); 665 658 if (IS_ERR(next)) { ··· 679 674 /* Wait for reply. */ 680 675 repv = r535_gsp_rpc_handle_reply(gsp, fn, policy, payload_size + 681 676 sizeof(*rpc)); 677 + if (!IS_ERR(repv)) 678 + kvfree(msg); 682 679 } else { 683 680 repv = r535_gsp_rpc_send(gsp, payload, policy, gsp_rpc_len); 684 681 }