diff options
-rw-r--r-- | kernel/trace/trace_kprobe.c | 48 | ||||
-rw-r--r-- | kernel/trace/trace_probe.c | 47 | ||||
-rw-r--r-- | kernel/trace/trace_probe.h | 7 | ||||
-rw-r--r-- | kernel/trace/trace_uprobe.c | 44 |
4 files changed, 50 insertions, 96 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index fec67188c4d2..d313bcc259dc 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -548,7 +548,6 @@ static int create_trace_kprobe(int argc, char **argv) | |||
548 | bool is_return = false, is_delete = false; | 548 | bool is_return = false, is_delete = false; |
549 | char *symbol = NULL, *event = NULL, *group = NULL; | 549 | char *symbol = NULL, *event = NULL, *group = NULL; |
550 | int maxactive = 0; | 550 | int maxactive = 0; |
551 | char *arg; | ||
552 | long offset = 0; | 551 | long offset = 0; |
553 | void *addr = NULL; | 552 | void *addr = NULL; |
554 | char buf[MAX_EVENT_NAME_LEN]; | 553 | char buf[MAX_EVENT_NAME_LEN]; |
@@ -676,53 +675,10 @@ static int create_trace_kprobe(int argc, char **argv) | |||
676 | } | 675 | } |
677 | 676 | ||
678 | /* parse arguments */ | 677 | /* parse arguments */ |
679 | ret = 0; | ||
680 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { | 678 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { |
681 | struct probe_arg *parg = &tk->tp.args[i]; | 679 | ret = traceprobe_parse_probe_arg(&tk->tp, i, argv[i], flags); |
682 | 680 | if (ret) | |
683 | /* Increment count for freeing args in error case */ | ||
684 | tk->tp.nr_args++; | ||
685 | |||
686 | /* Parse argument name */ | ||
687 | arg = strchr(argv[i], '='); | ||
688 | if (arg) { | ||
689 | *arg++ = '\0'; | ||
690 | parg->name = kstrdup(argv[i], GFP_KERNEL); | ||
691 | } else { | ||
692 | arg = argv[i]; | ||
693 | /* If argument name is omitted, set "argN" */ | ||
694 | snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1); | ||
695 | parg->name = kstrdup(buf, GFP_KERNEL); | ||
696 | } | ||
697 | |||
698 | if (!parg->name) { | ||
699 | pr_info("Failed to allocate argument[%d] name.\n", i); | ||
700 | ret = -ENOMEM; | ||
701 | goto error; | ||
702 | } | ||
703 | |||
704 | if (!is_good_name(parg->name)) { | ||
705 | pr_info("Invalid argument[%d] name: %s\n", | ||
706 | i, parg->name); | ||
707 | ret = -EINVAL; | ||
708 | goto error; | ||
709 | } | ||
710 | |||
711 | if (traceprobe_conflict_field_name(parg->name, | ||
712 | tk->tp.args, i)) { | ||
713 | pr_info("Argument[%d] name '%s' conflicts with " | ||
714 | "another field.\n", i, argv[i]); | ||
715 | ret = -EINVAL; | ||
716 | goto error; | ||
717 | } | ||
718 | |||
719 | /* Parse fetch argument */ | ||
720 | ret = traceprobe_parse_probe_arg(arg, &tk->tp.size, parg, | ||
721 | flags); | ||
722 | if (ret) { | ||
723 | pr_info("Parse error at argument[%d]. (%d)\n", i, ret); | ||
724 | goto error; | 681 | goto error; |
725 | } | ||
726 | } | 682 | } |
727 | 683 | ||
728 | ret = register_trace_kprobe(tk); | 684 | ret = register_trace_kprobe(tk); |
diff --git a/kernel/trace/trace_probe.c b/kernel/trace/trace_probe.c index bd30e9398d2a..449150c6a87f 100644 --- a/kernel/trace/trace_probe.c +++ b/kernel/trace/trace_probe.c | |||
@@ -348,7 +348,7 @@ static int __parse_bitfield_probe_arg(const char *bf, | |||
348 | } | 348 | } |
349 | 349 | ||
350 | /* String length checking wrapper */ | 350 | /* String length checking wrapper */ |
351 | int traceprobe_parse_probe_arg(char *arg, ssize_t *size, | 351 | static int traceprobe_parse_probe_arg_body(char *arg, ssize_t *size, |
352 | struct probe_arg *parg, unsigned int flags) | 352 | struct probe_arg *parg, unsigned int flags) |
353 | { | 353 | { |
354 | struct fetch_insn *code, *scode, *tmp = NULL; | 354 | struct fetch_insn *code, *scode, *tmp = NULL; |
@@ -491,8 +491,8 @@ fail: | |||
491 | } | 491 | } |
492 | 492 | ||
493 | /* Return 1 if name is reserved or already used by another argument */ | 493 | /* Return 1 if name is reserved or already used by another argument */ |
494 | int traceprobe_conflict_field_name(const char *name, | 494 | static int traceprobe_conflict_field_name(const char *name, |
495 | struct probe_arg *args, int narg) | 495 | struct probe_arg *args, int narg) |
496 | { | 496 | { |
497 | int i; | 497 | int i; |
498 | 498 | ||
@@ -507,6 +507,47 @@ int traceprobe_conflict_field_name(const char *name, | |||
507 | return 0; | 507 | return 0; |
508 | } | 508 | } |
509 | 509 | ||
510 | int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, char *arg, | ||
511 | unsigned int flags) | ||
512 | { | ||
513 | struct probe_arg *parg = &tp->args[i]; | ||
514 | char *body; | ||
515 | int ret; | ||
516 | |||
517 | /* Increment count for freeing args in error case */ | ||
518 | tp->nr_args++; | ||
519 | |||
520 | body = strchr(arg, '='); | ||
521 | if (body) { | ||
522 | parg->name = kmemdup_nul(arg, body - arg, GFP_KERNEL); | ||
523 | body++; | ||
524 | } else { | ||
525 | /* If argument name is omitted, set "argN" */ | ||
526 | parg->name = kasprintf(GFP_KERNEL, "arg%d", i + 1); | ||
527 | body = arg; | ||
528 | } | ||
529 | if (!parg->name) | ||
530 | return -ENOMEM; | ||
531 | |||
532 | if (!is_good_name(parg->name)) { | ||
533 | pr_info("Invalid argument[%d] name: %s\n", | ||
534 | i, parg->name); | ||
535 | return -EINVAL; | ||
536 | } | ||
537 | |||
538 | if (traceprobe_conflict_field_name(parg->name, tp->args, i)) { | ||
539 | pr_info("Argument[%d]: '%s' conflicts with another field.\n", | ||
540 | i, parg->name); | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | |||
544 | /* Parse fetch argument */ | ||
545 | ret = traceprobe_parse_probe_arg_body(body, &tp->size, parg, flags); | ||
546 | if (ret) | ||
547 | pr_info("Parse error at argument[%d]. (%d)\n", i, ret); | ||
548 | return ret; | ||
549 | } | ||
550 | |||
510 | void traceprobe_free_probe_arg(struct probe_arg *arg) | 551 | void traceprobe_free_probe_arg(struct probe_arg *arg) |
511 | { | 552 | { |
512 | struct fetch_insn *code = arg->code; | 553 | struct fetch_insn *code = arg->code; |
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h index 974afc1a3e73..feeec261b356 100644 --- a/kernel/trace/trace_probe.h +++ b/kernel/trace/trace_probe.h | |||
@@ -272,11 +272,8 @@ find_event_file_link(struct trace_probe *tp, struct trace_event_file *file) | |||
272 | #define TPARG_FL_FENTRY BIT(2) | 272 | #define TPARG_FL_FENTRY BIT(2) |
273 | #define TPARG_FL_MASK GENMASK(2, 0) | 273 | #define TPARG_FL_MASK GENMASK(2, 0) |
274 | 274 | ||
275 | extern int traceprobe_parse_probe_arg(char *arg, ssize_t *size, | 275 | extern int traceprobe_parse_probe_arg(struct trace_probe *tp, int i, |
276 | struct probe_arg *parg, unsigned int flags); | 276 | char *arg, unsigned int flags); |
277 | |||
278 | extern int traceprobe_conflict_field_name(const char *name, | ||
279 | struct probe_arg *args, int narg); | ||
280 | 277 | ||
281 | extern int traceprobe_update_arg(struct probe_arg *arg); | 278 | extern int traceprobe_update_arg(struct probe_arg *arg); |
282 | extern void traceprobe_free_probe_arg(struct probe_arg *arg); | 279 | extern void traceprobe_free_probe_arg(struct probe_arg *arg); |
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index b708e4ff7ea7..6eaaa2150685 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c | |||
@@ -517,51 +517,11 @@ static int create_trace_uprobe(int argc, char **argv) | |||
517 | } | 517 | } |
518 | 518 | ||
519 | /* parse arguments */ | 519 | /* parse arguments */ |
520 | ret = 0; | ||
521 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { | 520 | for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) { |
522 | struct probe_arg *parg = &tu->tp.args[i]; | 521 | ret = traceprobe_parse_probe_arg(&tu->tp, i, argv[i], |
523 | |||
524 | /* Increment count for freeing args in error case */ | ||
525 | tu->tp.nr_args++; | ||
526 | |||
527 | /* Parse argument name */ | ||
528 | arg = strchr(argv[i], '='); | ||
529 | if (arg) { | ||
530 | *arg++ = '\0'; | ||
531 | parg->name = kstrdup(argv[i], GFP_KERNEL); | ||
532 | } else { | ||
533 | arg = argv[i]; | ||
534 | /* If argument name is omitted, set "argN" */ | ||
535 | snprintf(buf, MAX_EVENT_NAME_LEN, "arg%d", i + 1); | ||
536 | parg->name = kstrdup(buf, GFP_KERNEL); | ||
537 | } | ||
538 | |||
539 | if (!parg->name) { | ||
540 | pr_info("Failed to allocate argument[%d] name.\n", i); | ||
541 | ret = -ENOMEM; | ||
542 | goto error; | ||
543 | } | ||
544 | |||
545 | if (!is_good_name(parg->name)) { | ||
546 | pr_info("Invalid argument[%d] name: %s\n", i, parg->name); | ||
547 | ret = -EINVAL; | ||
548 | goto error; | ||
549 | } | ||
550 | |||
551 | if (traceprobe_conflict_field_name(parg->name, tu->tp.args, i)) { | ||
552 | pr_info("Argument[%d] name '%s' conflicts with " | ||
553 | "another field.\n", i, argv[i]); | ||
554 | ret = -EINVAL; | ||
555 | goto error; | ||
556 | } | ||
557 | |||
558 | /* Parse fetch argument */ | ||
559 | ret = traceprobe_parse_probe_arg(arg, &tu->tp.size, parg, | ||
560 | is_return ? TPARG_FL_RETURN : 0); | 522 | is_return ? TPARG_FL_RETURN : 0); |
561 | if (ret) { | 523 | if (ret) |
562 | pr_info("Parse error at argument[%d]. (%d)\n", i, ret); | ||
563 | goto error; | 524 | goto error; |
564 | } | ||
565 | } | 525 | } |
566 | 526 | ||
567 | ret = register_trace_uprobe(tu); | 527 | ret = register_trace_uprobe(tu); |