#include <linux/usbdevice_fs.h>
#include <linux/cdev.h>
#include <linux/notifier.h>
-#include <linux/security.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
#include <linux/moduleparam.h>
#define USB_DEVICE_MAX USB_MAXBUS * 128
static struct class *usb_device_class;
-/* Mutual exclusion for removal, open, and release */
-DEFINE_MUTEX(usbfs_mutex);
-
struct async {
struct list_head asynclist;
struct dev_state *ps;
void __user *userbuffer;
void __user *userurb;
struct urb *urb;
- u32 secid;
};
static int usbfs_snoop = 0;
sinfo.si_code = SI_ASYNCIO;
sinfo.si_addr = as->userurb;
kill_proc_info_as_uid(as->signr, &sinfo, as->pid, as->uid,
- as->euid, as->secid);
+ as->euid);
}
snoop(&urb->dev->dev, "urb complete\n");
snoop_urb(urb, as->userurb);
struct dev_state *ps;
int ret;
- /* Protect against simultaneous removal or release */
- mutex_lock(&usbfs_mutex);
-
+ /*
+ * no locking necessary here, as chrdev_open has the kernel lock
+ * (still acquire the kernel lock for safety)
+ */
ret = -ENOMEM;
if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
- goto out;
+ goto out_nolock;
+ lock_kernel();
ret = -ENOENT;
/* check if we are called from a real node or usbfs */
if (imajor(inode) == USB_DEVICE_MAJOR)
dev = usbdev_lookup_minor(iminor(inode));
if (!dev)
- dev = inode->i_private;
+ dev = inode->u.generic_ip;
if (!dev) {
kfree(ps);
goto out;
ps->disc_euid = current->euid;
ps->disccontext = NULL;
ps->ifclaimed = 0;
- security_task_getsecid(current, &ps->secid);
wmb();
list_add_tail(&ps->list, &dev->filelist);
file->private_data = ps;
out:
- mutex_unlock(&usbfs_mutex);
- return ret;
+ unlock_kernel();
+ out_nolock:
+ return ret;
}
static int usbdev_release(struct inode *inode, struct file *file)
unsigned int ifnum;
usb_lock_device(dev);
-
- /* Protect against simultaneous open */
- mutex_lock(&usbfs_mutex);
list_del_init(&ps->list);
- mutex_unlock(&usbfs_mutex);
-
for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed);
ifnum++) {
if (test_bit(ifnum, &ps->ifclaimed))
destroy_all_async(ps);
usb_unlock_device(dev);
usb_put_dev(dev);
+ ps->dev = NULL;
kfree(ps);
- return 0;
+ return 0;
}
static int proc_control(struct dev_state *ps, void __user *arg)
static int proc_resetdevice(struct dev_state *ps)
{
- return usb_reset_composite_device(ps->dev, NULL);
+ return usb_reset_device(ps->dev);
+
}
static int proc_setintf(struct dev_state *ps, void __user *arg)
if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_CONTROL)
return -EINVAL;
- /* min 8 byte setup packet, max 8 byte setup plus an arbitrary data stage */
- if (uurb->buffer_length < 8 || uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
+ /* min 8 byte setup packet, max arbitrary */
+ if (uurb->buffer_length < 8 || uurb->buffer_length > PAGE_SIZE)
return -EINVAL;
if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
return -ENOMEM;
return -EFAULT;
}
for (totlen = u = 0; u < uurb->number_of_packets; u++) {
- /* arbitrary limit, sufficient for USB 2.0 high-bandwidth iso */
- if (isopkt[u].length > 8192) {
+ if (isopkt[u].length > 1023) {
kfree(isopkt);
return -EINVAL;
}
as->pid = current->pid;
as->uid = current->uid;
as->euid = current->euid;
- security_task_getsecid(current, &as->secid);
if (!(uurb->endpoint & USB_DIR_IN)) {
if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, as->urb->transfer_buffer_length)) {
free_async(as);