diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-10-15 06:24:04 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-10-15 06:41:56 -0400 |
commit | a66abe7fbf7805a1a02f241bd5283265ff6706ec (patch) | |
tree | 7b39b4339f8b5caf56c4f76c485f07b23861999b /kernel/trace | |
parent | c171b552a7d316c7e1c3ad6f70a30178dd53e14c (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.c | 26 |
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 | ||
1425 | out_unlock: | ||
1422 | mutex_unlock(&event_mutex); | 1426 | mutex_unlock(&event_mutex); |
1423 | 1427 | ||
1424 | return err; | 1428 | return err; |