Skip to content

Commit 9e49ca7

Browse files
committed
tracing/string: Create and use __free(argv_free) in trace_dynevent.c
The function dyn_event_release() uses argv_split() which must be freed via argv_free(). It contains several error paths that do a goto out to call argv_free() for cleanup. This makes the code complex and error prone. Create a new __free() directive __free(argv_free) that will call argv_free() for data allocated with argv_split(), and use it in the dyn_event_release() function. Cc: Kees Cook <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Mathieu Desnoyers <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Andy Shevchenko <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/[email protected] Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 08b7673 commit 9e49ca7

File tree

2 files changed

+10
-16
lines changed

2 files changed

+10
-16
lines changed

include/linux/string.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <linux/args.h>
66
#include <linux/array_size.h>
7+
#include <linux/cleanup.h> /* for DEFINE_FREE() */
78
#include <linux/compiler.h> /* for inline */
89
#include <linux/types.h> /* for size_t */
910
#include <linux/stddef.h> /* for NULL */
@@ -312,6 +313,8 @@ extern void *kmemdup_array(const void *src, size_t count, size_t element_size, g
312313
extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
313314
extern void argv_free(char **argv);
314315

316+
DEFINE_FREE(argv_free, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T))
317+
315318
/* lib/cmdline.c */
316319
extern int get_option(char **str, int *pint);
317320
extern char *get_options(const char *str, int nints, int *ints);

kernel/trace/trace_dynevent.c

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,24 +74,19 @@ int dyn_event_release(const char *raw_command, struct dyn_event_operations *type
7474
struct dyn_event *pos, *n;
7575
char *system = NULL, *event, *p;
7676
int argc, ret = -ENOENT;
77-
char **argv;
77+
char **argv __free(argv_free) = argv_split(GFP_KERNEL, raw_command, &argc);
7878

79-
argv = argv_split(GFP_KERNEL, raw_command, &argc);
8079
if (!argv)
8180
return -ENOMEM;
8281

8382
if (argv[0][0] == '-') {
84-
if (argv[0][1] != ':') {
85-
ret = -EINVAL;
86-
goto out;
87-
}
83+
if (argv[0][1] != ':')
84+
return -EINVAL;
8885
event = &argv[0][2];
8986
} else {
9087
event = strchr(argv[0], ':');
91-
if (!event) {
92-
ret = -EINVAL;
93-
goto out;
94-
}
88+
if (!event)
89+
return -EINVAL;
9590
event++;
9691
}
9792

@@ -101,10 +96,8 @@ int dyn_event_release(const char *raw_command, struct dyn_event_operations *type
10196
event = p + 1;
10297
*p = '\0';
10398
}
104-
if (!system && event[0] == '\0') {
105-
ret = -EINVAL;
106-
goto out;
107-
}
99+
if (!system && event[0] == '\0')
100+
return -EINVAL;
108101

109102
mutex_lock(&event_mutex);
110103
for_each_dyn_event_safe(pos, n) {
@@ -120,8 +113,6 @@ int dyn_event_release(const char *raw_command, struct dyn_event_operations *type
120113
}
121114
tracing_reset_all_online_cpus();
122115
mutex_unlock(&event_mutex);
123-
out:
124-
argv_free(argv);
125116
return ret;
126117
}
127118

0 commit comments

Comments
 (0)