Skip to content

Commit fe60b0c

Browse files
mhiramatrostedt
authored andcommitted
tracing/probe: Reject exactly same probe event
Reject exactly same probe events as existing probes. Multiprobe allows user to define multiple probes on same event. If user appends a probe which exactly same definition (same probe address and same arguments) on existing event, the event will record same probe information twice. That can be confusing users, so reject it. Link: http://lkml.kernel.org/r/156879694602.31056.5533024778165036763.stgit@devnote2 Signed-off-by: Masami Hiramatsu <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent 44d00dc commit fe60b0c

File tree

3 files changed

+90
-17
lines changed

3 files changed

+90
-17
lines changed

kernel/trace/trace_kprobe.c

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -528,10 +528,53 @@ static int unregister_trace_kprobe(struct trace_kprobe *tk)
528528
return 0;
529529
}
530530

531+
static bool trace_kprobe_has_same_kprobe(struct trace_kprobe *orig,
532+
struct trace_kprobe *comp)
533+
{
534+
struct trace_probe_event *tpe = orig->tp.event;
535+
struct trace_probe *pos;
536+
int i;
537+
538+
list_for_each_entry(pos, &tpe->probes, list) {
539+
orig = container_of(pos, struct trace_kprobe, tp);
540+
if (strcmp(trace_kprobe_symbol(orig),
541+
trace_kprobe_symbol(comp)) ||
542+
trace_kprobe_offset(orig) != trace_kprobe_offset(comp))
543+
continue;
544+
545+
/*
546+
* trace_probe_compare_arg_type() ensured that nr_args and
547+
* each argument name and type are same. Let's compare comm.
548+
*/
549+
for (i = 0; i < orig->tp.nr_args; i++) {
550+
if (strcmp(orig->tp.args[i].comm,
551+
comp->tp.args[i].comm))
552+
continue;
553+
}
554+
555+
return true;
556+
}
557+
558+
return false;
559+
}
560+
531561
static int append_trace_kprobe(struct trace_kprobe *tk, struct trace_kprobe *to)
532562
{
533563
int ret;
534564

565+
ret = trace_probe_compare_arg_type(&tk->tp, &to->tp);
566+
if (ret) {
567+
/* Note that argument starts index = 2 */
568+
trace_probe_log_set_index(ret + 1);
569+
trace_probe_log_err(0, DIFF_ARG_TYPE);
570+
return -EEXIST;
571+
}
572+
if (trace_kprobe_has_same_kprobe(to, tk)) {
573+
trace_probe_log_set_index(0);
574+
trace_probe_log_err(0, SAME_PROBE);
575+
return -EEXIST;
576+
}
577+
535578
/* Append to existing event */
536579
ret = trace_probe_append(&tk->tp, &to->tp);
537580
if (ret)
@@ -568,14 +611,7 @@ static int register_trace_kprobe(struct trace_kprobe *tk)
568611
trace_probe_log_err(0, DIFF_PROBE_TYPE);
569612
ret = -EEXIST;
570613
} else {
571-
ret = trace_probe_compare_arg_type(&tk->tp, &old_tk->tp);
572-
if (ret) {
573-
/* Note that argument starts index = 2 */
574-
trace_probe_log_set_index(ret + 1);
575-
trace_probe_log_err(0, DIFF_ARG_TYPE);
576-
ret = -EEXIST;
577-
} else
578-
ret = append_trace_kprobe(tk, old_tk);
614+
ret = append_trace_kprobe(tk, old_tk);
579615
}
580616
goto end;
581617
}

kernel/trace/trace_probe.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,8 @@ extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
436436
C(BAD_INSN_BNDRY, "Probe point is not an instruction boundary"),\
437437
C(FAIL_REG_PROBE, "Failed to register probe event"),\
438438
C(DIFF_PROBE_TYPE, "Probe type is different from existing probe"),\
439-
C(DIFF_ARG_TYPE, "Argument type or name is different from existing probe"),
439+
C(DIFF_ARG_TYPE, "Argument type or name is different from existing probe"),\
440+
C(SAME_PROBE, "There is already the exact same probe event"),
440441

441442
#undef C
442443
#define C(a, b) TP_ERR_##a

kernel/trace/trace_uprobe.c

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -410,10 +410,53 @@ static int unregister_trace_uprobe(struct trace_uprobe *tu)
410410
return 0;
411411
}
412412

413+
static bool trace_uprobe_has_same_uprobe(struct trace_uprobe *orig,
414+
struct trace_uprobe *comp)
415+
{
416+
struct trace_probe_event *tpe = orig->tp.event;
417+
struct trace_probe *pos;
418+
struct inode *comp_inode = d_real_inode(comp->path.dentry);
419+
int i;
420+
421+
list_for_each_entry(pos, &tpe->probes, list) {
422+
orig = container_of(pos, struct trace_uprobe, tp);
423+
if (comp_inode != d_real_inode(orig->path.dentry) ||
424+
comp->offset != orig->offset)
425+
continue;
426+
427+
/*
428+
* trace_probe_compare_arg_type() ensured that nr_args and
429+
* each argument name and type are same. Let's compare comm.
430+
*/
431+
for (i = 0; i < orig->tp.nr_args; i++) {
432+
if (strcmp(orig->tp.args[i].comm,
433+
comp->tp.args[i].comm))
434+
continue;
435+
}
436+
437+
return true;
438+
}
439+
440+
return false;
441+
}
442+
413443
static int append_trace_uprobe(struct trace_uprobe *tu, struct trace_uprobe *to)
414444
{
415445
int ret;
416446

447+
ret = trace_probe_compare_arg_type(&tu->tp, &to->tp);
448+
if (ret) {
449+
/* Note that argument starts index = 2 */
450+
trace_probe_log_set_index(ret + 1);
451+
trace_probe_log_err(0, DIFF_ARG_TYPE);
452+
return -EEXIST;
453+
}
454+
if (trace_uprobe_has_same_uprobe(to, tu)) {
455+
trace_probe_log_set_index(0);
456+
trace_probe_log_err(0, SAME_PROBE);
457+
return -EEXIST;
458+
}
459+
417460
/* Append to existing event */
418461
ret = trace_probe_append(&tu->tp, &to->tp);
419462
if (!ret)
@@ -469,14 +512,7 @@ static int register_trace_uprobe(struct trace_uprobe *tu)
469512
trace_probe_log_err(0, DIFF_PROBE_TYPE);
470513
ret = -EEXIST;
471514
} else {
472-
ret = trace_probe_compare_arg_type(&tu->tp, &old_tu->tp);
473-
if (ret) {
474-
/* Note that argument starts index = 2 */
475-
trace_probe_log_set_index(ret + 1);
476-
trace_probe_log_err(0, DIFF_ARG_TYPE);
477-
ret = -EEXIST;
478-
} else
479-
ret = append_trace_uprobe(tu, old_tu);
515+
ret = append_trace_uprobe(tu, old_tu);
480516
}
481517
goto end;
482518
}

0 commit comments

Comments
 (0)