Merge branch 'compat-ioctl-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground
* 'compat-ioctl-merge' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground: usbdevfs: move compat_ioctl handling to devio.c lp: move compat_ioctl handling into lp.c compat_ioctl: pass compat pointer directly to handlers compat_ioctl: simplify lookup table compat_ioctl: simplify calling of handlers compat_ioctl: inline all conversion handlers compat_ioctl: Remove BKL compat_ioctl: remove all VT ioctl handling
This commit is contained in:
commit
92340ee319
|
@ -127,6 +127,7 @@
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/smp_lock.h>
|
#include <linux/smp_lock.h>
|
||||||
|
#include <linux/compat.h>
|
||||||
|
|
||||||
#include <linux/parport.h>
|
#include <linux/parport.h>
|
||||||
#undef LP_STATS
|
#undef LP_STATS
|
||||||
|
@ -571,13 +572,11 @@ static int lp_release(struct inode * inode, struct file * file)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lp_ioctl(struct inode *inode, struct file *file,
|
static int lp_do_ioctl(unsigned int minor, unsigned int cmd,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned long arg, void __user *argp)
|
||||||
{
|
{
|
||||||
unsigned int minor = iminor(inode);
|
|
||||||
int status;
|
int status;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
void __user *argp = (void __user *)arg;
|
|
||||||
|
|
||||||
#ifdef LP_DEBUG
|
#ifdef LP_DEBUG
|
||||||
printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
|
printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
|
||||||
|
@ -587,9 +586,6 @@ static int lp_ioctl(struct inode *inode, struct file *file,
|
||||||
if ((LP_F(minor) & LP_EXIST) == 0)
|
if ((LP_F(minor) & LP_EXIST) == 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
switch ( cmd ) {
|
switch ( cmd ) {
|
||||||
struct timeval par_timeout;
|
|
||||||
long to_jiffies;
|
|
||||||
|
|
||||||
case LPTIME:
|
case LPTIME:
|
||||||
LP_TIME(minor) = arg * HZ/100;
|
LP_TIME(minor) = arg * HZ/100;
|
||||||
break;
|
break;
|
||||||
|
@ -652,34 +648,101 @@ static int lp_ioctl(struct inode *inode, struct file *file,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LPSETTIMEOUT:
|
|
||||||
if (copy_from_user (&par_timeout, argp,
|
|
||||||
sizeof (struct timeval))) {
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
/* Convert to jiffies, place in lp_table */
|
|
||||||
if ((par_timeout.tv_sec < 0) ||
|
|
||||||
(par_timeout.tv_usec < 0)) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
to_jiffies = DIV_ROUND_UP(par_timeout.tv_usec, 1000000/HZ);
|
|
||||||
to_jiffies += par_timeout.tv_sec * (long) HZ;
|
|
||||||
if (to_jiffies <= 0) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
lp_table[minor].timeout = to_jiffies;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lp_set_timeout(unsigned int minor, struct timeval *par_timeout)
|
||||||
|
{
|
||||||
|
long to_jiffies;
|
||||||
|
|
||||||
|
/* Convert to jiffies, place in lp_table */
|
||||||
|
if ((par_timeout->tv_sec < 0) ||
|
||||||
|
(par_timeout->tv_usec < 0)) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
to_jiffies = DIV_ROUND_UP(par_timeout->tv_usec, 1000000/HZ);
|
||||||
|
to_jiffies += par_timeout->tv_sec * (long) HZ;
|
||||||
|
if (to_jiffies <= 0) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
lp_table[minor].timeout = to_jiffies;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long lp_ioctl(struct file *file, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
unsigned int minor;
|
||||||
|
struct timeval par_timeout;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
minor = iminor(file->f_path.dentry->d_inode);
|
||||||
|
lock_kernel();
|
||||||
|
switch (cmd) {
|
||||||
|
case LPSETTIMEOUT:
|
||||||
|
if (copy_from_user(&par_timeout, (void __user *)arg,
|
||||||
|
sizeof (struct timeval))) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = lp_set_timeout(minor, &par_timeout);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
unlock_kernel();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
static long lp_compat_ioctl(struct file *file, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
unsigned int minor;
|
||||||
|
struct timeval par_timeout;
|
||||||
|
struct compat_timeval __user *tc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
minor = iminor(file->f_path.dentry->d_inode);
|
||||||
|
lock_kernel();
|
||||||
|
switch (cmd) {
|
||||||
|
case LPSETTIMEOUT:
|
||||||
|
tc = compat_ptr(arg);
|
||||||
|
if (get_user(par_timeout.tv_sec, &tc->tv_sec) ||
|
||||||
|
get_user(par_timeout.tv_usec, &tc->tv_usec)) {
|
||||||
|
ret = -EFAULT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = lp_set_timeout(minor, &par_timeout);
|
||||||
|
break;
|
||||||
|
#ifdef LP_STATS
|
||||||
|
case LPGETSTATS:
|
||||||
|
/* FIXME: add an implementation if you set LP_STATS */
|
||||||
|
ret = -EINVAL;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
unlock_kernel();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct file_operations lp_fops = {
|
static const struct file_operations lp_fops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.write = lp_write,
|
.write = lp_write,
|
||||||
.ioctl = lp_ioctl,
|
.unlocked_ioctl = lp_ioctl,
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
.compat_ioctl = lp_compat_ioctl,
|
||||||
|
#endif
|
||||||
.open = lp_open,
|
.open = lp_open,
|
||||||
.release = lp_release,
|
.release = lp_release,
|
||||||
#ifdef CONFIG_PARPORT_1284
|
#ifdef CONFIG_PARPORT_1284
|
||||||
|
|
|
@ -1388,6 +1388,46 @@ static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
|
static int proc_control_compat(struct dev_state *ps,
|
||||||
|
struct usbdevfs_ctrltransfer32 __user *p32)
|
||||||
|
{
|
||||||
|
struct usbdevfs_ctrltransfer __user *p;
|
||||||
|
__u32 udata;
|
||||||
|
p = compat_alloc_user_space(sizeof(*p));
|
||||||
|
if (copy_in_user(p, p32, (sizeof(*p32) - sizeof(compat_caddr_t))) ||
|
||||||
|
get_user(udata, &p32->data) ||
|
||||||
|
put_user(compat_ptr(udata), &p->data))
|
||||||
|
return -EFAULT;
|
||||||
|
return proc_control(ps, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int proc_bulk_compat(struct dev_state *ps,
|
||||||
|
struct usbdevfs_bulktransfer32 __user *p32)
|
||||||
|
{
|
||||||
|
struct usbdevfs_bulktransfer __user *p;
|
||||||
|
compat_uint_t n;
|
||||||
|
compat_caddr_t addr;
|
||||||
|
|
||||||
|
p = compat_alloc_user_space(sizeof(*p));
|
||||||
|
|
||||||
|
if (get_user(n, &p32->ep) || put_user(n, &p->ep) ||
|
||||||
|
get_user(n, &p32->len) || put_user(n, &p->len) ||
|
||||||
|
get_user(n, &p32->timeout) || put_user(n, &p->timeout) ||
|
||||||
|
get_user(addr, &p32->data) || put_user(compat_ptr(addr), &p->data))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
return proc_bulk(ps, p);
|
||||||
|
}
|
||||||
|
static int proc_disconnectsignal_compat(struct dev_state *ps, void __user *arg)
|
||||||
|
{
|
||||||
|
struct usbdevfs_disconnectsignal32 ds;
|
||||||
|
|
||||||
|
if (copy_from_user(&ds, arg, sizeof(ds)))
|
||||||
|
return -EFAULT;
|
||||||
|
ps->discsignr = ds.signr;
|
||||||
|
ps->disccontext = compat_ptr(ds.context);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int get_urb32(struct usbdevfs_urb *kurb,
|
static int get_urb32(struct usbdevfs_urb *kurb,
|
||||||
struct usbdevfs_urb32 __user *uurb)
|
struct usbdevfs_urb32 __user *uurb)
|
||||||
|
@ -1482,6 +1522,7 @@ static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
|
||||||
return processcompl_compat(as, (void __user * __user *)arg);
|
return processcompl_compat(as, (void __user * __user *)arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int proc_disconnectsignal(struct dev_state *ps, void __user *arg)
|
static int proc_disconnectsignal(struct dev_state *ps, void __user *arg)
|
||||||
|
@ -1648,12 +1689,12 @@ static int proc_release_port(struct dev_state *ps, void __user *arg)
|
||||||
* are assuming that somehow the configuration has been prevented from
|
* are assuming that somehow the configuration has been prevented from
|
||||||
* changing. But there's no mechanism to ensure that...
|
* changing. But there's no mechanism to ensure that...
|
||||||
*/
|
*/
|
||||||
static int usbdev_ioctl(struct inode *inode, struct file *file,
|
static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
|
||||||
unsigned int cmd, unsigned long arg)
|
void __user *p)
|
||||||
{
|
{
|
||||||
struct dev_state *ps = file->private_data;
|
struct dev_state *ps = file->private_data;
|
||||||
|
struct inode *inode = file->f_path.dentry->d_inode;
|
||||||
struct usb_device *dev = ps->dev;
|
struct usb_device *dev = ps->dev;
|
||||||
void __user *p = (void __user *)arg;
|
|
||||||
int ret = -ENOTTY;
|
int ret = -ENOTTY;
|
||||||
|
|
||||||
if (!(file->f_mode & FMODE_WRITE))
|
if (!(file->f_mode & FMODE_WRITE))
|
||||||
|
@ -1726,6 +1767,24 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
|
case USBDEVFS_CONTROL32:
|
||||||
|
snoop(&dev->dev, "%s: CONTROL32\n", __func__);
|
||||||
|
ret = proc_control_compat(ps, p);
|
||||||
|
if (ret >= 0)
|
||||||
|
inode->i_mtime = CURRENT_TIME;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USBDEVFS_BULK32:
|
||||||
|
snoop(&dev->dev, "%s: BULK32\n", __func__);
|
||||||
|
ret = proc_bulk_compat(ps, p);
|
||||||
|
if (ret >= 0)
|
||||||
|
inode->i_mtime = CURRENT_TIME;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USBDEVFS_DISCSIGNAL32:
|
||||||
|
snoop(&dev->dev, "%s: DISCSIGNAL32\n", __func__);
|
||||||
|
ret = proc_disconnectsignal_compat(ps, p);
|
||||||
|
break;
|
||||||
|
|
||||||
case USBDEVFS_SUBMITURB32:
|
case USBDEVFS_SUBMITURB32:
|
||||||
snoop(&dev->dev, "%s: SUBMITURB32\n", __func__);
|
snoop(&dev->dev, "%s: SUBMITURB32\n", __func__);
|
||||||
|
@ -1745,7 +1804,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USBDEVFS_IOCTL32:
|
case USBDEVFS_IOCTL32:
|
||||||
snoop(&dev->dev, "%s: IOCTL\n", __func__);
|
snoop(&dev->dev, "%s: IOCTL32\n", __func__);
|
||||||
ret = proc_ioctl_compat(ps, ptr_to_compat(p));
|
ret = proc_ioctl_compat(ps, ptr_to_compat(p));
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1801,6 +1860,32 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long usbdev_ioctl(struct file *file, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
lock_kernel();
|
||||||
|
ret = usbdev_do_ioctl(file, cmd, (void __user *)arg);
|
||||||
|
unlock_kernel();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_COMPAT
|
||||||
|
static long usbdev_compat_ioctl(struct file *file, unsigned int cmd,
|
||||||
|
unsigned long arg)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
lock_kernel();
|
||||||
|
ret = usbdev_do_ioctl(file, cmd, compat_ptr(arg));
|
||||||
|
unlock_kernel();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* No kernel lock - fine */
|
/* No kernel lock - fine */
|
||||||
static unsigned int usbdev_poll(struct file *file,
|
static unsigned int usbdev_poll(struct file *file,
|
||||||
struct poll_table_struct *wait)
|
struct poll_table_struct *wait)
|
||||||
|
@ -1817,13 +1902,16 @@ static unsigned int usbdev_poll(struct file *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct file_operations usbdev_file_operations = {
|
const struct file_operations usbdev_file_operations = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.llseek = usbdev_lseek,
|
.llseek = usbdev_lseek,
|
||||||
.read = usbdev_read,
|
.read = usbdev_read,
|
||||||
.poll = usbdev_poll,
|
.poll = usbdev_poll,
|
||||||
.ioctl = usbdev_ioctl,
|
.unlocked_ioctl = usbdev_ioctl,
|
||||||
.open = usbdev_open,
|
#ifdef CONFIG_COMPAT
|
||||||
.release = usbdev_release,
|
.compat_ioctl = usbdev_compat_ioctl,
|
||||||
|
#endif
|
||||||
|
.open = usbdev_open,
|
||||||
|
.release = usbdev_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void usbdev_remove(struct usb_device *udev)
|
static void usbdev_remove(struct usb_device *udev)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -128,6 +128,29 @@ struct usbdevfs_hub_portinfo {
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
|
|
||||||
|
struct usbdevfs_ctrltransfer32 {
|
||||||
|
u8 bRequestType;
|
||||||
|
u8 bRequest;
|
||||||
|
u16 wValue;
|
||||||
|
u16 wIndex;
|
||||||
|
u16 wLength;
|
||||||
|
u32 timeout; /* in milliseconds */
|
||||||
|
compat_caddr_t data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usbdevfs_bulktransfer32 {
|
||||||
|
compat_uint_t ep;
|
||||||
|
compat_uint_t len;
|
||||||
|
compat_uint_t timeout; /* in milliseconds */
|
||||||
|
compat_caddr_t data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct usbdevfs_disconnectsignal32 {
|
||||||
|
compat_int_t signr;
|
||||||
|
compat_caddr_t context;
|
||||||
|
};
|
||||||
|
|
||||||
struct usbdevfs_urb32 {
|
struct usbdevfs_urb32 {
|
||||||
unsigned char type;
|
unsigned char type;
|
||||||
unsigned char endpoint;
|
unsigned char endpoint;
|
||||||
|
@ -153,7 +176,9 @@ struct usbdevfs_ioctl32 {
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer)
|
#define USBDEVFS_CONTROL _IOWR('U', 0, struct usbdevfs_ctrltransfer)
|
||||||
|
#define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32)
|
||||||
#define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer)
|
#define USBDEVFS_BULK _IOWR('U', 2, struct usbdevfs_bulktransfer)
|
||||||
|
#define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32)
|
||||||
#define USBDEVFS_RESETEP _IOR('U', 3, unsigned int)
|
#define USBDEVFS_RESETEP _IOR('U', 3, unsigned int)
|
||||||
#define USBDEVFS_SETINTERFACE _IOR('U', 4, struct usbdevfs_setinterface)
|
#define USBDEVFS_SETINTERFACE _IOR('U', 4, struct usbdevfs_setinterface)
|
||||||
#define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int)
|
#define USBDEVFS_SETCONFIGURATION _IOR('U', 5, unsigned int)
|
||||||
|
@ -166,6 +191,7 @@ struct usbdevfs_ioctl32 {
|
||||||
#define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *)
|
#define USBDEVFS_REAPURBNDELAY _IOW('U', 13, void *)
|
||||||
#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, __u32)
|
#define USBDEVFS_REAPURBNDELAY32 _IOW('U', 13, __u32)
|
||||||
#define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal)
|
#define USBDEVFS_DISCSIGNAL _IOR('U', 14, struct usbdevfs_disconnectsignal)
|
||||||
|
#define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32)
|
||||||
#define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int)
|
#define USBDEVFS_CLAIMINTERFACE _IOR('U', 15, unsigned int)
|
||||||
#define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int)
|
#define USBDEVFS_RELEASEINTERFACE _IOR('U', 16, unsigned int)
|
||||||
#define USBDEVFS_CONNECTINFO _IOW('U', 17, struct usbdevfs_connectinfo)
|
#define USBDEVFS_CONNECTINFO _IOW('U', 17, struct usbdevfs_connectinfo)
|
||||||
|
|
Loading…
Reference in New Issue