[PATCH] drm/amdgpu/psp: prevent page fault by checking write_frame address(v2) -v2: update the ring_buffer_end address

Alex Deucher alexdeucher at gmail.com
Wed Oct 18 02:22:56 UTC 2017


On Mon, Oct 16, 2017 at 11:26 PM, Evan Quan <evan.quan at amd.com> wrote:
> Change-Id: If3b79428b32ffab57b4e75f9c20c2b2d7e600223
> Signed-off-by: Evan Quan <evan.quan at amd.com>

Please include a better commit message.  Something like:
Prevent a a possible buffer overflow when updating the ring buffer by
bounds checking the command frame against the available space in the
ring buffer.


> ---
>  drivers/gpu/drm/amd/amdgpu/psp_v10_0.c | 16 ++++++++++++++--
>  drivers/gpu/drm/amd/amdgpu/psp_v3_1.c  | 16 ++++++++++++++--
>  2 files changed, 28 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
> index 77cab1f..7d31c74 100644
> --- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
> @@ -257,6 +257,9 @@ int psp_v10_0_cmd_submit(struct psp_context *psp,
>         unsigned int psp_write_ptr_reg = 0;
>         struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem;
>         struct psp_ring *ring = &psp->km_ring;
> +       struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem;
> +       struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start +
> +               ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1;
>         struct amdgpu_device *adev = psp->adev;
>         uint32_t ring_size_dw = ring->ring_size / 4;
>         uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4;
> @@ -266,9 +269,18 @@ int psp_v10_0_cmd_submit(struct psp_context *psp,
>
>         /* Update KM RB frame pointer to new frame */
>         if ((psp_write_ptr_reg % ring_size_dw) == 0)
> -               write_frame = ring->ring_mem;
> +               write_frame = ring_buffer_start;
>         else
> -               write_frame = ring->ring_mem + (psp_write_ptr_reg / rb_frame_size_dw);
> +               write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw);
> +       /* Check invalid write_frame ptr address */
> +       if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) {
> +               DRM_ERROR("ring_buffer_start = %x; ring_buffer_end = %x; write_frame = %x\n",
> +                               ring_buffer_start,
> +                               ring_buffer_end,
> +                               write_frame);
> +               DRM_ERROR("write_frame is pointing to address out of bounds\n");
> +               return -EINVAL;
> +       }
>
>         /* Initialize KM RB frame */
>         memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame));
> diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
> index bcbe30d..3f0eecf 100644
> --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
> @@ -367,6 +367,9 @@ int psp_v3_1_cmd_submit(struct psp_context *psp,
>         unsigned int psp_write_ptr_reg = 0;
>         struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem;
>         struct psp_ring *ring = &psp->km_ring;
> +       struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem;
> +       struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start +
> +               ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1;
>         struct amdgpu_device *adev = psp->adev;
>         uint32_t ring_size_dw = ring->ring_size / 4;
>         uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4;
> @@ -378,9 +381,18 @@ int psp_v3_1_cmd_submit(struct psp_context *psp,
>         /* write_frame ptr increments by size of rb_frame in bytes */
>         /* psp_write_ptr_reg increments by size of rb_frame in DWORDs */
>         if ((psp_write_ptr_reg % ring_size_dw) == 0)
> -               write_frame = ring->ring_mem;
> +               write_frame = ring_buffer_start;
>         else
> -               write_frame = ring->ring_mem + (psp_write_ptr_reg / rb_frame_size_dw);
> +               write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw);
> +       /* Check invalid write_frame ptr address */
> +       if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) {
> +               DRM_ERROR("ring_buffer_start = %x; ring_buffer_end = %x; write_frame = %x\n",
> +                               ring_buffer_start,
> +                               ring_buffer_end,
> +                               write_frame);
> +               DRM_ERROR("write_frame is pointing to address out of bounds\n");
> +               return -EINVAL;
> +       }
>
>         /* Initialize KM RB frame */
>         memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame));
> --
> 2.7.4
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


More information about the amd-gfx mailing list