Skip to content

Commit cfb58e2

Browse files
valschneiderrostedt
authored andcommitted
tracing/filters: Dynamically allocate filter_pred.regex
Every predicate allocation includes a MAX_FILTER_STR_VAL (256) char array in the regex field, even if the predicate function does not use the field. A later commit will introduce a dynamically allocated cpumask to struct filter_pred, which will require a dedicated freeing function. Bite the bullet and make filter_pred.regex dynamically allocated. While at it, reorder the fields of filter_pred to fill in the byte holes. The struct now fits on a single cacheline. No change in behaviour intended. The kfree()'s were patched via Coccinelle: @@ struct filter_pred *pred; @@ -kfree(pred); +free_predicate(pred); Link: https://lkml.kernel.org/r/20230707172155.70873-2-vschneid@redhat.com Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Juri Lelli <juri.lelli@redhat.com> Cc: Daniel Bristot de Oliveira <bristot@redhat.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Cc: Leonardo Bras <leobras@redhat.com> Cc: Frederic Weisbecker <frederic@kernel.org> Signed-off-by: Valentin Schneider <vschneid@redhat.com> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent 7c1130e commit cfb58e2

1 file changed

Lines changed: 39 additions & 25 deletions

File tree

kernel/trace/trace_events_filter.c

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,15 @@ enum filter_pred_fn {
7070
};
7171

7272
struct filter_pred {
73-
enum filter_pred_fn fn_num;
74-
u64 val;
75-
u64 val2;
76-
struct regex regex;
73+
struct regex *regex;
7774
unsigned short *ops;
7875
struct ftrace_event_field *field;
79-
int offset;
76+
u64 val;
77+
u64 val2;
78+
enum filter_pred_fn fn_num;
79+
int offset;
8080
int not;
81-
int op;
81+
int op;
8282
};
8383

8484
/*
@@ -186,6 +186,14 @@ enum {
186186
PROCESS_OR = 4,
187187
};
188188

189+
static void free_predicate(struct filter_pred *pred)
190+
{
191+
if (pred) {
192+
kfree(pred->regex);
193+
kfree(pred);
194+
}
195+
}
196+
189197
/*
190198
* Without going into a formal proof, this explains the method that is used in
191199
* parsing the logical expressions.
@@ -623,7 +631,7 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
623631
kfree(inverts);
624632
if (prog_stack) {
625633
for (i = 0; prog_stack[i].pred; i++)
626-
kfree(prog_stack[i].pred);
634+
free_predicate(prog_stack[i].pred);
627635
kfree(prog_stack);
628636
}
629637
return ERR_PTR(ret);
@@ -750,7 +758,7 @@ static int filter_pred_string(struct filter_pred *pred, void *event)
750758
char *addr = (char *)(event + pred->offset);
751759
int cmp, match;
752760

753-
cmp = pred->regex.match(addr, &pred->regex, pred->regex.field_len);
761+
cmp = pred->regex->match(addr, pred->regex, pred->regex->field_len);
754762

755763
match = cmp ^ pred->not;
756764

@@ -763,7 +771,7 @@ static __always_inline int filter_pchar(struct filter_pred *pred, char *str)
763771
int len;
764772

765773
len = strlen(str) + 1; /* including tailing '\0' */
766-
cmp = pred->regex.match(str, &pred->regex, len);
774+
cmp = pred->regex->match(str, pred->regex, len);
767775

768776
match = cmp ^ pred->not;
769777

@@ -813,7 +821,7 @@ static int filter_pred_strloc(struct filter_pred *pred, void *event)
813821
char *addr = (char *)(event + str_loc);
814822
int cmp, match;
815823

816-
cmp = pred->regex.match(addr, &pred->regex, str_len);
824+
cmp = pred->regex->match(addr, pred->regex, str_len);
817825

818826
match = cmp ^ pred->not;
819827

@@ -836,7 +844,7 @@ static int filter_pred_strrelloc(struct filter_pred *pred, void *event)
836844
char *addr = (char *)(&item[1]) + str_loc;
837845
int cmp, match;
838846

839-
cmp = pred->regex.match(addr, &pred->regex, str_len);
847+
cmp = pred->regex->match(addr, pred->regex, str_len);
840848

841849
match = cmp ^ pred->not;
842850

@@ -874,7 +882,7 @@ static int filter_pred_comm(struct filter_pred *pred, void *event)
874882
{
875883
int cmp;
876884

877-
cmp = pred->regex.match(current->comm, &pred->regex,
885+
cmp = pred->regex->match(current->comm, pred->regex,
878886
TASK_COMM_LEN);
879887
return cmp ^ pred->not;
880888
}
@@ -1004,7 +1012,7 @@ enum regex_type filter_parse_regex(char *buff, int len, char **search, int *not)
10041012

10051013
static void filter_build_regex(struct filter_pred *pred)
10061014
{
1007-
struct regex *r = &pred->regex;
1015+
struct regex *r = pred->regex;
10081016
char *search;
10091017
enum regex_type type = MATCH_FULL;
10101018

@@ -1169,7 +1177,7 @@ static void free_prog(struct event_filter *filter)
11691177
return;
11701178

11711179
for (i = 0; prog[i].pred; i++)
1172-
kfree(prog[i].pred);
1180+
free_predicate(prog[i].pred);
11731181
kfree(prog);
11741182
}
11751183

@@ -1553,9 +1561,12 @@ static int parse_pred(const char *str, void *data,
15531561
goto err_free;
15541562
}
15551563

1556-
pred->regex.len = len;
1557-
strncpy(pred->regex.pattern, str + s, len);
1558-
pred->regex.pattern[len] = 0;
1564+
pred->regex = kzalloc(sizeof(*pred->regex), GFP_KERNEL);
1565+
if (!pred->regex)
1566+
goto err_mem;
1567+
pred->regex->len = len;
1568+
strncpy(pred->regex->pattern, str + s, len);
1569+
pred->regex->pattern[len] = 0;
15591570

15601571
/* This is either a string, or an integer */
15611572
} else if (str[i] == '\'' || str[i] == '"') {
@@ -1597,9 +1608,12 @@ static int parse_pred(const char *str, void *data,
15971608
goto err_free;
15981609
}
15991610

1600-
pred->regex.len = len;
1601-
strncpy(pred->regex.pattern, str + s, len);
1602-
pred->regex.pattern[len] = 0;
1611+
pred->regex = kzalloc(sizeof(*pred->regex), GFP_KERNEL);
1612+
if (!pred->regex)
1613+
goto err_mem;
1614+
pred->regex->len = len;
1615+
strncpy(pred->regex->pattern, str + s, len);
1616+
pred->regex->pattern[len] = 0;
16031617

16041618
filter_build_regex(pred);
16051619

@@ -1608,7 +1622,7 @@ static int parse_pred(const char *str, void *data,
16081622

16091623
} else if (field->filter_type == FILTER_STATIC_STRING) {
16101624
pred->fn_num = FILTER_PRED_FN_STRING;
1611-
pred->regex.field_len = field->size;
1625+
pred->regex->field_len = field->size;
16121626

16131627
} else if (field->filter_type == FILTER_DYN_STRING) {
16141628
pred->fn_num = FILTER_PRED_FN_STRLOC;
@@ -1691,10 +1705,10 @@ static int parse_pred(const char *str, void *data,
16911705
return i;
16921706

16931707
err_free:
1694-
kfree(pred);
1708+
free_predicate(pred);
16951709
return -EINVAL;
16961710
err_mem:
1697-
kfree(pred);
1711+
free_predicate(pred);
16981712
return -ENOMEM;
16991713
}
17001714

@@ -2287,8 +2301,8 @@ static int ftrace_function_set_filter_pred(struct filter_pred *pred,
22872301
return ret;
22882302

22892303
return __ftrace_function_set_filter(pred->op == OP_EQ,
2290-
pred->regex.pattern,
2291-
pred->regex.len,
2304+
pred->regex->pattern,
2305+
pred->regex->len,
22922306
data);
22932307
}
22942308

0 commit comments

Comments
 (0)