Blob Blame History Raw
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Sat, 3 Jun 2017 21:33:26 -0400
Subject: mga: switch compat ioctls to drm_ioctl_kernel()
Git-commit: aeba03903063e9fea885d32318e1546d9b7e83a8
Patch-mainline: v4.13-rc1
References: FATE#326289 FATE#326079 FATE#326049 FATE#322398 FATE#326166

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/gpu/drm/drm_ioctl.c     |    1 
 drivers/gpu/drm/mga/mga_drv.h   |    2 
 drivers/gpu/drm/mga/mga_ioc32.c |  145 ++++++++++++++++------------------------
 drivers/gpu/drm/mga/mga_state.c |    2 
 4 files changed, 62 insertions(+), 88 deletions(-)

--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -719,6 +719,7 @@ long drm_ioctl_kernel(struct file *file,
 	}
 	return retcode;
 }
+EXPORT_SYMBOL(drm_ioctl_kernel);
 
 /**
  * drm_ioctl - ioctl callback implementation for DRM drivers
--- a/drivers/gpu/drm/mga/mga_drv.h
+++ b/drivers/gpu/drm/mga/mga_drv.h
@@ -159,6 +159,8 @@ extern int mga_dma_bootstrap(struct drm_
 			     struct drm_file *file_priv);
 extern int mga_dma_init(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
+extern int mga_getparam(struct drm_device *dev, void *data,
+			struct drm_file *file_priv);
 extern int mga_dma_flush(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 extern int mga_dma_reset(struct drm_device *dev, void *data,
--- a/drivers/gpu/drm/mga/mga_ioc32.c
+++ b/drivers/gpu/drm/mga/mga_ioc32.c
@@ -61,46 +61,25 @@ static int compat_mga_init(struct file *
 			   unsigned long arg)
 {
 	drm_mga_init32_t init32;
-	drm_mga_init_t __user *init;
-	int err = 0, i;
+	drm_mga_init_t init;
 
 	if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
 		return -EFAULT;
 
-	init = compat_alloc_user_space(sizeof(*init));
-	if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
-	    || __put_user(init32.func, &init->func)
-	    || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
-	    || __put_user(init32.chipset, &init->chipset)
-	    || __put_user(init32.sgram, &init->sgram)
-	    || __put_user(init32.maccess, &init->maccess)
-	    || __put_user(init32.fb_cpp, &init->fb_cpp)
-	    || __put_user(init32.front_offset, &init->front_offset)
-	    || __put_user(init32.front_pitch, &init->front_pitch)
-	    || __put_user(init32.back_offset, &init->back_offset)
-	    || __put_user(init32.back_pitch, &init->back_pitch)
-	    || __put_user(init32.depth_cpp, &init->depth_cpp)
-	    || __put_user(init32.depth_offset, &init->depth_offset)
-	    || __put_user(init32.depth_pitch, &init->depth_pitch)
-	    || __put_user(init32.fb_offset, &init->fb_offset)
-	    || __put_user(init32.mmio_offset, &init->mmio_offset)
-	    || __put_user(init32.status_offset, &init->status_offset)
-	    || __put_user(init32.warp_offset, &init->warp_offset)
-	    || __put_user(init32.primary_offset, &init->primary_offset)
-	    || __put_user(init32.buffers_offset, &init->buffers_offset))
-		return -EFAULT;
+	init.func = init32.func;
+	init.sarea_priv_offset = init32.sarea_priv_offset;
+	memcpy(&init.chipset, &init32.chipset,
+		offsetof(drm_mga_init_t, fb_offset) -
+		offsetof(drm_mga_init_t, chipset));
+	init.fb_offset = init32.fb_offset;
+	init.mmio_offset = init32.mmio_offset;
+	init.status_offset = init32.status_offset;
+	init.warp_offset = init32.warp_offset;
+	init.primary_offset = init32.primary_offset;
+	init.buffers_offset = init32.buffers_offset;
 
-	for (i = 0; i < MGA_NR_TEX_HEAPS; i++) {
-		err |=
-		    __put_user(init32.texture_offset[i],
-			       &init->texture_offset[i]);
-		err |=
-		    __put_user(init32.texture_size[i], &init->texture_size[i]);
-	}
-	if (err)
-		return -EFAULT;
-
-	return drm_ioctl(file, DRM_IOCTL_MGA_INIT, (unsigned long)init);
+	return drm_ioctl_kernel(file, mga_dma_init, &init,
+				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
 }
 
 typedef struct drm_mga_getparam32 {
@@ -112,19 +91,14 @@ static int compat_mga_getparam(struct fi
 			       unsigned long arg)
 {
 	drm_mga_getparam32_t getparam32;
-	drm_mga_getparam_t __user *getparam;
+	drm_mga_getparam_t getparam;
 
 	if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
 		return -EFAULT;
 
-	getparam = compat_alloc_user_space(sizeof(*getparam));
-	if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
-	    || __put_user(getparam32.param, &getparam->param)
-	    || __put_user((void __user *)(unsigned long)getparam32.value,
-			  &getparam->value))
-		return -EFAULT;
-
-	return drm_ioctl(file, DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
+	getparam.param = getparam32.param;
+	getparam.value = compat_ptr(getparam32.value);
+	return drm_ioctl_kernel(file, mga_getparam, &getparam, DRM_AUTH);
 }
 
 typedef struct drm_mga_drm_bootstrap32 {
@@ -141,48 +115,33 @@ static int compat_mga_dma_bootstrap(stru
 				    unsigned long arg)
 {
 	drm_mga_dma_bootstrap32_t dma_bootstrap32;
-	drm_mga_dma_bootstrap_t __user *dma_bootstrap;
+	drm_mga_dma_bootstrap_t __user dma_bootstrap;
 	int err;
 
 	if (copy_from_user(&dma_bootstrap32, (void __user *)arg,
 			   sizeof(dma_bootstrap32)))
 		return -EFAULT;
 
-	dma_bootstrap = compat_alloc_user_space(sizeof(*dma_bootstrap));
-	if (!access_ok(VERIFY_WRITE, dma_bootstrap, sizeof(*dma_bootstrap))
-	    || __put_user(dma_bootstrap32.texture_handle,
-			  &dma_bootstrap->texture_handle)
-	    || __put_user(dma_bootstrap32.texture_size,
-			  &dma_bootstrap->texture_size)
-	    || __put_user(dma_bootstrap32.primary_size,
-			  &dma_bootstrap->primary_size)
-	    || __put_user(dma_bootstrap32.secondary_bin_count,
-			  &dma_bootstrap->secondary_bin_count)
-	    || __put_user(dma_bootstrap32.secondary_bin_size,
-			  &dma_bootstrap->secondary_bin_size)
-	    || __put_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
-	    || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
-		return -EFAULT;
+	dma_bootstrap.texture_handle = dma_bootstrap32.texture_handle;
+	dma_bootstrap.texture_size = dma_bootstrap32.texture_size;
+	dma_bootstrap.primary_size = dma_bootstrap32.primary_size;
+	dma_bootstrap.secondary_bin_count = dma_bootstrap32.secondary_bin_count;
+	dma_bootstrap.secondary_bin_size = dma_bootstrap32.secondary_bin_size;
+	dma_bootstrap.agp_mode = dma_bootstrap32.agp_mode;
+	dma_bootstrap.agp_size = dma_bootstrap32.agp_size;
 
-	err = drm_ioctl(file, DRM_IOCTL_MGA_DMA_BOOTSTRAP,
-			(unsigned long)dma_bootstrap);
+	err = drm_ioctl_kernel(file, mga_dma_bootstrap, &dma_bootstrap,
+				DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY);
 	if (err)
 		return err;
 
-	if (__get_user(dma_bootstrap32.texture_handle,
-		       &dma_bootstrap->texture_handle)
-	    || __get_user(dma_bootstrap32.texture_size,
-			  &dma_bootstrap->texture_size)
-	    || __get_user(dma_bootstrap32.primary_size,
-			  &dma_bootstrap->primary_size)
-	    || __get_user(dma_bootstrap32.secondary_bin_count,
-			  &dma_bootstrap->secondary_bin_count)
-	    || __get_user(dma_bootstrap32.secondary_bin_size,
-			  &dma_bootstrap->secondary_bin_size)
-	    || __get_user(dma_bootstrap32.agp_mode, &dma_bootstrap->agp_mode)
-	    || __get_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size))
-		return -EFAULT;
-
+	dma_bootstrap32.texture_handle = dma_bootstrap.texture_handle;
+	dma_bootstrap32.texture_size = dma_bootstrap.texture_size;
+	dma_bootstrap32.primary_size = dma_bootstrap.primary_size;
+	dma_bootstrap32.secondary_bin_count = dma_bootstrap.secondary_bin_count;
+	dma_bootstrap32.secondary_bin_size = dma_bootstrap.secondary_bin_size;
+	dma_bootstrap32.agp_mode = dma_bootstrap.agp_mode;
+	dma_bootstrap32.agp_size = dma_bootstrap.agp_size;
 	if (copy_to_user((void __user *)arg, &dma_bootstrap32,
 			 sizeof(dma_bootstrap32)))
 		return -EFAULT;
@@ -190,10 +149,14 @@ static int compat_mga_dma_bootstrap(stru
 	return 0;
 }
 
-drm_ioctl_compat_t *mga_compat_ioctls[] = {
-	[DRM_MGA_INIT] = compat_mga_init,
-	[DRM_MGA_GETPARAM] = compat_mga_getparam,
-	[DRM_MGA_DMA_BOOTSTRAP] = compat_mga_dma_bootstrap,
+static struct {
+	drm_ioctl_compat_t *fn;
+	char *name;
+} mga_compat_ioctls[] = {
+#define DRM_IOCTL32_DEF(n, f)[DRM_##n] = {.fn = f, .name = #n}
+	DRM_IOCTL32_DEF(MGA_INIT, compat_mga_init),
+	DRM_IOCTL32_DEF(MGA_GETPARAM, compat_mga_getparam),
+	DRM_IOCTL32_DEF(MGA_DMA_BOOTSTRAP, compat_mga_dma_bootstrap),
 };
 
 /**
@@ -208,19 +171,27 @@ drm_ioctl_compat_t *mga_compat_ioctls[]
 long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	unsigned int nr = DRM_IOCTL_NR(cmd);
+	struct drm_file *file_priv = filp->private_data;
 	drm_ioctl_compat_t *fn = NULL;
 	int ret;
 
 	if (nr < DRM_COMMAND_BASE)
 		return drm_compat_ioctl(filp, cmd, arg);
 
-	if (nr < DRM_COMMAND_BASE + ARRAY_SIZE(mga_compat_ioctls))
-		fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
-
-	if (fn != NULL)
-		ret = (*fn) (filp, cmd, arg);
-	else
-		ret = drm_ioctl(filp, cmd, arg);
+	if (nr >= DRM_COMMAND_BASE + ARRAY_SIZE(mga_compat_ioctls))
+		return drm_ioctl(filp, cmd, arg);
 
+	fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE].fn;
+	if (!fn)
+		return drm_ioctl(filp, cmd, arg);
+
+	DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
+		  task_pid_nr(current),
+		  (long)old_encode_dev(file_priv->minor->kdev->devt),
+		  file_priv->authenticated,
+		  mga_compat_ioctls[nr - DRM_COMMAND_BASE].name);
+	ret = (*fn) (filp, cmd, arg);
+	if (ret)
+		DRM_DEBUG("ret = %d\n", ret);
 	return ret;
 }
--- a/drivers/gpu/drm/mga/mga_state.c
+++ b/drivers/gpu/drm/mga/mga_state.c
@@ -1005,7 +1005,7 @@ static int mga_dma_blit(struct drm_devic
 	return 0;
 }
 
-static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
+int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_getparam_t *param = data;