The guest maps the PF response in shared VRAM (struct ras_cmd_ctx in the command buffer). After amdgpu_virt_send_remote_ras_cmd() returns, the code validated rcmd->output_size against the caller buffer, then copied rcmd->output_buff_raw using rcmd->output_size again. A malicious PF could change output_size between those reads so the memcpy length exceeds the caller’s output_size and overflows guest stack or heap buffers.
Snapshot output_size with READ_ONCE() once, assign cmd->output_size from that value, and use the same snapshot for the bounds check and memcpy. Also read cmd_res once with READ_ONCE() so the error branch and cmd->cmd_res assignment do not observe different values from shared memory. Signed-off-by: Chenglei Xie <[email protected]> Change-Id: I815c5edc234a651a29657d126bf117be9364920a --- .../drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c index 838eb91aef391..4a10c19128fb1 100644 --- a/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c +++ b/drivers/gpu/drm/amd/ras/ras_mgr/amdgpu_virt_ras_cmd.c @@ -108,15 +108,19 @@ static int amdgpu_virt_ras_remote_ioctl_cmd(struct ras_core_context *ras_core, ret = amdgpu_virt_send_remote_ras_cmd(ras_core->dev, shared_mem.gpa, mem_len); if (!ret) { - if (rcmd->cmd_res) { - ret = rcmd->cmd_res; + uint32_t cmd_res = READ_ONCE(rcmd->cmd_res); + uint32_t osz; + + if (cmd_res) { + ret = cmd_res; goto out; } - cmd->cmd_res = rcmd->cmd_res; - cmd->output_size = rcmd->output_size; - if (rcmd->output_size && (rcmd->output_size <= output_size) && output_data) - memcpy(output_data, rcmd->output_buff_raw, rcmd->output_size); + osz = READ_ONCE(rcmd->output_size); + cmd->cmd_res = cmd_res; + cmd->output_size = osz; + if (osz && osz <= output_size && output_data) + memcpy(output_data, rcmd->output_buff_raw, osz); } out: -- 2.34.1
