]> granicus.if.org Git - spl/commitdiff
Register a basic compat ioctl handler (32 vs 64 bit compat)
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 21 Jul 2009 17:13:58 +0000 (10:13 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 21 Jul 2009 17:13:58 +0000 (10:13 -0700)
Simply pass the ioctl on to the normal handler.  If the ioctl
helper macros are used correctly this should be safe as they
will handle the packing/unpacking of the data encoded in the
ioctl command.  And actually, if the caller does not use the
IO* macros at all, and just passes small values, it will probably
be OK as well.  We only get in to trouble if they try and use
the upper 32-bits.  Endianness is not really a concern here, we
we are pretty much assumed they user and kernel will match.

module/spl/spl-module.c

index 4a2be89dab26a9745bf4f58536a0aba046d615a4..aa3d56195cc23f8b8901a6807816157e5425871e 100644 (file)
@@ -54,7 +54,7 @@ out:
 }
 
 static int
-mod_generic_ioctl(struct inode *ino, struct file *filp,
+mod_generic_ioctl(struct inode *ino, struct file *file,
                  unsigned int cmd, unsigned long arg)
 {
        struct dev_info *di;
@@ -66,11 +66,21 @@ mod_generic_ioctl(struct inode *ino, struct file *filp,
                return EINVAL;
 
        rc = di->di_ops->devo_cb_ops->cb_ioctl(di->di_dev,
-                                              (int)cmd,(intptr_t)arg,
+                                              (int)cmd, (intptr_t)arg,
                                               flags, cr, &rvalp);
        return rc;
 }
 
+#ifdef CONFIG_COMPAT
+/* Compatibility handler for ioctls from 32-bit ELF binaries */
+static long
+mod_generic_compat_ioctl(struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
+       return mod_generic_ioctl(file->f_dentry->d_inode, file, cmd, arg);
+}
+#endif /* CONFIG_COMPAT */
+
 int
 __ddi_create_minor_node(dev_info_t *di, char *name, int spec_type,
                         minor_t minor_num, char *node_type,
@@ -107,8 +117,12 @@ __ddi_create_minor_node(dev_info_t *di, char *name, int spec_type,
 
        /* Setup the fops to cb_ops mapping */
        fops->owner = mod;
-       if (cb_ops->cb_ioctl)
+       if (cb_ops->cb_ioctl) {
                fops->ioctl = mod_generic_ioctl;
+#ifdef CONFIG_COMPAT
+               fops->compat_ioctl = mod_generic_compat_ioctl;
+#endif
+       }
 
 #if 0
        if (cb_ops->cb_open)