diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-10-07 18:28:07 -0400 |
---|---|---|
committer | Frederic Weisbecker <fweisbec@gmail.com> | 2009-10-12 17:31:49 -0400 |
commit | a703d946e883d8e447d0597de556e2effd110372 (patch) | |
tree | 2c2e37552d6a91d294e86f2247ac5d96c8b862ba /kernel/trace/trace_kprobe.c | |
parent | 2e06ff6389aedafc4a3a374344ac70672252f9b5 (diff) |
tracing/kprobes: Avoid field name confliction
Check whether the argument name is in conflict with other field names
while creating a kprobe through the debugfs interface.
Changes in v3:
- Check strcmp() == 0 instead of !strcmp().
Changes in v2:
- Add common_lock_depth to reserved name list.
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Jim Keniston <jkenisto@us.ibm.com>
Cc: Frank Ch. Eigler <fche@redhat.com>
LKML-Reference: <20091007222807.1684.26880.stgit@dhcp-100-2-132.bos.redhat.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
-rw-r--r-- | kernel/trace/trace_kprobe.c | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 3313fa74ce5f..bb6cb2bc6fae 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -38,6 +38,25 @@ | |||
38 | #define MAX_EVENT_NAME_LEN 64 | 38 | #define MAX_EVENT_NAME_LEN 64 |
39 | #define KPROBE_EVENT_SYSTEM "kprobes" | 39 | #define KPROBE_EVENT_SYSTEM "kprobes" |
40 | 40 | ||
41 | /* Reserved field names */ | ||
42 | #define FIELD_STRING_IP "ip" | ||
43 | #define FIELD_STRING_NARGS "nargs" | ||
44 | #define FIELD_STRING_RETIP "ret_ip" | ||
45 | #define FIELD_STRING_FUNC "func" | ||
46 | |||
47 | const char *reserved_field_names[] = { | ||
48 | "common_type", | ||
49 | "common_flags", | ||
50 | "common_preempt_count", | ||
51 | "common_pid", | ||
52 | "common_tgid", | ||
53 | "common_lock_depth", | ||
54 | FIELD_STRING_IP, | ||
55 | FIELD_STRING_NARGS, | ||
56 | FIELD_STRING_RETIP, | ||
57 | FIELD_STRING_FUNC, | ||
58 | }; | ||
59 | |||
41 | /* currently, trace_kprobe only supports X86. */ | 60 | /* currently, trace_kprobe only supports X86. */ |
42 | 61 | ||
43 | struct fetch_func { | 62 | struct fetch_func { |
@@ -537,6 +556,20 @@ static int parse_probe_arg(char *arg, struct fetch_func *ff, int is_return) | |||
537 | return ret; | 556 | return ret; |
538 | } | 557 | } |
539 | 558 | ||
559 | /* Return 1 if name is reserved or already used by another argument */ | ||
560 | static int conflict_field_name(const char *name, | ||
561 | struct probe_arg *args, int narg) | ||
562 | { | ||
563 | int i; | ||
564 | for (i = 0; i < ARRAY_SIZE(reserved_field_names); i++) | ||
565 | if (strcmp(reserved_field_names[i], name) == 0) | ||
566 | return 1; | ||
567 | for (i = 0; i < narg; i++) | ||
568 | if (strcmp(args[i].name, name) == 0) | ||
569 | return 1; | ||
570 | return 0; | ||
571 | } | ||
572 | |||
540 | static int create_trace_probe(int argc, char **argv) | 573 | static int create_trace_probe(int argc, char **argv) |
541 | { | 574 | { |
542 | /* | 575 | /* |
@@ -637,6 +670,12 @@ static int create_trace_probe(int argc, char **argv) | |||
637 | *arg++ = '\0'; | 670 | *arg++ = '\0'; |
638 | else | 671 | else |
639 | arg = argv[i]; | 672 | arg = argv[i]; |
673 | |||
674 | if (conflict_field_name(argv[i], tp->args, i)) { | ||
675 | ret = -EINVAL; | ||
676 | goto error; | ||
677 | } | ||
678 | |||
640 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); | 679 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); |
641 | 680 | ||
642 | /* Parse fetch argument */ | 681 | /* Parse fetch argument */ |
@@ -1039,8 +1078,8 @@ static int kprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
1039 | if (!ret) | 1078 | if (!ret) |
1040 | return ret; | 1079 | return ret; |
1041 | 1080 | ||
1042 | DEFINE_FIELD(unsigned long, ip, "ip", 0); | 1081 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); |
1043 | DEFINE_FIELD(int, nargs, "nargs", 1); | 1082 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); |
1044 | /* Set argument names as fields */ | 1083 | /* Set argument names as fields */ |
1045 | for (i = 0; i < tp->nr_args; i++) | 1084 | for (i = 0; i < tp->nr_args; i++) |
1046 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); | 1085 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); |
@@ -1057,9 +1096,9 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
1057 | if (!ret) | 1096 | if (!ret) |
1058 | return ret; | 1097 | return ret; |
1059 | 1098 | ||
1060 | DEFINE_FIELD(unsigned long, func, "func", 0); | 1099 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); |
1061 | DEFINE_FIELD(unsigned long, ret_ip, "ret_ip", 0); | 1100 | DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); |
1062 | DEFINE_FIELD(int, nargs, "nargs", 1); | 1101 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); |
1063 | /* Set argument names as fields */ | 1102 | /* Set argument names as fields */ |
1064 | for (i = 0; i < tp->nr_args; i++) | 1103 | for (i = 0; i < tp->nr_args; i++) |
1065 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); | 1104 | DEFINE_FIELD(unsigned long, args[i], tp->args[i].name, 0); |
@@ -1108,15 +1147,16 @@ static int kprobe_event_show_format(struct ftrace_event_call *call, | |||
1108 | int ret, i; | 1147 | int ret, i; |
1109 | struct trace_probe *tp = (struct trace_probe *)call->data; | 1148 | struct trace_probe *tp = (struct trace_probe *)call->data; |
1110 | 1149 | ||
1111 | SHOW_FIELD(unsigned long, ip, "ip"); | 1150 | SHOW_FIELD(unsigned long, ip, FIELD_STRING_IP); |
1112 | SHOW_FIELD(int, nargs, "nargs"); | 1151 | SHOW_FIELD(int, nargs, FIELD_STRING_NARGS); |
1113 | 1152 | ||
1114 | /* Show fields */ | 1153 | /* Show fields */ |
1115 | for (i = 0; i < tp->nr_args; i++) | 1154 | for (i = 0; i < tp->nr_args; i++) |
1116 | SHOW_FIELD(unsigned long, args[i], tp->args[i].name); | 1155 | SHOW_FIELD(unsigned long, args[i], tp->args[i].name); |
1117 | trace_seq_puts(s, "\n"); | 1156 | trace_seq_puts(s, "\n"); |
1118 | 1157 | ||
1119 | return __probe_event_show_format(s, tp, "(%lx)", "REC->ip"); | 1158 | return __probe_event_show_format(s, tp, "(%lx)", |
1159 | "REC->" FIELD_STRING_IP); | ||
1120 | } | 1160 | } |
1121 | 1161 | ||
1122 | static int kretprobe_event_show_format(struct ftrace_event_call *call, | 1162 | static int kretprobe_event_show_format(struct ftrace_event_call *call, |
@@ -1126,9 +1166,9 @@ static int kretprobe_event_show_format(struct ftrace_event_call *call, | |||
1126 | int ret, i; | 1166 | int ret, i; |
1127 | struct trace_probe *tp = (struct trace_probe *)call->data; | 1167 | struct trace_probe *tp = (struct trace_probe *)call->data; |
1128 | 1168 | ||
1129 | SHOW_FIELD(unsigned long, func, "func"); | 1169 | SHOW_FIELD(unsigned long, func, FIELD_STRING_FUNC); |
1130 | SHOW_FIELD(unsigned long, ret_ip, "ret_ip"); | 1170 | SHOW_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP); |
1131 | SHOW_FIELD(int, nargs, "nargs"); | 1171 | SHOW_FIELD(int, nargs, FIELD_STRING_NARGS); |
1132 | 1172 | ||
1133 | /* Show fields */ | 1173 | /* Show fields */ |
1134 | for (i = 0; i < tp->nr_args; i++) | 1174 | for (i = 0; i < tp->nr_args; i++) |
@@ -1136,7 +1176,8 @@ static int kretprobe_event_show_format(struct ftrace_event_call *call, | |||
1136 | trace_seq_puts(s, "\n"); | 1176 | trace_seq_puts(s, "\n"); |
1137 | 1177 | ||
1138 | return __probe_event_show_format(s, tp, "(%lx <- %lx)", | 1178 | return __probe_event_show_format(s, tp, "(%lx <- %lx)", |
1139 | "REC->func, REC->ret_ip"); | 1179 | "REC->" FIELD_STRING_FUNC |
1180 | ", REC->" FIELD_STRING_RETIP); | ||
1140 | } | 1181 | } |
1141 | 1182 | ||
1142 | #ifdef CONFIG_EVENT_PROFILE | 1183 | #ifdef CONFIG_EVENT_PROFILE |