Commit cd9fc221 authored by Christian König's avatar Christian König Committed by Kamal Mostafa

drm/radeon: make UVD handle checking more strict

commit a1b403da upstream.

Invalid messages can crash the hw otherwise.
Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarKamal Mostafa <kamal@canonical.com>
parent 1d718ecf
...@@ -388,50 +388,64 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, ...@@ -388,50 +388,64 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
return -EINVAL; return -EINVAL;
} }
if (msg_type == 1) { switch (msg_type) {
/* it's a decode msg, calc buffer sizes */ case 0:
r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
/* calc image size (width * height) */
img_size = msg[6] * msg[7];
radeon_bo_kunmap(bo);
if (r)
return r;
} else if (msg_type == 2) {
/* it's a destroy msg, free the handle */
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
radeon_bo_kunmap(bo);
return 0;
} else {
/* it's a create msg, calc image size (width * height) */ /* it's a create msg, calc image size (width * height) */
img_size = msg[7] * msg[8]; img_size = msg[7] * msg[8];
radeon_bo_kunmap(bo); radeon_bo_kunmap(bo);
if (msg_type != 0) { /* try to alloc a new handle */
DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type); for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
DRM_ERROR("Handle 0x%x already in use!\n", handle);
return -EINVAL; return -EINVAL;
} }
/* it's a create msg, no special handling needed */ if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
p->rdev->uvd.filp[i] = p->filp;
p->rdev->uvd.img_size[i] = img_size;
return 0;
} }
}
DRM_ERROR("No more free UVD handles!\n");
return -EINVAL;
/* create or decode, validate the handle */ case 1:
/* it's a decode msg, calc buffer sizes */
r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
radeon_bo_kunmap(bo);
if (r)
return r;
/* validate the handle */
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
if (atomic_read(&p->rdev->uvd.handles[i]) == handle) if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
if (p->rdev->uvd.filp[i] != p->filp) {
DRM_ERROR("UVD handle collision detected!\n");
return -EINVAL;
}
return 0; return 0;
} }
}
/* handle not found try to alloc a new one */ DRM_ERROR("Invalid UVD handle 0x%x!\n", handle);
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) { return -ENOENT;
if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
p->rdev->uvd.filp[i] = p->filp; case 2:
p->rdev->uvd.img_size[i] = img_size; /* it's a destroy msg, free the handle */
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
radeon_bo_kunmap(bo);
return 0; return 0;
}
default:
DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
return -EINVAL;
} }
DRM_ERROR("No more free UVD handles!\n"); BUG();
return -EINVAL; return -EINVAL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment