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; |
