aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/r128
diff options
context:
space:
mode:
authorBen Hutchings <ben@decadent.org.uk>2009-08-23 11:59:04 -0400
committerDave Airlie <airlied@redhat.com>2009-08-30 19:09:30 -0400
commit7dc482dfeeeefcfd000d4271c4626937406756d7 (patch)
tree2ec9a70ecad5f7cb94136d53d98d587837f05ef3 /drivers/gpu/drm/r128
parent70967ab9c0c9017645d167d33675eab996633631 (diff)
drm/r128: Add test for initialisation to all ioctls that require it
Almost all r128's private ioctls require that the CCE state has already been initialised. However, most do not test that this has been done, and will proceed to dereference a null pointer. This may result in a security vulnerability, since some ioctls are unprivileged. This adds a macro for the common initialisation test and changes all ioctl implementations that require prior initialisation to use that macro. Also, r128_do_init_cce() does not test that the CCE state has not been initialised already. Repeated initialisation may lead to a crash or resource leak. This adds that test. Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/r128')
-rw-r--r--drivers/gpu/drm/r128/r128_cce.c18
-rw-r--r--drivers/gpu/drm/r128/r128_drv.h8
-rw-r--r--drivers/gpu/drm/r128/r128_state.c36
3 files changed, 41 insertions, 21 deletions
diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c
index 15252f60bbd3..4c39a407aa4a 100644
--- a/drivers/gpu/drm/r128/r128_cce.c
+++ b/drivers/gpu/drm/r128/r128_cce.c
@@ -346,6 +346,11 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
346 346
347 DRM_DEBUG("\n"); 347 DRM_DEBUG("\n");
348 348
349 if (dev->dev_private) {
350 DRM_DEBUG("called when already initialized\n");
351 return -EINVAL;
352 }
353
349 dev_priv = kzalloc(sizeof(drm_r128_private_t), GFP_KERNEL); 354 dev_priv = kzalloc(sizeof(drm_r128_private_t), GFP_KERNEL);
350 if (dev_priv == NULL) 355 if (dev_priv == NULL)
351 return -ENOMEM; 356 return -ENOMEM;
@@ -647,6 +652,8 @@ int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_pri
647 652
648 LOCK_TEST_WITH_RETURN(dev, file_priv); 653 LOCK_TEST_WITH_RETURN(dev, file_priv);
649 654
655 DEV_INIT_TEST_WITH_RETURN(dev_priv);
656
650 if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) { 657 if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) {
651 DRM_DEBUG("while CCE running\n"); 658 DRM_DEBUG("while CCE running\n");
652 return 0; 659 return 0;
@@ -669,6 +676,8 @@ int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv
669 676
670 LOCK_TEST_WITH_RETURN(dev, file_priv); 677 LOCK_TEST_WITH_RETURN(dev, file_priv);
671 678
679 DEV_INIT_TEST_WITH_RETURN(dev_priv);
680
672 /* Flush any pending CCE commands. This ensures any outstanding 681 /* Flush any pending CCE commands. This ensures any outstanding
673 * commands are exectuted by the engine before we turn it off. 682 * commands are exectuted by the engine before we turn it off.
674 */ 683 */
@@ -706,10 +715,7 @@ int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_pri
706 715
707 LOCK_TEST_WITH_RETURN(dev, file_priv); 716 LOCK_TEST_WITH_RETURN(dev, file_priv);
708 717
709 if (!dev_priv) { 718 DEV_INIT_TEST_WITH_RETURN(dev_priv);
710 DRM_DEBUG("called before init done\n");
711 return -EINVAL;
712 }
713 719
714 r128_do_cce_reset(dev_priv); 720 r128_do_cce_reset(dev_priv);
715 721
@@ -726,6 +732,8 @@ int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv
726 732
727 LOCK_TEST_WITH_RETURN(dev, file_priv); 733 LOCK_TEST_WITH_RETURN(dev, file_priv);
728 734
735 DEV_INIT_TEST_WITH_RETURN(dev_priv);
736
729 if (dev_priv->cce_running) { 737 if (dev_priv->cce_running) {
730 r128_do_cce_flush(dev_priv); 738 r128_do_cce_flush(dev_priv);
731 } 739 }
@@ -739,6 +747,8 @@ int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_
739 747
740 LOCK_TEST_WITH_RETURN(dev, file_priv); 748 LOCK_TEST_WITH_RETURN(dev, file_priv);
741 749
750 DEV_INIT_TEST_WITH_RETURN(dev->dev_private);
751
742 return r128_do_engine_reset(dev); 752 return r128_do_engine_reset(dev);
743} 753}
744 754
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h
index 797a26c42dab..3c60829d82e9 100644
--- a/drivers/gpu/drm/r128/r128_drv.h
+++ b/drivers/gpu/drm/r128/r128_drv.h
@@ -422,6 +422,14 @@ static __inline__ void r128_update_ring_snapshot(drm_r128_private_t * dev_priv)
422 * Misc helper macros 422 * Misc helper macros
423 */ 423 */
424 424
425#define DEV_INIT_TEST_WITH_RETURN(_dev_priv) \
426do { \
427 if (!_dev_priv) { \
428 DRM_ERROR("called with no initialization\n"); \
429 return -EINVAL; \
430 } \
431} while (0)
432
425#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ 433#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \
426do { \ 434do { \
427 drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \ 435 drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c
index 026a48c95c8f..af2665cf4718 100644
--- a/drivers/gpu/drm/r128/r128_state.c
+++ b/drivers/gpu/drm/r128/r128_state.c
@@ -1244,14 +1244,18 @@ static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple)
1244static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) 1244static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
1245{ 1245{
1246 drm_r128_private_t *dev_priv = dev->dev_private; 1246 drm_r128_private_t *dev_priv = dev->dev_private;
1247 drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; 1247 drm_r128_sarea_t *sarea_priv;
1248 drm_r128_clear_t *clear = data; 1248 drm_r128_clear_t *clear = data;
1249 DRM_DEBUG("\n"); 1249 DRM_DEBUG("\n");
1250 1250
1251 LOCK_TEST_WITH_RETURN(dev, file_priv); 1251 LOCK_TEST_WITH_RETURN(dev, file_priv);
1252 1252
1253 DEV_INIT_TEST_WITH_RETURN(dev_priv);
1254
1253 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1255 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1254 1256
1257 sarea_priv = dev_priv->sarea_priv;
1258
1255 if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) 1259 if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
1256 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; 1260 sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS;
1257 1261
@@ -1312,6 +1316,8 @@ static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *fi
1312 1316
1313 LOCK_TEST_WITH_RETURN(dev, file_priv); 1317 LOCK_TEST_WITH_RETURN(dev, file_priv);
1314 1318
1319 DEV_INIT_TEST_WITH_RETURN(dev_priv);
1320
1315 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1321 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1316 1322
1317 if (!dev_priv->page_flipping) 1323 if (!dev_priv->page_flipping)
@@ -1331,6 +1337,8 @@ static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *fi
1331 1337
1332 LOCK_TEST_WITH_RETURN(dev, file_priv); 1338 LOCK_TEST_WITH_RETURN(dev, file_priv);
1333 1339
1340 DEV_INIT_TEST_WITH_RETURN(dev_priv);
1341
1334 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1342 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1335 1343
1336 if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) 1344 if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS)
@@ -1354,10 +1362,7 @@ static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *
1354 1362
1355 LOCK_TEST_WITH_RETURN(dev, file_priv); 1363 LOCK_TEST_WITH_RETURN(dev, file_priv);
1356 1364
1357 if (!dev_priv) { 1365 DEV_INIT_TEST_WITH_RETURN(dev_priv);
1358 DRM_ERROR("called with no initialization\n");
1359 return -EINVAL;
1360 }
1361 1366
1362 DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", 1367 DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
1363 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); 1368 DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
@@ -1410,10 +1415,7 @@ static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file
1410 1415
1411 LOCK_TEST_WITH_RETURN(dev, file_priv); 1416 LOCK_TEST_WITH_RETURN(dev, file_priv);
1412 1417
1413 if (!dev_priv) { 1418 DEV_INIT_TEST_WITH_RETURN(dev_priv);
1414 DRM_ERROR("called with no initialization\n");
1415 return -EINVAL;
1416 }
1417 1419
1418 DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID, 1420 DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID,
1419 elts->idx, elts->start, elts->end, elts->discard); 1421 elts->idx, elts->start, elts->end, elts->discard);
@@ -1476,6 +1478,8 @@ static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *fi
1476 1478
1477 LOCK_TEST_WITH_RETURN(dev, file_priv); 1479 LOCK_TEST_WITH_RETURN(dev, file_priv);
1478 1480
1481 DEV_INIT_TEST_WITH_RETURN(dev_priv);
1482
1479 DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx); 1483 DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx);
1480 1484
1481 if (blit->idx < 0 || blit->idx >= dma->buf_count) { 1485 if (blit->idx < 0 || blit->idx >= dma->buf_count) {
@@ -1501,6 +1505,8 @@ static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *f
1501 1505
1502 LOCK_TEST_WITH_RETURN(dev, file_priv); 1506 LOCK_TEST_WITH_RETURN(dev, file_priv);
1503 1507
1508 DEV_INIT_TEST_WITH_RETURN(dev_priv);
1509
1504 RING_SPACE_TEST_WITH_RETURN(dev_priv); 1510 RING_SPACE_TEST_WITH_RETURN(dev_priv);
1505 1511
1506 ret = -EINVAL; 1512 ret = -EINVAL;
@@ -1531,6 +1537,8 @@ static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file
1531 1537
1532 LOCK_TEST_WITH_RETURN(dev, file_priv); 1538 LOCK_TEST_WITH_RETURN(dev, file_priv);
1533 1539
1540 DEV_INIT_TEST_WITH_RETURN(dev_priv);
1541
1534 if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) 1542 if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32)))
1535 return -EFAULT; 1543 return -EFAULT;
1536 1544
@@ -1555,10 +1563,7 @@ static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file
1555 1563
1556 LOCK_TEST_WITH_RETURN(dev, file_priv); 1564 LOCK_TEST_WITH_RETURN(dev, file_priv);
1557 1565
1558 if (!dev_priv) { 1566 DEV_INIT_TEST_WITH_RETURN(dev_priv);
1559 DRM_ERROR("called with no initialization\n");
1560 return -EINVAL;
1561 }
1562 1567
1563 DRM_DEBUG("idx=%d s=%d e=%d d=%d\n", 1568 DRM_DEBUG("idx=%d s=%d e=%d d=%d\n",
1564 indirect->idx, indirect->start, indirect->end, 1569 indirect->idx, indirect->start, indirect->end,
@@ -1620,10 +1625,7 @@ static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *fi
1620 drm_r128_getparam_t *param = data; 1625 drm_r128_getparam_t *param = data;
1621 int value; 1626 int value;
1622 1627
1623 if (!dev_priv) { 1628 DEV_INIT_TEST_WITH_RETURN(dev_priv);
1624 DRM_ERROR("called with no initialization\n");
1625 return -EINVAL;
1626 }
1627 1629
1628 DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); 1630 DRM_DEBUG("pid=%d\n", DRM_CURRENTPID);
1629 1631