diff options
| author | Srinivasan Shanmugam <srinivasan.shanmugam@amd.com> | 2025-11-21 16:28:20 +0530 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2025-11-26 11:50:43 -0500 |
| commit | 93c19634f72fb32284e5775b44e4076c059d8e67 (patch) | |
| tree | 64d9b924c5d2a9ab08966f846eec26b59eae22d4 /drivers/gpu/drm/amd/amdgpu | |
| parent | f3854e04b708d73276c4488231a8bd66d30b4671 (diff) | |
drm/amdgpu: Fix CPER ring debugfs read buffer overflow risk
The CPER ring debugfs read code always writes a 12-byte header when the
file is read for the first time (*offset == 0):
copy_to_user(buf, ring_header, 12);
But the code never checks whether the user buffer (@size) is at least
12 bytes long. After writing the 12-byte header, the code then gives the
full original @size to the CPER payload handler:
record_req->buf_size = size;
This means the function can write:
12 bytes (header) + payload bytes (up to @size)
into a buffer that is only @size bytes big. In other words, the kernel
may write more data than the user asked for. This can overflow the user
buffer.
The fix is:
- If the user buffer is smaller than 12 bytes on the first read,
return -EINVAL instead of copying the header.
- After writing the 12-byte header, subtract 12 from @size and pass
the reduced size to record_req->buf_size. This ensures the CPER
payload only uses the remaining free space in the buffer.
Reads after the first one (*offset != 0) do not write the header, so
their behavior stays exactly the same. The only user-visible change is
that tiny buffers now fail safely instead of risking an overflow.
Fixes:
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c:523
amdgpu_ras_cper_debugfs_read()
warn: userbuf overflow? is 'ring_header_size' <= 'size'
Fixes: 527e3d40339b ("drm/amd/ras: Add CPER ring read for uniras")
Reported by: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Xiang Liu <xiang.liu@amd.com>
Cc: Tao Zhou <tao.zhou1@amd.com>
Cc: Yang Wang <kevinyang.wang@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index cd8873c6931a..c596b6df2e2d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -520,9 +520,14 @@ static ssize_t amdgpu_ras_cper_debugfs_read(struct file *f, char __user *buf, return -ENOMEM; if (!(*offset)) { + /* Need at least 12 bytes for the header on the first read */ + if (size < ring_header_size) + return -EINVAL; + if (copy_to_user(buf, ring_header, ring_header_size)) return -EFAULT; buf += ring_header_size; + size -= ring_header_size; } r = amdgpu_ras_mgr_handle_ras_cmd(ring->adev, |