]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Thu, 6 Feb 2020 16:45:21 +0000 (11:45 -0500)
committerSasha Levin <sashal@kernel.org>
Thu, 6 Feb 2020 16:45:21 +0000 (11:45 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-5.4/series
queue-5.4/tracing-fix-now-invalid-var_ref_vals-assumption-in-t.patch [new file with mode: 0644]

index 4abeaca3a984bfa5bb68956902d87d62449143ef..24fba9ed730ea97429d9c447e4562bc0b1e441d0 100644 (file)
@@ -59,3 +59,4 @@ lib-test_kasan.c-fix-memory-leak-in-kmalloc_oob_krealloc_more.patch
 irqdomain-fix-a-memory-leak-in-irq_domain_push_irq.patch
 x86-cpu-update-cached-hle-state-on-write-to-tsx_ctrl_cpuid_clear.patch
 platform-x86-intel_scu_ipc-fix-interrupt-support.patch
+tracing-fix-now-invalid-var_ref_vals-assumption-in-t.patch
diff --git a/queue-5.4/tracing-fix-now-invalid-var_ref_vals-assumption-in-t.patch b/queue-5.4/tracing-fix-now-invalid-var_ref_vals-assumption-in-t.patch
new file mode 100644 (file)
index 0000000..c4e43f8
--- /dev/null
@@ -0,0 +1,175 @@
+From 54feac28ad34896c168218c34c7de434678dea05 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jan 2020 21:18:18 -0500
+Subject: tracing: Fix now invalid var_ref_vals assumption in trace action
+
+From: Tom Zanussi <zanussi@kernel.org>
+
+[ Upstream commit d380dcde9a07ca5de4805dee11f58a98ec0ad6ff ]
+
+The patch 'tracing: Fix histogram code when expression has same var as
+value' added code to return an existing variable reference when
+creating a new variable reference, which resulted in var_ref_vals
+slots being reused instead of being duplicated.
+
+The implementation of the trace action assumes that the end of the
+var_ref_vals array starting at action_data.var_ref_idx corresponds to
+the values that will be assigned to the trace params. The patch
+mentioned above invalidates that assumption, which means that each
+param needs to explicitly specify its index into var_ref_vals.
+
+This fix changes action_data.var_ref_idx to an array of var ref
+indexes to account for that.
+
+Link: https://lore.kernel.org/r/1580335695.6220.8.camel@kernel.org
+
+Fixes: 8bcebc77e85f ("tracing: Fix histogram code when expression has same var as value")
+Signed-off-by: Tom Zanussi <zanussi@kernel.org>
+Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/trace_events_hist.c | 53 +++++++++++++++++++++++---------
+ 1 file changed, 38 insertions(+), 15 deletions(-)
+
+diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
+index 205692181e7bc..4be7fc84d6b6a 100644
+--- a/kernel/trace/trace_events_hist.c
++++ b/kernel/trace/trace_events_hist.c
+@@ -470,11 +470,12 @@ struct action_data {
+        * When a histogram trigger is hit, the values of any
+        * references to variables, including variables being passed
+        * as parameters to synthetic events, are collected into a
+-       * var_ref_vals array.  This var_ref_idx is the index of the
+-       * first param in the array to be passed to the synthetic
+-       * event invocation.
++       * var_ref_vals array.  This var_ref_idx array is an array of
++       * indices into the var_ref_vals array, one for each synthetic
++       * event param, and is passed to the synthetic event
++       * invocation.
+        */
+-      unsigned int            var_ref_idx;
++      unsigned int            var_ref_idx[TRACING_MAP_VARS_MAX];
+       struct synth_event      *synth_event;
+       bool                    use_trace_keyword;
+       char                    *synth_event_name;
+@@ -875,14 +876,14 @@ static struct trace_event_functions synth_event_funcs = {
+ static notrace void trace_event_raw_event_synth(void *__data,
+                                               u64 *var_ref_vals,
+-                                              unsigned int var_ref_idx)
++                                              unsigned int *var_ref_idx)
+ {
+       struct trace_event_file *trace_file = __data;
+       struct synth_trace_event *entry;
+       struct trace_event_buffer fbuffer;
+       struct ring_buffer *buffer;
+       struct synth_event *event;
+-      unsigned int i, n_u64;
++      unsigned int i, n_u64, val_idx;
+       int fields_size = 0;
+       event = trace_file->event_call->data;
+@@ -905,15 +906,16 @@ static notrace void trace_event_raw_event_synth(void *__data,
+               goto out;
+       for (i = 0, n_u64 = 0; i < event->n_fields; i++) {
++              val_idx = var_ref_idx[i];
+               if (event->fields[i]->is_string) {
+-                      char *str_val = (char *)(long)var_ref_vals[var_ref_idx + i];
++                      char *str_val = (char *)(long)var_ref_vals[val_idx];
+                       char *str_field = (char *)&entry->fields[n_u64];
+                       strscpy(str_field, str_val, STR_VAR_LEN_MAX);
+                       n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
+               } else {
+                       struct synth_field *field = event->fields[i];
+-                      u64 val = var_ref_vals[var_ref_idx + i];
++                      u64 val = var_ref_vals[val_idx];
+                       switch (field->size) {
+                       case 1:
+@@ -1113,10 +1115,10 @@ static struct tracepoint *alloc_synth_tracepoint(char *name)
+ }
+ typedef void (*synth_probe_func_t) (void *__data, u64 *var_ref_vals,
+-                                  unsigned int var_ref_idx);
++                                  unsigned int *var_ref_idx);
+ static inline void trace_synth(struct synth_event *event, u64 *var_ref_vals,
+-                             unsigned int var_ref_idx)
++                             unsigned int *var_ref_idx)
+ {
+       struct tracepoint *tp = event->tp;
+@@ -2655,6 +2657,22 @@ static int init_var_ref(struct hist_field *ref_field,
+       goto out;
+ }
++static int find_var_ref_idx(struct hist_trigger_data *hist_data,
++                          struct hist_field *var_field)
++{
++      struct hist_field *ref_field;
++      int i;
++
++      for (i = 0; i < hist_data->n_var_refs; i++) {
++              ref_field = hist_data->var_refs[i];
++              if (ref_field->var.idx == var_field->var.idx &&
++                  ref_field->var.hist_data == var_field->hist_data)
++                      return i;
++      }
++
++      return -ENOENT;
++}
++
+ /**
+  * create_var_ref - Create a variable reference and attach it to trigger
+  * @hist_data: The trigger that will be referencing the variable
+@@ -4228,11 +4246,11 @@ static int trace_action_create(struct hist_trigger_data *hist_data,
+       struct trace_array *tr = hist_data->event_file->tr;
+       char *event_name, *param, *system = NULL;
+       struct hist_field *hist_field, *var_ref;
+-      unsigned int i, var_ref_idx;
++      unsigned int i;
+       unsigned int field_pos = 0;
+       struct synth_event *event;
+       char *synth_event_name;
+-      int ret = 0;
++      int var_ref_idx, ret = 0;
+       lockdep_assert_held(&event_mutex);
+@@ -4249,8 +4267,6 @@ static int trace_action_create(struct hist_trigger_data *hist_data,
+       event->ref++;
+-      var_ref_idx = hist_data->n_var_refs;
+-
+       for (i = 0; i < data->n_params; i++) {
+               char *p;
+@@ -4299,6 +4315,14 @@ static int trace_action_create(struct hist_trigger_data *hist_data,
+                               goto err;
+                       }
++                      var_ref_idx = find_var_ref_idx(hist_data, var_ref);
++                      if (WARN_ON(var_ref_idx < 0)) {
++                              ret = var_ref_idx;
++                              goto err;
++                      }
++
++                      data->var_ref_idx[i] = var_ref_idx;
++
+                       field_pos++;
+                       kfree(p);
+                       continue;
+@@ -4317,7 +4341,6 @@ static int trace_action_create(struct hist_trigger_data *hist_data,
+       }
+       data->synth_event = event;
+-      data->var_ref_idx = var_ref_idx;
+  out:
+       return ret;
+  err:
+-- 
+2.20.1
+