diff options
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 47 | 
1 files changed, 29 insertions, 18 deletions
| diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index b52d397e57eb..6ea90c0e2c96 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -282,6 +282,18 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); | |||
| 282 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, | 282 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, | 
| 283 | struct pt_regs *regs); | 283 | struct pt_regs *regs); | 
| 284 | 284 | ||
| 285 | /* Check the name is good for event/group */ | ||
| 286 | static int check_event_name(const char *name) | ||
| 287 | { | ||
| 288 | if (!isalpha(*name) && *name != '_') | ||
| 289 | return 0; | ||
| 290 | while (*++name != '\0') { | ||
| 291 | if (!isalpha(*name) && !isdigit(*name) && *name != '_') | ||
| 292 | return 0; | ||
| 293 | } | ||
| 294 | return 1; | ||
| 295 | } | ||
| 296 | |||
| 285 | /* | 297 | /* | 
| 286 | * Allocate new trace_probe and initialize it (including kprobes). | 298 | * Allocate new trace_probe and initialize it (including kprobes). | 
| 287 | */ | 299 | */ | 
| @@ -293,10 +305,11 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 293 | int nargs, int is_return) | 305 | int nargs, int is_return) | 
| 294 | { | 306 | { | 
| 295 | struct trace_probe *tp; | 307 | struct trace_probe *tp; | 
| 308 | int ret = -ENOMEM; | ||
| 296 | 309 | ||
| 297 | tp = kzalloc(SIZEOF_TRACE_PROBE(nargs), GFP_KERNEL); | 310 | tp = kzalloc(SIZEOF_TRACE_PROBE(nargs), GFP_KERNEL); | 
| 298 | if (!tp) | 311 | if (!tp) | 
| 299 | return ERR_PTR(-ENOMEM); | 312 | return ERR_PTR(ret); | 
| 300 | 313 | ||
| 301 | if (symbol) { | 314 | if (symbol) { | 
| 302 | tp->symbol = kstrdup(symbol, GFP_KERNEL); | 315 | tp->symbol = kstrdup(symbol, GFP_KERNEL); | 
| @@ -312,14 +325,20 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 312 | else | 325 | else | 
| 313 | tp->rp.kp.pre_handler = kprobe_dispatcher; | 326 | tp->rp.kp.pre_handler = kprobe_dispatcher; | 
| 314 | 327 | ||
| 315 | if (!event) | 328 | if (!event || !check_event_name(event)) { | 
| 329 | ret = -EINVAL; | ||
| 316 | goto error; | 330 | goto error; | 
| 331 | } | ||
| 332 | |||
| 317 | tp->call.name = kstrdup(event, GFP_KERNEL); | 333 | tp->call.name = kstrdup(event, GFP_KERNEL); | 
| 318 | if (!tp->call.name) | 334 | if (!tp->call.name) | 
| 319 | goto error; | 335 | goto error; | 
| 320 | 336 | ||
| 321 | if (!group) | 337 | if (!group || !check_event_name(group)) { | 
| 338 | ret = -EINVAL; | ||
| 322 | goto error; | 339 | goto error; | 
| 340 | } | ||
| 341 | |||
| 323 | tp->call.system = kstrdup(group, GFP_KERNEL); | 342 | tp->call.system = kstrdup(group, GFP_KERNEL); | 
| 324 | if (!tp->call.system) | 343 | if (!tp->call.system) | 
| 325 | goto error; | 344 | goto error; | 
| @@ -330,7 +349,7 @@ error: | |||
| 330 | kfree(tp->call.name); | 349 | kfree(tp->call.name); | 
| 331 | kfree(tp->symbol); | 350 | kfree(tp->symbol); | 
| 332 | kfree(tp); | 351 | kfree(tp); | 
| 333 | return ERR_PTR(-ENOMEM); | 352 | return ERR_PTR(ret); | 
| 334 | } | 353 | } | 
| 335 | 354 | ||
| 336 | static void free_probe_arg(struct probe_arg *arg) | 355 | static void free_probe_arg(struct probe_arg *arg) | 
| @@ -695,10 +714,10 @@ static int create_trace_probe(int argc, char **argv) | |||
| 695 | if (!event) { | 714 | if (!event) { | 
| 696 | /* Make a new event name */ | 715 | /* Make a new event name */ | 
| 697 | if (symbol) | 716 | if (symbol) | 
| 698 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@%s%+ld", | 717 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_%ld", | 
| 699 | is_return ? 'r' : 'p', symbol, offset); | 718 | is_return ? 'r' : 'p', symbol, offset); | 
| 700 | else | 719 | else | 
| 701 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@0x%p", | 720 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p", | 
| 702 | is_return ? 'r' : 'p', addr); | 721 | is_return ? 'r' : 'p', addr); | 
| 703 | event = buf; | 722 | event = buf; | 
| 704 | } | 723 | } | 
| @@ -1132,10 +1151,6 @@ static int kprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
| 1132 | struct kprobe_trace_entry field; | 1151 | struct kprobe_trace_entry field; | 
| 1133 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1152 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 
| 1134 | 1153 | ||
| 1135 | ret = trace_define_common_fields(event_call); | ||
| 1136 | if (ret) | ||
| 1137 | return ret; | ||
| 1138 | |||
| 1139 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); | 1154 | DEFINE_FIELD(unsigned long, ip, FIELD_STRING_IP, 0); | 
| 1140 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); | 1155 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); | 
| 1141 | /* Set argument names as fields */ | 1156 | /* Set argument names as fields */ | 
| @@ -1150,10 +1165,6 @@ static int kretprobe_event_define_fields(struct ftrace_event_call *event_call) | |||
| 1150 | struct kretprobe_trace_entry field; | 1165 | struct kretprobe_trace_entry field; | 
| 1151 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 1166 | struct trace_probe *tp = (struct trace_probe *)event_call->data; | 
| 1152 | 1167 | ||
| 1153 | ret = trace_define_common_fields(event_call); | ||
| 1154 | if (ret) | ||
| 1155 | return ret; | ||
| 1156 | |||
| 1157 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); | 1168 | DEFINE_FIELD(unsigned long, func, FIELD_STRING_FUNC, 0); | 
| 1158 | DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); | 1169 | DEFINE_FIELD(unsigned long, ret_ip, FIELD_STRING_RETIP, 0); | 
| 1159 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); | 1170 | DEFINE_FIELD(int, nargs, FIELD_STRING_NARGS, 1); | 
| @@ -1190,10 +1201,11 @@ static int __probe_event_show_format(struct trace_seq *s, | |||
| 1190 | #undef SHOW_FIELD | 1201 | #undef SHOW_FIELD | 
| 1191 | #define SHOW_FIELD(type, item, name) \ | 1202 | #define SHOW_FIELD(type, item, name) \ | 
| 1192 | do { \ | 1203 | do { \ | 
| 1193 | ret = trace_seq_printf(s, "\tfield: " #type " %s;\t" \ | 1204 | ret = trace_seq_printf(s, "\tfield:" #type " %s;\t" \ | 
| 1194 | "offset:%u;\tsize:%u;\n", name, \ | 1205 | "offset:%u;\tsize:%u;\tsigned:%d;\n", name,\ | 
| 1195 | (unsigned int)offsetof(typeof(field), item),\ | 1206 | (unsigned int)offsetof(typeof(field), item),\ | 
| 1196 | (unsigned int)sizeof(type)); \ | 1207 | (unsigned int)sizeof(type), \ | 
| 1208 | is_signed_type(type)); \ | ||
| 1197 | if (!ret) \ | 1209 | if (!ret) \ | 
| 1198 | return 0; \ | 1210 | return 0; \ | 
| 1199 | } while (0) | 1211 | } while (0) | 
| @@ -1453,7 +1465,6 @@ static int register_probe_event(struct trace_probe *tp) | |||
| 1453 | call->unregfunc = probe_event_disable; | 1465 | call->unregfunc = probe_event_disable; | 
| 1454 | 1466 | ||
| 1455 | #ifdef CONFIG_EVENT_PROFILE | 1467 | #ifdef CONFIG_EVENT_PROFILE | 
| 1456 | atomic_set(&call->profile_count, -1); | ||
| 1457 | call->profile_enable = probe_profile_enable; | 1468 | call->profile_enable = probe_profile_enable; | 
| 1458 | call->profile_disable = probe_profile_disable; | 1469 | call->profile_disable = probe_profile_disable; | 
| 1459 | #endif | 1470 | #endif | 
