Control: tag -1 patch moreinfo Please test whether the attached patches fix this. You can find instructions for rebuilding the kernel package at: https://kernel-handbook.alioth.debian.org/ch-common-tasks.html#s-common-official Ben. -- Ben Hutchings Design a system any fool can use, and only a fool will want to use it.
From: Ben Hutchings <ben@decadent.org.uk> Date: Fri, 27 Jan 2017 00:28:33 +0000 Subject: [1/2] ALSA: line6: toneport: Add error checks to toneport_setup() etc. Origin: https://git.kernel.org/linus/fc5e7a3683e1a0ce039c7ed8440ae49d60e6dfd6 Bug-Debian: https://bugs.debian.org/852749 toneport_setup() currently ignores all errors and returns void. Make it and toneport_update_led() report errors, and make toneport_init() check for this. Fixes: 705ececd1c60 ("Staging: add line6 usb driver") Signed-off-by: Ben Hutchings <ben@decadent.org.uk> --- sound/usb/line6/toneport.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c index 8e22f430d700..646c27a79f68 100644 --- a/sound/usb/line6/toneport.c +++ b/sound/usb/line6/toneport.c @@ -294,11 +294,11 @@ static bool toneport_has_led(struct usb_line6_toneport *toneport) static const char * const led_colors[2] = { "red", "green" }; static const int led_init_vals[2] = { 0x00, 0x26 }; -static void toneport_update_led(struct usb_line6_toneport *toneport) +static int toneport_update_led(struct usb_line6_toneport *toneport) { - toneport_send_cmd(toneport->line6.usbdev, - (toneport->leds[0].dev.brightness << 8) | 0x0002, - toneport->leds[1].dev.brightness); + return toneport_send_cmd(toneport->line6.usbdev, + (toneport->leds[0].dev.brightness << 8) | 0x0002, + toneport->leds[1].dev.brightness); } static void toneport_led_brightness_set(struct led_classdev *led_cdev, @@ -365,29 +365,42 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport) /* Setup Toneport device. */ -static void toneport_setup(struct usb_line6_toneport *toneport) +static int toneport_setup(struct usb_line6_toneport *toneport) { int ticks; struct usb_line6 *line6 = &toneport->line6; struct usb_device *usbdev = line6->usbdev; + int err; /* sync time on device with host: */ ticks = (int)get_seconds(); - line6_write_data(line6, 0x80c6, &ticks, 4); + err = line6_write_data(line6, 0x80c6, &ticks, 4); + if (err < 0) + return err; /* enable device: */ - toneport_send_cmd(usbdev, 0x0301, 0x0000); + err = toneport_send_cmd(usbdev, 0x0301, 0x0000); + if (err < 0) + return err; /* initialize source select: */ - if (toneport_has_source_select(toneport)) - toneport_send_cmd(usbdev, - toneport_source_info[toneport->source].code, - 0x0000); + if (toneport_has_source_select(toneport)) { + err = toneport_send_cmd(usbdev, + toneport_source_info[toneport->source].code, + 0x0000); + if (err < 0) + return err; + } - if (toneport_has_led(toneport)) - toneport_update_led(toneport); + if (toneport_has_led(toneport)) { + err = toneport_update_led(toneport); + if (err < 0) + return err; + } mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); + + return 0; } /* @@ -451,7 +464,9 @@ static int toneport_init(struct usb_line6 *line6, return err; } - toneport_setup(toneport); + err = toneport_setup(toneport); + if (err < 0) + return err; /* register audio system: */ return snd_card_register(line6->card);
From: Ben Hutchings <ben@decadent.org.uk> Date: Fri, 27 Jan 2017 00:40:49 +0000 Subject: [2/2] ALSA: line6: Move USB message buffers off-stack Origin: https://git.kernel.org/linus/13d338f1016e8898c98faa9c790d7056ef934307 Bug-Debian: https://bugs.debian.org/852749 Allocating USB buffers on the stack is not portable, and no longer works on x86_64 (with VMAP_STACK enabled as per default). Fixes: 705ececd1c60 ("Staging: add line6 usb driver") Signed-off-by: Ben Hutchings <ben@decadent.org.uk> --- sound/usb/line6/driver.c | 64 +++++++++++++++++++++++++++++----------------- sound/usb/line6/podhd.c | 22 ++++++++++------ sound/usb/line6/toneport.c | 10 +++++--- 3 files changed, 61 insertions(+), 35 deletions(-) diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 90009c0b3a92..b3a7f0c809da 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -337,12 +337,16 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, { struct usb_device *usbdev = line6->usbdev; int ret; - unsigned char len; + unsigned char *len; unsigned count; if (address > 0xffff || datalen > 0xff) return -EINVAL; + len = kmalloc(1, GFP_ATOMIC); + if (!len) + return -ENOMEM; + /* query the serial number: */ ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, @@ -351,7 +355,7 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, if (ret < 0) { dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); - return ret; + goto out; } /* Wait for data length. We'll get 0xff until length arrives. */ @@ -361,28 +365,30 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0x0012, 0x0000, &len, 1, + 0x0012, 0x0000, len, 1, LINE6_TIMEOUT * HZ); if (ret < 0) { dev_err(line6->ifcdev, "receive length failed (error %d)\n", ret); - return ret; + goto out; } - if (len != 0xff) + if (*len != 0xff) break; } - if (len == 0xff) { + if (*len == 0xff) { dev_err(line6->ifcdev, "read failed after %d retries\n", count); - return -EIO; - } else if (len != datalen) { + ret = -EIO; + goto out; + } else if (*len != datalen) { /* should be equal or something went wrong */ dev_err(line6->ifcdev, "length mismatch (expected %d, got %d)\n", - (int)datalen, (int)len); - return -EIO; + (int)datalen, (int)*len); + ret = -EIO; + goto out; } /* receive the result: */ @@ -391,12 +397,14 @@ int line6_read_data(struct usb_line6 *line6, unsigned address, void *data, 0x0013, 0x0000, data, datalen, LINE6_TIMEOUT * HZ); - if (ret < 0) { + if (ret < 0) dev_err(line6->ifcdev, "read failed (error %d)\n", ret); - return ret; - } + else + ret = 0; - return 0; +out: + kfree(len); + return ret; } EXPORT_SYMBOL_GPL(line6_read_data); @@ -408,12 +416,16 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, { struct usb_device *usbdev = line6->usbdev; int ret; - unsigned char status; + unsigned char *status; int count; if (address > 0xffff || datalen > 0xffff) return -EINVAL; + status = kmalloc(1, GFP_ATOMIC); + if (!status) + return -ENOMEM; + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 0x0022, address, data, datalen, @@ -422,7 +434,7 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, if (ret < 0) { dev_err(line6->ifcdev, "write request failed (error %d)\n", ret); - return ret; + goto out; } for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) { @@ -433,28 +445,32 @@ int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x0012, 0x0000, - &status, 1, LINE6_TIMEOUT * HZ); + status, 1, LINE6_TIMEOUT * HZ); if (ret < 0) { dev_err(line6->ifcdev, "receiving status failed (error %d)\n", ret); - return ret; + goto out; } - if (status != 0xff) + if (*status != 0xff) break; } - if (status == 0xff) { + if (*status == 0xff) { dev_err(line6->ifcdev, "write failed after %d retries\n", count); - return -EIO; - } else if (status != 0) { + ret = -EIO; + } else if (*status != 0) { dev_err(line6->ifcdev, "write failed (error %d)\n", ret); - return -EIO; + ret = -EIO; + } else { + ret = 0; } - return 0; +out: + kfree(status); + return ret; } EXPORT_SYMBOL_GPL(line6_write_data); diff --git a/sound/usb/line6/podhd.c b/sound/usb/line6/podhd.c index 6ab23e5aee71..b59939fa4d27 100644 --- a/sound/usb/line6/podhd.c +++ b/sound/usb/line6/podhd.c @@ -222,28 +222,32 @@ static void podhd_startup_start_workqueue(unsigned long data) static int podhd_dev_start(struct usb_line6_podhd *pod) { int ret; - u8 init_bytes[8]; + u8 *init_bytes; int i; struct usb_device *usbdev = pod->line6.usbdev; + init_bytes = kmalloc(8, GFP_ATOMIC); + if (!init_bytes) + return -ENOMEM; + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 0x11, 0, NULL, 0, LINE6_TIMEOUT * HZ); if (ret < 0) { dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); - return ret; + goto out; } /* NOTE: looks like some kind of ping message */ ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0x11, 0x0, - &init_bytes, 3, LINE6_TIMEOUT * HZ); + init_bytes, 3, LINE6_TIMEOUT * HZ); if (ret < 0) { dev_err(pod->line6.ifcdev, "receive length failed (error %d)\n", ret); - return ret; + goto out; } pod->firmware_version = @@ -252,7 +256,7 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) for (i = 0; i <= 16; i++) { ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8); if (ret < 0) - return ret; + goto out; } ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), @@ -260,10 +264,12 @@ static int podhd_dev_start(struct usb_line6_podhd *pod) USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, 1, 0, NULL, 0, LINE6_TIMEOUT * HZ); - if (ret < 0) - return ret; + if (ret > 0) + ret = 0; - return 0; +out: + kfree(init_bytes); + return ret; } static void podhd_startup_workqueue(struct work_struct *work) diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c index 646c27a79f68..62998af0db0b 100644 --- a/sound/usb/line6/toneport.c +++ b/sound/usb/line6/toneport.c @@ -367,14 +367,18 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport) */ static int toneport_setup(struct usb_line6_toneport *toneport) { - int ticks; + int *ticks; struct usb_line6 *line6 = &toneport->line6; struct usb_device *usbdev = line6->usbdev; int err; /* sync time on device with host: */ - ticks = (int)get_seconds(); - err = line6_write_data(line6, 0x80c6, &ticks, 4); + ticks = kmalloc(sizeof(*ticks), GFP_ATOMIC); + if (!ticks) + return -ENOMEM; + *ticks = (int)get_seconds(); + err = line6_write_data(line6, 0x80c6, ticks, 4); + kfree(ticks); if (err < 0) return err;
Attachment:
signature.asc
Description: This is a digitally signed message part