#include <linux/cdev.h>
#include <linux/notifier.h>
#include <linux/security.h>
+#include <linux/user_namespace.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
#include <linux/moduleparam.h>
wait_queue_head_t wait; /* wake up if a request completed */
unsigned int discsignr;
struct pid *disc_pid;
- uid_t disc_uid, disc_euid;
+ const struct cred *cred;
void __user *disccontext;
unsigned long ifclaimed;
u32 secid;
struct list_head asynclist;
struct dev_state *ps;
struct pid *pid;
- uid_t uid, euid;
+ const struct cred *cred;
unsigned int signr;
unsigned int ifnum;
void __user *userbuffer;
static void free_async(struct async *as)
{
put_pid(as->pid);
+ put_cred(as->cred);
kfree(as->urb->transfer_buffer);
kfree(as->urb->setup_packet);
usb_free_urb(as->urb);
struct dev_state *ps = as->ps;
struct siginfo sinfo;
struct pid *pid = NULL;
- uid_t uid = 0;
- uid_t euid = 0;
u32 secid = 0;
+ const struct cred *cred = NULL;
int signr;
spin_lock(&ps->lock);
sinfo.si_errno = as->status;
sinfo.si_code = SI_ASYNCIO;
sinfo.si_addr = as->userurb;
- pid = as->pid;
- uid = as->uid;
- euid = as->euid;
+ pid = get_pid(as->pid);
+ cred = get_cred(as->cred);
secid = as->secid;
}
snoop(&urb->dev->dev, "urb complete\n");
cancel_bulk_urbs(ps, as->bulk_addr);
spin_unlock(&ps->lock);
- if (signr)
- kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid,
- euid, secid);
+ if (signr) {
+ kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred, secid);
+ put_pid(pid);
+ put_cred(cred);
+ }
wake_up(&ps->wait);
}
}
static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
- unsigned int index)
+ unsigned int request, unsigned int index)
{
int ret = 0;
+ struct usb_host_interface *alt_setting;
if (ps->dev->state != USB_STATE_UNAUTHENTICATED
&& ps->dev->state != USB_STATE_ADDRESS
if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype))
return 0;
+ /*
+ * check for the special corner case 'get_device_id' in the printer
+ * class specification, where wIndex is (interface << 8 | altsetting)
+ * instead of just interface
+ */
+ if (requesttype == 0xa1 && request == 0) {
+ alt_setting = usb_find_alt_setting(ps->dev->actconfig,
+ index >> 8, index & 0xff);
+ if (alt_setting
+ && alt_setting->desc.bInterfaceClass == USB_CLASS_PRINTER)
+ index >>= 8;
+ }
+
index &= 0xff;
switch (requesttype & USB_RECIP_MASK) {
case USB_RECIP_ENDPOINT:
{
struct usb_device *dev = NULL;
struct dev_state *ps;
- const struct cred *cred = current_cred();
int ret;
ret = -ENOMEM;
init_waitqueue_head(&ps->wait);
ps->discsignr = 0;
ps->disc_pid = get_pid(task_pid(current));
- ps->disc_uid = cred->uid;
- ps->disc_euid = cred->euid;
+ ps->cred = get_current_cred();
ps->disccontext = NULL;
ps->ifclaimed = 0;
security_task_getsecid(current, &ps->secid);
usb_unlock_device(dev);
usb_put_dev(dev);
put_pid(ps->disc_pid);
+ put_cred(ps->cred);
as = async_getcompleted(ps);
while (as) {
if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
return -EFAULT;
- ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex);
+ ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.bRequest,
+ ctrl.wIndex);
if (ret)
return ret;
wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */
struct usb_host_endpoint *ep;
struct async *as;
struct usb_ctrlrequest *dr = NULL;
- const struct cred *cred = current_cred();
unsigned int u, totlen, isofrmlen;
int ret, ifnum = -1;
int is_in;
kfree(dr);
return -EINVAL;
}
- ret = check_ctrlrecip(ps, dr->bRequestType,
+ ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest,
le16_to_cpup(&dr->wIndex));
if (ret) {
kfree(dr);
as->signr = uurb->signr;
as->ifnum = ifnum;
as->pid = get_pid(task_pid(current));
- as->uid = cred->uid;
- as->euid = cred->euid;
+ as->cred = get_current_cred();
security_task_getsecid(current, &as->secid);
if (!is_in && uurb->buffer_length > 0) {
if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
sinfo.si_errno = EPIPE;
sinfo.si_code = SI_ASYNCIO;
sinfo.si_addr = ps->disccontext;
- kill_pid_info_as_uid(ps->discsignr, &sinfo,
- ps->disc_pid, ps->disc_uid,
- ps->disc_euid, ps->secid);
+ kill_pid_info_as_cred(ps->discsignr, &sinfo,
+ ps->disc_pid, ps->cred, ps->secid);
}
}
}