From: Brian Behlendorf Date: Tue, 21 Jul 2009 17:13:58 +0000 (-0700) Subject: Register a basic compat ioctl handler (32 vs 64 bit compat) X-Git-Tag: zfs-0.8.0-rc1~152^2~678 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=78d6de97bd0749b03af86ff5f76edae4bfb18b42;p=zfs Register a basic compat ioctl handler (32 vs 64 bit compat) 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. --- diff --git a/module/spl/spl-module.c b/module/spl/spl-module.c index 4a2be89da..aa3d56195 100644 --- a/module/spl/spl-module.c +++ b/module/spl/spl-module.c @@ -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)