Ensures that when dynamic events requests a match with arguments that they match what is in the user_event. Link: https://lkml.kernel.org/r/20220118204326.2169-4-beaub@linux.microsoft.com
Unified · Split
| @@ -39,6 +39,7 @@ · 38 unmodified lines | ||
| 39 | 39 | #define MAX_EVENT_DESC 512 |
| 40 | 40 | #define EVENT_NAME(user_event) ((user_event)->tracepoint.name) |
| 41 | 41 | #define MAX_FIELD_ARRAY_SIZE 1024 |
| 42 | +#define MAX_FIELD_ARG_NAME 256 | |
| 42 | 43 | |
| 43 | 44 | static char *register_page_data; |
| 44 | 45 | |
| @@ -700,13 +701,87 @@ static int user_event_free(struct dyn_event *ev) · 655 unmodified lines | ||
| 700 | 701 | return destroy_user_event(user); |
| 701 | 702 | } |
| 702 | 703 | |
| 704 | +static bool user_field_match(struct ftrace_event_field *field, int argc, | |
| 705 | + const char **argv, int *iout) | |
| 706 | +{ | |
| 707 | + char *field_name, *arg_name; | |
| 708 | + int len, pos, i = *iout; | |
| 709 | + bool colon = false, match = false; | |
| 710 | + | |
| 711 | + if (i >= argc) | |
| 712 | + return false; | |
| 713 | + | |
| 714 | + len = MAX_FIELD_ARG_NAME; | |
| 715 | + field_name = kmalloc(len, GFP_KERNEL); | |
| 716 | + arg_name = kmalloc(len, GFP_KERNEL); | |
| 717 | + | |
| 718 | + if (!arg_name || !field_name) | |
| 719 | + goto out; | |
| 720 | + | |
| 721 | + pos = 0; | |
| 722 | + | |
| 723 | + for (; i < argc; ++i) { | |
| 724 | + if (i != *iout) | |
| 725 | + pos += snprintf(arg_name + pos, len - pos, " "); | |
| 726 | + | |
| 727 | + pos += snprintf(arg_name + pos, len - pos, argv[i]); | |
| 728 | + | |
| 729 | + if (strchr(argv[i], ';')) { | |
| 730 | + ++i; | |
| 731 | + colon = true; | |
| 732 | + break; | |
| 733 | + } | |
| 734 | + } | |
| 735 | + | |
| 736 | + pos = 0; | |
| 737 | + | |
| 738 | + pos += snprintf(field_name + pos, len - pos, field->type); | |
| 739 | + pos += snprintf(field_name + pos, len - pos, " "); | |
| 740 | + pos += snprintf(field_name + pos, len - pos, field->name); | |
| 741 | + | |
| 742 | + if (colon) | |
| 743 | + pos += snprintf(field_name + pos, len - pos, ";"); | |
| 744 | + | |
| 745 | + *iout = i; | |
| 746 | + | |
| 747 | + match = strcmp(arg_name, field_name) == 0; | |
| 748 | +out: | |
| 749 | + kfree(arg_name); | |
| 750 | + kfree(field_name); | |
| 751 | + | |
| 752 | + return match; | |
| 753 | +} | |
| 754 | + | |
| 755 | +static bool user_fields_match(struct user_event *user, int argc, | |
| 756 | + const char **argv) | |
| 757 | +{ | |
| 758 | + struct ftrace_event_field *field, *next; | |
| 759 | + struct list_head *head = &user->fields; | |
| 760 | + int i = 0; | |
| 761 | + | |
| 762 | + list_for_each_entry_safe_reverse(field, next, head, link) | |
| 763 | + if (!user_field_match(field, argc, argv, &i)) | |
| 764 | + return false; | |
| 765 | + | |
| 766 | + if (i != argc) | |
| 767 | + return false; | |
| 768 | + | |
| 769 | + return true; | |
| 770 | +} | |
| 771 | + | |
| 703 | 772 | static bool user_event_match(const char *system, const char *event, |
| 704 | 773 | int argc, const char **argv, struct dyn_event *ev) |
| 705 | 774 | { |
| 706 | 775 | struct user_event *user = container_of(ev, struct user_event, devent); |
| 776 | + bool match; | |
| 707 | 777 | |
| 708 | − return strcmp(EVENT_NAME(user), event) == 0 && | |
| 778 | + match = strcmp(EVENT_NAME(user), event) == 0 && | |
| 709 | 779 | (!system || strcmp(system, USER_EVENTS_SYSTEM) == 0); |
| 780 | + | |
| 781 | + if (match && argc > 0) | |
| 782 | + match = user_fields_match(user, argc, argv); | |
| 783 | + | |
| 784 | + return match; | |
| 710 | 785 | } |
| 711 | 786 | |
| 712 | 787 | static struct dyn_event_operations user_event_dops = { |