mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-07 14:24:18 +08:00
drm/amdgpu/psp: prevent page fault by checking write_frame address(v4)
- Prevent a possible buffer overflow when updating the ring buffer by bounds checking the command frame against the available space in the ring buffer. v2: update the ring_buffer_end address v3: update the commit log v4: squash in print fix (Michel) Signed-off-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
0722382dcc
commit
4694257e7d
@ -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,16 @@ 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 = %p; ring_buffer_end = %p; write_frame = %p\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));
|
||||
|
@ -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,16 @@ 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 = %p; ring_buffer_end = %p; write_frame = %p\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));
|
||||
|
Loading…
Reference in New Issue
Block a user