Skip to content

Commit 87a342f

Browse files
Li Zefanrostedt
authored andcommitted
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 <[email protected]> LKML-Reference: <[email protected]> Signed-off-by: Steven Rostedt <[email protected]>
1 parent 43b51ea commit 87a342f

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

include/linux/ftrace_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ enum {
144144
FILTER_OTHER = 0,
145145
FILTER_STATIC_STRING,
146146
FILTER_DYN_STRING,
147+
FILTER_PTR_STRING,
147148
};
148149

149150
extern int trace_define_field(struct ftrace_event_call *call,

kernel/trace/trace_events_filter.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,20 @@ static int filter_pred_string(struct filter_pred *pred, void *event,
163163
return match;
164164
}
165165

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+
166180
/*
167181
* Filter predicate for dynamic sized arrays of characters.
168182
* These are implemented through a list of strings at the end
@@ -489,7 +503,8 @@ int filter_assign_type(const char *type)
489503
static bool is_string_field(struct ftrace_event_field *field)
490504
{
491505
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;
493508
}
494509

495510
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,
579594
}
580595

581596
if (is_string_field(field)) {
597+
pred->str_len = field->size;
598+
582599
if (field->filter_type == FILTER_STATIC_STRING)
583600
fn = filter_pred_string;
584-
else
601+
else if (field->filter_type == FILTER_DYN_STRING)
585602
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+
}
587607
} else {
588608
if (field->is_signed)
589609
ret = strict_strtoll(pred->str_val, 0, &val);

0 commit comments

Comments
 (0)