diff options
author | Leo Liu <leo.liu@amd.com> | 2015-09-15 10:38:38 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2015-09-23 17:23:40 -0400 |
commit | 5146419e6feb99cfbc8dbf005dd2f62603e15efb (patch) | |
tree | 19f7ce488cff30bc0e9d198fff7970a78dfb0fa4 | |
parent | 1ee4478a26cf55c8f8a6219d7e99f2b48959394d (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.c | 68 |
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 | ||