public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] hiddev: Add 32bit ioctl compatibilty
@ 2007-10-12 23:51 Philip Langdale
  2007-10-13  0:02 ` Al Viro
  0 siblings, 1 reply; 7+ messages in thread
From: Philip Langdale @ 2007-10-12 23:51 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: LKML

The hiddev driver currently lacks 32bit ioctl compatibility, so
if you're running with a 64bit kernel and 32bit userspace, it won't
work.

I'm pretty sure that the only thing missing is a compat_ioctl
implementation as all structs have fixed size fields.

With this change I can use revoco to configure my MX Revolution mouse.

Signed-off-by: Philip Langdale <philipl@overt.org>

--- linux-2.6.23/drivers/hid/usbhid/hiddev.c	2007-10-09 13:31:38.000000000 -0700
+++ linux-phil/drivers/hid/usbhid/hiddev.c	2007-10-12 15:02:15.000000000 -0700
@@ -34,6 +34,7 @@
 #include <linux/usb.h>
 #include <linux/hid.h>
 #include <linux/hiddev.h>
+#include <linux/compat.h>
 #include "usbhid.h"

 #ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -738,6 +738,14 @@
 	return -EINVAL;
 }

+#ifdef CONFIG_COMPAT
+static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	return hiddev_ioctl(inode, file, cmd, compat_ptr(arg));
+}
+#endif
+
 static const struct file_operations hiddev_fops = {
 	.owner =	THIS_MODULE,
 	.read =		hiddev_read,
@@ -747,6 +754,9 @@
 	.release =	hiddev_release,
 	.ioctl =	hiddev_ioctl,
 	.fasync =	hiddev_fasync,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= hiddev_compat_ioctl,
+#endif
 };

 static struct usb_class_driver hiddev_class = {

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] hiddev: Add 32bit ioctl compatibilty
  2007-10-12 23:51 [PATCH] hiddev: Add 32bit ioctl compatibilty Philip Langdale
@ 2007-10-13  0:02 ` Al Viro
  2007-10-13 17:42   ` Philip Langdale
  2007-10-20 15:50   ` [PATCH] compat_ioctl: introduce generic_compat_ioctl helper Arnd Bergmann
  0 siblings, 2 replies; 7+ messages in thread
From: Al Viro @ 2007-10-13  0:02 UTC (permalink / raw)
  To: Philip Langdale; +Cc: Jiri Kosina, LKML

On Fri, Oct 12, 2007 at 04:51:00PM -0700, Philip Langdale wrote:
> The hiddev driver currently lacks 32bit ioctl compatibility, so
> if you're running with a 64bit kernel and 32bit userspace, it won't
> work.
> 
> I'm pretty sure that the only thing missing is a compat_ioctl
> implementation as all structs have fixed size fields.
> 
> +static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
> +{
> +	struct inode *inode = file->f_path.dentry->d_inode;
> +	return hiddev_ioctl(inode, file, cmd, compat_ptr(arg));
> +}

Just how many instances of that sucker do we need?  It's nothing but

     struct inode *inode = file->f_path.dentry->d_inode;
     return file->f_op->ioctl(inode, file, cmd, compat_ptr(arg));

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] hiddev: Add 32bit ioctl compatibilty
  2007-10-13  0:02 ` Al Viro
@ 2007-10-13 17:42   ` Philip Langdale
  2007-10-20 15:50   ` [PATCH] compat_ioctl: introduce generic_compat_ioctl helper Arnd Bergmann
  1 sibling, 0 replies; 7+ messages in thread
From: Philip Langdale @ 2007-10-13 17:42 UTC (permalink / raw)
  To: Al Viro; +Cc: Jiri Kosina, LKML

Al Viro wrote:
>>
>> +static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
>> +{
>> +	struct inode *inode = file->f_path.dentry->d_inode;
>> +	return hiddev_ioctl(inode, file, cmd, compat_ptr(arg));
>> +}
> 
> Just how many instances of that sucker do we need?  It's nothing but
> 
>      struct inode *inode = file->f_path.dentry->d_inode;
>      return file->f_op->ioctl(inode, file, cmd, compat_ptr(arg));
> 

So, I don't actually know what you're looking for, but of the 140 occasions
that .compat_ioctl is implemented in Linus' tree, I can't find another one
that actually uses this form. So, writing a shared implementation doesn't pick
off any low hanging fruit. Now, it's possible that some of the other implementations
could be reduced to this form - but for now, it seems the answer to your question
is 'one' in either case. :-)

--phil

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH] compat_ioctl: introduce generic_compat_ioctl helper
  2007-10-13  0:02 ` Al Viro
  2007-10-13 17:42   ` Philip Langdale
@ 2007-10-20 15:50   ` Arnd Bergmann
  2007-10-20 16:03     ` [PATCH] hiddev: simplify 32bit ioctl compatibilty Arnd Bergmann
  2007-10-20 16:11     ` [PATCH] compat_ioctl: introduce generic_compat_ioctl helper Christoph Hellwig
  1 sibling, 2 replies; 7+ messages in thread
From: Arnd Bergmann @ 2007-10-20 15:50 UTC (permalink / raw)
  To: Al Viro; +Cc: Philip Langdale, Jiri Kosina, LKML

Many drivers use only compatible ioctl numbers. In order to
avoid having to write a special compat_ioctl handler for each
of them or listing every ioctl number in fs/compat_ioctl.c,
let's introduce a generic handler that simply calls the
driver specific f_op->unlocked_ioctl() or f_op->ioctl() handler.

Signed-off-by: Arnd Bergman <arnd@arndb.de>
---
On Saturday 13 October 2007, Al Viro wrote:
> Just how many instances of that sucker do we need?  It's nothing but
> 
>      struct inode *inode = file->f_path.dentry->d_inode;
>      return file->f_op->ioctl(inode, file, cmd, compat_ptr(arg));

Is this what you had in mind? I've been meaning to do something like
it for some time, but had forgotten about it.

I guess we can kill a significant amount of COMPATIBLE_IOCTL
lines in fs/compat_ioctl.c with this.

Index: linux-2.6/fs/compat_ioctl.c
===================================================================
--- linux-2.6.orig/fs/compat_ioctl.c
+++ linux-2.6/fs/compat_ioctl.c
@@ -1877,6 +1877,30 @@ lp_timeout_trans(unsigned int fd, unsign
 	return sys_ioctl(fd, cmd, (unsigned long)tn);
 }
 
+/*
+ * Helper function for device drivers that only have COMPATIBLE_IOCTL
+ * numbers. This can be used as f_op->compat_ioctl without any #ifdef
+ * and will simply call the native ioctl handler with the argument
+ * pointer.
+ * Don't use for drivers that interpret arg as an unsigned long instead
+ * of a pointer.
+ */
+long generic_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int ret = -ENOTTY;
+	arg = (unsigned long)compat_ptr(arg);
+
+	if (file->f_op->unlocked_ioctl)
+		ret = file->f_op->unlocked_ioctl(file, cmd, arg);
+	else if (file->f_op->ioctl) {
+		lock_kernel();
+		ret = file->f_op->ioctl(file->f_dentry->d_inode, file, cmd, arg);
+		unlock_kernel();
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(generic_compat_ioctl);
 
 typedef int (*ioctl_trans_handler_t)(unsigned int, unsigned int,
 					unsigned long, struct file *);
Index: linux-2.6/include/linux/fs.h
===================================================================
--- linux-2.6.orig/include/linux/fs.h
+++ linux-2.6/include/linux/fs.h
@@ -1807,6 +1807,12 @@ extern void do_generic_mapping_read(stru
 extern int generic_segment_checks(const struct iovec *iov,
 		unsigned long *nr_segs, size_t *count, int access_flags);
 
+#ifdef CONFIG_COMPAT
+extern long generic_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+#else
+#define generic_compat_ioctl (long (*)(struct file *, unsigned int, unsigned long))NULL
+#endif
+
 /* fs/splice.c */
 extern ssize_t generic_file_splice_read(struct file *, loff_t *,
 		struct pipe_inode_info *, size_t, unsigned int);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH] hiddev: simplify 32bit ioctl compatibilty
  2007-10-20 15:50   ` [PATCH] compat_ioctl: introduce generic_compat_ioctl helper Arnd Bergmann
@ 2007-10-20 16:03     ` Arnd Bergmann
  2007-10-20 16:11     ` [PATCH] compat_ioctl: introduce generic_compat_ioctl helper Christoph Hellwig
  1 sibling, 0 replies; 7+ messages in thread
From: Arnd Bergmann @ 2007-10-20 16:03 UTC (permalink / raw)
  To: Al Viro; +Cc: Philip Langdale, Jiri Kosina, LKML

hiddev has both entries in fs/compat_ioctl.c and its own
compat_ioctl() handler. Remove both and use the new generic_compat_ioctl
helper instead.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Index: linux-2.6/drivers/hid/hidraw.c
===================================================================
--- linux-2.6.orig/drivers/hid/hidraw.c
+++ linux-2.6/drivers/hid/hidraw.c
@@ -268,6 +268,7 @@ static const struct file_operations hidr
 	.open =         hidraw_open,
 	.release =      hidraw_release,
 	.ioctl =        hidraw_ioctl,
+	.compat_ioctl = generic_compat_ioctl,
 };
 
 void hidraw_report_event(struct hid_device *hid, u8 *data, int len)
Index: linux-2.6/drivers/hid/usbhid/hiddev.c
===================================================================
--- linux-2.6.orig/drivers/hid/usbhid/hiddev.c
+++ linux-2.6/drivers/hid/usbhid/hiddev.c
@@ -739,14 +739,6 @@ inval:
 	return -EINVAL;
 }
 
-#ifdef CONFIG_COMPAT
-static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct inode *inode = file->f_path.dentry->d_inode;
-	return hiddev_ioctl(inode, file, cmd, compat_ptr(arg));
-}
-#endif
-
 static const struct file_operations hiddev_fops = {
 	.owner =	THIS_MODULE,
 	.read =		hiddev_read,
@@ -756,9 +748,7 @@ static const struct file_operations hidd
 	.release =	hiddev_release,
 	.ioctl =	hiddev_ioctl,
 	.fasync =	hiddev_fasync,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= hiddev_compat_ioctl,
-#endif
+	.compat_ioctl = generic_compat_ioctl,
 };
 
 static struct usb_class_driver hiddev_class = {
Index: linux-2.6/fs/compat_ioctl.c
===================================================================
--- linux-2.6.orig/fs/compat_ioctl.c
+++ linux-2.6/fs/compat_ioctl.c
@@ -102,8 +102,6 @@
 #include <linux/filter.h>
 #include <linux/pktcdvd.h>
 
-#include <linux/hiddev.h>
-
 #include <linux/dvb/audio.h>
 #include <linux/dvb/dmx.h>
 #include <linux/dvb/frontend.h>
@@ -2575,23 +2573,6 @@ COMPATIBLE_IOCTL(SIOCSIWPOWER)
 COMPATIBLE_IOCTL(SIOCGIWPOWER)
 COMPATIBLE_IOCTL(SIOCSIWAUTH)
 COMPATIBLE_IOCTL(SIOCGIWAUTH)
-/* hiddev */
-COMPATIBLE_IOCTL(HIDIOCGVERSION)
-COMPATIBLE_IOCTL(HIDIOCAPPLICATION)
-COMPATIBLE_IOCTL(HIDIOCGDEVINFO)
-COMPATIBLE_IOCTL(HIDIOCGSTRING)
-COMPATIBLE_IOCTL(HIDIOCINITREPORT)
-COMPATIBLE_IOCTL(HIDIOCGREPORT)
-COMPATIBLE_IOCTL(HIDIOCSREPORT)
-COMPATIBLE_IOCTL(HIDIOCGREPORTINFO)
-COMPATIBLE_IOCTL(HIDIOCGFIELDINFO)
-COMPATIBLE_IOCTL(HIDIOCGUSAGE)
-COMPATIBLE_IOCTL(HIDIOCSUSAGE)
-COMPATIBLE_IOCTL(HIDIOCGUCODE)
-COMPATIBLE_IOCTL(HIDIOCGFLAG)
-COMPATIBLE_IOCTL(HIDIOCSFLAG)
-COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINDEX)
-COMPATIBLE_IOCTL(HIDIOCGCOLLECTIONINFO)
 /* dvb */
 COMPATIBLE_IOCTL(AUDIO_STOP)
 COMPATIBLE_IOCTL(AUDIO_PLAY)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] compat_ioctl: introduce generic_compat_ioctl helper
  2007-10-20 15:50   ` [PATCH] compat_ioctl: introduce generic_compat_ioctl helper Arnd Bergmann
  2007-10-20 16:03     ` [PATCH] hiddev: simplify 32bit ioctl compatibilty Arnd Bergmann
@ 2007-10-20 16:11     ` Christoph Hellwig
  2007-10-20 16:23       ` Arnd Bergmann
  1 sibling, 1 reply; 7+ messages in thread
From: Christoph Hellwig @ 2007-10-20 16:11 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Al Viro, Philip Langdale, Jiri Kosina, LKML

On Sat, Oct 20, 2007 at 05:50:57PM +0200, Arnd Bergmann wrote:
> Many drivers use only compatible ioctl numbers. In order to
> avoid having to write a special compat_ioctl handler for each
> of them or listing every ioctl number in fs/compat_ioctl.c,
> let's introduce a generic handler that simply calls the
> driver specific f_op->unlocked_ioctl() or f_op->ioctl() handler.

At least for the unlocked_ioctl case this is not nessecary because
the driver an simply set both the unlocked_ioctl and compat_ioctl
handlers to the same function.  For the drivers not using unlocked_ioctl
yet a function like this makes sense in theory, but I'd prefer to
just switch them to ->unlocked_ioctl.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] compat_ioctl: introduce generic_compat_ioctl helper
  2007-10-20 16:11     ` [PATCH] compat_ioctl: introduce generic_compat_ioctl helper Christoph Hellwig
@ 2007-10-20 16:23       ` Arnd Bergmann
  0 siblings, 0 replies; 7+ messages in thread
From: Arnd Bergmann @ 2007-10-20 16:23 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Al Viro, Philip Langdale, Jiri Kosina, LKML

On Saturday 20 October 2007, Christoph Hellwig wrote:
> At least for the unlocked_ioctl case this is not nessecary because
> the driver an simply set both the unlocked_ioctl and compat_ioctl
> handlers to the same function.  For the drivers not using unlocked_ioctl
> yet a function like this makes sense in theory, but I'd prefer to
> just switch them to ->unlocked_ioctl.
> 

There is still the problem with s390 compat_ptr() conversion, a driver
using the same handler for both may interpret a pointer with the high
bit set as out of range.

	Arnd <><

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2007-10-20 16:23 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-12 23:51 [PATCH] hiddev: Add 32bit ioctl compatibilty Philip Langdale
2007-10-13  0:02 ` Al Viro
2007-10-13 17:42   ` Philip Langdale
2007-10-20 15:50   ` [PATCH] compat_ioctl: introduce generic_compat_ioctl helper Arnd Bergmann
2007-10-20 16:03     ` [PATCH] hiddev: simplify 32bit ioctl compatibilty Arnd Bergmann
2007-10-20 16:11     ` [PATCH] compat_ioctl: introduce generic_compat_ioctl helper Christoph Hellwig
2007-10-20 16:23       ` Arnd Bergmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox