summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/trace_kprobe.c48
-rw-r--r--kernel/trace/trace_probe.c47
-rw-r--r--kernel/trace/trace_probe.h7
-rw-r--r--kernel/trace/trace_uprobe.c44
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 */
351int traceprobe_parse_probe_arg(char *arg, ssize_t *size, 351static 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 */
494int traceprobe_conflict_field_name(const char *name, 494static 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
510int 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
510void traceprobe_free_probe_arg(struct probe_arg *arg) 551void 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
275extern int traceprobe_parse_probe_arg(char *arg, ssize_t *size, 275extern 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
278extern int traceprobe_conflict_field_name(const char *name,
279 struct probe_arg *args, int narg);
280 277
281extern int traceprobe_update_arg(struct probe_arg *arg); 278extern int traceprobe_update_arg(struct probe_arg *arg);
282extern void traceprobe_free_probe_arg(struct probe_arg *arg); 279extern 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);