aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd
diff options
context:
space:
mode:
authorEvan Quan <evan.quan@amd.com>2017-10-16 04:51:28 -0400
committerAlex Deucher <alexander.deucher@amd.com>2017-10-25 23:09:38 -0400
commit4694257e7d4757fedaa8dcd18bb5ff52e76a2765 (patch)
tree7495d845c5878ac1d2497156d5705787bad30df0 /drivers/gpu/drm/amd
parent0722382dcc4fd4e53c12db2c2eda9c5c9c903432 (diff)
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>
Diffstat (limited to 'drivers/gpu/drm/amd')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v10_0.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v3_1.c14
2 files changed, 24 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 dea7c909ca5f..4e20d91d5d50 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,
257 unsigned int psp_write_ptr_reg = 0; 257 unsigned int psp_write_ptr_reg = 0;
258 struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem; 258 struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem;
259 struct psp_ring *ring = &psp->km_ring; 259 struct psp_ring *ring = &psp->km_ring;
260 struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem;
261 struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start +
262 ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1;
260 struct amdgpu_device *adev = psp->adev; 263 struct amdgpu_device *adev = psp->adev;
261 uint32_t ring_size_dw = ring->ring_size / 4; 264 uint32_t ring_size_dw = ring->ring_size / 4;
262 uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; 265 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,
266 269
267 /* Update KM RB frame pointer to new frame */ 270 /* Update KM RB frame pointer to new frame */
268 if ((psp_write_ptr_reg % ring_size_dw) == 0) 271 if ((psp_write_ptr_reg % ring_size_dw) == 0)
269 write_frame = ring->ring_mem; 272 write_frame = ring_buffer_start;
270 else 273 else
271 write_frame = ring->ring_mem + (psp_write_ptr_reg / rb_frame_size_dw); 274 write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw);
275 /* Check invalid write_frame ptr address */
276 if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) {
277 DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n",
278 ring_buffer_start, ring_buffer_end, write_frame);
279 DRM_ERROR("write_frame is pointing to address out of bounds\n");
280 return -EINVAL;
281 }
272 282
273 /* Initialize KM RB frame */ 283 /* Initialize KM RB frame */
274 memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); 284 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 cee5c396b277..c7bcfe8e286c 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,
367 unsigned int psp_write_ptr_reg = 0; 367 unsigned int psp_write_ptr_reg = 0;
368 struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem; 368 struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem;
369 struct psp_ring *ring = &psp->km_ring; 369 struct psp_ring *ring = &psp->km_ring;
370 struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem;
371 struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start +
372 ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1;
370 struct amdgpu_device *adev = psp->adev; 373 struct amdgpu_device *adev = psp->adev;
371 uint32_t ring_size_dw = ring->ring_size / 4; 374 uint32_t ring_size_dw = ring->ring_size / 4;
372 uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; 375 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,
378 /* write_frame ptr increments by size of rb_frame in bytes */ 381 /* write_frame ptr increments by size of rb_frame in bytes */
379 /* psp_write_ptr_reg increments by size of rb_frame in DWORDs */ 382 /* psp_write_ptr_reg increments by size of rb_frame in DWORDs */
380 if ((psp_write_ptr_reg % ring_size_dw) == 0) 383 if ((psp_write_ptr_reg % ring_size_dw) == 0)
381 write_frame = ring->ring_mem; 384 write_frame = ring_buffer_start;
382 else 385 else
383 write_frame = ring->ring_mem + (psp_write_ptr_reg / rb_frame_size_dw); 386 write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw);
387 /* Check invalid write_frame ptr address */
388 if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) {
389 DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n",
390 ring_buffer_start, ring_buffer_end, write_frame);
391 DRM_ERROR("write_frame is pointing to address out of bounds\n");
392 return -EINVAL;
393 }
384 394
385 /* Initialize KM RB frame */ 395 /* Initialize KM RB frame */
386 memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); 396 memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame));