Skip to content

Commit b61387c

Browse files
mhiramatrostedt
authored andcommitted
tracing/uprobe: Fix to make trace_uprobe_filter alignment safe
Commit 99c9a92 ("tracing/uprobe: Fix double perf_event linking on multiprobe uprobe") moved trace_uprobe_filter on trace_probe_event. However, since it introduced a flexible data structure with char array and type casting, the alignment of trace_uprobe_filter can be broken. This changes the type of the array to trace_uprobe_filter data strucure to fix it. Link: http://lore.kernel.org/r/[email protected] Link: http://lkml.kernel.org/r/157966340499.5107.10978352478952144902.stgit@devnote2 Fixes: 99c9a92 ("tracing/uprobe: Fix double perf_event linking on multiprobe uprobe") Suggested-by: Peter Zijlstra <[email protected]> Signed-off-by: Masami Hiramatsu <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent bf24daa commit b61387c

File tree

4 files changed

+22
-28
lines changed

4 files changed

+22
-28
lines changed

kernel/trace/trace_kprobe.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ static struct trace_kprobe *alloc_trace_kprobe(const char *group,
290290
INIT_HLIST_NODE(&tk->rp.kp.hlist);
291291
INIT_LIST_HEAD(&tk->rp.kp.list);
292292

293-
ret = trace_probe_init(&tk->tp, event, group, 0);
293+
ret = trace_probe_init(&tk->tp, event, group, false);
294294
if (ret < 0)
295295
goto error;
296296

kernel/trace/trace_probe.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -984,16 +984,19 @@ void trace_probe_cleanup(struct trace_probe *tp)
984984
}
985985

986986
int trace_probe_init(struct trace_probe *tp, const char *event,
987-
const char *group, size_t event_data_size)
987+
const char *group, bool alloc_filter)
988988
{
989989
struct trace_event_call *call;
990+
size_t size = sizeof(struct trace_probe_event);
990991
int ret = 0;
991992

992993
if (!event || !group)
993994
return -EINVAL;
994995

995-
tp->event = kzalloc(sizeof(struct trace_probe_event) + event_data_size,
996-
GFP_KERNEL);
996+
if (alloc_filter)
997+
size += sizeof(struct trace_uprobe_filter);
998+
999+
tp->event = kzalloc(size, GFP_KERNEL);
9971000
if (!tp->event)
9981001
return -ENOMEM;
9991002

kernel/trace/trace_probe.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,14 +223,20 @@ struct probe_arg {
223223
const struct fetch_type *type; /* Type of this argument */
224224
};
225225

226+
struct trace_uprobe_filter {
227+
rwlock_t rwlock;
228+
int nr_systemwide;
229+
struct list_head perf_events;
230+
};
231+
226232
/* Event call and class holder */
227233
struct trace_probe_event {
228234
unsigned int flags; /* For TP_FLAG_* */
229235
struct trace_event_class class;
230236
struct trace_event_call call;
231237
struct list_head files;
232238
struct list_head probes;
233-
char data[0];
239+
struct trace_uprobe_filter filter[0];
234240
};
235241

236242
struct trace_probe {
@@ -323,7 +329,7 @@ static inline bool trace_probe_has_single_file(struct trace_probe *tp)
323329
}
324330

325331
int trace_probe_init(struct trace_probe *tp, const char *event,
326-
const char *group, size_t event_data_size);
332+
const char *group, bool alloc_filter);
327333
void trace_probe_cleanup(struct trace_probe *tp);
328334
int trace_probe_append(struct trace_probe *tp, struct trace_probe *to);
329335
void trace_probe_unlink(struct trace_probe *tp);

kernel/trace/trace_uprobe.c

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@ struct uprobe_trace_entry_head {
3434
#define DATAOF_TRACE_ENTRY(entry, is_return) \
3535
((void*)(entry) + SIZEOF_TRACE_ENTRY(is_return))
3636

37-
struct trace_uprobe_filter {
38-
rwlock_t rwlock;
39-
int nr_systemwide;
40-
struct list_head perf_events;
41-
};
42-
4337
static int trace_uprobe_create(int argc, const char **argv);
4438
static int trace_uprobe_show(struct seq_file *m, struct dyn_event *ev);
4539
static int trace_uprobe_release(struct dyn_event *ev);
@@ -263,14 +257,6 @@ process_fetch_insn(struct fetch_insn *code, struct pt_regs *regs, void *dest,
263257
}
264258
NOKPROBE_SYMBOL(process_fetch_insn)
265259

266-
static struct trace_uprobe_filter *
267-
trace_uprobe_get_filter(struct trace_uprobe *tu)
268-
{
269-
struct trace_probe_event *event = tu->tp.event;
270-
271-
return (struct trace_uprobe_filter *)&event->data[0];
272-
}
273-
274260
static inline void init_trace_uprobe_filter(struct trace_uprobe_filter *filter)
275261
{
276262
rwlock_init(&filter->rwlock);
@@ -358,16 +344,15 @@ alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
358344
if (!tu)
359345
return ERR_PTR(-ENOMEM);
360346

361-
ret = trace_probe_init(&tu->tp, event, group,
362-
sizeof(struct trace_uprobe_filter));
347+
ret = trace_probe_init(&tu->tp, event, group, true);
363348
if (ret < 0)
364349
goto error;
365350

366351
dyn_event_init(&tu->devent, &trace_uprobe_ops);
367352
tu->consumer.handler = uprobe_dispatcher;
368353
if (is_ret)
369354
tu->consumer.ret_handler = uretprobe_dispatcher;
370-
init_trace_uprobe_filter(trace_uprobe_get_filter(tu));
355+
init_trace_uprobe_filter(tu->tp.event->filter);
371356
return tu;
372357

373358
error:
@@ -1076,7 +1061,7 @@ static void __probe_event_disable(struct trace_probe *tp)
10761061
struct trace_uprobe *tu;
10771062

10781063
tu = container_of(tp, struct trace_uprobe, tp);
1079-
WARN_ON(!uprobe_filter_is_empty(trace_uprobe_get_filter(tu)));
1064+
WARN_ON(!uprobe_filter_is_empty(tu->tp.event->filter));
10801065

10811066
list_for_each_entry(pos, trace_probe_probe_list(tp), list) {
10821067
tu = container_of(pos, struct trace_uprobe, tp);
@@ -1117,7 +1102,7 @@ static int probe_event_enable(struct trace_event_call *call,
11171102
}
11181103

11191104
tu = container_of(tp, struct trace_uprobe, tp);
1120-
WARN_ON(!uprobe_filter_is_empty(trace_uprobe_get_filter(tu)));
1105+
WARN_ON(!uprobe_filter_is_empty(tu->tp.event->filter));
11211106

11221107
if (enabled)
11231108
return 0;
@@ -1281,7 +1266,7 @@ static int uprobe_perf_close(struct trace_event_call *call,
12811266
return -ENODEV;
12821267

12831268
tu = container_of(tp, struct trace_uprobe, tp);
1284-
if (trace_uprobe_filter_remove(trace_uprobe_get_filter(tu), event))
1269+
if (trace_uprobe_filter_remove(tu->tp.event->filter, event))
12851270
return 0;
12861271

12871272
list_for_each_entry(pos, trace_probe_probe_list(tp), list) {
@@ -1306,7 +1291,7 @@ static int uprobe_perf_open(struct trace_event_call *call,
13061291
return -ENODEV;
13071292

13081293
tu = container_of(tp, struct trace_uprobe, tp);
1309-
if (trace_uprobe_filter_add(trace_uprobe_get_filter(tu), event))
1294+
if (trace_uprobe_filter_add(tu->tp.event->filter, event))
13101295
return 0;
13111296

13121297
list_for_each_entry(pos, trace_probe_probe_list(tp), list) {
@@ -1328,7 +1313,7 @@ static bool uprobe_perf_filter(struct uprobe_consumer *uc,
13281313
int ret;
13291314

13301315
tu = container_of(uc, struct trace_uprobe, consumer);
1331-
filter = trace_uprobe_get_filter(tu);
1316+
filter = tu->tp.event->filter;
13321317

13331318
read_lock(&filter->rwlock);
13341319
ret = __uprobe_perf_filter(filter, mm);

0 commit comments

Comments
 (0)