aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian König <christian.koenig@amd.com>2013-08-05 08:10:57 -0400
committerAlex Deucher <alexander.deucher@amd.com>2013-08-07 17:37:16 -0400
commit56cc2c15389770d2f95a791f73d0ab6b15d530e1 (patch)
tree910652fc42c01fd8a4f1eac5eabc62eea5bbbd88
parent641a00593f7d07eab778fbabf546fb68fff3d5ce (diff)
drm/radeon: add more UVD CS checking
Improve error handling in case userspace sends us an invalid command buffer. Signed-off-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--drivers/gpu/drm/radeon/radeon_uvd.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c
index 4fec195e0dd4..f1c15754e73c 100644
--- a/drivers/gpu/drm/radeon/radeon_uvd.c
+++ b/drivers/gpu/drm/radeon/radeon_uvd.c
@@ -357,8 +357,10 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
357 } 357 }
358 358
359 r = radeon_bo_kmap(bo, &ptr); 359 r = radeon_bo_kmap(bo, &ptr);
360 if (r) 360 if (r) {
361 DRM_ERROR("Failed mapping the UVD message (%d)!\n", r);
361 return r; 362 return r;
363 }
362 364
363 msg = ptr + offset; 365 msg = ptr + offset;
364 366
@@ -384,8 +386,14 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
384 radeon_bo_kunmap(bo); 386 radeon_bo_kunmap(bo);
385 return 0; 387 return 0;
386 } else { 388 } else {
387 /* it's a create msg, no special handling needed */
388 radeon_bo_kunmap(bo); 389 radeon_bo_kunmap(bo);
390
391 if (msg_type != 0) {
392 DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
393 return -EINVAL;
394 }
395
396 /* it's a create msg, no special handling needed */
389 } 397 }
390 398
391 /* create or decode, validate the handle */ 399 /* create or decode, validate the handle */
@@ -408,7 +416,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
408 416
409static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, 417static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
410 int data0, int data1, 418 int data0, int data1,
411 unsigned buf_sizes[]) 419 unsigned buf_sizes[], bool *has_msg_cmd)
412{ 420{
413 struct radeon_cs_chunk *relocs_chunk; 421 struct radeon_cs_chunk *relocs_chunk;
414 struct radeon_cs_reloc *reloc; 422 struct radeon_cs_reloc *reloc;
@@ -437,7 +445,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
437 445
438 if (cmd < 0x4) { 446 if (cmd < 0x4) {
439 if ((end - start) < buf_sizes[cmd]) { 447 if ((end - start) < buf_sizes[cmd]) {
440 DRM_ERROR("buffer to small (%d / %d)!\n", 448 DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd,
441 (unsigned)(end - start), buf_sizes[cmd]); 449 (unsigned)(end - start), buf_sizes[cmd]);
442 return -EINVAL; 450 return -EINVAL;
443 } 451 }
@@ -462,9 +470,17 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
462 } 470 }
463 471
464 if (cmd == 0) { 472 if (cmd == 0) {
473 if (*has_msg_cmd) {
474 DRM_ERROR("More than one message in a UVD-IB!\n");
475 return -EINVAL;
476 }
477 *has_msg_cmd = true;
465 r = radeon_uvd_cs_msg(p, reloc->robj, offset, buf_sizes); 478 r = radeon_uvd_cs_msg(p, reloc->robj, offset, buf_sizes);
466 if (r) 479 if (r)
467 return r; 480 return r;
481 } else if (!*has_msg_cmd) {
482 DRM_ERROR("Message needed before other commands are send!\n");
483 return -EINVAL;
468 } 484 }
469 485
470 return 0; 486 return 0;
@@ -473,7 +489,8 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
473static int radeon_uvd_cs_reg(struct radeon_cs_parser *p, 489static int radeon_uvd_cs_reg(struct radeon_cs_parser *p,
474 struct radeon_cs_packet *pkt, 490 struct radeon_cs_packet *pkt,
475 int *data0, int *data1, 491 int *data0, int *data1,
476 unsigned buf_sizes[]) 492 unsigned buf_sizes[],
493 bool *has_msg_cmd)
477{ 494{
478 int i, r; 495 int i, r;
479 496
@@ -487,7 +504,8 @@ static int radeon_uvd_cs_reg(struct radeon_cs_parser *p,
487 *data1 = p->idx; 504 *data1 = p->idx;
488 break; 505 break;
489 case UVD_GPCOM_VCPU_CMD: 506 case UVD_GPCOM_VCPU_CMD:
490 r = radeon_uvd_cs_reloc(p, *data0, *data1, buf_sizes); 507 r = radeon_uvd_cs_reloc(p, *data0, *data1,
508 buf_sizes, has_msg_cmd);
491 if (r) 509 if (r)
492 return r; 510 return r;
493 break; 511 break;
@@ -508,6 +526,9 @@ int radeon_uvd_cs_parse(struct radeon_cs_parser *p)
508 struct radeon_cs_packet pkt; 526 struct radeon_cs_packet pkt;
509 int r, data0 = 0, data1 = 0; 527 int r, data0 = 0, data1 = 0;
510 528
529 /* does the IB has a msg command */
530 bool has_msg_cmd = false;
531
511 /* minimum buffer sizes */ 532 /* minimum buffer sizes */
512 unsigned buf_sizes[] = { 533 unsigned buf_sizes[] = {
513 [0x00000000] = 2048, 534 [0x00000000] = 2048,
@@ -534,8 +555,8 @@ int radeon_uvd_cs_parse(struct radeon_cs_parser *p)
534 return r; 555 return r;
535 switch (pkt.type) { 556 switch (pkt.type) {
536 case RADEON_PACKET_TYPE0: 557 case RADEON_PACKET_TYPE0:
537 r = radeon_uvd_cs_reg(p, &pkt, &data0, 558 r = radeon_uvd_cs_reg(p, &pkt, &data0, &data1,
538 &data1, buf_sizes); 559 buf_sizes, &has_msg_cmd);
539 if (r) 560 if (r)
540 return r; 561 return r;
541 break; 562 break;
@@ -547,6 +568,12 @@ int radeon_uvd_cs_parse(struct radeon_cs_parser *p)
547 return -EINVAL; 568 return -EINVAL;
548 } 569 }
549 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); 570 } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
571
572 if (!has_msg_cmd) {
573 DRM_ERROR("UVD-IBs need a msg command!\n");
574 return -EINVAL;
575 }
576
550 return 0; 577 return 0;
551} 578}
552 579