Skip to content

Commit a1b403d

Browse files
ChristianKoenigAMDalexdeucher
authored andcommitted
drm/radeon: make UVD handle checking more strict
Invalid messages can crash the hw otherwise. Signed-off-by: Christian König <christian.koenig@amd.com> CC: stable@vger.kernel.org Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 29c63fe commit a1b403d

File tree

1 file changed

+43
-29
lines changed

1 file changed

+43
-29
lines changed

drivers/gpu/drm/radeon/radeon_uvd.c

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -436,50 +436,64 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
436436
return -EINVAL;
437437
}
438438

439-
if (msg_type == 1) {
439+
switch (msg_type) {
440+
case 0:
441+
/* it's a create msg, calc image size (width * height) */
442+
img_size = msg[7] * msg[8];
443+
radeon_bo_kunmap(bo);
444+
445+
/* try to alloc a new handle */
446+
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
447+
if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
448+
DRM_ERROR("Handle 0x%x already in use!\n", handle);
449+
return -EINVAL;
450+
}
451+
452+
if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
453+
p->rdev->uvd.filp[i] = p->filp;
454+
p->rdev->uvd.img_size[i] = img_size;
455+
return 0;
456+
}
457+
}
458+
459+
DRM_ERROR("No more free UVD handles!\n");
460+
return -EINVAL;
461+
462+
case 1:
440463
/* it's a decode msg, calc buffer sizes */
441464
r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
442-
/* calc image size (width * height) */
443-
img_size = msg[6] * msg[7];
444465
radeon_bo_kunmap(bo);
445466
if (r)
446467
return r;
447468

448-
} else if (msg_type == 2) {
469+
/* validate the handle */
470+
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
471+
if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
472+
if (p->rdev->uvd.filp[i] != p->filp) {
473+
DRM_ERROR("UVD handle collision detected!\n");
474+
return -EINVAL;
475+
}
476+
return 0;
477+
}
478+
}
479+
480+
DRM_ERROR("Invalid UVD handle 0x%x!\n", handle);
481+
return -ENOENT;
482+
483+
case 2:
449484
/* it's a destroy msg, free the handle */
450485
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
451486
atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
452487
radeon_bo_kunmap(bo);
453488
return 0;
454-
} else {
455-
/* it's a create msg, calc image size (width * height) */
456-
img_size = msg[7] * msg[8];
457-
radeon_bo_kunmap(bo);
458489

459-
if (msg_type != 0) {
460-
DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
461-
return -EINVAL;
462-
}
463-
464-
/* it's a create msg, no special handling needed */
465-
}
466-
467-
/* create or decode, validate the handle */
468-
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
469-
if (atomic_read(&p->rdev->uvd.handles[i]) == handle)
470-
return 0;
471-
}
490+
default:
472491

473-
/* handle not found try to alloc a new one */
474-
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
475-
if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
476-
p->rdev->uvd.filp[i] = p->filp;
477-
p->rdev->uvd.img_size[i] = img_size;
478-
return 0;
479-
}
492+
DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
493+
return -EINVAL;
480494
}
481495

482-
DRM_ERROR("No more free UVD handles!\n");
496+
BUG();
483497
return -EINVAL;
484498
}
485499

0 commit comments

Comments
 (0)