Skip to content

Commit

Permalink
Merge branch 'compat-ioctl-merge' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/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
  • Loading branch information
torvalds committed Dec 12, 2009
2 parents a1c36e5 + 637e8a6 commit 92340ee
Show file tree
Hide file tree
Showing 4 changed files with 417 additions and 601 deletions.
115 changes: 89 additions & 26 deletions drivers/char/lp.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/smp_lock.h>
#include <linux/compat.h>

#include <linux/parport.h>
#undef LP_STATS
Expand Down Expand Up @@ -571,13 +572,11 @@ static int lp_release(struct inode * inode, struct file * file)
return 0;
}

static int lp_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static int lp_do_ioctl(unsigned int minor, unsigned int cmd,
unsigned long arg, void __user *argp)
{
unsigned int minor = iminor(inode);
int status;
int retval = 0;
void __user *argp = (void __user *)arg;

#ifdef LP_DEBUG
printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
Expand All @@ -587,9 +586,6 @@ static int lp_ioctl(struct inode *inode, struct file *file,
if ((LP_F(minor) & LP_EXIST) == 0)
return -ENODEV;
switch ( cmd ) {
struct timeval par_timeout;
long to_jiffies;

case LPTIME:
LP_TIME(minor) = arg * HZ/100;
break;
Expand Down Expand Up @@ -652,34 +648,101 @@ static int lp_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
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:
retval = -EINVAL;
}
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 = {
.owner = THIS_MODULE,
.write = lp_write,
.ioctl = lp_ioctl,
.unlocked_ioctl = lp_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = lp_compat_ioctl,
#endif
.open = lp_open,
.release = lp_release,
#ifdef CONFIG_PARPORT_1284
Expand Down
110 changes: 99 additions & 11 deletions drivers/usb/core/devio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1388,6 +1388,46 @@ static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
}

#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,
struct usbdevfs_urb32 __user *uurb)
Expand Down Expand Up @@ -1482,6 +1522,7 @@ static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
return processcompl_compat(as, (void __user * __user *)arg);
}


#endif

static int proc_disconnectsignal(struct dev_state *ps, void __user *arg)
Expand Down Expand Up @@ -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
* changing. But there's no mechanism to ensure that...
*/
static int usbdev_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
void __user *p)
{
struct dev_state *ps = file->private_data;
struct inode *inode = file->f_path.dentry->d_inode;
struct usb_device *dev = ps->dev;
void __user *p = (void __user *)arg;
int ret = -ENOTTY;

if (!(file->f_mode & FMODE_WRITE))
Expand Down Expand Up @@ -1726,6 +1767,24 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
break;

#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:
snoop(&dev->dev, "%s: SUBMITURB32\n", __func__);
Expand All @@ -1745,7 +1804,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
break;

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));
break;
#endif
Expand Down Expand Up @@ -1801,6 +1860,32 @@ static int usbdev_ioctl(struct inode *inode, struct file *file,
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 */
static unsigned int usbdev_poll(struct file *file,
struct poll_table_struct *wait)
Expand All @@ -1817,13 +1902,16 @@ static unsigned int usbdev_poll(struct file *file,
}

const struct file_operations usbdev_file_operations = {
.owner = THIS_MODULE,
.llseek = usbdev_lseek,
.read = usbdev_read,
.poll = usbdev_poll,
.ioctl = usbdev_ioctl,
.open = usbdev_open,
.release = usbdev_release,
.owner = THIS_MODULE,
.llseek = usbdev_lseek,
.read = usbdev_read,
.poll = usbdev_poll,
.unlocked_ioctl = usbdev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = usbdev_compat_ioctl,
#endif
.open = usbdev_open,
.release = usbdev_release,
};

static void usbdev_remove(struct usb_device *udev)
Expand Down
Loading

0 comments on commit 92340ee

Please sign in to comment.