aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-10-15 06:24:04 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-15 06:41:56 -0400
commita66abe7fbf7805a1a02f241bd5283265ff6706ec (patch)
tree7b39b4339f8b5caf56c4f76c485f07b23861999b /kernel/trace
parentc171b552a7d316c7e1c3ad6f70a30178dd53e14c (diff)
tracing/events: Fix locking imbalance in the filter code
Américo Wang noticed that we have a locking imbalance in the error paths of ftrace_profile_set_filter(), causing potential leakage of event_mutex. Also clean up other error codepaths related to event_mutex while at it. Plus fix an initialized variable in the subsystem filter code. Reported-by: Américo Wang <xiyou.wangcong@gmail.com> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Tom Zanussi <tzanussi@gmail.com> LKML-Reference: <2375c9f90910150247u5ccb8e2at58c764e385ffa490@mail.gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace_events_filter.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index e27bb6acc2dd..21d34757b955 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -1230,10 +1230,10 @@ static int replace_system_preds(struct event_subsystem *system,
1230 struct filter_parse_state *ps, 1230 struct filter_parse_state *ps,
1231 char *filter_string) 1231 char *filter_string)
1232{ 1232{
1233 struct event_filter *filter = system->filter;
1233 struct ftrace_event_call *call; 1234 struct ftrace_event_call *call;
1234 struct event_filter *filter;
1235 int err;
1236 bool fail = true; 1235 bool fail = true;
1236 int err;
1237 1237
1238 list_for_each_entry(call, &ftrace_events, list) { 1238 list_for_each_entry(call, &ftrace_events, list) {
1239 1239
@@ -1262,7 +1262,7 @@ static int replace_system_preds(struct event_subsystem *system,
1262 1262
1263 if (fail) { 1263 if (fail) {
1264 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0); 1264 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
1265 return err; 1265 return -EINVAL;
1266 } 1266 }
1267 return 0; 1267 return 0;
1268} 1268}
@@ -1281,8 +1281,7 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1281 if (!strcmp(strstrip(filter_string), "0")) { 1281 if (!strcmp(strstrip(filter_string), "0")) {
1282 filter_disable_preds(call); 1282 filter_disable_preds(call);
1283 remove_filter_string(call->filter); 1283 remove_filter_string(call->filter);
1284 mutex_unlock(&event_mutex); 1284 goto out_unlock;
1285 return 0;
1286 } 1285 }
1287 1286
1288 err = -ENOMEM; 1287 err = -ENOMEM;
@@ -1330,8 +1329,7 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1330 if (!strcmp(strstrip(filter_string), "0")) { 1329 if (!strcmp(strstrip(filter_string), "0")) {
1331 filter_free_subsystem_preds(system); 1330 filter_free_subsystem_preds(system);
1332 remove_filter_string(system->filter); 1331 remove_filter_string(system->filter);
1333 mutex_unlock(&event_mutex); 1332 goto out_unlock;
1334 return 0;
1335 } 1333 }
1336 1334
1337 err = -ENOMEM; 1335 err = -ENOMEM;
@@ -1386,15 +1384,20 @@ int ftrace_profile_set_filter(struct perf_event *event, int event_id,
1386 if (call->id == event_id) 1384 if (call->id == event_id)
1387 break; 1385 break;
1388 } 1386 }
1387
1388 err = -EINVAL;
1389 if (!call) 1389 if (!call)
1390 return -EINVAL; 1390 goto out_unlock;
1391 1391
1392 err = -EEXIST;
1392 if (event->filter) 1393 if (event->filter)
1393 return -EEXIST; 1394 goto out_unlock;
1394 1395
1395 filter = __alloc_preds(); 1396 filter = __alloc_preds();
1396 if (IS_ERR(filter)) 1397 if (IS_ERR(filter)) {
1397 return PTR_ERR(filter); 1398 err = PTR_ERR(filter);
1399 goto out_unlock;
1400 }
1398 1401
1399 err = -ENOMEM; 1402 err = -ENOMEM;
1400 ps = kzalloc(sizeof(*ps), GFP_KERNEL); 1403 ps = kzalloc(sizeof(*ps), GFP_KERNEL);
@@ -1419,6 +1422,7 @@ free_preds:
1419 if (err) 1422 if (err)
1420 __free_preds(filter); 1423 __free_preds(filter);
1421 1424
1425out_unlock:
1422 mutex_unlock(&event_mutex); 1426 mutex_unlock(&event_mutex);
1423 1427
1424 return err; 1428 return err;