diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-01-09 02:38:23 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-01-09 02:38:23 -0500 |
commit | da733563be5a9da26fe81d9f007262d00b846e22 (patch) | |
tree | db28291df94a2043af2123911984c5c173da4e6f /drivers/usb/core/devio.c | |
parent | 6ccbcf2cb41131f8d56ef0723bf3f7c1f8486076 (diff) | |
parent | dab78d7924598ea4031663dd10db814e2e324928 (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'drivers/usb/core/devio.c')
-rw-r--r-- | drivers/usb/core/devio.c | 57 |
1 files changed, 35 insertions, 22 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 37518dfdeb98..e3beaf229ee3 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/cdev.h> | 46 | #include <linux/cdev.h> |
47 | #include <linux/notifier.h> | 47 | #include <linux/notifier.h> |
48 | #include <linux/security.h> | 48 | #include <linux/security.h> |
49 | #include <linux/user_namespace.h> | ||
49 | #include <asm/uaccess.h> | 50 | #include <asm/uaccess.h> |
50 | #include <asm/byteorder.h> | 51 | #include <asm/byteorder.h> |
51 | #include <linux/moduleparam.h> | 52 | #include <linux/moduleparam.h> |
@@ -68,7 +69,7 @@ struct dev_state { | |||
68 | wait_queue_head_t wait; /* wake up if a request completed */ | 69 | wait_queue_head_t wait; /* wake up if a request completed */ |
69 | unsigned int discsignr; | 70 | unsigned int discsignr; |
70 | struct pid *disc_pid; | 71 | struct pid *disc_pid; |
71 | uid_t disc_uid, disc_euid; | 72 | const struct cred *cred; |
72 | void __user *disccontext; | 73 | void __user *disccontext; |
73 | unsigned long ifclaimed; | 74 | unsigned long ifclaimed; |
74 | u32 secid; | 75 | u32 secid; |
@@ -79,7 +80,7 @@ struct async { | |||
79 | struct list_head asynclist; | 80 | struct list_head asynclist; |
80 | struct dev_state *ps; | 81 | struct dev_state *ps; |
81 | struct pid *pid; | 82 | struct pid *pid; |
82 | uid_t uid, euid; | 83 | const struct cred *cred; |
83 | unsigned int signr; | 84 | unsigned int signr; |
84 | unsigned int ifnum; | 85 | unsigned int ifnum; |
85 | void __user *userbuffer; | 86 | void __user *userbuffer; |
@@ -248,6 +249,7 @@ static struct async *alloc_async(unsigned int numisoframes) | |||
248 | static void free_async(struct async *as) | 249 | static void free_async(struct async *as) |
249 | { | 250 | { |
250 | put_pid(as->pid); | 251 | put_pid(as->pid); |
252 | put_cred(as->cred); | ||
251 | kfree(as->urb->transfer_buffer); | 253 | kfree(as->urb->transfer_buffer); |
252 | kfree(as->urb->setup_packet); | 254 | kfree(as->urb->setup_packet); |
253 | usb_free_urb(as->urb); | 255 | usb_free_urb(as->urb); |
@@ -393,9 +395,8 @@ static void async_completed(struct urb *urb) | |||
393 | struct dev_state *ps = as->ps; | 395 | struct dev_state *ps = as->ps; |
394 | struct siginfo sinfo; | 396 | struct siginfo sinfo; |
395 | struct pid *pid = NULL; | 397 | struct pid *pid = NULL; |
396 | uid_t uid = 0; | ||
397 | uid_t euid = 0; | ||
398 | u32 secid = 0; | 398 | u32 secid = 0; |
399 | const struct cred *cred = NULL; | ||
399 | int signr; | 400 | int signr; |
400 | 401 | ||
401 | spin_lock(&ps->lock); | 402 | spin_lock(&ps->lock); |
@@ -407,9 +408,8 @@ static void async_completed(struct urb *urb) | |||
407 | sinfo.si_errno = as->status; | 408 | sinfo.si_errno = as->status; |
408 | sinfo.si_code = SI_ASYNCIO; | 409 | sinfo.si_code = SI_ASYNCIO; |
409 | sinfo.si_addr = as->userurb; | 410 | sinfo.si_addr = as->userurb; |
410 | pid = as->pid; | 411 | pid = get_pid(as->pid); |
411 | uid = as->uid; | 412 | cred = get_cred(as->cred); |
412 | euid = as->euid; | ||
413 | secid = as->secid; | 413 | secid = as->secid; |
414 | } | 414 | } |
415 | snoop(&urb->dev->dev, "urb complete\n"); | 415 | snoop(&urb->dev->dev, "urb complete\n"); |
@@ -422,9 +422,11 @@ static void async_completed(struct urb *urb) | |||
422 | cancel_bulk_urbs(ps, as->bulk_addr); | 422 | cancel_bulk_urbs(ps, as->bulk_addr); |
423 | spin_unlock(&ps->lock); | 423 | spin_unlock(&ps->lock); |
424 | 424 | ||
425 | if (signr) | 425 | if (signr) { |
426 | kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid, | 426 | kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred, secid); |
427 | euid, secid); | 427 | put_pid(pid); |
428 | put_cred(cred); | ||
429 | } | ||
428 | 430 | ||
429 | wake_up(&ps->wait); | 431 | wake_up(&ps->wait); |
430 | } | 432 | } |
@@ -607,9 +609,10 @@ static int findintfep(struct usb_device *dev, unsigned int ep) | |||
607 | } | 609 | } |
608 | 610 | ||
609 | static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, | 611 | static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, |
610 | unsigned int index) | 612 | unsigned int request, unsigned int index) |
611 | { | 613 | { |
612 | int ret = 0; | 614 | int ret = 0; |
615 | struct usb_host_interface *alt_setting; | ||
613 | 616 | ||
614 | if (ps->dev->state != USB_STATE_UNAUTHENTICATED | 617 | if (ps->dev->state != USB_STATE_UNAUTHENTICATED |
615 | && ps->dev->state != USB_STATE_ADDRESS | 618 | && ps->dev->state != USB_STATE_ADDRESS |
@@ -618,6 +621,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, | |||
618 | if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) | 621 | if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) |
619 | return 0; | 622 | return 0; |
620 | 623 | ||
624 | /* | ||
625 | * check for the special corner case 'get_device_id' in the printer | ||
626 | * class specification, where wIndex is (interface << 8 | altsetting) | ||
627 | * instead of just interface | ||
628 | */ | ||
629 | if (requesttype == 0xa1 && request == 0) { | ||
630 | alt_setting = usb_find_alt_setting(ps->dev->actconfig, | ||
631 | index >> 8, index & 0xff); | ||
632 | if (alt_setting | ||
633 | && alt_setting->desc.bInterfaceClass == USB_CLASS_PRINTER) | ||
634 | index >>= 8; | ||
635 | } | ||
636 | |||
621 | index &= 0xff; | 637 | index &= 0xff; |
622 | switch (requesttype & USB_RECIP_MASK) { | 638 | switch (requesttype & USB_RECIP_MASK) { |
623 | case USB_RECIP_ENDPOINT: | 639 | case USB_RECIP_ENDPOINT: |
@@ -656,7 +672,6 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
656 | { | 672 | { |
657 | struct usb_device *dev = NULL; | 673 | struct usb_device *dev = NULL; |
658 | struct dev_state *ps; | 674 | struct dev_state *ps; |
659 | const struct cred *cred = current_cred(); | ||
660 | int ret; | 675 | int ret; |
661 | 676 | ||
662 | ret = -ENOMEM; | 677 | ret = -ENOMEM; |
@@ -706,8 +721,7 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
706 | init_waitqueue_head(&ps->wait); | 721 | init_waitqueue_head(&ps->wait); |
707 | ps->discsignr = 0; | 722 | ps->discsignr = 0; |
708 | ps->disc_pid = get_pid(task_pid(current)); | 723 | ps->disc_pid = get_pid(task_pid(current)); |
709 | ps->disc_uid = cred->uid; | 724 | ps->cred = get_current_cred(); |
710 | ps->disc_euid = cred->euid; | ||
711 | ps->disccontext = NULL; | 725 | ps->disccontext = NULL; |
712 | ps->ifclaimed = 0; | 726 | ps->ifclaimed = 0; |
713 | security_task_getsecid(current, &ps->secid); | 727 | security_task_getsecid(current, &ps->secid); |
@@ -749,6 +763,7 @@ static int usbdev_release(struct inode *inode, struct file *file) | |||
749 | usb_unlock_device(dev); | 763 | usb_unlock_device(dev); |
750 | usb_put_dev(dev); | 764 | usb_put_dev(dev); |
751 | put_pid(ps->disc_pid); | 765 | put_pid(ps->disc_pid); |
766 | put_cred(ps->cred); | ||
752 | 767 | ||
753 | as = async_getcompleted(ps); | 768 | as = async_getcompleted(ps); |
754 | while (as) { | 769 | while (as) { |
@@ -770,7 +785,8 @@ static int proc_control(struct dev_state *ps, void __user *arg) | |||
770 | 785 | ||
771 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) | 786 | if (copy_from_user(&ctrl, arg, sizeof(ctrl))) |
772 | return -EFAULT; | 787 | return -EFAULT; |
773 | ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex); | 788 | ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.bRequest, |
789 | ctrl.wIndex); | ||
774 | if (ret) | 790 | if (ret) |
775 | return ret; | 791 | return ret; |
776 | wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */ | 792 | wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */ |
@@ -1048,7 +1064,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1048 | struct usb_host_endpoint *ep; | 1064 | struct usb_host_endpoint *ep; |
1049 | struct async *as; | 1065 | struct async *as; |
1050 | struct usb_ctrlrequest *dr = NULL; | 1066 | struct usb_ctrlrequest *dr = NULL; |
1051 | const struct cred *cred = current_cred(); | ||
1052 | unsigned int u, totlen, isofrmlen; | 1067 | unsigned int u, totlen, isofrmlen; |
1053 | int ret, ifnum = -1; | 1068 | int ret, ifnum = -1; |
1054 | int is_in; | 1069 | int is_in; |
@@ -1100,7 +1115,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1100 | kfree(dr); | 1115 | kfree(dr); |
1101 | return -EINVAL; | 1116 | return -EINVAL; |
1102 | } | 1117 | } |
1103 | ret = check_ctrlrecip(ps, dr->bRequestType, | 1118 | ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest, |
1104 | le16_to_cpup(&dr->wIndex)); | 1119 | le16_to_cpup(&dr->wIndex)); |
1105 | if (ret) { | 1120 | if (ret) { |
1106 | kfree(dr); | 1121 | kfree(dr); |
@@ -1262,8 +1277,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, | |||
1262 | as->signr = uurb->signr; | 1277 | as->signr = uurb->signr; |
1263 | as->ifnum = ifnum; | 1278 | as->ifnum = ifnum; |
1264 | as->pid = get_pid(task_pid(current)); | 1279 | as->pid = get_pid(task_pid(current)); |
1265 | as->uid = cred->uid; | 1280 | as->cred = get_current_cred(); |
1266 | as->euid = cred->euid; | ||
1267 | security_task_getsecid(current, &as->secid); | 1281 | security_task_getsecid(current, &as->secid); |
1268 | if (!is_in && uurb->buffer_length > 0) { | 1282 | if (!is_in && uurb->buffer_length > 0) { |
1269 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, | 1283 | if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, |
@@ -1981,9 +1995,8 @@ static void usbdev_remove(struct usb_device *udev) | |||
1981 | sinfo.si_errno = EPIPE; | 1995 | sinfo.si_errno = EPIPE; |
1982 | sinfo.si_code = SI_ASYNCIO; | 1996 | sinfo.si_code = SI_ASYNCIO; |
1983 | sinfo.si_addr = ps->disccontext; | 1997 | sinfo.si_addr = ps->disccontext; |
1984 | kill_pid_info_as_uid(ps->discsignr, &sinfo, | 1998 | kill_pid_info_as_cred(ps->discsignr, &sinfo, |
1985 | ps->disc_pid, ps->disc_uid, | 1999 | ps->disc_pid, ps->cred, ps->secid); |
1986 | ps->disc_euid, ps->secid); | ||
1987 | } | 2000 | } |
1988 | } | 2001 | } |
1989 | } | 2002 | } |