]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 9 Oct 2012 23:59:52 +0000 (08:59 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 9 Oct 2012 23:59:52 +0000 (08:59 +0900)
added patches:
hid-hidraw-don-t-deallocate-memory-when-it-is-in-use.patch

queue-3.6/hid-hidraw-don-t-deallocate-memory-when-it-is-in-use.patch [new file with mode: 0644]
queue-3.6/series

diff --git a/queue-3.6/hid-hidraw-don-t-deallocate-memory-when-it-is-in-use.patch b/queue-3.6/hid-hidraw-don-t-deallocate-memory-when-it-is-in-use.patch
new file mode 100644 (file)
index 0000000..ee552ad
--- /dev/null
@@ -0,0 +1,135 @@
+From 4fe9f8e203fdad1524c04beb390f3c6099781ed9 Mon Sep 17 00:00:00 2001
+From: Ratan Nalumasu <ratan@google.com>
+Date: Sat, 22 Sep 2012 11:46:30 -0700
+Subject: HID: hidraw: don't deallocate memory when it is in use
+
+From: Ratan Nalumasu <ratan@google.com>
+
+commit 4fe9f8e203fdad1524c04beb390f3c6099781ed9 upstream.
+
+When a device is unplugged, wait for all processes that have opened the device
+to close before deallocating the device.
+
+Signed-off-by: Ratan Nalumasu <ratan@google.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Cc: Kees Cook <keescook@chromium.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hidraw.c |   69 +++++++++++++++++++--------------------------------
+ 1 file changed, 26 insertions(+), 43 deletions(-)
+
+--- a/drivers/hid/hidraw.c
++++ b/drivers/hid/hidraw.c
+@@ -42,6 +42,7 @@ static struct cdev hidraw_cdev;
+ static struct class *hidraw_class;
+ static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
+ static DEFINE_MUTEX(minors_lock);
++static void drop_ref(struct hidraw *hid, int exists_bit);
+ static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+ {
+@@ -113,7 +114,7 @@ static ssize_t hidraw_send_report(struct
+       __u8 *buf;
+       int ret = 0;
+-      if (!hidraw_table[minor]) {
++      if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+               ret = -ENODEV;
+               goto out;
+       }
+@@ -261,7 +262,7 @@ static int hidraw_open(struct inode *ino
+       }
+       mutex_lock(&minors_lock);
+-      if (!hidraw_table[minor]) {
++      if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+               err = -ENODEV;
+               goto out_unlock;
+       }
+@@ -298,36 +299,12 @@ out:
+ static int hidraw_release(struct inode * inode, struct file * file)
+ {
+       unsigned int minor = iminor(inode);
+-      struct hidraw *dev;
+       struct hidraw_list *list = file->private_data;
+-      int ret;
+-      int i;
+-
+-      mutex_lock(&minors_lock);
+-      if (!hidraw_table[minor]) {
+-              ret = -ENODEV;
+-              goto unlock;
+-      }
++      drop_ref(hidraw_table[minor], 0);
+       list_del(&list->node);
+-      dev = hidraw_table[minor];
+-      if (!--dev->open) {
+-              if (list->hidraw->exist) {
+-                      hid_hw_power(dev->hid, PM_HINT_NORMAL);
+-                      hid_hw_close(dev->hid);
+-              } else {
+-                      kfree(list->hidraw);
+-              }
+-      }
+-
+-      for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
+-              kfree(list->buffer[i].value);
+       kfree(list);
+-      ret = 0;
+-unlock:
+-      mutex_unlock(&minors_lock);
+-
+-      return ret;
++      return 0;
+ }
+ static long hidraw_ioctl(struct file *file, unsigned int cmd,
+@@ -529,21 +506,7 @@ EXPORT_SYMBOL_GPL(hidraw_connect);
+ void hidraw_disconnect(struct hid_device *hid)
+ {
+       struct hidraw *hidraw = hid->hidraw;
+-
+-      mutex_lock(&minors_lock);
+-      hidraw->exist = 0;
+-
+-      device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+-
+-      hidraw_table[hidraw->minor] = NULL;
+-
+-      if (hidraw->open) {
+-              hid_hw_close(hid);
+-              wake_up_interruptible(&hidraw->wait);
+-      } else {
+-              kfree(hidraw);
+-      }
+-      mutex_unlock(&minors_lock);
++      drop_ref(hidraw, 1);
+ }
+ EXPORT_SYMBOL_GPL(hidraw_disconnect);
+@@ -585,3 +548,23 @@ void hidraw_exit(void)
+       unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
+ }
++
++static void drop_ref(struct hidraw *hidraw, int exists_bit)
++{
++      mutex_lock(&minors_lock);
++      if (exists_bit) {
++              hid_hw_close(hidraw->hid);
++              hidraw->exist = 0;
++              if (hidraw->open)
++                      wake_up_interruptible(&hidraw->wait);
++      } else {
++              --hidraw->open;
++      }
++
++      if (!hidraw->open && !hidraw->exist) {
++              device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
++              hidraw_table[hidraw->minor] = NULL;
++              kfree(hidraw);
++      }
++      mutex_unlock(&minors_lock);
++}
index 2210e648f130fc4895ad9f64e531c50d064aebc3..0a042ac1a3c1115750e683860092de8da32f7b56 100644 (file)
@@ -80,3 +80,4 @@ drm-radeon-kms-allow-strmout_base_update-on-rs780-and-rs880.patch
 drm-radeon-allow-mip_address-0-for-msaa-textures-on-evergreen.patch
 drm-radeon-add-msi-quirk-for-gateway-rs690.patch
 drm-radeon-force-msis-on-rs690-asics.patch
+hid-hidraw-don-t-deallocate-memory-when-it-is-in-use.patch