]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
.32 patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Wed, 15 Sep 2010 22:17:33 +0000 (15:17 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 15 Sep 2010 22:17:33 +0000 (15:17 -0700)
16 files changed:
queue-2.6.32/gcov-fix-null-pointer-dereference-for-certain-module-types.patch [new file with mode: 0644]
queue-2.6.32/hid-fix-suspend-crash-by-moving-initializations-earlier.patch [new file with mode: 0644]
queue-2.6.32/hid-usbhid-initialize-interface-pointers-early-enough.patch [new file with mode: 0644]
queue-2.6.32/irda-off-by-one.patch [new file with mode: 0644]
queue-2.6.32/libata-skip-eh-autopsy-and-recovery-during-suspend.patch [new file with mode: 0644]
queue-2.6.32/mmc-fix-the-use-of-kunmap_atomic-in-tmio_mmc.h.patch [new file with mode: 0644]
queue-2.6.32/oprofile-fix-crash-when-accessing-freed-task-structs.patch [new file with mode: 0644]
queue-2.6.32/oprofile-x86-fix-init_sysfs-error-handling.patch [new file with mode: 0644]
queue-2.6.32/oprofile-x86-fix-init_sysfs-function-stub.patch [new file with mode: 0644]
queue-2.6.32/series
queue-2.6.32/sysfs-checking-for-null-instead-of-err_ptr.patch [new file with mode: 0644]
queue-2.6.32/tmio_mmc-don-t-clear-unhandled-pending-interrupts.patch [new file with mode: 0644]
queue-2.6.32/tracing-do-not-allow-llseek-to-set_ftrace_filter.patch [new file with mode: 0644]
queue-2.6.32/tracing-fix-a-race-in-function-profile.patch [new file with mode: 0644]
queue-2.6.32/tracing-t_start-reset-ftrace_iter_hash-in-case-of-seek-pread.patch [new file with mode: 0644]
queue-2.6.32/tun-don-t-add-sysfs-attributes-to-devices-without-sysfs-directories.patch [new file with mode: 0644]

diff --git a/queue-2.6.32/gcov-fix-null-pointer-dereference-for-certain-module-types.patch b/queue-2.6.32/gcov-fix-null-pointer-dereference-for-certain-module-types.patch
new file mode 100644 (file)
index 0000000..dccdaaa
--- /dev/null
@@ -0,0 +1,404 @@
+From 85a0fdfd0f967507f3903e8419bc7e408f5a59de Mon Sep 17 00:00:00 2001
+From: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
+Date: Thu, 9 Sep 2010 16:37:35 -0700
+Subject: gcov: fix null-pointer dereference for certain module types
+
+From: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
+
+commit 85a0fdfd0f967507f3903e8419bc7e408f5a59de upstream.
+
+The gcov-kernel infrastructure expects that each object file is loaded
+only once.  This may not be true, e.g.  when loading multiple kernel
+modules which are linked to the same object file.  As a result, loading
+such kernel modules will result in incorrect gcov results while unloading
+will cause a null-pointer dereference.
+
+This patch fixes these problems by changing the gcov-kernel infrastructure
+so that multiple profiling data sets can be associated with one debugfs
+entry.  It applies to 2.6.36-rc1.
+
+Signed-off-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
+Reported-by: Werner Spies <werner.spies@thalesgroup.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/gcov/fs.c |  244 ++++++++++++++++++++++++++++++++++++++++---------------
+ 1 file changed, 180 insertions(+), 64 deletions(-)
+
+--- a/kernel/gcov/fs.c
++++ b/kernel/gcov/fs.c
+@@ -33,10 +33,11 @@
+  * @children: child nodes
+  * @all: list head for list of all nodes
+  * @parent: parent node
+- * @info: associated profiling data structure if not a directory
+- * @ghost: when an object file containing profiling data is unloaded we keep a
+- *         copy of the profiling data here to allow collecting coverage data
+- *         for cleanup code. Such a node is called a "ghost".
++ * @loaded_info: array of pointers to profiling data sets for loaded object
++ *   files.
++ * @num_loaded: number of profiling data sets for loaded object files.
++ * @unloaded_info: accumulated copy of profiling data sets for unloaded
++ *   object files. Used only when gcov_persist=1.
+  * @dentry: main debugfs entry, either a directory or data file
+  * @links: associated symbolic links
+  * @name: data file basename
+@@ -51,10 +52,11 @@ struct gcov_node {
+       struct list_head children;
+       struct list_head all;
+       struct gcov_node *parent;
+-      struct gcov_info *info;
+-      struct gcov_info *ghost;
++      struct gcov_info **loaded_info;
++      struct gcov_info *unloaded_info;
+       struct dentry *dentry;
+       struct dentry **links;
++      int num_loaded;
+       char name[0];
+ };
+@@ -136,16 +138,37 @@ static const struct seq_operations gcov_
+ };
+ /*
+- * Return the profiling data set for a given node. This can either be the
+- * original profiling data structure or a duplicate (also called "ghost")
+- * in case the associated object file has been unloaded.
++ * Return a profiling data set associated with the given node. This is
++ * either a data set for a loaded object file or a data set copy in case
++ * all associated object files have been unloaded.
+  */
+ static struct gcov_info *get_node_info(struct gcov_node *node)
+ {
+-      if (node->info)
+-              return node->info;
++      if (node->num_loaded > 0)
++              return node->loaded_info[0];
+-      return node->ghost;
++      return node->unloaded_info;
++}
++
++/*
++ * Return a newly allocated profiling data set which contains the sum of
++ * all profiling data associated with the given node.
++ */
++static struct gcov_info *get_accumulated_info(struct gcov_node *node)
++{
++      struct gcov_info *info;
++      int i = 0;
++
++      if (node->unloaded_info)
++              info = gcov_info_dup(node->unloaded_info);
++      else
++              info = gcov_info_dup(node->loaded_info[i++]);
++      if (!info)
++              return NULL;
++      for (; i < node->num_loaded; i++)
++              gcov_info_add(info, node->loaded_info[i]);
++
++      return info;
+ }
+ /*
+@@ -163,9 +186,10 @@ static int gcov_seq_open(struct inode *i
+       mutex_lock(&node_lock);
+       /*
+        * Read from a profiling data copy to minimize reference tracking
+-       * complexity and concurrent access.
++       * complexity and concurrent access and to keep accumulating multiple
++       * profiling data sets associated with one node simple.
+        */
+-      info = gcov_info_dup(get_node_info(node));
++      info = get_accumulated_info(node);
+       if (!info)
+               goto out_unlock;
+       iter = gcov_iter_new(info);
+@@ -225,12 +249,25 @@ static struct gcov_node *get_node_by_nam
+       return NULL;
+ }
++/*
++ * Reset all profiling data associated with the specified node.
++ */
++static void reset_node(struct gcov_node *node)
++{
++      int i;
++
++      if (node->unloaded_info)
++              gcov_info_reset(node->unloaded_info);
++      for (i = 0; i < node->num_loaded; i++)
++              gcov_info_reset(node->loaded_info[i]);
++}
++
+ static void remove_node(struct gcov_node *node);
+ /*
+  * write() implementation for gcov data files. Reset profiling data for the
+- * associated file. If the object file has been unloaded (i.e. this is
+- * a "ghost" node), remove the debug fs node as well.
++ * corresponding file. If all associated object files have been unloaded,
++ * remove the debug fs node as well.
+  */
+ static ssize_t gcov_seq_write(struct file *file, const char __user *addr,
+                             size_t len, loff_t *pos)
+@@ -245,10 +282,10 @@ static ssize_t gcov_seq_write(struct fil
+       node = get_node_by_name(info->filename);
+       if (node) {
+               /* Reset counts or remove node for unloaded modules. */
+-              if (node->ghost)
++              if (node->num_loaded == 0)
+                       remove_node(node);
+               else
+-                      gcov_info_reset(node->info);
++                      reset_node(node);
+       }
+       /* Reset counts for open file. */
+       gcov_info_reset(info);
+@@ -378,7 +415,10 @@ static void init_node(struct gcov_node *
+       INIT_LIST_HEAD(&node->list);
+       INIT_LIST_HEAD(&node->children);
+       INIT_LIST_HEAD(&node->all);
+-      node->info = info;
++      if (node->loaded_info) {
++              node->loaded_info[0] = info;
++              node->num_loaded = 1;
++      }
+       node->parent = parent;
+       if (name)
+               strcpy(node->name, name);
+@@ -394,9 +434,13 @@ static struct gcov_node *new_node(struct
+       struct gcov_node *node;
+       node = kzalloc(sizeof(struct gcov_node) + strlen(name) + 1, GFP_KERNEL);
+-      if (!node) {
+-              pr_warning("out of memory\n");
+-              return NULL;
++      if (!node)
++              goto err_nomem;
++      if (info) {
++              node->loaded_info = kcalloc(1, sizeof(struct gcov_info *),
++                                         GFP_KERNEL);
++              if (!node->loaded_info)
++                      goto err_nomem;
+       }
+       init_node(node, info, name, parent);
+       /* Differentiate between gcov data file nodes and directory nodes. */
+@@ -416,6 +460,11 @@ static struct gcov_node *new_node(struct
+       list_add(&node->all, &all_head);
+       return node;
++
++err_nomem:
++      kfree(node);
++      pr_warning("out of memory\n");
++      return NULL;
+ }
+ /* Remove symbolic links associated with node. */
+@@ -441,8 +490,9 @@ static void release_node(struct gcov_nod
+       list_del(&node->all);
+       debugfs_remove(node->dentry);
+       remove_links(node);
+-      if (node->ghost)
+-              gcov_info_free(node->ghost);
++      kfree(node->loaded_info);
++      if (node->unloaded_info)
++              gcov_info_free(node->unloaded_info);
+       kfree(node);
+ }
+@@ -477,7 +527,7 @@ static struct gcov_node *get_child_by_na
+ /*
+  * write() implementation for reset file. Reset all profiling data to zero
+- * and remove ghost nodes.
++ * and remove nodes for which all associated object files are unloaded.
+  */
+ static ssize_t reset_write(struct file *file, const char __user *addr,
+                          size_t len, loff_t *pos)
+@@ -487,8 +537,8 @@ static ssize_t reset_write(struct file *
+       mutex_lock(&node_lock);
+ restart:
+       list_for_each_entry(node, &all_head, all) {
+-              if (node->info)
+-                      gcov_info_reset(node->info);
++              if (node->num_loaded > 0)
++                      reset_node(node);
+               else if (list_empty(&node->children)) {
+                       remove_node(node);
+                       /* Several nodes may have gone - restart loop. */
+@@ -564,37 +614,115 @@ err_remove:
+ }
+ /*
+- * The profiling data set associated with this node is being unloaded. Store a
+- * copy of the profiling data and turn this node into a "ghost".
++ * Associate a profiling data set with an existing node. Needs to be called
++ * with node_lock held.
+  */
+-static int ghost_node(struct gcov_node *node)
++static void add_info(struct gcov_node *node, struct gcov_info *info)
+ {
+-      node->ghost = gcov_info_dup(node->info);
+-      if (!node->ghost) {
+-              pr_warning("could not save data for '%s' (out of memory)\n",
+-                         node->info->filename);
+-              return -ENOMEM;
++      struct gcov_info **loaded_info;
++      int num = node->num_loaded;
++
++      /*
++       * Prepare new array. This is done first to simplify cleanup in
++       * case the new data set is incompatible, the node only contains
++       * unloaded data sets and there's not enough memory for the array.
++       */
++      loaded_info = kcalloc(num + 1, sizeof(struct gcov_info *), GFP_KERNEL);
++      if (!loaded_info) {
++              pr_warning("could not add '%s' (out of memory)\n",
++                         info->filename);
++              return;
++      }
++      memcpy(loaded_info, node->loaded_info,
++             num * sizeof(struct gcov_info *));
++      loaded_info[num] = info;
++      /* Check if the new data set is compatible. */
++      if (num == 0) {
++              /*
++               * A module was unloaded, modified and reloaded. The new
++               * data set replaces the copy of the last one.
++               */
++              if (!gcov_info_is_compatible(node->unloaded_info, info)) {
++                      pr_warning("discarding saved data for %s "
++                                 "(incompatible version)\n", info->filename);
++                      gcov_info_free(node->unloaded_info);
++                      node->unloaded_info = NULL;
++              }
++      } else {
++              /*
++               * Two different versions of the same object file are loaded.
++               * The initial one takes precedence.
++               */
++              if (!gcov_info_is_compatible(node->loaded_info[0], info)) {
++                      pr_warning("could not add '%s' (incompatible "
++                                 "version)\n", info->filename);
++                      kfree(loaded_info);
++                      return;
++              }
+       }
+-      node->info = NULL;
++      /* Overwrite previous array. */
++      kfree(node->loaded_info);
++      node->loaded_info = loaded_info;
++      node->num_loaded = num + 1;
++}
+-      return 0;
++/*
++ * Return the index of a profiling data set associated with a node.
++ */
++static int get_info_index(struct gcov_node *node, struct gcov_info *info)
++{
++      int i;
++
++      for (i = 0; i < node->num_loaded; i++) {
++              if (node->loaded_info[i] == info)
++                      return i;
++      }
++      return -ENOENT;
+ }
+ /*
+- * Profiling data for this node has been loaded again. Add profiling data
+- * from previous instantiation and turn this node into a regular node.
++ * Save the data of a profiling data set which is being unloaded.
+  */
+-static void revive_node(struct gcov_node *node, struct gcov_info *info)
++static void save_info(struct gcov_node *node, struct gcov_info *info)
+ {
+-      if (gcov_info_is_compatible(node->ghost, info))
+-              gcov_info_add(info, node->ghost);
++      if (node->unloaded_info)
++              gcov_info_add(node->unloaded_info, info);
+       else {
+-              pr_warning("discarding saved data for '%s' (version changed)\n",
++              node->unloaded_info = gcov_info_dup(info);
++              if (!node->unloaded_info) {
++                      pr_warning("could not save data for '%s' "
++                                 "(out of memory)\n", info->filename);
++              }
++      }
++}
++
++/*
++ * Disassociate a profiling data set from a node. Needs to be called with
++ * node_lock held.
++ */
++static void remove_info(struct gcov_node *node, struct gcov_info *info)
++{
++      int i;
++
++      i = get_info_index(node, info);
++      if (i < 0) {
++              pr_warning("could not remove '%s' (not found)\n",
+                          info->filename);
++              return;
+       }
+-      gcov_info_free(node->ghost);
+-      node->ghost = NULL;
+-      node->info = info;
++      if (gcov_persist)
++              save_info(node, info);
++      /* Shrink array. */
++      node->loaded_info[i] = node->loaded_info[node->num_loaded - 1];
++      node->num_loaded--;
++      if (node->num_loaded > 0)
++              return;
++      /* Last loaded data set was removed. */
++      kfree(node->loaded_info);
++      node->loaded_info = NULL;
++      node->num_loaded = 0;
++      if (!node->unloaded_info)
++              remove_node(node);
+ }
+ /*
+@@ -609,30 +737,18 @@ void gcov_event(enum gcov_action action,
+       node = get_node_by_name(info->filename);
+       switch (action) {
+       case GCOV_ADD:
+-              /* Add new node or revive ghost. */
+-              if (!node) {
++              if (node)
++                      add_info(node, info);
++              else
+                       add_node(info);
+-                      break;
+-              }
+-              if (gcov_persist)
+-                      revive_node(node, info);
+-              else {
+-                      pr_warning("could not add '%s' (already exists)\n",
+-                                 info->filename);
+-              }
+               break;
+       case GCOV_REMOVE:
+-              /* Remove node or turn into ghost. */
+-              if (!node) {
++              if (node)
++                      remove_info(node, info);
++              else {
+                       pr_warning("could not remove '%s' (not found)\n",
+                                  info->filename);
+-                      break;
+               }
+-              if (gcov_persist) {
+-                      if (!ghost_node(node))
+-                              break;
+-              }
+-              remove_node(node);
+               break;
+       }
+       mutex_unlock(&node_lock);
diff --git a/queue-2.6.32/hid-fix-suspend-crash-by-moving-initializations-earlier.patch b/queue-2.6.32/hid-fix-suspend-crash-by-moving-initializations-earlier.patch
new file mode 100644 (file)
index 0000000..f36f0e8
--- /dev/null
@@ -0,0 +1,61 @@
+From fde4e2f73208b8f34f123791e39c0cb6bc74b32a Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Fri, 7 May 2010 10:41:10 -0400
+Subject: HID: fix suspend crash by moving initializations earlier
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit fde4e2f73208b8f34f123791e39c0cb6bc74b32a upstream.
+
+Although the usbhid driver allocates its usbhid structure in the probe
+routine, several critical fields in that structure don't get
+initialized until usbhid_start().  However if report descriptor
+parsing fails then usbhid_start() is never called.  This leads to
+problems during system suspend -- the system will freeze.
+
+This patch (as1378) fixes the bug by moving the initialization
+statements up into usbhid_probe().
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Reported-by: Bruno Prémont <bonbons@linux-vserver.org>
+Tested-By: Bruno Prémont <bonbons@linux-vserver.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Cc: maximilian attems <max@stro.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/hid/usbhid/hid-core.c |   13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -1000,13 +1000,6 @@ static int usbhid_start(struct hid_devic
+               }
+       }
+-      init_waitqueue_head(&usbhid->wait);
+-      INIT_WORK(&usbhid->reset_work, hid_reset);
+-      INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
+-      setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
+-
+-      spin_lock_init(&usbhid->lock);
+-
+       usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
+       if (!usbhid->urbctrl) {
+               ret = -ENOMEM;
+@@ -1180,6 +1173,12 @@ static int usbhid_probe(struct usb_inter
+       usbhid->intf = intf;
+       usbhid->ifnum = interface->desc.bInterfaceNumber;
++      init_waitqueue_head(&usbhid->wait);
++      INIT_WORK(&usbhid->reset_work, hid_reset);
++      INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues);
++      setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
++      spin_lock_init(&usbhid->lock);
++
+       ret = hid_add_device(hid);
+       if (ret) {
+               if (ret != -ENODEV)
diff --git a/queue-2.6.32/hid-usbhid-initialize-interface-pointers-early-enough.patch b/queue-2.6.32/hid-usbhid-initialize-interface-pointers-early-enough.patch
new file mode 100644 (file)
index 0000000..33c7a9c
--- /dev/null
@@ -0,0 +1,50 @@
+From 57ab12e418ec4fe24c11788bb1bbdabb29d05679 Mon Sep 17 00:00:00 2001
+From: Jiri Kosina <jkosina@suse.cz>
+Date: Wed, 17 Feb 2010 14:25:01 +0100
+Subject: HID: usbhid: initialize interface pointers early enough
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jiri Kosina <jkosina@suse.cz>
+
+commit 57ab12e418ec4fe24c11788bb1bbdabb29d05679 upstream.
+
+Move the initialization of USB interface pointers from _start()
+over to _probe() callback, which is where it belongs.
+
+This fixes case where interface is NULL when parsing of report
+descriptor fails.
+
+LKML-Reference: <20100213135720.603e5f64@neptune.home>
+Reported-by: Alan Stern <stern@rowland.harvard.edu>
+Tested-by: Bruno Prémont <bonbons@linux-vserver.org>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Cc: maximilian attems <max@stro.at>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/hid/usbhid/hid-core.c |    5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/hid/usbhid/hid-core.c
++++ b/drivers/hid/usbhid/hid-core.c
+@@ -1007,9 +1007,6 @@ static int usbhid_start(struct hid_devic
+       spin_lock_init(&usbhid->lock);
+-      usbhid->intf = intf;
+-      usbhid->ifnum = interface->desc.bInterfaceNumber;
+-
+       usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
+       if (!usbhid->urbctrl) {
+               ret = -ENOMEM;
+@@ -1180,6 +1177,8 @@ static int usbhid_probe(struct usb_inter
+       hid->driver_data = usbhid;
+       usbhid->hid = hid;
++      usbhid->intf = intf;
++      usbhid->ifnum = interface->desc.bInterfaceNumber;
+       ret = hid_add_device(hid);
+       if (ret) {
diff --git a/queue-2.6.32/irda-off-by-one.patch b/queue-2.6.32/irda-off-by-one.patch
new file mode 100644 (file)
index 0000000..a59d7a6
--- /dev/null
@@ -0,0 +1,33 @@
+From cf9b94f88bdbe8a02015fc30d7c232b2d262d4ad Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <error27@gmail.com>
+Date: Sat, 4 Sep 2010 03:14:35 +0000
+Subject: irda: off by one
+
+From: Dan Carpenter <error27@gmail.com>
+
+commit cf9b94f88bdbe8a02015fc30d7c232b2d262d4ad upstream.
+
+This is an off by one.  We would go past the end when we NUL terminate
+the "value" string at end of the function.  The "value" buffer is
+allocated in irlan_client_parse_response() or
+irlan_provider_parse_command().
+
+CC: stable@kernel.org
+Signed-off-by: Dan Carpenter <error27@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+
+---
+ net/irda/irlan/irlan_common.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/irda/irlan/irlan_common.c
++++ b/net/irda/irlan/irlan_common.c
+@@ -1101,7 +1101,7 @@ int irlan_extract_param(__u8 *buf, char
+       memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
+       le16_to_cpus(&val_len); n+=2;
+-      if (val_len > 1016) {
++      if (val_len >= 1016) {
+               IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ );
+               return -RSP_INVALID_COMMAND_FORMAT;
+       }
diff --git a/queue-2.6.32/libata-skip-eh-autopsy-and-recovery-during-suspend.patch b/queue-2.6.32/libata-skip-eh-autopsy-and-recovery-during-suspend.patch
new file mode 100644 (file)
index 0000000..9f5c1e0
--- /dev/null
@@ -0,0 +1,78 @@
+From e2f3d75fc0e4a0d03c61872bad39ffa2e74a04ff Mon Sep 17 00:00:00 2001
+From: Tejun Heo <htejun@gmail.com>
+Date: Tue, 7 Sep 2010 14:05:31 +0200
+Subject: libata: skip EH autopsy and recovery during suspend
+
+From: Tejun Heo <htejun@gmail.com>
+
+commit e2f3d75fc0e4a0d03c61872bad39ffa2e74a04ff upstream.
+
+For some mysterious reason, certain hardware reacts badly to usual EH
+actions while the system is going for suspend.  As the devices won't
+be needed until the system is resumed, ask EH to skip usual autopsy
+and recovery and proceed directly to suspend.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Tested-by: Stephan Diestelhorst <stephan.diestelhorst@amd.com>
+Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/ata/libata-core.c |   14 +++++++++++++-
+ drivers/ata/libata-eh.c   |    4 ++++
+ include/linux/libata.h    |    1 +
+ 3 files changed, 18 insertions(+), 1 deletion(-)
+
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -5504,6 +5504,7 @@ static int ata_host_request_pm(struct at
+  */
+ int ata_host_suspend(struct ata_host *host, pm_message_t mesg)
+ {
++      unsigned int ehi_flags = ATA_EHI_QUIET;
+       int rc;
+       /*
+@@ -5512,7 +5513,18 @@ int ata_host_suspend(struct ata_host *ho
+        */
+       ata_lpm_enable(host);
+-      rc = ata_host_request_pm(host, mesg, 0, ATA_EHI_QUIET, 1);
++      /*
++       * On some hardware, device fails to respond after spun down
++       * for suspend.  As the device won't be used before being
++       * resumed, we don't need to touch the device.  Ask EH to skip
++       * the usual stuff and proceed directly to suspend.
++       *
++       * http://thread.gmane.org/gmane.linux.ide/46764
++       */
++      if (mesg.event == PM_EVENT_SUSPEND)
++              ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY;
++
++      rc = ata_host_request_pm(host, mesg, 0, ehi_flags, 1);
+       if (rc == 0)
+               host->dev->power.power_state = mesg;
+       return rc;
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -3149,6 +3149,10 @@ static int ata_eh_skip_recovery(struct a
+       if (link->flags & ATA_LFLAG_DISABLED)
+               return 1;
++      /* skip if explicitly requested */
++      if (ehc->i.flags & ATA_EHI_NO_RECOVERY)
++              return 1;
++
+       /* thaw frozen port and recover failed devices */
+       if ((ap->pflags & ATA_PFLAG_FROZEN) || ata_link_nr_enabled(link))
+               return 0;
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -339,6 +339,7 @@ enum {
+       ATA_EHI_HOTPLUGGED      = (1 << 0),  /* could have been hotplugged */
+       ATA_EHI_NO_AUTOPSY      = (1 << 2),  /* no autopsy */
+       ATA_EHI_QUIET           = (1 << 3),  /* be quiet */
++      ATA_EHI_NO_RECOVERY     = (1 << 4),  /* no recovery */
+       ATA_EHI_DID_SOFTRESET   = (1 << 16), /* already soft-reset this port */
+       ATA_EHI_DID_HARDRESET   = (1 << 17), /* already soft-reset this port */
diff --git a/queue-2.6.32/mmc-fix-the-use-of-kunmap_atomic-in-tmio_mmc.h.patch b/queue-2.6.32/mmc-fix-the-use-of-kunmap_atomic-in-tmio_mmc.h.patch
new file mode 100644 (file)
index 0000000..571bcb5
--- /dev/null
@@ -0,0 +1,84 @@
+From 5600efb1bc2745d93ae0bc08130117a84f2b9d69 Mon Sep 17 00:00:00 2001
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Date: Thu, 9 Sep 2010 16:37:43 -0700
+Subject: mmc: fix the use of kunmap_atomic() in tmio_mmc.h
+
+From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+
+commit 5600efb1bc2745d93ae0bc08130117a84f2b9d69 upstream.
+
+kunmap_atomic() takes the cookie, returned by the kmap_atomic() as its
+argument and not the page address, used as an argument to kmap_atomic().
+This patch fixes the compile error:
+
+In file included from drivers/mmc/host/tmio_mmc.c:37:
+drivers/mmc/host/tmio_mmc.h: In function 'tmio_mmc_kunmap_atomic':
+drivers/mmc/host/tmio_mmc.h:192: error: negative width in bit-field '<anonymous>'
+
+Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+Acked-by: Eric Miao <eric.y.miao@gmail.com>
+Tested-by: Magnus Damm <damm@opensource.se>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/mmc/host/tmio_mmc.c |    7 ++++---
+ drivers/mmc/host/tmio_mmc.h |    8 +++-----
+ 2 files changed, 7 insertions(+), 8 deletions(-)
+
+--- a/drivers/mmc/host/tmio_mmc.c
++++ b/drivers/mmc/host/tmio_mmc.c
+@@ -161,6 +161,7 @@ tmio_mmc_start_command(struct tmio_mmc_h
+ static inline void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
+ {
+       struct mmc_data *data = host->data;
++      void *sg_virt;
+       unsigned short *buf;
+       unsigned int count;
+       unsigned long flags;
+@@ -170,8 +171,8 @@ static inline void tmio_mmc_pio_irq(stru
+               return;
+       }
+-      buf = (unsigned short *)(tmio_mmc_kmap_atomic(host, &flags) +
+-            host->sg_off);
++      sg_virt = tmio_mmc_kmap_atomic(host->sg_ptr, &flags);
++      buf = (unsigned short *)(sg_virt + host->sg_off);
+       count = host->sg_ptr->length - host->sg_off;
+       if (count > data->blksz)
+@@ -188,7 +189,7 @@ static inline void tmio_mmc_pio_irq(stru
+       host->sg_off += count;
+-      tmio_mmc_kunmap_atomic(host, &flags);
++      tmio_mmc_kunmap_atomic(sg_virt, &flags);
+       if (host->sg_off == host->sg_ptr->length)
+               tmio_mmc_next_sg(host);
+--- a/drivers/mmc/host/tmio_mmc.h
++++ b/drivers/mmc/host/tmio_mmc.h
+@@ -197,19 +197,17 @@ static inline int tmio_mmc_next_sg(struc
+       return --host->sg_len;
+ }
+-static inline char *tmio_mmc_kmap_atomic(struct tmio_mmc_host *host,
++static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
+       unsigned long *flags)
+ {
+-      struct scatterlist *sg = host->sg_ptr;
+-
+       local_irq_save(*flags);
+       return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
+ }
+-static inline void tmio_mmc_kunmap_atomic(struct tmio_mmc_host *host,
++static inline void tmio_mmc_kunmap_atomic(void *virt,
+       unsigned long *flags)
+ {
+-      kunmap_atomic(sg_page(host->sg_ptr), KM_BIO_SRC_IRQ);
++      kunmap_atomic(virt, KM_BIO_SRC_IRQ);
+       local_irq_restore(*flags);
+ }
diff --git a/queue-2.6.32/oprofile-fix-crash-when-accessing-freed-task-structs.patch b/queue-2.6.32/oprofile-fix-crash-when-accessing-freed-task-structs.patch
new file mode 100644 (file)
index 0000000..2631f17
--- /dev/null
@@ -0,0 +1,132 @@
+From 750d857c682f4db60d14722d430c7ccc35070962 Mon Sep 17 00:00:00 2001
+From: Robert Richter <robert.richter@amd.com>
+Date: Fri, 13 Aug 2010 16:29:04 +0200
+Subject: oprofile: fix crash when accessing freed task structs
+
+From: Robert Richter <robert.richter@amd.com>
+
+commit 750d857c682f4db60d14722d430c7ccc35070962 upstream.
+
+This patch fixes a crash during shutdown reported below. The crash is
+caused by accessing already freed task structs. The fix changes the
+order for registering and unregistering notifier callbacks.
+
+All notifiers must be initialized before buffers start working. To
+stop buffer synchronization we cancel all workqueues, unregister the
+notifier callback and then flush all buffers. After all of this we
+finally can free all tasks listed.
+
+This should avoid accessing freed tasks.
+
+On 22.07.10 01:14:40, Benjamin Herrenschmidt wrote:
+
+> So the initial observation is a spinlock bad magic followed by a crash
+> in the spinlock debug code:
+>
+> [ 1541.586531] BUG: spinlock bad magic on CPU#5, events/5/136
+> [ 1541.597564] Unable to handle kernel paging request for data at address 0x6b6b6b6b6b6b6d03
+>
+> Backtrace looks like:
+>
+>       spin_bug+0x74/0xd4
+>       ._raw_spin_lock+0x48/0x184
+>       ._spin_lock+0x10/0x24
+>       .get_task_mm+0x28/0x8c
+>       .sync_buffer+0x1b4/0x598
+>       .wq_sync_buffer+0xa0/0xdc
+>       .worker_thread+0x1d8/0x2a8
+>       .kthread+0xa8/0xb4
+>       .kernel_thread+0x54/0x70
+>
+> So we are accessing a freed task struct in the work queue when
+> processing the samples.
+
+Reported-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Signed-off-by: Robert Richter <robert.richter@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/oprofile/buffer_sync.c |   27 ++++++++++++++-------------
+ drivers/oprofile/cpu_buffer.c  |    2 --
+ 2 files changed, 14 insertions(+), 15 deletions(-)
+
+--- a/drivers/oprofile/buffer_sync.c
++++ b/drivers/oprofile/buffer_sync.c
+@@ -140,16 +140,6 @@ static struct notifier_block module_load
+       .notifier_call = module_load_notify,
+ };
+-
+-static void end_sync(void)
+-{
+-      end_cpu_work();
+-      /* make sure we don't leak task structs */
+-      process_task_mortuary();
+-      process_task_mortuary();
+-}
+-
+-
+ int sync_start(void)
+ {
+       int err;
+@@ -157,7 +147,7 @@ int sync_start(void)
+       if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL))
+               return -ENOMEM;
+-      start_cpu_work();
++      mutex_lock(&buffer_mutex);
+       err = task_handoff_register(&task_free_nb);
+       if (err)
+@@ -172,7 +162,10 @@ int sync_start(void)
+       if (err)
+               goto out4;
++      start_cpu_work();
++
+ out:
++      mutex_unlock(&buffer_mutex);
+       return err;
+ out4:
+       profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
+@@ -181,7 +174,6 @@ out3:
+ out2:
+       task_handoff_unregister(&task_free_nb);
+ out1:
+-      end_sync();
+       free_cpumask_var(marked_cpus);
+       goto out;
+ }
+@@ -189,11 +181,20 @@ out1:
+ void sync_stop(void)
+ {
++      /* flush buffers */
++      mutex_lock(&buffer_mutex);
++      end_cpu_work();
+       unregister_module_notifier(&module_load_nb);
+       profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
+       profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
+       task_handoff_unregister(&task_free_nb);
+-      end_sync();
++      mutex_unlock(&buffer_mutex);
++      flush_scheduled_work();
++
++      /* make sure we don't leak task structs */
++      process_task_mortuary();
++      process_task_mortuary();
++
+       free_cpumask_var(marked_cpus);
+ }
+--- a/drivers/oprofile/cpu_buffer.c
++++ b/drivers/oprofile/cpu_buffer.c
+@@ -121,8 +121,6 @@ void end_cpu_work(void)
+               cancel_delayed_work(&b->work);
+       }
+-
+-      flush_scheduled_work();
+ }
+ /*
diff --git a/queue-2.6.32/oprofile-x86-fix-init_sysfs-error-handling.patch b/queue-2.6.32/oprofile-x86-fix-init_sysfs-error-handling.patch
new file mode 100644 (file)
index 0000000..d28cec7
--- /dev/null
@@ -0,0 +1,59 @@
+From 10f0412f57f2a76a90eff4376f59cbb0a39e4e18 Mon Sep 17 00:00:00 2001
+From: Robert Richter <robert.richter@amd.com>
+Date: Mon, 30 Aug 2010 10:56:18 +0200
+Subject: oprofile, x86: fix init_sysfs error handling
+
+From: Robert Richter <robert.richter@amd.com>
+
+commit 10f0412f57f2a76a90eff4376f59cbb0a39e4e18 upstream.
+
+On failure init_sysfs() might not properly free resources. The error
+code of the function is not checked. And, when reinitializing the exit
+function might be called twice. This patch fixes all this.
+
+Signed-off-by: Robert Richter <robert.richter@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/oprofile/nmi_int.c |   16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/oprofile/nmi_int.c
++++ b/arch/x86/oprofile/nmi_int.c
+@@ -518,8 +518,13 @@ static int __init init_sysfs(void)
+       int error;
+       error = sysdev_class_register(&oprofile_sysclass);
+-      if (!error)
+-              error = sysdev_register(&device_oprofile);
++      if (error)
++              return error;
++
++      error = sysdev_register(&device_oprofile);
++      if (error)
++              sysdev_class_unregister(&oprofile_sysclass);
++
+       return error;
+ }
+@@ -645,6 +650,8 @@ int __init op_nmi_init(struct oprofile_o
+       char *cpu_type = NULL;
+       int ret = 0;
++      using_nmi = 0;
++
+       if (!cpu_has_apic)
+               return -ENODEV;
+@@ -727,7 +734,10 @@ int __init op_nmi_init(struct oprofile_o
+       mux_init(ops);
+-      init_sysfs();
++      ret = init_sysfs();
++      if (ret)
++              return ret;
++
+       using_nmi = 1;
+       printk(KERN_INFO "oprofile: using NMI interrupt.\n");
+       return 0;
diff --git a/queue-2.6.32/oprofile-x86-fix-init_sysfs-function-stub.patch b/queue-2.6.32/oprofile-x86-fix-init_sysfs-function-stub.patch
new file mode 100644 (file)
index 0000000..4653491
--- /dev/null
@@ -0,0 +1,48 @@
+From 269f45c25028c75fe10e6d9be86e7202ab461fbc Mon Sep 17 00:00:00 2001
+From: Robert Richter <robert.richter@amd.com>
+Date: Wed, 1 Sep 2010 14:50:50 +0200
+Subject: oprofile, x86: fix init_sysfs() function stub
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Robert Richter <robert.richter@amd.com>
+
+commit 269f45c25028c75fe10e6d9be86e7202ab461fbc upstream.
+
+The use of the return value of init_sysfs() with commit
+
+ 10f0412 oprofile, x86: fix init_sysfs error handling
+
+discovered the following build error for !CONFIG_PM:
+
+ .../linux/arch/x86/oprofile/nmi_int.c: In function ‘op_nmi_init’:
+ .../linux/arch/x86/oprofile/nmi_int.c:784: error: expected expression before ‘do’
+ make[2]: *** [arch/x86/oprofile/nmi_int.o] Error 1
+ make[1]: *** [arch/x86/oprofile] Error 2
+
+This patch fixes this.
+
+Reported-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Robert Richter <robert.richter@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ arch/x86/oprofile/nmi_int.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/oprofile/nmi_int.c
++++ b/arch/x86/oprofile/nmi_int.c
+@@ -535,8 +535,10 @@ static void exit_sysfs(void)
+ }
+ #else
+-#define init_sysfs() do { } while (0)
+-#define exit_sysfs() do { } while (0)
++
++static inline int  init_sysfs(void) { return 0; }
++static inline void exit_sysfs(void) { }
++
+ #endif /* CONFIG_PM */
+ static int __init p4_init(char **cpu_type)
index 2985ef8ec91e1c0bb211e63346ef9c8680462d6c..119eb0917048b777d017645cc4c02054f072de96 100644 (file)
@@ -33,3 +33,18 @@ usb-cdc-acm-add-pseudo-modem-without-at-command-capabilities.patch
 usb-cdc-acm-fixing-crash-when-acm-probing-interfaces-with-no-endpoint-descriptors.patch
 alsa-hda-fix-auto-parser-of-alc269vb-for-hp-pin-nid-0x21.patch
 alsa-seq-oss-fix-double-free-at-error-path-of-snd_seq_oss_open.patch
+sysfs-checking-for-null-instead-of-err_ptr.patch
+tun-don-t-add-sysfs-attributes-to-devices-without-sysfs-directories.patch
+oprofile-fix-crash-when-accessing-freed-task-structs.patch
+oprofile-x86-fix-init_sysfs-error-handling.patch
+oprofile-x86-fix-init_sysfs-function-stub.patch
+hid-usbhid-initialize-interface-pointers-early-enough.patch
+hid-fix-suspend-crash-by-moving-initializations-earlier.patch
+libata-skip-eh-autopsy-and-recovery-during-suspend.patch
+tracing-fix-a-race-in-function-profile.patch
+tracing-do-not-allow-llseek-to-set_ftrace_filter.patch
+tracing-t_start-reset-ftrace_iter_hash-in-case-of-seek-pread.patch
+irda-off-by-one.patch
+gcov-fix-null-pointer-dereference-for-certain-module-types.patch
+tmio_mmc-don-t-clear-unhandled-pending-interrupts.patch
+mmc-fix-the-use-of-kunmap_atomic-in-tmio_mmc.h.patch
diff --git a/queue-2.6.32/sysfs-checking-for-null-instead-of-err_ptr.patch b/queue-2.6.32/sysfs-checking-for-null-instead-of-err_ptr.patch
new file mode 100644 (file)
index 0000000..5517364
--- /dev/null
@@ -0,0 +1,30 @@
+From 57f9bdac2510cd7fda58e4a111d250861eb1ebeb Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <error27@gmail.com>
+Date: Wed, 25 Aug 2010 09:12:29 +0200
+Subject: sysfs: checking for NULL instead of ERR_PTR
+
+From: Dan Carpenter <error27@gmail.com>
+
+commit 57f9bdac2510cd7fda58e4a111d250861eb1ebeb upstream.
+
+d_path() returns an ERR_PTR and it doesn't return NULL.
+
+Signed-off-by: Dan Carpenter <error27@gmail.com>
+Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ fs/sysfs/file.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/sysfs/file.c
++++ b/fs/sysfs/file.c
+@@ -340,7 +340,7 @@ static int sysfs_open_file(struct inode
+       char *p;
+       p = d_path(&file->f_path, last_sysfs_file, sizeof(last_sysfs_file));
+-      if (p)
++      if (!IS_ERR(p))
+               memmove(last_sysfs_file, p, strlen(p) + 1);
+       /* need attr_sd for attr and ops, its parent for kobj */
diff --git a/queue-2.6.32/tmio_mmc-don-t-clear-unhandled-pending-interrupts.patch b/queue-2.6.32/tmio_mmc-don-t-clear-unhandled-pending-interrupts.patch
new file mode 100644 (file)
index 0000000..a1902da
--- /dev/null
@@ -0,0 +1,53 @@
+From b78d6c5f51935ba89df8db33a57bacb547aa7325 Mon Sep 17 00:00:00 2001
+From: Yusuke Goda <yusuke.goda.sx@renesas.com>
+Date: Thu, 9 Sep 2010 16:37:39 -0700
+Subject: tmio_mmc: don't clear unhandled pending interrupts
+
+From: Yusuke Goda <yusuke.goda.sx@renesas.com>
+
+commit b78d6c5f51935ba89df8db33a57bacb547aa7325 upstream.
+
+Previously, it was possible for ack_mmc_irqs() to clear pending interrupt
+bits in the CTL_STATUS register, even though the interrupt handler had not
+been called.  This was because of a race that existed when doing a
+read-modify-write sequence on CTL_STATUS.  After the read step in this
+sequence, if an interrupt occurred (causing one of the bits in CTL_STATUS
+to be set) the write step would inadvertently clear it.
+
+Observed with the TMIO_STAT_RXRDY bit together with CMD53 on AR6002 and
+BCM4318 SDIO cards in polled mode.
+
+This patch eliminates this race by only writing to CTL_STATUS and clearing
+the interrupts that were passed as an argument to ack_mmc_irqs()."
+
+[matt@console-pimps.org: rewrote changelog]
+Signed-off-by: Yusuke Goda <yusuke.goda.sx@renesas.com>
+Acked-by: Magnus Damm <damm@opensource.se>"
+Tested-by: Arnd Hannemann <arnd@arndnet.de>"
+Acked-by: Ian Molton <ian@mnementh.co.uk>
+Cc: Matt Fleming <matt@console-pimps.org>
+Cc: Samuel Ortiz <sameo@linux.intel.com>
+Cc: Paul Mundt <lethal@linux-sh.org>
+Cc: <linux-mmc@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/mmc/host/tmio_mmc.h |    5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/drivers/mmc/host/tmio_mmc.h
++++ b/drivers/mmc/host/tmio_mmc.h
+@@ -102,10 +102,7 @@
+ #define ack_mmc_irqs(host, i) \
+       do { \
+-              u32 mask;\
+-              mask  = sd_ctrl_read32((host), CTL_STATUS); \
+-              mask &= ~((i) & TMIO_MASK_IRQ); \
+-              sd_ctrl_write32((host), CTL_STATUS, mask); \
++              sd_ctrl_write32((host), CTL_STATUS, ~(i)); \
+       } while (0)
diff --git a/queue-2.6.32/tracing-do-not-allow-llseek-to-set_ftrace_filter.patch b/queue-2.6.32/tracing-do-not-allow-llseek-to-set_ftrace_filter.patch
new file mode 100644 (file)
index 0000000..f71a8a6
--- /dev/null
@@ -0,0 +1,54 @@
+From 9c55cb12c1c172e2d51e85fbb5a4796ca86b77e7 Mon Sep 17 00:00:00 2001
+From: Steven Rostedt <srostedt@redhat.com>
+Date: Wed, 8 Sep 2010 11:20:37 -0400
+Subject: tracing: Do not allow llseek to set_ftrace_filter
+
+From: Steven Rostedt <srostedt@redhat.com>
+
+commit 9c55cb12c1c172e2d51e85fbb5a4796ca86b77e7 upstream.
+
+Reading the file set_ftrace_filter does three things.
+
+1) shows whether or not filters are set for the function tracer
+2) shows what functions are set for the function tracer
+3) shows what triggers are set on any functions
+
+3 is independent from 1 and 2.
+
+The way this file currently works is that it is a state machine,
+and as you read it, it may change state. But this assumption breaks
+when you use lseek() on the file. The state machine gets out of sync
+and the t_show() may use the wrong pointer and cause a kernel oops.
+
+Luckily, this will only kill the app that does the lseek, but the app
+dies while holding a mutex. This prevents anyone else from using the
+set_ftrace_filter file (or any other function tracing file for that matter).
+
+A real fix for this is to rewrite the code, but that is too much for
+a -rc release or stable. This patch simply disables llseek on the
+set_ftrace_filter() file for now, and we can do the proper fix for the
+next major release.
+
+Reported-by: Robert Swiecki <swiecki@google.com>
+Cc: Chris Wright <chrisw@sous-sol.org>
+Cc: Tavis Ormandy <taviso@google.com>
+Cc: Eugene Teo <eugene@redhat.com>
+Cc: vendor-sec@lst.de
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/trace/ftrace.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -2400,7 +2400,7 @@ static const struct file_operations ftra
+       .open = ftrace_filter_open,
+       .read = seq_read,
+       .write = ftrace_filter_write,
+-      .llseek = ftrace_regex_lseek,
++      .llseek = no_llseek,
+       .release = ftrace_filter_release,
+ };
diff --git a/queue-2.6.32/tracing-fix-a-race-in-function-profile.patch b/queue-2.6.32/tracing-fix-a-race-in-function-profile.patch
new file mode 100644 (file)
index 0000000..981fd1a
--- /dev/null
@@ -0,0 +1,73 @@
+From 3aaba20f26f58843e8f20611e5c0b1c06954310f Mon Sep 17 00:00:00 2001
+From: Li Zefan <lizf@cn.fujitsu.com>
+Date: Mon, 23 Aug 2010 16:50:12 +0800
+Subject: tracing: Fix a race in function profile
+
+From: Li Zefan <lizf@cn.fujitsu.com>
+
+commit 3aaba20f26f58843e8f20611e5c0b1c06954310f upstream.
+
+While we are reading trace_stat/functionX and someone just
+disabled function_profile at that time, we can trigger this:
+
+       divide error: 0000 [#1] PREEMPT SMP
+       ...
+       EIP is at function_stat_show+0x90/0x230
+       ...
+
+This fix just takes the ftrace_profile_lock and checks if
+rec->counter is 0. If it's 0, we know the profile buffer
+has been reset.
+
+Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
+LKML-Reference: <4C723644.4040708@cn.fujitsu.com>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/trace/ftrace.c |   15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -369,11 +369,18 @@ static int function_stat_show(struct seq
+ {
+       struct ftrace_profile *rec = v;
+       char str[KSYM_SYMBOL_LEN];
++      int ret = 0;
+ #ifdef CONFIG_FUNCTION_GRAPH_TRACER
+-      static DEFINE_MUTEX(mutex);
+       static struct trace_seq s;
+       unsigned long long avg;
+ #endif
++      mutex_lock(&ftrace_profile_lock);
++
++      /* we raced with function_profile_reset() */
++      if (unlikely(rec->counter == 0)) {
++              ret = -EBUSY;
++              goto out;
++      }
+       kallsyms_lookup(rec->ip, NULL, NULL, NULL, str);
+       seq_printf(m, "  %-30.30s  %10lu", str, rec->counter);
+@@ -383,17 +390,17 @@ static int function_stat_show(struct seq
+       avg = rec->time;
+       do_div(avg, rec->counter);
+-      mutex_lock(&mutex);
+       trace_seq_init(&s);
+       trace_print_graph_duration(rec->time, &s);
+       trace_seq_puts(&s, "    ");
+       trace_print_graph_duration(avg, &s);
+       trace_print_seq(m, &s);
+-      mutex_unlock(&mutex);
+ #endif
+       seq_putc(m, '\n');
++out:
++      mutex_unlock(&ftrace_profile_lock);
+-      return 0;
++      return ret;
+ }
+ static void ftrace_profile_reset(struct ftrace_profile_stat *stat)
diff --git a/queue-2.6.32/tracing-t_start-reset-ftrace_iter_hash-in-case-of-seek-pread.patch b/queue-2.6.32/tracing-t_start-reset-ftrace_iter_hash-in-case-of-seek-pread.patch
new file mode 100644 (file)
index 0000000..af020f5
--- /dev/null
@@ -0,0 +1,36 @@
+From df09162550fbb53354f0c88e85b5d0e6129ee9cc Mon Sep 17 00:00:00 2001
+From: Chris Wright <chrisw@sous-sol.org>
+Date: Thu, 9 Sep 2010 16:34:59 -0700
+Subject: tracing: t_start: reset FTRACE_ITER_HASH in case of seek/pread
+
+From: Chris Wright <chrisw@sous-sol.org>
+
+commit df09162550fbb53354f0c88e85b5d0e6129ee9cc upstream.
+
+Be sure to avoid entering t_show() with FTRACE_ITER_HASH set without
+having properly started the iterator to iterate the hash.  This case is
+degenerate and, as discovered by Robert Swiecki, can cause t_hash_show()
+to misuse a pointer.  This causes a NULL ptr deref with possible security
+implications.  Tracked as CVE-2010-3079.
+
+Cc: Robert Swiecki <swiecki@google.com>
+Cc: Eugene Teo <eugene@redhat.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ kernel/trace/ftrace.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -1480,6 +1480,8 @@ static void *t_start(struct seq_file *m,
+               if (*pos > 0)
+                       return t_hash_start(m, pos);
+               iter->flags |= FTRACE_ITER_PRINTALL;
++              /* reset in case of seek/pread */
++              iter->flags &= ~FTRACE_ITER_HASH;
+               return iter;
+       }
diff --git a/queue-2.6.32/tun-don-t-add-sysfs-attributes-to-devices-without-sysfs-directories.patch b/queue-2.6.32/tun-don-t-add-sysfs-attributes-to-devices-without-sysfs-directories.patch
new file mode 100644 (file)
index 0000000..106b1eb
--- /dev/null
@@ -0,0 +1,38 @@
+From ben@decadent.org.uk  Wed Sep 15 14:50:16 2010
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Thu, 09 Sep 2010 05:21:16 +0100
+Subject: tun: Don't add sysfs attributes to devices without sysfs directories
+To: stable@kernel.org
+Cc: 594845@bugs.debian.org
+Message-ID: <1284006076.5323.590.camel@localhost>
+
+From: Ben Hutchings <ben@decadent.org.uk>
+
+This applies to 2.6.32 *only*.  It has not been applied upstream since
+the limitation no longer exists.
+
+Prior to Linux 2.6.35, net devices outside the initial net namespace
+did not have sysfs directories.  Attempting to add attributes to
+them will trigger a BUG().
+
+Reported-and-tested-by: Russell Stuart <russell-debian@stuart.id.au>
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Acked-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/tun.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -1006,7 +1006,8 @@ static int tun_set_iff(struct net *net,
+               if (err < 0)
+                       goto err_free_sk;
+-              if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
++              if (!net_eq(dev_net(tun->dev), &init_net) ||
++                  device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
+                   device_create_file(&tun->dev->dev, &dev_attr_owner) ||
+                   device_create_file(&tun->dev->dev, &dev_attr_group))
+                       printk(KERN_ERR "Failed to create tun sysfs files\n");