diff options
Diffstat (limited to 'drivers/gpu/drm/drm_drv.c')
| -rw-r--r-- | drivers/gpu/drm/drm_drv.c | 25 |
1 files changed, 19 insertions, 6 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 90288ec7c284..84da748555bc 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c | |||
| @@ -55,6 +55,9 @@ | |||
| 55 | static int drm_version(struct drm_device *dev, void *data, | 55 | static int drm_version(struct drm_device *dev, void *data, |
| 56 | struct drm_file *file_priv); | 56 | struct drm_file *file_priv); |
| 57 | 57 | ||
| 58 | #define DRM_IOCTL_DEF(ioctl, _func, _flags) \ | ||
| 59 | [DRM_IOCTL_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0} | ||
| 60 | |||
| 58 | /** Ioctl table */ | 61 | /** Ioctl table */ |
| 59 | static struct drm_ioctl_desc drm_ioctls[] = { | 62 | static struct drm_ioctl_desc drm_ioctls[] = { |
| 60 | DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0), | 63 | DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0), |
| @@ -421,6 +424,7 @@ long drm_ioctl(struct file *filp, | |||
| 421 | int retcode = -EINVAL; | 424 | int retcode = -EINVAL; |
| 422 | char stack_kdata[128]; | 425 | char stack_kdata[128]; |
| 423 | char *kdata = NULL; | 426 | char *kdata = NULL; |
| 427 | unsigned int usize, asize; | ||
| 424 | 428 | ||
| 425 | dev = file_priv->minor->dev; | 429 | dev = file_priv->minor->dev; |
| 426 | atomic_inc(&dev->ioctl_count); | 430 | atomic_inc(&dev->ioctl_count); |
| @@ -436,11 +440,18 @@ long drm_ioctl(struct file *filp, | |||
| 436 | ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) | 440 | ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) |
| 437 | goto err_i1; | 441 | goto err_i1; |
| 438 | if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) && | 442 | if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) && |
| 439 | (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) | 443 | (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) { |
| 444 | u32 drv_size; | ||
| 440 | ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; | 445 | ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE]; |
| 446 | drv_size = _IOC_SIZE(ioctl->cmd_drv); | ||
| 447 | usize = asize = _IOC_SIZE(cmd); | ||
| 448 | if (drv_size > asize) | ||
| 449 | asize = drv_size; | ||
| 450 | } | ||
| 441 | else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) { | 451 | else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) { |
| 442 | ioctl = &drm_ioctls[nr]; | 452 | ioctl = &drm_ioctls[nr]; |
| 443 | cmd = ioctl->cmd; | 453 | cmd = ioctl->cmd; |
| 454 | usize = asize = _IOC_SIZE(cmd); | ||
| 444 | } else | 455 | } else |
| 445 | goto err_i1; | 456 | goto err_i1; |
| 446 | 457 | ||
| @@ -460,10 +471,10 @@ long drm_ioctl(struct file *filp, | |||
| 460 | retcode = -EACCES; | 471 | retcode = -EACCES; |
| 461 | } else { | 472 | } else { |
| 462 | if (cmd & (IOC_IN | IOC_OUT)) { | 473 | if (cmd & (IOC_IN | IOC_OUT)) { |
| 463 | if (_IOC_SIZE(cmd) <= sizeof(stack_kdata)) { | 474 | if (asize <= sizeof(stack_kdata)) { |
| 464 | kdata = stack_kdata; | 475 | kdata = stack_kdata; |
| 465 | } else { | 476 | } else { |
| 466 | kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); | 477 | kdata = kmalloc(asize, GFP_KERNEL); |
| 467 | if (!kdata) { | 478 | if (!kdata) { |
| 468 | retcode = -ENOMEM; | 479 | retcode = -ENOMEM; |
| 469 | goto err_i1; | 480 | goto err_i1; |
| @@ -473,11 +484,13 @@ long drm_ioctl(struct file *filp, | |||
| 473 | 484 | ||
| 474 | if (cmd & IOC_IN) { | 485 | if (cmd & IOC_IN) { |
| 475 | if (copy_from_user(kdata, (void __user *)arg, | 486 | if (copy_from_user(kdata, (void __user *)arg, |
| 476 | _IOC_SIZE(cmd)) != 0) { | 487 | usize) != 0) { |
| 477 | retcode = -EFAULT; | 488 | retcode = -EFAULT; |
| 478 | goto err_i1; | 489 | goto err_i1; |
| 479 | } | 490 | } |
| 480 | } | 491 | } else |
| 492 | memset(kdata, 0, usize); | ||
| 493 | |||
| 481 | if (ioctl->flags & DRM_UNLOCKED) | 494 | if (ioctl->flags & DRM_UNLOCKED) |
| 482 | retcode = func(dev, kdata, file_priv); | 495 | retcode = func(dev, kdata, file_priv); |
| 483 | else { | 496 | else { |
| @@ -488,7 +501,7 @@ long drm_ioctl(struct file *filp, | |||
| 488 | 501 | ||
| 489 | if (cmd & IOC_OUT) { | 502 | if (cmd & IOC_OUT) { |
| 490 | if (copy_to_user((void __user *)arg, kdata, | 503 | if (copy_to_user((void __user *)arg, kdata, |
| 491 | _IOC_SIZE(cmd)) != 0) | 504 | usize) != 0) |
| 492 | retcode = -EFAULT; | 505 | retcode = -EFAULT; |
| 493 | } | 506 | } |
| 494 | } | 507 | } |
