[PATCH] drm: Don't overwrite user ioctl arg unless requested

Daniel Vetter daniel at ffwll.ch
Thu Jul 14 08:13:17 UTC 2016


On Thu, Jul 14, 2016 at 09:46:24AM +0200, Christian König wrote:
> Am 12.07.2016 um 16:59 schrieb Chris Wilson:
> > Currently, we completely ignore the user when it comes to the in/out
> > direction of the ioctl argument, as we simply cannot trust userspace.
> > (For example, they might request a copy of the modified ioctl argument
> > when the driver is not expecting such and so leak kernel stack.)
> > However, blindly copying over the target address may also lead to a
> > spurious EFAULT, and a failure after the ioctl was completed
> > successfully. This is important in order to avoid an ABI break when
> > extending an ioctl from IOR to IORW. Similar to how we only copy the
> > intersection of the kernel arg size and the user arg size, we only want
> > to copy back the kernel arg data iff both the kernel and userspace
> > request the copy.
> > 
> > Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
> 
> Seems to make a lot of sense to me, patch is Reviewed-by: Christian König
> <christian.koenig at amd.com>

Applied to drm-misc, thanks.
-Daniel

> 
> Regards,
> Christian.
> 
> > ---
> >   drivers/gpu/drm/drm_ioctl.c | 50 ++++++++++++++++++++-------------------------
> >   1 file changed, 22 insertions(+), 28 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
> > index 2c87c1df0910..33af4a5ddca1 100644
> > --- a/drivers/gpu/drm/drm_ioctl.c
> > +++ b/drivers/gpu/drm/drm_ioctl.c
> > @@ -648,7 +648,7 @@ long drm_ioctl(struct file *filp,
> >   	int retcode = -EINVAL;
> >   	char stack_kdata[128];
> >   	char *kdata = NULL;
> > -	unsigned int usize, asize, drv_size;
> > +	unsigned int in_size, out_size, drv_size, ksize;
> >   	bool is_driver_ioctl;
> >   	dev = file_priv->minor->dev;
> > @@ -671,9 +671,12 @@ long drm_ioctl(struct file *filp,
> >   	}
> >   	drv_size = _IOC_SIZE(ioctl->cmd);
> > -	usize = _IOC_SIZE(cmd);
> > -	asize = max(usize, drv_size);
> > -	cmd = ioctl->cmd;
> > +	out_size = in_size = _IOC_SIZE(cmd);
> > +	if ((cmd & ioctl->cmd & IOC_IN) == 0)
> > +		in_size = 0;
> > +	if ((cmd & ioctl->cmd & IOC_OUT) == 0)
> > +		out_size = 0;
> > +	ksize = max(max(in_size, out_size), drv_size);
> >   	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
> >   		  task_pid_nr(current),
> > @@ -693,30 +696,24 @@ long drm_ioctl(struct file *filp,
> >   	if (unlikely(retcode))
> >   		goto err_i1;
> > -	if (cmd & (IOC_IN | IOC_OUT)) {
> > -		if (asize <= sizeof(stack_kdata)) {
> > -			kdata = stack_kdata;
> > -		} else {
> > -			kdata = kmalloc(asize, GFP_KERNEL);
> > -			if (!kdata) {
> > -				retcode = -ENOMEM;
> > -				goto err_i1;
> > -			}
> > +	if (ksize <= sizeof(stack_kdata)) {
> > +		kdata = stack_kdata;
> > +	} else {
> > +		kdata = kmalloc(ksize, GFP_KERNEL);
> > +		if (!kdata) {
> > +			retcode = -ENOMEM;
> > +			goto err_i1;
> >   		}
> > -		if (asize > usize)
> > -			memset(kdata + usize, 0, asize - usize);
> >   	}
> > -	if (cmd & IOC_IN) {
> > -		if (copy_from_user(kdata, (void __user *)arg,
> > -				   usize) != 0) {
> > -			retcode = -EFAULT;
> > -			goto err_i1;
> > -		}
> > -	} else if (cmd & IOC_OUT) {
> > -		memset(kdata, 0, usize);
> > +	if (copy_from_user(kdata, (void __user *)arg, in_size) != 0) {
> > +		retcode = -EFAULT;
> > +		goto err_i1;
> >   	}
> > +	if (ksize > in_size)
> > +		memset(kdata + in_size, 0, ksize - in_size);
> > +
> >   	/* Enforce sane locking for kms driver ioctls. Core ioctls are
> >   	 * too messy still. */
> >   	if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) ||
> > @@ -728,11 +725,8 @@ long drm_ioctl(struct file *filp,
> >   		mutex_unlock(&drm_global_mutex);
> >   	}
> > -	if (cmd & IOC_OUT) {
> > -		if (copy_to_user((void __user *)arg, kdata,
> > -				 usize) != 0)
> > -			retcode = -EFAULT;
> > -	}
> > +	if (copy_to_user((void __user *)arg, kdata, out_size) != 0)
> > +		retcode = -EFAULT;
> >         err_i1:
> >   	if (!ioctl)
> 
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the dri-devel mailing list