aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLi Zefan <lizf@cn.fujitsu.com>2009-06-16 04:39:41 -0400
committerSteven Rostedt <rostedt@goodmis.org>2009-06-16 16:25:37 -0400
commit00e95830a4d6e49f764fdb19896a89199bc0aa3b (patch)
tree972a3872cb48474777da0f9e3121fcc6924e197d /kernel
parent57be88878e7aa38750384704d811485a607bbda4 (diff)
tracing/filters: fix race between filter setting and module unload
Module unload is protected by event_mutex, while setting filter is protected by filter_mutex. This leads to the race: echo 'bar == 0 || bar == 10' \ | > sample/filter | | insmod sample.ko add_pred("bar == 0") | -> n_preds == 1 | add_pred("bar == 100") | -> n_preds == 2 | | rmmod sample.ko | insmod sample.ko add_pred("&&") | -> n_preds == 1 (should be 3) | Now event->filter->preds is corrupted. An then when filter_match_preds() is called, the WARN_ON() in it will be triggered. To avoid the race, we remove filter_mutex, and replace it with event_mutex. [ Impact: prevent corruption of filters by module removing and loading ] Signed-off-by: Li Zefan <lizf@cn.fujitsu.com> LKML-Reference: <4A375A4D.6000205@cn.fujitsu.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace_events_filter.c27
1 files changed, 10 insertions, 17 deletions
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index d9f01c1a042b..936c621bbf46 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -27,8 +27,6 @@
27#include "trace.h" 27#include "trace.h"
28#include "trace_output.h" 28#include "trace_output.h"
29 29
30static DEFINE_MUTEX(filter_mutex);
31
32enum filter_op_ids 30enum filter_op_ids
33{ 31{
34 OP_OR, 32 OP_OR,
@@ -294,12 +292,12 @@ void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s)
294{ 292{
295 struct event_filter *filter = call->filter; 293 struct event_filter *filter = call->filter;
296 294
297 mutex_lock(&filter_mutex); 295 mutex_lock(&event_mutex);
298 if (filter->filter_string) 296 if (filter->filter_string)
299 trace_seq_printf(s, "%s\n", filter->filter_string); 297 trace_seq_printf(s, "%s\n", filter->filter_string);
300 else 298 else
301 trace_seq_printf(s, "none\n"); 299 trace_seq_printf(s, "none\n");
302 mutex_unlock(&filter_mutex); 300 mutex_unlock(&event_mutex);
303} 301}
304 302
305void print_subsystem_event_filter(struct event_subsystem *system, 303void print_subsystem_event_filter(struct event_subsystem *system,
@@ -307,12 +305,12 @@ void print_subsystem_event_filter(struct event_subsystem *system,
307{ 305{
308 struct event_filter *filter = system->filter; 306 struct event_filter *filter = system->filter;
309 307
310 mutex_lock(&filter_mutex); 308 mutex_lock(&event_mutex);
311 if (filter->filter_string) 309 if (filter->filter_string)
312 trace_seq_printf(s, "%s\n", filter->filter_string); 310 trace_seq_printf(s, "%s\n", filter->filter_string);
313 else 311 else
314 trace_seq_printf(s, "none\n"); 312 trace_seq_printf(s, "none\n");
315 mutex_unlock(&filter_mutex); 313 mutex_unlock(&event_mutex);
316} 314}
317 315
318static struct ftrace_event_field * 316static struct ftrace_event_field *
@@ -434,7 +432,6 @@ static void filter_free_subsystem_preds(struct event_subsystem *system)
434 filter->n_preds = 0; 432 filter->n_preds = 0;
435 } 433 }
436 434
437 mutex_lock(&event_mutex);
438 list_for_each_entry(call, &ftrace_events, list) { 435 list_for_each_entry(call, &ftrace_events, list) {
439 if (!call->define_fields) 436 if (!call->define_fields)
440 continue; 437 continue;
@@ -444,7 +441,6 @@ static void filter_free_subsystem_preds(struct event_subsystem *system)
444 remove_filter_string(call->filter); 441 remove_filter_string(call->filter);
445 } 442 }
446 } 443 }
447 mutex_unlock(&event_mutex);
448} 444}
449 445
450static int filter_add_pred_fn(struct filter_parse_state *ps, 446static int filter_add_pred_fn(struct filter_parse_state *ps,
@@ -631,7 +627,6 @@ static int filter_add_subsystem_pred(struct filter_parse_state *ps,
631 filter->preds[filter->n_preds] = pred; 627 filter->preds[filter->n_preds] = pred;
632 filter->n_preds++; 628 filter->n_preds++;
633 629
634 mutex_lock(&event_mutex);
635 list_for_each_entry(call, &ftrace_events, list) { 630 list_for_each_entry(call, &ftrace_events, list) {
636 631
637 if (!call->define_fields) 632 if (!call->define_fields)
@@ -642,14 +637,12 @@ static int filter_add_subsystem_pred(struct filter_parse_state *ps,
642 637
643 err = filter_add_pred(ps, call, pred); 638 err = filter_add_pred(ps, call, pred);
644 if (err) { 639 if (err) {
645 mutex_unlock(&event_mutex);
646 filter_free_subsystem_preds(system); 640 filter_free_subsystem_preds(system);
647 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0); 641 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
648 goto out; 642 goto out;
649 } 643 }
650 replace_filter_string(call->filter, filter_string); 644 replace_filter_string(call->filter, filter_string);
651 } 645 }
652 mutex_unlock(&event_mutex);
653out: 646out:
654 return err; 647 return err;
655} 648}
@@ -1076,12 +1069,12 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1076 1069
1077 struct filter_parse_state *ps; 1070 struct filter_parse_state *ps;
1078 1071
1079 mutex_lock(&filter_mutex); 1072 mutex_lock(&event_mutex);
1080 1073
1081 if (!strcmp(strstrip(filter_string), "0")) { 1074 if (!strcmp(strstrip(filter_string), "0")) {
1082 filter_disable_preds(call); 1075 filter_disable_preds(call);
1083 remove_filter_string(call->filter); 1076 remove_filter_string(call->filter);
1084 mutex_unlock(&filter_mutex); 1077 mutex_unlock(&event_mutex);
1085 return 0; 1078 return 0;
1086 } 1079 }
1087 1080
@@ -1109,7 +1102,7 @@ out:
1109 postfix_clear(ps); 1102 postfix_clear(ps);
1110 kfree(ps); 1103 kfree(ps);
1111out_unlock: 1104out_unlock:
1112 mutex_unlock(&filter_mutex); 1105 mutex_unlock(&event_mutex);
1113 1106
1114 return err; 1107 return err;
1115} 1108}
@@ -1121,12 +1114,12 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1121 1114
1122 struct filter_parse_state *ps; 1115 struct filter_parse_state *ps;
1123 1116
1124 mutex_lock(&filter_mutex); 1117 mutex_lock(&event_mutex);
1125 1118
1126 if (!strcmp(strstrip(filter_string), "0")) { 1119 if (!strcmp(strstrip(filter_string), "0")) {
1127 filter_free_subsystem_preds(system); 1120 filter_free_subsystem_preds(system);
1128 remove_filter_string(system->filter); 1121 remove_filter_string(system->filter);
1129 mutex_unlock(&filter_mutex); 1122 mutex_unlock(&event_mutex);
1130 return 0; 1123 return 0;
1131 } 1124 }
1132 1125
@@ -1154,7 +1147,7 @@ out:
1154 postfix_clear(ps); 1147 postfix_clear(ps);
1155 kfree(ps); 1148 kfree(ps);
1156out_unlock: 1149out_unlock:
1157 mutex_unlock(&filter_mutex); 1150 mutex_unlock(&event_mutex);
1158 1151
1159 return err; 1152 return err;
1160} 1153}