mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 04:02:20 +00:00
user-event updates for v6.10:
- Minor update to the user_events interface The ABI of creating a user event states that the fields are separated by semicolons, and spaces should be ignored. But the parsing expected at least one space to be there (which was incorrect). Fix the reading of the string to handle fields separated by semicolons but no space between them. This does extend the API sightly as now "field;field" will now be parsed and not cause an error. But it should not cause any regressions as no logic should expect it to fail. Note, that the logic that parses the event fields to create the trace_event works with no spaces after the semi-colon. It is the logic that tests against existing events that is inconsistent. This causes registering an event without using spaces to succeed if it doesn't exist, but makes the same call that tries to register to the same event, but doesn't use spaces, fail. -----BEGIN PGP SIGNATURE----- iIoEABYIADIWIQRRSw7ePDh/lE+zeZMp5XQQmuv6qgUCZkZN1hQccm9zdGVkdEBn b29kbWlzLm9yZwAKCRAp5XQQmuv6qvCXAQDO8b2GeCuAMa2SW7PMFdpB2Tc2F5v4 WPBEKaLb0TU+7AEAwR0rCm22p9rpke754lcpZDz7xJNcyiyMkyXeJWCauQA= =PYwP -----END PGP SIGNATURE----- Merge tag 'trace-user-events-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace Pull tracing user-event updates from Steven Rostedt: - Minor update to the user_events interface The ABI of creating a user event states that the fields are separated by semicolons, and spaces should be ignored. But the parsing expected at least one space to be there (which was incorrect). Fix the reading of the string to handle fields separated by semicolons but no space between them. This does extend the API sightly as now "field;field" will now be parsed and not cause an error. But it should not cause any regressions as no logic should expect it to fail. Note, that the logic that parses the event fields to create the trace_event works with no spaces after the semi-colon. It is the logic that tests against existing events that is inconsistent. This causes registering an event without using spaces to succeed if it doesn't exist, but makes the same call that tries to register to the same event, but doesn't use spaces, fail. * tag 'trace-user-events-v6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace: selftests/user_events: Add non-spacing separator check tracing/user_events: Fix non-spaced field matching
This commit is contained in:
commit
fa3889d970
@ -1989,6 +1989,80 @@ static int user_event_set_tp_name(struct user_event *user)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Counts how many ';' without a trailing space are in the args.
|
||||
*/
|
||||
static int count_semis_no_space(char *args)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
while ((args = strchr(args, ';'))) {
|
||||
args++;
|
||||
|
||||
if (!isspace(*args))
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies the arguments while ensuring all ';' have a trailing space.
|
||||
*/
|
||||
static char *insert_space_after_semis(char *args, int count)
|
||||
{
|
||||
char *fixed, *pos;
|
||||
int len;
|
||||
|
||||
len = strlen(args) + count;
|
||||
fixed = kmalloc(len + 1, GFP_KERNEL);
|
||||
|
||||
if (!fixed)
|
||||
return NULL;
|
||||
|
||||
pos = fixed;
|
||||
|
||||
/* Insert a space after ';' if there is no trailing space. */
|
||||
while (*args) {
|
||||
*pos = *args++;
|
||||
|
||||
if (*pos++ == ';' && !isspace(*args))
|
||||
*pos++ = ' ';
|
||||
}
|
||||
|
||||
*pos = '\0';
|
||||
|
||||
return fixed;
|
||||
}
|
||||
|
||||
static char **user_event_argv_split(char *args, int *argc)
|
||||
{
|
||||
char **split;
|
||||
char *fixed;
|
||||
int count;
|
||||
|
||||
/* Count how many ';' without a trailing space */
|
||||
count = count_semis_no_space(args);
|
||||
|
||||
/* No fixup is required */
|
||||
if (!count)
|
||||
return argv_split(GFP_KERNEL, args, argc);
|
||||
|
||||
/* We must fixup 'field;field' to 'field; field' */
|
||||
fixed = insert_space_after_semis(args, count);
|
||||
|
||||
if (!fixed)
|
||||
return NULL;
|
||||
|
||||
/* We do a normal split afterwards */
|
||||
split = argv_split(GFP_KERNEL, fixed, argc);
|
||||
|
||||
/* We can free since argv_split makes a copy */
|
||||
kfree(fixed);
|
||||
|
||||
return split;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses the event name, arguments and flags then registers if successful.
|
||||
* The name buffer lifetime is owned by this method for success cases only.
|
||||
@ -2012,7 +2086,7 @@ static int user_event_parse(struct user_event_group *group, char *name,
|
||||
return -EPERM;
|
||||
|
||||
if (args) {
|
||||
argv = argv_split(GFP_KERNEL, args, &argc);
|
||||
argv = user_event_argv_split(args, &argc);
|
||||
|
||||
if (!argv)
|
||||
return -ENOMEM;
|
||||
|
@ -261,6 +261,12 @@ TEST_F(user, register_events) {
|
||||
ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®));
|
||||
ASSERT_EQ(0, reg.write_index);
|
||||
|
||||
/* Register without separator spacing should still match */
|
||||
reg.enable_bit = 29;
|
||||
reg.name_args = (__u64)"__test_event u32 field1;u32 field2";
|
||||
ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®));
|
||||
ASSERT_EQ(0, reg.write_index);
|
||||
|
||||
/* Multiple registers to same name but different args should fail */
|
||||
reg.enable_bit = 29;
|
||||
reg.name_args = (__u64)"__test_event u32 field1;";
|
||||
@ -288,6 +294,8 @@ TEST_F(user, register_events) {
|
||||
ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSUNREG, &unreg));
|
||||
unreg.disable_bit = 30;
|
||||
ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSUNREG, &unreg));
|
||||
unreg.disable_bit = 29;
|
||||
ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSUNREG, &unreg));
|
||||
|
||||
/* Delete should have been auto-done after close and unregister */
|
||||
close(self->data_fd);
|
||||
|
Loading…
Reference in New Issue
Block a user