From: Arnd Bergmann <arnd@arndb.de>
To: Dave Airlie <airlied@gmail.com>
Cc: David Miller <davem@davemloft.net>,
airlied@linux.ie, dri-devel@lists.sourceforge.net,
andi@firstfloor.org, linux-kernel@vger.kernel.org
Subject: Re: is avoiding compat ioctls possible?
Date: Fri, 30 Oct 2009 11:13:42 +0100 [thread overview]
Message-ID: <200910301113.43174.arnd@arndb.de> (raw)
In-Reply-To: <21d7e9970910291813u19cdd361u2facb864db58a712@mail.gmail.com>
On Friday 30 October 2009, Dave Airlie wrote:
> Btw when I mentioned ioctls I meant more than radeon, all the KMS
> ioctls in the common drm_crtc.c file suffer from this problem as well.
>
> Hence why I still believe either my drm specific inline or something
> more generic (granted I can see why a generic solution would be ugly).
>
> You patch below does suffer from a lot of #ifdefs and cut-n-paste
> that is a lot better suited to doing in an inline or macro. We can then
> comment that inline saying if anyone else does this we will be most
> unhappy.
I think it would be better to do a conversion of the pointers in
a separate compat handler, but then call the regular function, which
in case of drm already take a kernel pointer. That would be much simpler
than the compat_alloc_user_space tricks in the current code and
also cleaner than trying to handle both cases in one function using
is_compat_task().
See the (not even compile-tested) example below as an illustration
of what I think you should do. If you convert all functions in
drm_ioc32.c to this scheme, you can replace drm_compat_ioctl and
drm_compat_ioctls[] with drm_generic_compat_ioctl.
Arnd <><
diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c
index 282d9fd..334345b 100644
--- a/drivers/gpu/drm/drm_ioc32.c
+++ b/drivers/gpu/drm/drm_ioc32.c
@@ -1040,6 +1040,122 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
return 0;
}
+static int compat_drm_mode_getblob_ioctl(struct drm_device *dev,
+ struct drm_mode_get_blob __user *out_resp_user,
+ struct drm_file *file_priv)
+{
+ struct drm_mode_get_blob out_resp;
+ int ret;
+
+ ret = copy_from_user(&out_resp, out_resp_user, sizeof(out_resp))
+ if (ret)
+ return -EFAULT;
+
+ out_resp.data = (unsigned long)compat_ptr(out_resp.data);
+
+ ret = drm_mode_getblob_ioctl(dev, &out_resp, file_priv);
+ if (ret)
+ return ret;
+
+ ret = copy_to_user(out_resp_user, &out_resp, sizeof(out_resp))
+ if (ret)
+ return -EFAULT;
+ return 0;
+}
+
+static int compat_drm_mode_gamma_set_ioctl(struct drm_device *dev,
+ struct drm_mode_crtc_lut __user *crtc_lut_user,
+ struct drm_file *file_priv)
+{
+ struct drm_mode_crtc_lut crtc_lut;
+
+ ret = copy_from_user(&crtc_lut, crtc_lut_user, sizeof(crtc_lut))
+ if (ret)
+ return -EFAULT;
+
+ crtc_lut.red = (unsigned long)compat_ptr(crtc_lut.red);
+ crtc_lut.green = (unsigned long)compat_ptr(crtc_lut.green);
+ crtc_lut.blue = (unsigned long)compat_ptr(crtc_lut.blue);
+
+ ret = drm_mode_gamma_set_ioctl(dev, &crtc_lut, file_priv);
+
+ return ret;
+}
+
+static int compat_drm_mode_gamma_get_ioctl(struct drm_device *dev,
+ struct drm_mode_crtc_lut __user *crtc_lut_user,
+ struct drm_file *file_priv)
+{
+ struct drm_mode_crtc_lut crtc_lut;
+
+ ret = copy_from_user(&crtc_lut, crtc_lut_user, sizeof(crtc_lut))
+ if (ret)
+ return -EFAULT;
+
+ crtc_lut.red = (unsigned long)compat_ptr(crtc_lut.red);
+ crtc_lut.green = (unsigned long)compat_ptr(crtc_lut.green);
+ crtc_lut.blue = (unsigned long)compat_ptr(crtc_lut.blue);
+
+ ret = drm_mode_gamma_get_ioctl(dev, &crtc_lut, file_priv);
+
+ return ret;
+}
+
+static int drm_generic_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct drm_file *file_priv = filp->private_data;
+ struct drm_device *dev = file_priv->minor->dev;
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ int ret;
+
+ atomic_inc(&dev->ioctl_count);
+ atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
+ ++file_priv->ioctl_count;
+
+ if ((nr >= DRM_CORE_IOCTL_COUNT) &&
+ ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END)))
+ goto err_i1;
+ if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) &&
+ (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls))
+ ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+ else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) {
+ ioctl = &drm_ioctls[nr];
+ cmd = ioctl->cmd;
+ } else
+ goto err_i1;
+
+ if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
+ ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
+ ((ioctl->flags & DRM_MASTER) && !file_priv->is_master) ||
+ (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL))) {
+ ret = -EACCES;
+ goto err_il;
+ }
+
+ switch (cmd) {
+ case DRM_IOCTL_MODE_GETPROPBLOB:
+ ret = compat_drm_mode_getblob_ioctl(dev,
+ compat_ptr(arg), file_priv);
+ break;
+
+ case DRM_IOCTL_MODE_GETGAMMA:
+ ret = compat_drm_mode_gamma_set_ioctl(dev,
+ compat_ptr(arg), file_priv);
+ break;
+
+ case DRM_IOCTL_MODE_GETGAMMA:
+ ret = compat_drm_mode_gamma_get_ioctl(dev,
+ compat_ptr(arg), file_priv);
+ break;
+ }
+
+ err_i1:
+ atomic_dec(&dev->ioctl_count);
+
+ return ret;
+}
+
drm_ioctl_compat_t *drm_compat_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
@@ -1072,6 +1188,9 @@ drm_ioctl_compat_t *drm_compat_ioctls[] = {
[DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW32)] = compat_drm_update_draw,
#endif
[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
+ [DRM_IOCTL_MODE_GETPROPBLOB] = drm_generic_compat_ioctl,
+ [DRM_IOCTL_MODE_GETGAMMA] = drm_generic_compat_ioctl,
+ [DRM_IOCTL_MODE_SETGAMMA] = drm_generic_compat_ioctl,
};
/**
next prev parent reply other threads:[~2009-10-30 10:13 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-28 1:22 is avoiding compat ioctls possible? Dave Airlie
2009-10-28 2:25 ` David Miller
2009-10-28 3:01 ` Dave Airlie
2009-10-28 2:53 ` Andi Kleen
2009-10-28 3:05 ` Dave Airlie
2009-10-28 3:19 ` Andi Kleen
2009-10-28 3:28 ` Dave Airlie
2009-10-28 3:34 ` Andi Kleen
2009-10-28 3:43 ` David Miller
2009-10-28 3:41 ` David Miller
2009-10-28 21:05 ` Maciej W. Rozycki
2009-10-29 8:27 ` Arnd Bergmann
2009-10-28 3:38 ` David Miller
2009-10-28 3:43 ` Dave Airlie
2009-10-28 3:45 ` David Miller
2009-10-28 3:51 ` Andi Kleen
2009-10-28 3:54 ` Dave Airlie
2009-10-28 5:28 ` David Miller
2009-10-28 5:42 ` Dave Airlie
2009-10-28 6:04 ` David Miller
2009-10-28 7:53 ` David Miller
2009-10-28 7:59 ` Andi Kleen
2009-10-28 8:11 ` David Miller
2009-10-28 8:19 ` Andi Kleen
2009-10-28 8:28 ` David Miller
2009-10-28 12:13 ` Arnd Bergmann
2009-10-28 12:16 ` David Miller
2009-10-28 15:40 ` Arnd Bergmann
2009-10-29 5:41 ` David Miller
2009-10-29 8:16 ` Arnd Bergmann
2009-10-29 8:34 ` Heiko Carstens
2009-10-29 8:39 ` David Miller
2009-10-28 12:17 ` David Miller
2009-10-30 1:13 ` Dave Airlie
2009-10-30 10:13 ` Arnd Bergmann [this message]
2009-11-18 0:26 ` Dave Airlie
2009-11-18 9:09 ` Andi Kleen
2009-11-18 14:42 ` Arnd Bergmann
2009-10-28 3:37 ` David Miller
2009-10-28 4:36 ` Andi Kleen
2009-10-28 5:29 ` David Miller
2009-10-28 10:27 ` Arnd Bergmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200910301113.43174.arnd@arndb.de \
--to=arnd@arndb.de \
--cc=airlied@gmail.com \
--cc=airlied@linux.ie \
--cc=andi@firstfloor.org \
--cc=davem@davemloft.net \
--cc=dri-devel@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.