]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Mar 2014 04:25:46 +0000 (21:25 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Mar 2014 04:25:46 +0000 (21:25 -0700)
added patches:
firewire-don-t-use-prepare_delayed_work.patch
firewire-net-fix-use-after-free.patch
tracing-do-not-add-event-files-for-modules-that-fail-tracepoints.patch

queue-3.4/firewire-don-t-use-prepare_delayed_work.patch [new file with mode: 0644]
queue-3.4/firewire-net-fix-use-after-free.patch [new file with mode: 0644]
queue-3.4/series
queue-3.4/tracing-do-not-add-event-files-for-modules-that-fail-tracepoints.patch [new file with mode: 0644]

diff --git a/queue-3.4/firewire-don-t-use-prepare_delayed_work.patch b/queue-3.4/firewire-don-t-use-prepare_delayed_work.patch
new file mode 100644 (file)
index 0000000..8657d6c
--- /dev/null
@@ -0,0 +1,187 @@
+From 70044d71d31d6973665ced5be04ef39ac1c09a48 Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Fri, 7 Mar 2014 10:19:57 -0500
+Subject: firewire: don't use PREPARE_DELAYED_WORK
+
+From: Tejun Heo <tj@kernel.org>
+
+commit 70044d71d31d6973665ced5be04ef39ac1c09a48 upstream.
+
+PREPARE_[DELAYED_]WORK() are being phased out.  They have few users
+and a nasty surprise in terms of reentrancy guarantee as workqueue
+considers work items to be different if they don't have the same work
+function.
+
+firewire core-device and sbp2 have been been multiplexing work items
+with multiple work functions.  Introduce fw_device_workfn() and
+sbp2_lu_workfn() which invoke fw_device->workfn and
+sbp2_logical_unit->workfn respectively and always use the two
+functions as the work functions and update the users to set the
+->workfn fields instead of overriding work functions using
+PREPARE_DELAYED_WORK().
+
+This fixes a variety of possible regressions since a2c1c57be8d9
+"workqueue: consider work function when searching for busy work items"
+due to which fw_workqueue lost its required non-reentrancy property.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Acked-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
+Cc: linux1394-devel@lists.sourceforge.net
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/firewire/core-device.c |   22 +++++++++++++++-------
+ drivers/firewire/sbp2.c        |   17 +++++++++++++----
+ include/linux/firewire.h       |    1 +
+ 3 files changed, 29 insertions(+), 11 deletions(-)
+
+--- a/drivers/firewire/core-device.c
++++ b/drivers/firewire/core-device.c
+@@ -878,7 +878,7 @@ static int lookup_existing_device(struct
+               old->config_rom_retries = 0;
+               fw_notice(card, "rediscovered device %s\n", dev_name(dev));
+-              PREPARE_DELAYED_WORK(&old->work, fw_device_update);
++              old->workfn = fw_device_update;
+               fw_schedule_device_work(old, 0);
+               if (current_node == card->root_node)
+@@ -1040,7 +1040,7 @@ static void fw_device_init(struct work_s
+       if (atomic_cmpxchg(&device->state,
+                          FW_DEVICE_INITIALIZING,
+                          FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
+-              PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
++              device->workfn = fw_device_shutdown;
+               fw_schedule_device_work(device, SHUTDOWN_DELAY);
+       } else {
+               fw_notice(card, "created device %s: GUID %08x%08x, S%d00\n",
+@@ -1172,13 +1172,20 @@ static void fw_device_refresh(struct wor
+                 dev_name(&device->device));
+  gone:
+       atomic_set(&device->state, FW_DEVICE_GONE);
+-      PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
++      device->workfn = fw_device_shutdown;
+       fw_schedule_device_work(device, SHUTDOWN_DELAY);
+  out:
+       if (node_id == card->root_node->node_id)
+               fw_schedule_bm_work(card, 0);
+ }
++static void fw_device_workfn(struct work_struct *work)
++{
++      struct fw_device *device = container_of(to_delayed_work(work),
++                                              struct fw_device, work);
++      device->workfn(work);
++}
++
+ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ {
+       struct fw_device *device;
+@@ -1228,7 +1235,8 @@ void fw_node_event(struct fw_card *card,
+                * power-up after getting plugged in.  We schedule the
+                * first config rom scan half a second after bus reset.
+                */
+-              INIT_DELAYED_WORK(&device->work, fw_device_init);
++              device->workfn = fw_device_init;
++              INIT_DELAYED_WORK(&device->work, fw_device_workfn);
+               fw_schedule_device_work(device, INITIAL_DELAY);
+               break;
+@@ -1244,7 +1252,7 @@ void fw_node_event(struct fw_card *card,
+               if (atomic_cmpxchg(&device->state,
+                           FW_DEVICE_RUNNING,
+                           FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
+-                      PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
++                      device->workfn = fw_device_refresh;
+                       fw_schedule_device_work(device,
+                               device->is_local ? 0 : INITIAL_DELAY);
+               }
+@@ -1259,7 +1267,7 @@ void fw_node_event(struct fw_card *card,
+               smp_wmb();  /* update node_id before generation */
+               device->generation = card->generation;
+               if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
+-                      PREPARE_DELAYED_WORK(&device->work, fw_device_update);
++                      device->workfn = fw_device_update;
+                       fw_schedule_device_work(device, 0);
+               }
+               break;
+@@ -1284,7 +1292,7 @@ void fw_node_event(struct fw_card *card,
+               device = node->data;
+               if (atomic_xchg(&device->state,
+                               FW_DEVICE_GONE) == FW_DEVICE_RUNNING) {
+-                      PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
++                      device->workfn = fw_device_shutdown;
+                       fw_schedule_device_work(device,
+                               list_empty(&card->link) ? 0 : SHUTDOWN_DELAY);
+               }
+--- a/drivers/firewire/sbp2.c
++++ b/drivers/firewire/sbp2.c
+@@ -146,6 +146,7 @@ struct sbp2_logical_unit {
+        */
+       int generation;
+       int retries;
++      work_func_t workfn;
+       struct delayed_work work;
+       bool has_sdev;
+       bool blocked;
+@@ -865,7 +866,7 @@ static void sbp2_login(struct work_struc
+       /* set appropriate retry limit(s) in BUSY_TIMEOUT register */
+       sbp2_set_busy_timeout(lu);
+-      PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect);
++      lu->workfn = sbp2_reconnect;
+       sbp2_agent_reset(lu);
+       /* This was a re-login. */
+@@ -919,7 +920,7 @@ static void sbp2_login(struct work_struc
+        * If a bus reset happened, sbp2_update will have requeued
+        * lu->work already.  Reset the work from reconnect to login.
+        */
+-      PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
++      lu->workfn = sbp2_login;
+ }
+ static void sbp2_reconnect(struct work_struct *work)
+@@ -953,7 +954,7 @@ static void sbp2_reconnect(struct work_s
+                   lu->retries++ >= 5) {
+                       dev_err(tgt_dev(tgt), "failed to reconnect\n");
+                       lu->retries = 0;
+-                      PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
++                      lu->workfn = sbp2_login;
+               }
+               sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
+@@ -973,6 +974,13 @@ static void sbp2_reconnect(struct work_s
+       sbp2_conditionally_unblock(lu);
+ }
++static void sbp2_lu_workfn(struct work_struct *work)
++{
++      struct sbp2_logical_unit *lu = container_of(to_delayed_work(work),
++                                              struct sbp2_logical_unit, work);
++      lu->workfn(work);
++}
++
+ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
+ {
+       struct sbp2_logical_unit *lu;
+@@ -999,7 +1007,8 @@ static int sbp2_add_logical_unit(struct
+       lu->blocked  = false;
+       ++tgt->dont_block;
+       INIT_LIST_HEAD(&lu->orb_list);
+-      INIT_DELAYED_WORK(&lu->work, sbp2_login);
++      lu->workfn = sbp2_login;
++      INIT_DELAYED_WORK(&lu->work, sbp2_lu_workfn);
+       list_add_tail(&lu->link, &tgt->lu_list);
+       return 0;
+--- a/include/linux/firewire.h
++++ b/include/linux/firewire.h
+@@ -186,6 +186,7 @@ struct fw_device {
+       unsigned irmc:1;
+       unsigned bc_implemented:2;
++      work_func_t workfn;
+       struct delayed_work work;
+       struct fw_attribute_group attribute_group;
+ };
diff --git a/queue-3.4/firewire-net-fix-use-after-free.patch b/queue-3.4/firewire-net-fix-use-after-free.patch
new file mode 100644 (file)
index 0000000..ab2cd21
--- /dev/null
@@ -0,0 +1,45 @@
+From 8987583366ae9e03c306c2b7d73bdb952df1d08d Mon Sep 17 00:00:00 2001
+From: Stefan Richter <stefanr@s5r6.in-berlin.de>
+Date: Tue, 18 Feb 2014 22:25:15 +0100
+Subject: firewire: net: fix use after free
+
+From: Stefan Richter <stefanr@s5r6.in-berlin.de>
+
+commit 8987583366ae9e03c306c2b7d73bdb952df1d08d upstream.
+
+Commit 8408dc1c14c1 "firewire: net: use dev_printk API" introduced a
+use-after-free in a failure path.  fwnet_transmit_packet_failed(ptask)
+may free ptask, then the dev_err() call dereferenced it.  The fix is
+straightforward; simply reorder the two calls.
+
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/firewire/net.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/firewire/net.c
++++ b/drivers/firewire/net.c
+@@ -1014,8 +1014,6 @@ static void fwnet_write_complete(struct
+       if (rcode == RCODE_COMPLETE) {
+               fwnet_transmit_packet_done(ptask);
+       } else {
+-              fwnet_transmit_packet_failed(ptask);
+-
+               if (printk_timed_ratelimit(&j,  1000) || rcode != last_rcode) {
+                       dev_err(&ptask->dev->netdev->dev,
+                               "fwnet_write_complete failed: %x (skipped %d)\n",
+@@ -1023,8 +1021,10 @@ static void fwnet_write_complete(struct
+                       errors_skipped = 0;
+                       last_rcode = rcode;
+-              } else
++              } else {
+                       errors_skipped++;
++              }
++              fwnet_transmit_packet_failed(ptask);
+       }
+ }
index 68320926052a1750b407ed178e6cd24ccd3f2f94..87aec2bdeca72f4d2eaee8a6cd86d550ae30bebc 100644 (file)
@@ -17,3 +17,6 @@ regulator-core-replace-direct-ops-enable-usage.patch
 x86-amd-numa-fix-northbridge-quirk-to-assign-correct-numa-node.patch
 genirq-remove-racy-waitqueue_active-check.patch
 cpuset-fix-a-race-condition-in-__cpuset_node_allowed_softwall.patch
+tracing-do-not-add-event-files-for-modules-that-fail-tracepoints.patch
+firewire-net-fix-use-after-free.patch
+firewire-don-t-use-prepare_delayed_work.patch
diff --git a/queue-3.4/tracing-do-not-add-event-files-for-modules-that-fail-tracepoints.patch b/queue-3.4/tracing-do-not-add-event-files-for-modules-that-fail-tracepoints.patch
new file mode 100644 (file)
index 0000000..462707c
--- /dev/null
@@ -0,0 +1,88 @@
+From 45ab2813d40d88fc575e753c38478de242d03f88 Mon Sep 17 00:00:00 2001
+From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
+Date: Wed, 26 Feb 2014 13:37:38 -0500
+Subject: tracing: Do not add event files for modules that fail tracepoints
+
+From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org>
+
+commit 45ab2813d40d88fc575e753c38478de242d03f88 upstream.
+
+If a module fails to add its tracepoints due to module tainting, do not
+create the module event infrastructure in the debugfs directory. As the events
+will not work and worse yet, they will silently fail, making the user wonder
+why the events they enable do not display anything.
+
+Having a warning on module load and the events not visible to the users
+will make the cause of the problem much clearer.
+
+Link: http://lkml.kernel.org/r/20140227154923.265882695@goodmis.org
+
+Fixes: 6d723736e472 "tracing/events: add support for modules to TRACE_EVENT"
+Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Cc: Rusty Russell <rusty@rustcorp.com.au>
+Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/tracepoint.h  |    6 ++++++
+ kernel/trace/trace_events.c |   10 ++++++++++
+ kernel/tracepoint.c         |    7 ++++++-
+ 3 files changed, 22 insertions(+), 1 deletion(-)
+
+--- a/include/linux/tracepoint.h
++++ b/include/linux/tracepoint.h
+@@ -60,6 +60,12 @@ struct tp_module {
+       unsigned int num_tracepoints;
+       struct tracepoint * const *tracepoints_ptrs;
+ };
++bool trace_module_has_bad_taint(struct module *mod);
++#else
++static inline bool trace_module_has_bad_taint(struct module *mod)
++{
++      return false;
++}
+ #endif /* CONFIG_MODULES */
+ struct tracepoint_iter {
+--- a/kernel/trace/trace_events.c
++++ b/kernel/trace/trace_events.c
+@@ -1354,6 +1354,16 @@ static void trace_module_add_events(stru
+       struct ftrace_module_file_ops *file_ops = NULL;
+       struct ftrace_event_call **call, **start, **end;
++      if (!mod->num_trace_events)
++              return;
++
++      /* Don't add infrastructure for mods without tracepoints */
++      if (trace_module_has_bad_taint(mod)) {
++              pr_err("%s: module has bad taint, not creating trace events\n",
++                     mod->name);
++              return;
++      }
++
+       start = mod->trace_events;
+       end = mod->trace_events + mod->num_trace_events;
+--- a/kernel/tracepoint.c
++++ b/kernel/tracepoint.c
+@@ -628,6 +628,11 @@ void tracepoint_iter_reset(struct tracep
+ EXPORT_SYMBOL_GPL(tracepoint_iter_reset);
+ #ifdef CONFIG_MODULES
++bool trace_module_has_bad_taint(struct module *mod)
++{
++      return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP));
++}
++
+ static int tracepoint_module_coming(struct module *mod)
+ {
+       struct tp_module *tp_mod, *iter;
+@@ -638,7 +643,7 @@ static int tracepoint_module_coming(stru
+        * module headers (for forced load), to make sure we don't cause a crash.
+        * Staging and out-of-tree GPL modules are fine.
+        */
+-      if (mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP)))
++      if (trace_module_has_bad_taint(mod))
+               return 0;
+       mutex_lock(&tracepoints_mutex);
+       tp_mod = kmalloc(sizeof(struct tp_module), GFP_KERNEL);