aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace.h27
-rw-r--r--kernel/trace/trace_events_filter.c155
2 files changed, 157 insertions, 25 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 86bcff94791a..8d0db6018fe4 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -702,20 +702,29 @@ struct event_subsystem {
702}; 702};
703 703
704struct filter_pred; 704struct filter_pred;
705struct regex;
705 706
706typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event, 707typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event,
707 int val1, int val2); 708 int val1, int val2);
708 709
710typedef int (*regex_match_func)(char *str, struct regex *r, int len);
711
712struct regex {
713 char pattern[MAX_FILTER_STR_VAL];
714 int len;
715 int field_len;
716 regex_match_func match;
717};
718
709struct filter_pred { 719struct filter_pred {
710 filter_pred_fn_t fn; 720 filter_pred_fn_t fn;
711 u64 val; 721 u64 val;
712 char str_val[MAX_FILTER_STR_VAL]; 722 struct regex regex;
713 int str_len; 723 char *field_name;
714 char *field_name; 724 int offset;
715 int offset; 725 int not;
716 int not; 726 int op;
717 int op; 727 int pop_n;
718 int pop_n;
719}; 728};
720 729
721extern void print_event_filter(struct ftrace_event_call *call, 730extern void print_event_filter(struct ftrace_event_call *call,
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 189663d82aa7..d3c94c139567 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -195,9 +195,9 @@ static int filter_pred_string(struct filter_pred *pred, void *event,
195 char *addr = (char *)(event + pred->offset); 195 char *addr = (char *)(event + pred->offset);
196 int cmp, match; 196 int cmp, match;
197 197
198 cmp = strncmp(addr, pred->str_val, pred->str_len); 198 cmp = pred->regex.match(addr, &pred->regex, pred->regex.field_len);
199 199
200 match = (!cmp) ^ pred->not; 200 match = cmp ^ pred->not;
201 201
202 return match; 202 return match;
203} 203}
@@ -209,9 +209,9 @@ static int filter_pred_pchar(struct filter_pred *pred, void *event,
209 char **addr = (char **)(event + pred->offset); 209 char **addr = (char **)(event + pred->offset);
210 int cmp, match; 210 int cmp, match;
211 211
212 cmp = strncmp(*addr, pred->str_val, pred->str_len); 212 cmp = pred->regex.match(*addr, &pred->regex, pred->regex.field_len);
213 213
214 match = (!cmp) ^ pred->not; 214 match = cmp ^ pred->not;
215 215
216 return match; 216 return match;
217} 217}
@@ -235,9 +235,9 @@ static int filter_pred_strloc(struct filter_pred *pred, void *event,
235 char *addr = (char *)(event + str_loc); 235 char *addr = (char *)(event + str_loc);
236 int cmp, match; 236 int cmp, match;
237 237
238 cmp = strncmp(addr, pred->str_val, str_len); 238 cmp = pred->regex.match(addr, &pred->regex, str_len);
239 239
240 match = (!cmp) ^ pred->not; 240 match = cmp ^ pred->not;
241 241
242 return match; 242 return match;
243} 243}
@@ -248,6 +248,126 @@ static int filter_pred_none(struct filter_pred *pred, void *event,
248 return 0; 248 return 0;
249} 249}
250 250
251/* Basic regex callbacks */
252static int regex_match_full(char *str, struct regex *r, int len)
253{
254 if (strncmp(str, r->pattern, len) == 0)
255 return 1;
256 return 0;
257}
258
259static int regex_match_front(char *str, struct regex *r, int len)
260{
261 if (strncmp(str, r->pattern, len) == 0)
262 return 1;
263 return 0;
264}
265
266static int regex_match_middle(char *str, struct regex *r, int len)
267{
268 if (strstr(str, r->pattern))
269 return 1;
270 return 0;
271}
272
273static int regex_match_end(char *str, struct regex *r, int len)
274{
275 char *ptr = strstr(str, r->pattern);
276
277 if (ptr && (ptr[r->len] == 0))
278 return 1;
279 return 0;
280}
281
282enum regex_type {
283 MATCH_FULL,
284 MATCH_FRONT_ONLY,
285 MATCH_MIDDLE_ONLY,
286 MATCH_END_ONLY,
287};
288
289/*
290 * Pass in a buffer containing a regex and this function will
291 * set search to point to the search part of the buffer and
292 * return the type of search it is (see enum above).
293 * This does modify buff.
294 *
295 * Returns enum type.
296 * search returns the pointer to use for comparison.
297 * not returns 1 if buff started with a '!'
298 * 0 otherwise.
299 */
300static enum regex_type
301filter_parse_regex(char *buff, int len, char **search, int *not)
302{
303 int type = MATCH_FULL;
304 int i;
305
306 if (buff[0] == '!') {
307 *not = 1;
308 buff++;
309 len--;
310 } else
311 *not = 0;
312
313 *search = buff;
314
315 for (i = 0; i < len; i++) {
316 if (buff[i] == '*') {
317 if (!i) {
318 *search = buff + 1;
319 type = MATCH_END_ONLY;
320 } else {
321 if (type == MATCH_END_ONLY)
322 type = MATCH_MIDDLE_ONLY;
323 else
324 type = MATCH_FRONT_ONLY;
325 buff[i] = 0;
326 break;
327 }
328 }
329 }
330
331 return type;
332}
333
334static int filter_build_regex(struct filter_pred *pred)
335{
336 struct regex *r = &pred->regex;
337 char *search, *dup;
338 enum regex_type type;
339 int not;
340
341 type = filter_parse_regex(r->pattern, r->len, &search, &not);
342 dup = kstrdup(search, GFP_KERNEL);
343 if (!dup)
344 return -ENOMEM;
345
346 strcpy(r->pattern, dup);
347 kfree(dup);
348
349 r->len = strlen(r->pattern);
350
351 switch (type) {
352 case MATCH_FULL:
353 r->match = regex_match_full;
354 break;
355 case MATCH_FRONT_ONLY:
356 r->match = regex_match_front;
357 break;
358 case MATCH_MIDDLE_ONLY:
359 r->match = regex_match_middle;
360 break;
361 case MATCH_END_ONLY:
362 r->match = regex_match_end;
363 break;
364 }
365
366 pred->not ^= not;
367
368 return 0;
369}
370
251/* return 1 if event matches, 0 otherwise (discard) */ 371/* return 1 if event matches, 0 otherwise (discard) */
252int filter_match_preds(struct ftrace_event_call *call, void *rec) 372int filter_match_preds(struct ftrace_event_call *call, void *rec)
253{ 373{
@@ -394,7 +514,7 @@ static void filter_clear_pred(struct filter_pred *pred)
394{ 514{
395 kfree(pred->field_name); 515 kfree(pred->field_name);
396 pred->field_name = NULL; 516 pred->field_name = NULL;
397 pred->str_len = 0; 517 pred->regex.len = 0;
398} 518}
399 519
400static int filter_set_pred(struct filter_pred *dest, 520static int filter_set_pred(struct filter_pred *dest,
@@ -658,21 +778,24 @@ static int filter_add_pred(struct filter_parse_state *ps,
658 } 778 }
659 779
660 if (is_string_field(field)) { 780 if (is_string_field(field)) {
661 pred->str_len = field->size; 781 ret = filter_build_regex(pred);
782 if (ret)
783 return ret;
662 784
663 if (field->filter_type == FILTER_STATIC_STRING) 785 if (field->filter_type == FILTER_STATIC_STRING) {
664 fn = filter_pred_string; 786 fn = filter_pred_string;
665 else if (field->filter_type == FILTER_DYN_STRING) 787 pred->regex.field_len = field->size;
666 fn = filter_pred_strloc; 788 } else if (field->filter_type == FILTER_DYN_STRING)
789 fn = filter_pred_strloc;
667 else { 790 else {
668 fn = filter_pred_pchar; 791 fn = filter_pred_pchar;
669 pred->str_len = strlen(pred->str_val); 792 pred->regex.field_len = strlen(pred->regex.pattern);
670 } 793 }
671 } else { 794 } else {
672 if (field->is_signed) 795 if (field->is_signed)
673 ret = strict_strtoll(pred->str_val, 0, &val); 796 ret = strict_strtoll(pred->regex.pattern, 0, &val);
674 else 797 else
675 ret = strict_strtoull(pred->str_val, 0, &val); 798 ret = strict_strtoull(pred->regex.pattern, 0, &val);
676 if (ret) { 799 if (ret) {
677 parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0); 800 parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0);
678 return -EINVAL; 801 return -EINVAL;
@@ -1042,8 +1165,8 @@ static struct filter_pred *create_pred(int op, char *operand1, char *operand2)
1042 return NULL; 1165 return NULL;
1043 } 1166 }
1044 1167
1045 strcpy(pred->str_val, operand2); 1168 strcpy(pred->regex.pattern, operand2);
1046 pred->str_len = strlen(operand2); 1169 pred->regex.len = strlen(pred->regex.pattern);
1047 1170
1048 pred->op = op; 1171 pred->op = op;
1049 1172