USB: mos7720: fix broken control requests

The parallel-port code of the drivers used a stack allocated
control-request buffer for asynchronous (and possibly deferred) control
requests. This not only violates the no-DMA-from-stack requirement but
could also lead to corrupt control requests being submitted.

Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Johan Hovold 2013-08-13 13:27:34 +02:00 committed by Greg Kroah-Hartman
parent 304ab4ab07
commit ef6c8c1d73

View File

@ -90,6 +90,7 @@ struct urbtracker {
struct list_head urblist_entry;
struct kref ref_count;
struct urb *urb;
struct usb_ctrlrequest *setup;
};
enum mos7715_pp_modes {
@ -271,6 +272,7 @@ static void destroy_urbtracker(struct kref *kref)
struct mos7715_parport *mos_parport = urbtrack->mos_parport;
usb_free_urb(urbtrack->urb);
kfree(urbtrack->setup);
kfree(urbtrack);
kref_put(&mos_parport->ref_count, destroy_mos_parport);
}
@ -355,7 +357,6 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
struct urbtracker *urbtrack;
int ret_val;
unsigned long flags;
struct usb_ctrlrequest setup;
struct usb_serial *serial = mos_parport->serial;
struct usb_device *usbdev = serial->dev;
@ -373,14 +374,20 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport,
kfree(urbtrack);
return -ENOMEM;
}
setup.bRequestType = (__u8)0x40;
setup.bRequest = (__u8)0x0e;
setup.wValue = get_reg_value(reg, dummy);
setup.wIndex = get_reg_index(reg);
setup.wLength = 0;
urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_KERNEL);
if (!urbtrack->setup) {
usb_free_urb(urbtrack->urb);
kfree(urbtrack);
return -ENOMEM;
}
urbtrack->setup->bRequestType = (__u8)0x40;
urbtrack->setup->bRequest = (__u8)0x0e;
urbtrack->setup->wValue = get_reg_value(reg, dummy);
urbtrack->setup->wIndex = get_reg_index(reg);
urbtrack->setup->wLength = 0;
usb_fill_control_urb(urbtrack->urb, usbdev,
usb_sndctrlpipe(usbdev, 0),
(unsigned char *)&setup,
(unsigned char *)urbtrack->setup,
NULL, 0, async_complete, urbtrack);
kref_init(&urbtrack->ref_count);
INIT_LIST_HEAD(&urbtrack->urblist_entry);