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:
Родитель
304ab4ab07
Коммит
ef6c8c1d73
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче