Commit 93c19634 authored by Srinivasan Shanmugam's avatar Srinivasan Shanmugam Committed by Alex Deucher
Browse files

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: 527e3d40 ("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: default avatarSrinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Reviewed-by: default avatarTao Zhou <tao.zhou1@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent f3854e04
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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,