AMD General

Thanks for the fix, the patch is:

Reviewed-by: Tao Zhou <[email protected]>

> -----Original Message-----
> From: amd-gfx <[email protected]> On Behalf Of Xiang
> Liu
> Sent: Thursday, May 7, 2026 10:00 PM
> To: [email protected]
> Cc: Zhang, Hawking <[email protected]>; Zhou1, Tao
> <[email protected]>; Liu, Xiang(Dean) <[email protected]>
> Subject: [PATCH] drm/amd/ras: Fix CPER ring debugfs read overflow
>
> The legacy CPER debugfs reader can reach the payload path without a valid
> pointer snapshot. The remaining user byte count is also treated as the ring
> occupancy in dwords, so reads past the header can copy more than
> requested.
>
> Take the CPER lock before sampling pointers. Resample rptr/wptr for payload
> reads, bound the payload copy by available dwords and the remaining user
> size, and advance the file position for each dword copied.
>
> Signed-off-by: Xiang Liu <[email protected]>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 29 +++++++++++++++++-----
> --
>  1 file changed, 21 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
> index 5de786551aaa..e47a155f4bb1 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
> @@ -552,8 +552,9 @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f,
> char __user *buf,
>                                       size_t size, loff_t *pos)
>  {
>       struct amdgpu_ring *ring = file_inode(f)->i_private;
> -     uint32_t value, result, early[3];
> +     u32 value, result, early[3] = { 0 };
>       uint64_t p;
> +     u32 avail_dw, start_dw, read_dw;
>       loff_t i;
>       int r;
>
> @@ -565,10 +566,10 @@ static ssize_t amdgpu_debugfs_ring_read(struct file
> *f, char __user *buf,
>
>       result = 0;
>
> -     if (*pos < 12) {
> -             if (ring->funcs->type == AMDGPU_RING_TYPE_CPER)
> -                     mutex_lock(&ring->adev->cper.ring_lock);
> +     if (ring->funcs->type == AMDGPU_RING_TYPE_CPER)
> +             mutex_lock(&ring->adev->cper.ring_lock);
>
> +     if (*pos < 12) {
>               early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask;
>               early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask;
>               early[2] = ring->wptr & ring->buf_mask; @@ -600,13 +601,24
> @@ static ssize_t amdgpu_debugfs_ring_read(struct file *f, char __user *buf,
>                       *pos += 4;
>               }
>       } else {
> +             early[0] = amdgpu_ring_get_rptr(ring) & ring->buf_mask;
> +             early[1] = amdgpu_ring_get_wptr(ring) & ring->buf_mask;
> +
>               p = early[0];
>               if (early[0] <= early[1])
> -                     size = (early[1] - early[0]);
> +                     avail_dw = early[1] - early[0];
>               else
> -                     size = ring->ring_size - (early[0] - early[1]);
> +                     avail_dw = ring->buf_mask + 1 - (early[0] - early[1]);
>
> -             while (size) {
> +             start_dw = (*pos > 12) ? ((*pos - 12) >> 2) : 0;
> +             if (start_dw >= avail_dw)
> +                     goto out;
> +
> +             p = (p + start_dw) & ring->ptr_mask;
> +             avail_dw -= start_dw;
> +             read_dw = min_t(u32, avail_dw, size >> 2);
> +
> +             while (read_dw) {
>                       if (p == early[1])
>                               goto out;
>
> @@ -619,9 +631,10 @@ static ssize_t amdgpu_debugfs_ring_read(struct file
> *f, char __user *buf,
>
>                       buf += 4;
>                       result += 4;
> -                     size--;
> +                     read_dw--;
>                       p++;
>                       p &= ring->ptr_mask;
> +                     *pos += 4;
>               }
>       }
>
> --
> 2.54.0

Reply via email to