linux/kernel/trace
Florent Revest 48cac3f4a9 bpf: Implement formatted output helpers with bstr_printf
BPF has three formatted output helpers: bpf_trace_printk, bpf_seq_printf
and bpf_snprintf. Their signatures specify that all arguments are
provided from the BPF world as u64s (in an array or as registers). All
of these helpers are currently implemented by calling functions such as
snprintf() whose signatures take a variable number of arguments, then
placed in a va_list by the compiler to call vsnprintf().

"d9c9e4db bpf: Factorize bpf_trace_printk and bpf_seq_printf" introduced
a bpf_printf_prepare function that fills an array of u64 sanitized
arguments with an array of "modifiers" which indicate what the "real"
size of each argument should be (given by the format specifier). The
BPF_CAST_FMT_ARG macro consumes these arrays and casts each argument to
its real size. However, the C promotion rules implicitely cast them all
back to u64s. Therefore, the arguments given to snprintf are u64s and
the va_list constructed by the compiler will use 64 bits for each
argument. On 64 bit machines, this happens to work well because 32 bit
arguments in va_lists need to occupy 64 bits anyway, but on 32 bit
architectures this breaks the layout of the va_list expected by the
called function and mangles values.

In "88a5c690b6 bpf: fix bpf_trace_printk on 32 bit archs", this problem
had been solved for bpf_trace_printk only with a "horrid workaround"
that emitted multiple calls to trace_printk where each call had
different argument types and generated different va_list layouts. One of
the call would be dynamically chosen at runtime. This was ok with the 3
arguments that bpf_trace_printk takes but bpf_seq_printf and
bpf_snprintf accept up to 12 arguments. Because this approach scales
code exponentially, it is not a viable option anymore.

Because the promotion rules are part of the language and because the
construction of a va_list is an arch-specific ABI, it's best to just
avoid variadic arguments and va_lists altogether. Thankfully the
kernel's snprintf() has an alternative in the form of bstr_printf() that
accepts arguments in a "binary buffer representation". These binary
buffers are currently created by vbin_printf and used in the tracing
subsystem to split the cost of printing into two parts: a fast one that
only dereferences and remembers values, and a slower one, called later,
that does the pretty-printing.

This patch refactors bpf_printf_prepare to construct binary buffers of
arguments consumable by bstr_printf() instead of arrays of arguments and
modifiers. This gets rid of BPF_CAST_FMT_ARG and greatly simplifies the
bpf_printf_prepare usage but there are a few gotchas that change how
bpf_printf_prepare needs to do things.

Currently, bpf_printf_prepare uses a per cpu temporary buffer as a
generic storage for strings and IP addresses. With this refactoring, the
temporary buffers now holds all the arguments in a structured binary
format.

To comply with the format expected by bstr_printf, certain format
specifiers also need to be pre-formatted: %pB and %pi6/%pi4/%pI4/%pI6.
Because vsnprintf subroutines for these specifiers are hard to expose,
we pre-format these arguments with calls to snprintf().

Reported-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Signed-off-by: Florent Revest <revest@chromium.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20210427174313.860948-3-revest@chromium.org
2021-04-27 15:56:31 -07:00
..
blktrace.c block-5.12-2021-02-27 2021-02-28 11:23:38 -08:00
bpf_trace.c bpf: Implement formatted output helpers with bstr_printf 2021-04-27 15:56:31 -07:00
bpf_trace.h bpf: Use dedicated bpf_trace_printk event instead of trace_printk() 2020-07-13 16:55:49 -07:00
error_report-traces.c tracing: add error_report_end trace point 2021-02-26 09:41:02 -08:00
fgraph.c fgraph: Initialize tracing_graph_pause at task creation 2021-01-29 15:07:32 -05:00
ftrace_internal.h
ftrace.c Add check of order < 0 before calling free_pages() 2021-03-31 10:14:55 -07:00
Kconfig tracing: Fix help text of TRACEPOINT_BENCHMARK in Kconfig 2021-03-04 09:45:17 -05:00
kprobe_event_gen_test.c
Makefile tracing: add error_report_end trace point 2021-02-26 09:41:02 -08:00
power-traces.c
preemptirq_delay_test.c kernel: trace: preemptirq_delay_test: add cpu affinity 2021-02-02 17:02:07 -05:00
ring_buffer_benchmark.c sched,tracing: Convert to sched_set_fifo() 2020-07-29 11:43:53 +02:00
ring_buffer.c ring-buffer: Add a little more information and a WARN when time stamp going backwards is detected 2021-03-04 09:45:17 -05:00
rpm-traces.c
synth_event_gen_test.c tracing: Remove the useless value assignment in test_create_synth_event() 2020-11-13 12:19:52 -05:00
trace_benchmark.c tracing: Fix some typos in comments 2020-11-10 20:39:40 -05:00
trace_benchmark.h
trace_boot.c tracing: Disable ftrace selftests when any tracer is running 2020-12-14 12:05:03 -05:00
trace_branch.c tracing: Merge irqflags + preempt counter. 2021-02-02 17:02:06 -05:00
trace_clock.c
trace_dynevent.c tracing/dynevent: Fix a memory leak in an error handling path 2021-04-13 12:29:48 -04:00
trace_dynevent.h tracing/dynevent: Delegate parsing to create function 2021-02-09 12:52:15 -05:00
trace_entries.h tracing: Fix some typos in comments 2020-11-10 20:39:40 -05:00
trace_event_perf.c tracing: Merge irqflags + preempt counter. 2021-02-02 17:02:06 -05:00
trace_events_filter_test.h
trace_events_filter.c tracing: Clean up after filter logic rewriting 2020-11-16 12:32:34 -05:00
trace_events_hist.c tracing: Fix some typos in comments 2020-11-10 20:39:40 -05:00
trace_events_inject.c tracing: Merge irqflags + preempt counter. 2021-02-02 17:02:06 -05:00
trace_events_synth.c tracing: Fix memory leak in __create_synth_event() 2021-03-04 09:45:57 -05:00
trace_events_trigger.c tracing: Fix event trigger to accept redundant spaces 2020-06-23 21:51:40 -04:00
trace_events.c Tracing updates for 5.12 2021-02-22 14:07:15 -08:00
trace_export.c tracing: Fix some typos in comments 2020-11-10 20:39:40 -05:00
trace_functions_graph.c tracing: Merge irqflags + preempt counter. 2021-02-02 17:02:06 -05:00
trace_functions.c tracing: Merge irqflags + preempt counter. 2021-02-02 17:02:06 -05:00
trace_hwlat.c tracing: Merge irqflags + preempt counter. 2021-02-02 17:02:06 -05:00
trace_irqsoff.c tracing: Merge irqflags + preempt counter. 2021-02-02 17:02:06 -05:00
trace_kdb.c
trace_kprobe_selftest.c
trace_kprobe_selftest.h
trace_kprobe.c Modules updates for v5.12 2021-02-23 10:15:33 -08:00
trace_mmiotrace.c tracing: Remove definition of DEBUG in trace_mmiotrace.c 2021-02-02 17:02:07 -05:00
trace_nop.c
trace_output.c tracing: Show real address for trace event arguments 2021-02-11 16:31:57 -05:00
trace_output.h ftrace: Add recording of functions that caused recursion 2020-11-06 08:42:26 -05:00
trace_preemptirq.c lockdep: fix order in trace_hardirqs_off_caller() 2020-09-14 10:08:07 +02:00
trace_printk.c Updates for tracing and bootconfig: 2020-10-15 15:51:28 -07:00
trace_probe_tmpl.h
trace_probe.c tracing/dynevent: Delegate parsing to create function 2021-02-09 12:52:15 -05:00
trace_probe.h tracing/dynevent: Delegate parsing to create function 2021-02-09 12:52:15 -05:00
trace_recursion_record.c ftrace: Add recording of functions that caused recursion 2020-11-06 08:42:26 -05:00
trace_sched_switch.c
trace_sched_wakeup.c tracing: Merge irqflags + preempt counter. 2021-02-02 17:02:06 -05:00
trace_selftest_dynamic.c
trace_selftest.c tracing: Disable ftrace selftests when any tracer is running 2020-12-14 12:05:03 -05:00
trace_seq.c
trace_stack.c ftrace: Have the callbacks receive a struct ftrace_regs instead of pt_regs 2020-11-13 12:14:55 -05:00
trace_stat.c tracing: make tracing_init_dentry() returns an integer instead of a d_entry pointer 2020-09-18 22:17:14 -04:00
trace_stat.h
trace_synth.h tracing: Add support for dynamic strings to synthetic events 2020-10-05 19:32:18 -04:00
trace_syscalls.c tracing: Merge irqflags + preempt counter. 2021-02-02 17:02:06 -05:00
trace_uprobe.c tracing/dynevent: Delegate parsing to create function 2021-02-09 12:52:15 -05:00
trace.c tracing: Fix stack trace event size 2021-04-01 14:06:33 -04:00
trace.h tracing: Remove duplicate declaration from trace.h 2021-03-04 09:44:47 -05:00
tracing_map.c tracing: Fix some typos in comments 2020-11-10 20:39:40 -05:00
tracing_map.h tracing: Fix some typos in comments 2020-11-10 20:39:40 -05:00