diff options
author | Alexander Z Lam <azl@google.com> | 2013-07-01 22:37:54 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-25 17:07:43 -0400 |
commit | 9713f78568d0053621530fb9cf06756394b4403c (patch) | |
tree | dba7b16aab7bc4d42bfc686b2f22171fe47cd4de /kernel | |
parent | b7f15519edb2e3c3d7d07d6a0780a4386ef23085 (diff) |
tracing: Protect ftrace_trace_arrays list in trace_events.c
commit a82274151af2b075163e3c42c828529dee311487 upstream.
There are multiple places where the ftrace_trace_arrays list is accessed in
trace_events.c without the trace_types_lock held.
Link: http://lkml.kernel.org/r/1372732674-22726-1-git-send-email-azl@google.com
Signed-off-by: Alexander Z Lam <azl@google.com>
Cc: Vaibhav Nagarnaik <vnagarnaik@google.com>
Cc: David Sharp <dhsharp@google.com>
Cc: Alexander Z Lam <lambchop468@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/trace.c | 2 | ||||
-rw-r--r-- | kernel/trace/trace.h | 2 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 11 |
3 files changed, 13 insertions, 2 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index b90c993462be..10d3f0871b48 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -240,7 +240,7 @@ static struct tracer *trace_types __read_mostly; | |||
240 | /* | 240 | /* |
241 | * trace_types_lock is used to protect the trace_types list. | 241 | * trace_types_lock is used to protect the trace_types list. |
242 | */ | 242 | */ |
243 | static DEFINE_MUTEX(trace_types_lock); | 243 | DEFINE_MUTEX(trace_types_lock); |
244 | 244 | ||
245 | /* | 245 | /* |
246 | * serialize the access of the ring buffer | 246 | * serialize the access of the ring buffer |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 20572ed88c5c..7944b9294599 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -224,6 +224,8 @@ enum { | |||
224 | 224 | ||
225 | extern struct list_head ftrace_trace_arrays; | 225 | extern struct list_head ftrace_trace_arrays; |
226 | 226 | ||
227 | extern struct mutex trace_types_lock; | ||
228 | |||
227 | /* | 229 | /* |
228 | * The global tracer (top) should be the first trace array added, | 230 | * The global tracer (top) should be the first trace array added, |
229 | * but we check the flag anyway. | 231 | * but we check the flag anyway. |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index bf56c1d07df3..f82d92dbd614 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -1011,6 +1011,7 @@ static int subsystem_open(struct inode *inode, struct file *filp) | |||
1011 | int ret; | 1011 | int ret; |
1012 | 1012 | ||
1013 | /* Make sure the system still exists */ | 1013 | /* Make sure the system still exists */ |
1014 | mutex_lock(&trace_types_lock); | ||
1014 | mutex_lock(&event_mutex); | 1015 | mutex_lock(&event_mutex); |
1015 | list_for_each_entry(tr, &ftrace_trace_arrays, list) { | 1016 | list_for_each_entry(tr, &ftrace_trace_arrays, list) { |
1016 | list_for_each_entry(dir, &tr->systems, list) { | 1017 | list_for_each_entry(dir, &tr->systems, list) { |
@@ -1026,6 +1027,7 @@ static int subsystem_open(struct inode *inode, struct file *filp) | |||
1026 | } | 1027 | } |
1027 | exit_loop: | 1028 | exit_loop: |
1028 | mutex_unlock(&event_mutex); | 1029 | mutex_unlock(&event_mutex); |
1030 | mutex_unlock(&trace_types_lock); | ||
1029 | 1031 | ||
1030 | if (!system) | 1032 | if (!system) |
1031 | return -ENODEV; | 1033 | return -ENODEV; |
@@ -1620,6 +1622,7 @@ static void __add_event_to_tracers(struct ftrace_event_call *call, | |||
1620 | int trace_add_event_call(struct ftrace_event_call *call) | 1622 | int trace_add_event_call(struct ftrace_event_call *call) |
1621 | { | 1623 | { |
1622 | int ret; | 1624 | int ret; |
1625 | mutex_lock(&trace_types_lock); | ||
1623 | mutex_lock(&event_mutex); | 1626 | mutex_lock(&event_mutex); |
1624 | 1627 | ||
1625 | ret = __register_event(call, NULL); | 1628 | ret = __register_event(call, NULL); |
@@ -1627,11 +1630,13 @@ int trace_add_event_call(struct ftrace_event_call *call) | |||
1627 | __add_event_to_tracers(call, NULL); | 1630 | __add_event_to_tracers(call, NULL); |
1628 | 1631 | ||
1629 | mutex_unlock(&event_mutex); | 1632 | mutex_unlock(&event_mutex); |
1633 | mutex_unlock(&trace_types_lock); | ||
1630 | return ret; | 1634 | return ret; |
1631 | } | 1635 | } |
1632 | 1636 | ||
1633 | /* | 1637 | /* |
1634 | * Must be called under locking both of event_mutex and trace_event_sem. | 1638 | * Must be called under locking of trace_types_lock, event_mutex and |
1639 | * trace_event_sem. | ||
1635 | */ | 1640 | */ |
1636 | static void __trace_remove_event_call(struct ftrace_event_call *call) | 1641 | static void __trace_remove_event_call(struct ftrace_event_call *call) |
1637 | { | 1642 | { |
@@ -1643,11 +1648,13 @@ static void __trace_remove_event_call(struct ftrace_event_call *call) | |||
1643 | /* Remove an event_call */ | 1648 | /* Remove an event_call */ |
1644 | void trace_remove_event_call(struct ftrace_event_call *call) | 1649 | void trace_remove_event_call(struct ftrace_event_call *call) |
1645 | { | 1650 | { |
1651 | mutex_lock(&trace_types_lock); | ||
1646 | mutex_lock(&event_mutex); | 1652 | mutex_lock(&event_mutex); |
1647 | down_write(&trace_event_sem); | 1653 | down_write(&trace_event_sem); |
1648 | __trace_remove_event_call(call); | 1654 | __trace_remove_event_call(call); |
1649 | up_write(&trace_event_sem); | 1655 | up_write(&trace_event_sem); |
1650 | mutex_unlock(&event_mutex); | 1656 | mutex_unlock(&event_mutex); |
1657 | mutex_unlock(&trace_types_lock); | ||
1651 | } | 1658 | } |
1652 | 1659 | ||
1653 | #define for_each_event(event, start, end) \ | 1660 | #define for_each_event(event, start, end) \ |
@@ -1791,6 +1798,7 @@ static int trace_module_notify(struct notifier_block *self, | |||
1791 | { | 1798 | { |
1792 | struct module *mod = data; | 1799 | struct module *mod = data; |
1793 | 1800 | ||
1801 | mutex_lock(&trace_types_lock); | ||
1794 | mutex_lock(&event_mutex); | 1802 | mutex_lock(&event_mutex); |
1795 | switch (val) { | 1803 | switch (val) { |
1796 | case MODULE_STATE_COMING: | 1804 | case MODULE_STATE_COMING: |
@@ -1801,6 +1809,7 @@ static int trace_module_notify(struct notifier_block *self, | |||
1801 | break; | 1809 | break; |
1802 | } | 1810 | } |
1803 | mutex_unlock(&event_mutex); | 1811 | mutex_unlock(&event_mutex); |
1812 | mutex_unlock(&trace_types_lock); | ||
1804 | 1813 | ||
1805 | return 0; | 1814 | return 0; |
1806 | } | 1815 | } |