| From 12e4c2d493e12b50f41d49d6e8f5cba81c9dd013 Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Thu, 12 Jan 2017 18:17:42 +0100 |
| Subject: [PATCH] HID: corsair: fix DMA buffers on stack |
| |
| commit 6d104af38b570d37aa32a5803b04c354f8ed513d upstream. |
| |
| Not all platforms support DMA to the stack, and specifically since v4.9 |
| this is no longer supported on x86 with VMAP_STACK either. |
| |
| Note that the macro-mode buffer was larger than necessary. |
| |
| Fixes: 6f78193ee9ea ("HID: corsair: Add Corsair Vengeance K90 driver") |
| Cc: stable <stable@vger.kernel.org> |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Signed-off-by: Jiri Kosina <jkosina@suse.cz> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c |
| index 717704e9ae07..5971907a23b1 100644 |
| --- a/drivers/hid/hid-corsair.c |
| +++ b/drivers/hid/hid-corsair.c |
| @@ -148,7 +148,11 @@ static enum led_brightness k90_backlight_get(struct led_classdev *led_cdev) |
| struct usb_interface *usbif = to_usb_interface(dev->parent); |
| struct usb_device *usbdev = interface_to_usbdev(usbif); |
| int brightness; |
| - char data[8]; |
| + char *data; |
| + |
| + data = kmalloc(8, GFP_KERNEL); |
| + if (!data) |
| + return -ENOMEM; |
| |
| ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), |
| K90_REQUEST_STATUS, |
| @@ -158,16 +162,22 @@ static enum led_brightness k90_backlight_get(struct led_classdev *led_cdev) |
| if (ret < 0) { |
| dev_warn(dev, "Failed to get K90 initial state (error %d).\n", |
| ret); |
| - return -EIO; |
| + ret = -EIO; |
| + goto out; |
| } |
| brightness = data[4]; |
| if (brightness < 0 || brightness > 3) { |
| dev_warn(dev, |
| "Read invalid backlight brightness: %02hhx.\n", |
| data[4]); |
| - return -EIO; |
| + ret = -EIO; |
| + goto out; |
| } |
| - return brightness; |
| + ret = brightness; |
| +out: |
| + kfree(data); |
| + |
| + return ret; |
| } |
| |
| static enum led_brightness k90_record_led_get(struct led_classdev *led_cdev) |
| @@ -253,7 +263,11 @@ static ssize_t k90_show_macro_mode(struct device *dev, |
| struct usb_interface *usbif = to_usb_interface(dev->parent); |
| struct usb_device *usbdev = interface_to_usbdev(usbif); |
| const char *macro_mode; |
| - char data[8]; |
| + char *data; |
| + |
| + data = kmalloc(2, GFP_KERNEL); |
| + if (!data) |
| + return -ENOMEM; |
| |
| ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), |
| K90_REQUEST_GET_MODE, |
| @@ -263,7 +277,8 @@ static ssize_t k90_show_macro_mode(struct device *dev, |
| if (ret < 0) { |
| dev_warn(dev, "Failed to get K90 initial mode (error %d).\n", |
| ret); |
| - return -EIO; |
| + ret = -EIO; |
| + goto out; |
| } |
| |
| switch (data[0]) { |
| @@ -277,10 +292,15 @@ static ssize_t k90_show_macro_mode(struct device *dev, |
| default: |
| dev_warn(dev, "K90 in unknown mode: %02hhx.\n", |
| data[0]); |
| - return -EIO; |
| + ret = -EIO; |
| + goto out; |
| } |
| |
| - return snprintf(buf, PAGE_SIZE, "%s\n", macro_mode); |
| + ret = snprintf(buf, PAGE_SIZE, "%s\n", macro_mode); |
| +out: |
| + kfree(data); |
| + |
| + return ret; |
| } |
| |
| static ssize_t k90_store_macro_mode(struct device *dev, |
| @@ -320,7 +340,11 @@ static ssize_t k90_show_current_profile(struct device *dev, |
| struct usb_interface *usbif = to_usb_interface(dev->parent); |
| struct usb_device *usbdev = interface_to_usbdev(usbif); |
| int current_profile; |
| - char data[8]; |
| + char *data; |
| + |
| + data = kmalloc(8, GFP_KERNEL); |
| + if (!data) |
| + return -ENOMEM; |
| |
| ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), |
| K90_REQUEST_STATUS, |
| @@ -330,16 +354,22 @@ static ssize_t k90_show_current_profile(struct device *dev, |
| if (ret < 0) { |
| dev_warn(dev, "Failed to get K90 initial state (error %d).\n", |
| ret); |
| - return -EIO; |
| + ret = -EIO; |
| + goto out; |
| } |
| current_profile = data[7]; |
| if (current_profile < 1 || current_profile > 3) { |
| dev_warn(dev, "Read invalid current profile: %02hhx.\n", |
| data[7]); |
| - return -EIO; |
| + ret = -EIO; |
| + goto out; |
| } |
| |
| - return snprintf(buf, PAGE_SIZE, "%d\n", current_profile); |
| + ret = snprintf(buf, PAGE_SIZE, "%d\n", current_profile); |
| +out: |
| + kfree(data); |
| + |
| + return ret; |
| } |
| |
| static ssize_t k90_store_current_profile(struct device *dev, |
| -- |
| 2.10.1 |
| |