Skip to content

Commit fc1a9dc

Browse files
Tom Zanussirostedt
authored andcommitted
tracing/histogram: Don't use strlen to find length of stacktrace variables
Because stacktraces are saved in dynamic strings, trace_event_raw_event_synth() uses strlen to determine the length of the stack. Stacktraces may contain 0-bytes, though, in the saved addresses, so the length found and passed to reserve() will be too small. Fix this by using the first unsigned long in the stack variables to store the actual number of elements in the stack and have trace_event_raw_event_synth() use that to determine the length of the stack. Link: https://lkml.kernel.org/r/1ed6906cd9d6477ef2bd8e63c61de20a9ffe64d7.1676063532.git.zanussi@kernel.org Signed-off-by: Tom Zanussi <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent 9c1c251 commit fc1a9dc

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

kernel/trace/trace_events_hist.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3137,13 +3137,15 @@ static inline void __update_field_vars(struct tracing_map_elt *elt,
31373137
size = min(val->size, STR_VAR_LEN_MAX);
31383138
strscpy(str, val_str, size);
31393139
} else {
3140+
char *stack_start = str + sizeof(unsigned long);
31403141
int e;
31413142

3142-
e = stack_trace_save((void *)str,
3143+
e = stack_trace_save((void *)stack_start,
31433144
HIST_STACKTRACE_DEPTH,
31443145
HIST_STACKTRACE_SKIP);
31453146
if (e < HIST_STACKTRACE_DEPTH - 1)
3146-
((unsigned long *)str)[e] = 0;
3147+
((unsigned long *)stack_start)[e] = 0;
3148+
*((unsigned long *)str) = e;
31473149
}
31483150
var_val = (u64)(uintptr_t)str;
31493151
}
@@ -5135,13 +5137,15 @@ static void hist_trigger_elt_update(struct hist_trigger_data *hist_data,
51355137
size = min(hist_field->size, STR_VAR_LEN_MAX);
51365138
strscpy(str, val_str, size);
51375139
} else {
5140+
char *stack_start = str + sizeof(unsigned long);
51385141
int e;
51395142

5140-
e = stack_trace_save((void *)str,
5143+
e = stack_trace_save((void *)stack_start,
51415144
HIST_STACKTRACE_DEPTH,
51425145
HIST_STACKTRACE_SKIP);
51435146
if (e < HIST_STACKTRACE_DEPTH - 1)
5144-
((unsigned long *)str)[e] = 0;
5147+
((unsigned long *)stack_start)[e] = 0;
5148+
*((unsigned long *)str) = e;
51455149
}
51465150
hist_val = (u64)(uintptr_t)str;
51475151
}

kernel/trace/trace_events_synth.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,12 @@ static notrace void trace_event_raw_event_synth(void *__data,
538538
val_idx = var_ref_idx[field_pos];
539539
str_val = (char *)(long)var_ref_vals[val_idx];
540540

541-
len = kern_fetch_store_strlen((unsigned long)str_val);
541+
if (event->dynamic_fields[i]->is_stack) {
542+
len = *((unsigned long *)str_val);
543+
len *= sizeof(unsigned long);
544+
} else {
545+
len = kern_fetch_store_strlen((unsigned long)str_val);
546+
}
542547

543548
fields_size += len;
544549
}

0 commit comments

Comments
 (0)