aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-10-28 12:05:14 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-10-28 12:05:14 -0700
commit23859ae44402f4d935b9ee548135dd1e65e2cbf4 (patch)
treebecf43cacf56fc0ab1b10a785abe59e8485806b1
parentMerge tag 'x86-urgent-2020-10-27' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip (diff)
parenttracing, synthetic events: Replace buggy strcat() with seq_buf operations (diff)
downloadwireguard-linux-23859ae44402f4d935b9ee548135dd1e65e2cbf4.tar.xz
wireguard-linux-23859ae44402f4d935b9ee548135dd1e65e2cbf4.zip
Merge tag 'trace-v5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing fix from Steven Rostedt: "Fix synthetic event "strcat" overrun New synthetic event code used strcat() and miscalculated the ending, causing the concatenation to write beyond the allocated memory. Instead of using strncat(), the code is switched over to seq_buf which has all the mechanisms in place to protect against writing more than what is allocated, and cleans up the code a bit" * tag 'trace-v5.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: tracing, synthetic events: Replace buggy strcat() with seq_buf operations
-rw-r--r--kernel/trace/trace_events_synth.c36
1 files changed, 22 insertions, 14 deletions
diff --git a/kernel/trace/trace_events_synth.c b/kernel/trace/trace_events_synth.c
index 3212e2c653b3..84b7cab55291 100644
--- a/kernel/trace/trace_events_synth.c
+++ b/kernel/trace/trace_events_synth.c
@@ -585,6 +585,7 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
struct synth_field *field;
const char *prefix = NULL, *field_type = argv[0], *field_name, *array;
int len, ret = 0;
+ struct seq_buf s;
ssize_t size;
if (field_type[0] == ';')
@@ -630,13 +631,9 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
field_type++;
len = strlen(field_type) + 1;
- if (array) {
- int l = strlen(array);
+ if (array)
+ len += strlen(array);
- if (l && array[l - 1] == ';')
- l--;
- len += l;
- }
if (prefix)
len += strlen(prefix);
@@ -645,14 +642,18 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
ret = -ENOMEM;
goto free;
}
+ seq_buf_init(&s, field->type, len);
if (prefix)
- strcat(field->type, prefix);
- strcat(field->type, field_type);
+ seq_buf_puts(&s, prefix);
+ seq_buf_puts(&s, field_type);
if (array) {
- strcat(field->type, array);
- if (field->type[len - 1] == ';')
- field->type[len - 1] = '\0';
+ seq_buf_puts(&s, array);
+ if (s.buffer[s.len - 1] == ';')
+ s.len--;
}
+ if (WARN_ON_ONCE(!seq_buf_buffer_left(&s)))
+ goto free;
+ s.buffer[s.len] = '\0';
size = synth_field_size(field->type);
if (size < 0) {
@@ -663,14 +664,21 @@ static struct synth_field *parse_synth_field(int argc, const char **argv,
if (synth_field_is_string(field->type)) {
char *type;
- type = kzalloc(sizeof("__data_loc ") + strlen(field->type) + 1, GFP_KERNEL);
+ len = sizeof("__data_loc ") + strlen(field->type) + 1;
+ type = kzalloc(len, GFP_KERNEL);
if (!type) {
ret = -ENOMEM;
goto free;
}
- strcat(type, "__data_loc ");
- strcat(type, field->type);
+ seq_buf_init(&s, type, len);
+ seq_buf_puts(&s, "__data_loc ");
+ seq_buf_puts(&s, field->type);
+
+ if (WARN_ON_ONCE(!seq_buf_buffer_left(&s)))
+ goto free;
+ s.buffer[s.len] = '\0';
+
kfree(field->type);
field->type = type;