From: Sasha Levin Date: Thu, 6 Feb 2020 16:45:21 +0000 (-0500) Subject: fixes for 5.4 X-Git-Tag: v4.19.103~122^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e1dc58da6e812124e1180e1c407a1767d9b2db54;p=thirdparty%2Fkernel%2Fstable-queue.git fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/series b/queue-5.4/series index 4abeaca3a98..24fba9ed730 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -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 index 00000000000..c4e43f8a335 --- /dev/null +++ b/queue-5.4/tracing-fix-now-invalid-var_ref_vals-assumption-in-t.patch @@ -0,0 +1,175 @@ +From 54feac28ad34896c168218c34c7de434678dea05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Jan 2020 21:18:18 -0500 +Subject: tracing: Fix now invalid var_ref_vals assumption in trace action + +From: Tom Zanussi + +[ 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 +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Sasha Levin +--- + 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 +