aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeo Liu <leo.liu@amd.com>2015-09-15 10:38:38 -0400
committerAlex Deucher <alexander.deucher@amd.com>2015-09-23 17:23:40 -0400
commit5146419e6feb99cfbc8dbf005dd2f62603e15efb (patch)
tree19f7ce488cff30bc0e9d198fff7970a78dfb0fa4
parent1ee4478a26cf55c8f8a6219d7e99f2b48959394d (diff)
drm/amdgpu: make UVD handle checking more strict
Invalid messages can crash the hw otherwise Ported from radeon commit a1b403da70e038ca6c6c6fe434d1d873546873a3 Signed-off-by: Leo Liu <leo.liu@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Cc: stable@vger.kernel.org
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c68
1 files changed, 41 insertions, 27 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 1a8e43b3039e..d0312364d950 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -543,46 +543,60 @@ static int amdgpu_uvd_cs_msg(struct amdgpu_uvd_cs_ctx *ctx,
543 return -EINVAL; 543 return -EINVAL;
544 } 544 }
545 545
546 if (msg_type == 1) { 546 switch (msg_type) {
547 case 0:
548 /* it's a create msg, calc image size (width * height) */
549 amdgpu_bo_kunmap(bo);
550
551 /* try to alloc a new handle */
552 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
553 if (atomic_read(&adev->uvd.handles[i]) == handle) {
554 DRM_ERROR("Handle 0x%x already in use!\n", handle);
555 return -EINVAL;
556 }
557
558 if (!atomic_cmpxchg(&adev->uvd.handles[i], 0, handle)) {
559 adev->uvd.filp[i] = ctx->parser->filp;
560 return 0;
561 }
562 }
563
564 DRM_ERROR("No more free UVD handles!\n");
565 return -EINVAL;
566
567 case 1:
547 /* it's a decode msg, calc buffer sizes */ 568 /* it's a decode msg, calc buffer sizes */
548 r = amdgpu_uvd_cs_msg_decode(msg, ctx->buf_sizes); 569 r = amdgpu_uvd_cs_msg_decode(msg, ctx->buf_sizes);
549 amdgpu_bo_kunmap(bo); 570 amdgpu_bo_kunmap(bo);
550 if (r) 571 if (r)
551 return r; 572 return r;
552 573
553 } else if (msg_type == 2) { 574 /* validate the handle */
575 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
576 if (atomic_read(&adev->uvd.handles[i]) == handle) {
577 if (adev->uvd.filp[i] != ctx->parser->filp) {
578 DRM_ERROR("UVD handle collision detected!\n");
579 return -EINVAL;
580 }
581 return 0;
582 }
583 }
584
585 DRM_ERROR("Invalid UVD handle 0x%x!\n", handle);
586 return -ENOENT;
587
588 case 2:
554 /* it's a destroy msg, free the handle */ 589 /* it's a destroy msg, free the handle */
555 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) 590 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i)
556 atomic_cmpxchg(&adev->uvd.handles[i], handle, 0); 591 atomic_cmpxchg(&adev->uvd.handles[i], handle, 0);
557 amdgpu_bo_kunmap(bo); 592 amdgpu_bo_kunmap(bo);
558 return 0; 593 return 0;
559 } else {
560 /* it's a create msg */
561 amdgpu_bo_kunmap(bo);
562
563 if (msg_type != 0) {
564 DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
565 return -EINVAL;
566 }
567
568 /* it's a create msg, no special handling needed */
569 }
570
571 /* create or decode, validate the handle */
572 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) {
573 if (atomic_read(&adev->uvd.handles[i]) == handle)
574 return 0;
575 }
576 594
577 /* handle not found try to alloc a new one */ 595 default:
578 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) { 596 DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
579 if (!atomic_cmpxchg(&adev->uvd.handles[i], 0, handle)) { 597 return -EINVAL;
580 adev->uvd.filp[i] = ctx->parser->filp;
581 return 0;
582 }
583 } 598 }
584 599 BUG();
585 DRM_ERROR("No more free UVD handles!\n");
586 return -EINVAL; 600 return -EINVAL;
587} 601}
588 602