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