diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2009-04-21 05:12:11 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-04-21 05:58:28 -0400 |
commit | f66578a7637b87810cbb9041c4e3a77fd2fa4706 (patch) | |
tree | 13b4ac67791369daa1b9559f427e128a70e6b9aa /kernel | |
parent | e8082f3f5a17d7a7bfc7dd1050a3f958dc034e9a (diff) |
tracing/filters: allow user-input to be integer-like string
Suppose we would like to trace all tasks named '123', but this
will fail:
# echo 'parent_comm == 123' > events/sched/sched_process_fork/filter
bash: echo: write error: Invalid argument
Don't guess the type of the filter pred in filter_parse(), but instead
we check it in __filter_add_pred().
[ Impact: extend allowed filter field string values ]
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Cc: Tom Zanussi <tzanussi@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <49ED8DEB.6000700@cn.fujitsu.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/trace_events_filter.c | 26 |
1 files changed, 12 insertions, 14 deletions
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index e0fcfd2a16d6..65418288f957 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
@@ -313,6 +313,7 @@ static int __filter_add_pred(struct ftrace_event_call *call, | |||
313 | { | 313 | { |
314 | struct ftrace_event_field *field; | 314 | struct ftrace_event_field *field; |
315 | filter_pred_fn_t fn; | 315 | filter_pred_fn_t fn; |
316 | unsigned long long val; | ||
316 | 317 | ||
317 | field = find_event_field(call, pred->field_name); | 318 | field = find_event_field(call, pred->field_name); |
318 | if (!field) | 319 | if (!field) |
@@ -322,14 +323,13 @@ static int __filter_add_pred(struct ftrace_event_call *call, | |||
322 | pred->offset = field->offset; | 323 | pred->offset = field->offset; |
323 | 324 | ||
324 | if (is_string_field(field->type)) { | 325 | if (is_string_field(field->type)) { |
325 | if (!pred->str_len) | ||
326 | return -EINVAL; | ||
327 | fn = filter_pred_string; | 326 | fn = filter_pred_string; |
328 | pred->str_len = field->size; | 327 | pred->str_len = field->size; |
329 | return filter_add_pred_fn(call, pred, fn); | 328 | return filter_add_pred_fn(call, pred, fn); |
330 | } else { | 329 | } else { |
331 | if (pred->str_len) | 330 | if (strict_strtoull(pred->str_val, 0, &val)) |
332 | return -EINVAL; | 331 | return -EINVAL; |
332 | pred->val = val; | ||
333 | } | 333 | } |
334 | 334 | ||
335 | switch (field->size) { | 335 | switch (field->size) { |
@@ -413,12 +413,16 @@ int filter_add_subsystem_pred(struct event_subsystem *system, | |||
413 | return 0; | 413 | return 0; |
414 | } | 414 | } |
415 | 415 | ||
416 | /* | ||
417 | * The filter format can be | ||
418 | * - 0, which means remove all filter preds | ||
419 | * - [||/&&] <field> ==/!= <val> | ||
420 | */ | ||
416 | int filter_parse(char **pbuf, struct filter_pred *pred) | 421 | int filter_parse(char **pbuf, struct filter_pred *pred) |
417 | { | 422 | { |
418 | char *tmp, *tok, *val_str = NULL; | 423 | char *tok, *val_str = NULL; |
419 | int tok_n = 0; | 424 | int tok_n = 0; |
420 | 425 | ||
421 | /* field ==/!= number, or/and field ==/!= number, number */ | ||
422 | while ((tok = strsep(pbuf, " \n"))) { | 426 | while ((tok = strsep(pbuf, " \n"))) { |
423 | if (tok_n == 0) { | 427 | if (tok_n == 0) { |
424 | if (!strcmp(tok, "0")) { | 428 | if (!strcmp(tok, "0")) { |
@@ -478,19 +482,13 @@ int filter_parse(char **pbuf, struct filter_pred *pred) | |||
478 | return -EINVAL; | 482 | return -EINVAL; |
479 | } | 483 | } |
480 | 484 | ||
485 | strcpy(pred->str_val, val_str); | ||
486 | pred->str_len = strlen(val_str); | ||
487 | |||
481 | pred->field_name = kstrdup(pred->field_name, GFP_KERNEL); | 488 | pred->field_name = kstrdup(pred->field_name, GFP_KERNEL); |
482 | if (!pred->field_name) | 489 | if (!pred->field_name) |
483 | return -ENOMEM; | 490 | return -ENOMEM; |
484 | 491 | ||
485 | pred->str_len = 0; | ||
486 | pred->val = simple_strtoull(val_str, &tmp, 0); | ||
487 | if (tmp == val_str) { | ||
488 | strncpy(pred->str_val, val_str, MAX_FILTER_STR_VAL); | ||
489 | pred->str_len = strlen(val_str); | ||
490 | pred->str_val[pred->str_len] = '\0'; | ||
491 | } else if (*tmp != '\0') | ||
492 | return -EINVAL; | ||
493 | |||
494 | return 0; | 492 | return 0; |
495 | } | 493 | } |
496 | 494 | ||