Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Leo Liu and committed by
Alex Deucher
5146419e 1ee4478a

+41 -27
+41 -27
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
··· 543 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 568 /* it's a decode msg, calc buffer sizes */ 548 569 r = amdgpu_uvd_cs_msg_decode(msg, ctx->buf_sizes); 549 570 amdgpu_bo_kunmap(bo); 550 571 if (r) 551 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 589 /* it's a destroy msg, free the handle */ 555 590 for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) 556 591 atomic_cmpxchg(&adev->uvd.handles[i], handle, 0); 557 592 amdgpu_bo_kunmap(bo); 558 593 return 0; 559 - } else { 560 - /* it's a create msg */ 561 - amdgpu_bo_kunmap(bo); 562 594 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 */ 595 + default: 596 + DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); 597 + return -EINVAL; 569 598 } 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 - 577 - /* handle not found try to alloc a new one */ 578 - for (i = 0; i < AMDGPU_MAX_UVD_HANDLES; ++i) { 579 - if (!atomic_cmpxchg(&adev->uvd.handles[i], 0, handle)) { 580 - adev->uvd.filp[i] = ctx->parser->filp; 581 - return 0; 582 - } 583 - } 584 - 585 - DRM_ERROR("No more free UVD handles!\n"); 599 + BUG(); 586 600 return -EINVAL; 587 601 } 588 602