diff options
Diffstat (limited to 'kernel/trace/trace_kprobe.c')
| -rw-r--r-- | kernel/trace/trace_kprobe.c | 43 |
1 files changed, 25 insertions, 18 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 8b27c9849b4..544301d29de 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
| @@ -514,8 +514,8 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); | |||
| 514 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, | 514 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, |
| 515 | struct pt_regs *regs); | 515 | struct pt_regs *regs); |
| 516 | 516 | ||
| 517 | /* Check the name is good for event/group */ | 517 | /* Check the name is good for event/group/fields */ |
| 518 | static int check_event_name(const char *name) | 518 | static int is_good_name(const char *name) |
| 519 | { | 519 | { |
| 520 | if (!isalpha(*name) && *name != '_') | 520 | if (!isalpha(*name) && *name != '_') |
| 521 | return 0; | 521 | return 0; |
| @@ -557,7 +557,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 557 | else | 557 | else |
| 558 | tp->rp.kp.pre_handler = kprobe_dispatcher; | 558 | tp->rp.kp.pre_handler = kprobe_dispatcher; |
| 559 | 559 | ||
| 560 | if (!event || !check_event_name(event)) { | 560 | if (!event || !is_good_name(event)) { |
| 561 | ret = -EINVAL; | 561 | ret = -EINVAL; |
| 562 | goto error; | 562 | goto error; |
| 563 | } | 563 | } |
| @@ -567,7 +567,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
| 567 | if (!tp->call.name) | 567 | if (!tp->call.name) |
| 568 | goto error; | 568 | goto error; |
| 569 | 569 | ||
| 570 | if (!group || !check_event_name(group)) { | 570 | if (!group || !is_good_name(group)) { |
| 571 | ret = -EINVAL; | 571 | ret = -EINVAL; |
| 572 | goto error; | 572 | goto error; |
| 573 | } | 573 | } |
| @@ -883,7 +883,7 @@ static int create_trace_probe(int argc, char **argv) | |||
| 883 | int i, ret = 0; | 883 | int i, ret = 0; |
| 884 | int is_return = 0, is_delete = 0; | 884 | int is_return = 0, is_delete = 0; |
| 885 | char *symbol = NULL, *event = NULL, *group = NULL; | 885 | char *symbol = NULL, *event = NULL, *group = NULL; |
| 886 | char *arg, *tmp; | 886 | char *arg; |
| 887 | unsigned long offset = 0; | 887 | unsigned long offset = 0; |
| 888 | void *addr = NULL; | 888 | void *addr = NULL; |
| 889 | char buf[MAX_EVENT_NAME_LEN]; | 889 | char buf[MAX_EVENT_NAME_LEN]; |
| @@ -992,26 +992,36 @@ static int create_trace_probe(int argc, char **argv) | |||
| 992 | /* parse arguments */ | 992 | /* parse arguments */ |
| 993 | ret = 0; | 993 | ret = 0; |
| 994 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { | 994 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { |
| 995 | /* Increment count for freeing args in error case */ | ||
| 996 | tp->nr_args++; | ||
| 997 | |||
| 995 | /* Parse argument name */ | 998 | /* Parse argument name */ |
| 996 | arg = strchr(argv[i], '='); | 999 | arg = strchr(argv[i], '='); |
| 997 | if (arg) | 1000 | if (arg) { |
| 998 | *arg++ = '\0'; | 1001 | *arg++ = '\0'; |
| 999 | else | 1002 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); |
| 1003 | } else { | ||
| 1000 | arg = argv[i]; | 1004 | arg = argv[i]; |
| 1005 | /* If argument name is omitted, set "argN" */ | ||
| 1006 | snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1); | ||
| 1007 | tp->args[i].name = kstrdup(buf, GFP_KERNEL); | ||
| 1008 | } | ||
| 1001 | 1009 | ||
| 1002 | tp->args[i].name = kstrdup(argv[i], GFP_KERNEL); | ||
| 1003 | if (!tp->args[i].name) { | 1010 | if (!tp->args[i].name) { |
| 1004 | pr_info("Failed to allocate argument%d name '%s'.\n", | 1011 | pr_info("Failed to allocate argument[%d] name.\n", i); |
| 1005 | i, argv[i]); | ||
| 1006 | ret = -ENOMEM; | 1012 | ret = -ENOMEM; |
| 1007 | goto error; | 1013 | goto error; |
| 1008 | } | 1014 | } |
| 1009 | tmp = strchr(tp->args[i].name, ':'); | 1015 | |
| 1010 | if (tmp) | 1016 | if (!is_good_name(tp->args[i].name)) { |
| 1011 | *tmp = '_'; /* convert : to _ */ | 1017 | pr_info("Invalid argument[%d] name: %s\n", |
| 1018 | i, tp->args[i].name); | ||
| 1019 | ret = -EINVAL; | ||
| 1020 | goto error; | ||
| 1021 | } | ||
| 1012 | 1022 | ||
| 1013 | if (conflict_field_name(tp->args[i].name, tp->args, i)) { | 1023 | if (conflict_field_name(tp->args[i].name, tp->args, i)) { |
| 1014 | pr_info("Argument%d name '%s' conflicts with " | 1024 | pr_info("Argument[%d] name '%s' conflicts with " |
| 1015 | "another field.\n", i, argv[i]); | 1025 | "another field.\n", i, argv[i]); |
| 1016 | ret = -EINVAL; | 1026 | ret = -EINVAL; |
| 1017 | goto error; | 1027 | goto error; |
| @@ -1020,12 +1030,9 @@ static int create_trace_probe(int argc, char **argv) | |||
| 1020 | /* Parse fetch argument */ | 1030 | /* Parse fetch argument */ |
| 1021 | ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); | 1031 | ret = parse_probe_arg(arg, tp, &tp->args[i], is_return); |
| 1022 | if (ret) { | 1032 | if (ret) { |
| 1023 | pr_info("Parse error at argument%d. (%d)\n", i, ret); | 1033 | pr_info("Parse error at argument[%d]. (%d)\n", i, ret); |
| 1024 | kfree(tp->args[i].name); | ||
| 1025 | goto error; | 1034 | goto error; |
| 1026 | } | 1035 | } |
| 1027 | |||
| 1028 | tp->nr_args++; | ||
| 1029 | } | 1036 | } |
| 1030 | 1037 | ||
| 1031 | ret = register_trace_probe(tp); | 1038 | ret = register_trace_probe(tp); |
