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
Showing the changes to kernel (1 of 1 file). Show all
Unified · Split
| @@ -39,6 +39,7 @@ · 38 unmodified lines | |||
| 39 | #define MAX_EVENT_DESC 512 | 39 | #define MAX_EVENT_DESC 512 |
| 40 | #define EVENT_NAME(user_event) ((user_event)->tracepoint.name) | 40 | #define EVENT_NAME(user_event) ((user_event)->tracepoint.name) |
| 41 | #define MAX_FIELD_ARRAY_SIZE 1024 | 41 | #define MAX_FIELD_ARRAY_SIZE 1024 |
| 42 | #define MAX_FIELD_ARG_NAME 256 | ||
| 42 | 43 | ||
| 43 | static char *register_page_data; | 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 | return destroy_user_event(user); | 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 | static bool user_event_match(const char *system, const char *event, | 772 | static bool user_event_match(const char *system, const char *event, |
| 704 | int argc, const char **argv, struct dyn_event *ev) | 773 | int argc, const char **argv, struct dyn_event *ev) |
| 705 | { | 774 | { |
| 706 | struct user_event *user = container_of(ev, struct user_event, devent); | 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 | (!system || strcmp(system, USER_EVENTS_SYSTEM) == 0); | 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 | static struct dyn_event_operations user_event_dops = { | 787 | static struct dyn_event_operations user_event_dops = { |