diff options
author | Li Zefan <lizf@cn.fujitsu.com> | 2009-08-06 22:33:43 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2009-08-26 00:32:07 -0400 |
commit | 87a342f5db69d53ea70493bb1ec69c9047677038 (patch) | |
tree | 89ec97b3a32d6508d10f1598201e48a24c08c46e /kernel | |
parent | 43b51ead3f752a3935116e5b1a94254b8573734f (diff) |
tracing/filters: Support filtering for char * strings
Usually, char * entries are dangerous in traces because the string
can be released whereas a pointer to it can still wait to be read from
the ring buffer.
But sometimes we can assume it's safe, like in case of RO data
(eg: __file__ or __line__, used in bkl trace event). If these RO data
are in a module and so is the call to the trace event, then it's safe,
because the ring buffer will be flushed once this module get unloaded.
To allow char * to be treated as a string:
TRACE_EVENT(...,
TP_STRUCT__entry(
__field_ext(const char *, name, FILTER_PTR_STRING)
...
)
...
);
The filtering will not dereference "char *" unless the developer
explicitly sets FILTER_PTR_STR in __field_ext.
Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
LKML-Reference: <4A7B9287.90205@cn.fujitsu.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/trace_events_filter.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 8a8e576733fc..9f03082c81d8 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
@@ -163,6 +163,20 @@ static int filter_pred_string(struct filter_pred *pred, void *event, | |||
163 | return match; | 163 | return match; |
164 | } | 164 | } |
165 | 165 | ||
166 | /* Filter predicate for char * pointers */ | ||
167 | static int filter_pred_pchar(struct filter_pred *pred, void *event, | ||
168 | int val1, int val2) | ||
169 | { | ||
170 | char **addr = (char **)(event + pred->offset); | ||
171 | int cmp, match; | ||
172 | |||
173 | cmp = strncmp(*addr, pred->str_val, pred->str_len); | ||
174 | |||
175 | match = (!cmp) ^ pred->not; | ||
176 | |||
177 | return match; | ||
178 | } | ||
179 | |||
166 | /* | 180 | /* |
167 | * Filter predicate for dynamic sized arrays of characters. | 181 | * Filter predicate for dynamic sized arrays of characters. |
168 | * These are implemented through a list of strings at the end | 182 | * These are implemented through a list of strings at the end |
@@ -489,7 +503,8 @@ int filter_assign_type(const char *type) | |||
489 | static bool is_string_field(struct ftrace_event_field *field) | 503 | static bool is_string_field(struct ftrace_event_field *field) |
490 | { | 504 | { |
491 | return field->filter_type == FILTER_DYN_STRING || | 505 | return field->filter_type == FILTER_DYN_STRING || |
492 | field->filter_type == FILTER_STATIC_STRING; | 506 | field->filter_type == FILTER_STATIC_STRING || |
507 | field->filter_type == FILTER_PTR_STRING; | ||
493 | } | 508 | } |
494 | 509 | ||
495 | static int is_legal_op(struct ftrace_event_field *field, int op) | 510 | static int is_legal_op(struct ftrace_event_field *field, int op) |
@@ -579,11 +594,16 @@ static int filter_add_pred(struct filter_parse_state *ps, | |||
579 | } | 594 | } |
580 | 595 | ||
581 | if (is_string_field(field)) { | 596 | if (is_string_field(field)) { |
597 | pred->str_len = field->size; | ||
598 | |||
582 | if (field->filter_type == FILTER_STATIC_STRING) | 599 | if (field->filter_type == FILTER_STATIC_STRING) |
583 | fn = filter_pred_string; | 600 | fn = filter_pred_string; |
584 | else | 601 | else if (field->filter_type == FILTER_DYN_STRING) |
585 | fn = filter_pred_strloc; | 602 | fn = filter_pred_strloc; |
586 | pred->str_len = field->size; | 603 | else { |
604 | fn = filter_pred_pchar; | ||
605 | pred->str_len = strlen(pred->str_val); | ||
606 | } | ||
587 | } else { | 607 | } else { |
588 | if (field->is_signed) | 608 | if (field->is_signed) |
589 | ret = strict_strtoll(pred->str_val, 0, &val); | 609 | ret = strict_strtoll(pred->str_val, 0, &val); |