diff options
Diffstat (limited to 'drivers/gpu/drm/drm_ioctl.c')
-rw-r--r-- | drivers/gpu/drm/drm_ioctl.c | 93 |
1 files changed, 69 insertions, 24 deletions
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index d93e7378c..8ce2a0c59 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -40,7 +40,7 @@ static int drm_version(struct drm_device *dev, void *data, struct drm_file *file_priv); -/** +/* * Get the bus id. * * \param inode device inode. @@ -75,7 +75,7 @@ drm_unset_busid(struct drm_device *dev, master->unique_len = 0; } -/** +/* * Set the bus id. * * \param inode device inode. @@ -149,7 +149,7 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv) return 0; } -/** +/* * Get a mapping information. * * \param inode device inode. @@ -201,7 +201,7 @@ static int drm_getmap(struct drm_device *dev, void *data, return 0; } -/** +/* * Get client information. * * \param inode device inode. @@ -244,7 +244,7 @@ static int drm_getclient(struct drm_device *dev, void *data, } } -/** +/* * Get statistics information. * * \param inode device inode. @@ -265,7 +265,7 @@ static int drm_getstats(struct drm_device *dev, void *data, return 0; } -/** +/* * Get device/driver capabilities */ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -318,7 +318,7 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ return 0; } -/** +/* * Set device/driver capabilities */ static int @@ -352,7 +352,7 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) return 0; } -/** +/* * Setversion ioctl. * * \param inode device inode. @@ -406,7 +406,18 @@ done: return retcode; } -/** No-op ioctl. */ +/** + * drm_noop - DRM no-op ioctl implemntation + * @dev: DRM device for the ioctl + * @data: data pointer for the ioctl + * @file_priv: DRM file for the ioctl call + * + * This no-op implementation for drm ioctls is useful for deprecated + * functionality where we can't return a failure code because existing userspace + * checks the result of the ioctl, but doesn't care about the action. + * + * Always returns successfully with 0. + */ int drm_noop(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -416,6 +427,28 @@ int drm_noop(struct drm_device *dev, void *data, EXPORT_SYMBOL(drm_noop); /** + * drm_invalid_op - DRM invalid ioctl implemntation + * @dev: DRM device for the ioctl + * @data: data pointer for the ioctl + * @file_priv: DRM file for the ioctl call + * + * This no-op implementation for drm ioctls is useful for deprecated + * functionality where we really don't want to allow userspace to call the ioctl + * any more. This is the case for old ums interfaces for drivers that + * transitioned to kms gradually and so kept the old legacy tables around. This + * only applies to radeon and i915 kms drivers, other drivers shouldn't need to + * use this function. + * + * Always fails with a return value of -EINVAL. + */ +int drm_invalid_op(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + return -EINVAL; +} +EXPORT_SYMBOL(drm_invalid_op); + +/* * Copy and IOCTL return string to user space */ static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value) @@ -438,7 +471,7 @@ static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value) return 0; } -/** +/* * Get version information * * \param inode device inode. @@ -470,7 +503,7 @@ static int drm_version(struct drm_device *dev, void *data, return err; } -/** +/* * drm_ioctl_permit - Check ioctl permissions against caller * * @flags: ioctl permission flags. @@ -518,7 +551,7 @@ EXPORT_SYMBOL(drm_ioctl_permit); .name = #ioctl \ } -/** Ioctl table */ +/* Ioctl table */ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW), @@ -571,7 +604,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), -#if __OS_HAS_AGP +#if IS_ENABLED(CONFIG_AGP) DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), @@ -635,16 +668,16 @@ static const struct drm_ioctl_desc drm_ioctls[] = { #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) /** - * Called whenever a process performs an ioctl on /dev/drm. - * - * \param inode device inode. - * \param file_priv DRM file private. - * \param cmd command. - * \param arg user argument. - * \return zero on success or negative number on failure. + * drm_ioctl - ioctl callback implementation for DRM drivers + * @filp: file this ioctl is called on + * @cmd: ioctl cmd number + * @arg: user argument * * Looks up the ioctl function in the ::ioctls table, checking for root * previleges if so required, and dispatches to the respective function. + * + * Returns: + * Zero on success, negative error code on failure. */ long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) @@ -658,13 +691,16 @@ long drm_ioctl(struct file *filp, char stack_kdata[128]; char *kdata = NULL; unsigned int usize, asize, drv_size; + bool is_driver_ioctl; dev = file_priv->minor->dev; if (drm_device_is_unplugged(dev)) return -ENODEV; - if (nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END) { + is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END; + + if (is_driver_ioctl) { /* driver ioctl */ if (nr - DRM_COMMAND_BASE >= dev->driver->num_ioctls) goto err_i1; @@ -723,7 +759,10 @@ long drm_ioctl(struct file *filp, memset(kdata, 0, usize); } - if (ioctl->flags & DRM_UNLOCKED) + /* Enforce sane locking for kms driver ioctls. Core ioctls are + * too messy still. */ + if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) || + (ioctl->flags & DRM_UNLOCKED)) retcode = func(dev, kdata, file_priv); else { mutex_lock(&drm_global_mutex); @@ -754,9 +793,15 @@ EXPORT_SYMBOL(drm_ioctl); /** * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags + * @nr: ioctl number + * @flags: where to return the ioctl permission flags + * + * This ioctl is only used by the vmwgfx driver to augment the access checks + * done by the drm core and insofar a pretty decent layering violation. This + * shouldn't be used by any drivers. * - * @nr: Ioctl number. - * @flags: Where to return the ioctl permission flags + * Returns: + * True if the @nr corresponds to a DRM core ioctl numer, false otherwise. */ bool drm_ioctl_flags(unsigned int nr, unsigned int *flags) { |