Re: [PATCH] drm/amdgpu: Fix TOCTOU on UniRAS command response size

2026-05-19 Thread Chai, Thomas
AMD General

Reviewed-by: YiPeng Chai 

Best Regards,
Thomas

From: Xie, Chenglei 
Sent: Tuesday, May 12, 2026 2:18 AM
To: [email protected] ; Chai, Thomas 

Cc: Chan, Hing Pong ; Luo, Zhigang ; 
Deucher, Alexander ; Xie, Chenglei 
; Chai, Thomas 
Subject: [PATCH] drm/amdgpu: Fix TOCTOU on UniRAS command response size

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 
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



[PATCH] drm/amdgpu: Fix TOCTOU on UniRAS command response size

2026-05-11 Thread Chenglei Xie
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 
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