|
|
Subscribe / Log in / New account

BPF Standard Streams

From:  Kumar Kartikeya Dwivedi <memxor-AT-gmail.com>
To:  bpf-AT-vger.kernel.org
Subject:  [PATCH bpf-next v1 00/11] BPF Standard Streams
Date:  Wed, 07 May 2025 10:17:09 -0700
Message-ID:  <20250507171720.1958296-1-memxor@gmail.com>
Cc:  Alexei Starovoitov <ast-AT-kernel.org>, Andrii Nakryiko <andrii-AT-kernel.org>, Daniel Borkmann <daniel-AT-iogearbox.net>, Martin KaFai Lau <martin.lau-AT-kernel.org>, Eduard Zingerman <eddyz87-AT-gmail.com>, Emil Tsalapatis <emil-AT-etsalapatis.com>, Barret Rhoden <brho-AT-google.com>, Matt Bobrowski <mattbobrowski-AT-google.com>, kkd-AT-meta.com, kernel-team-AT-meta.com
Archive-link:  Article

This set introduces a standard output interface with two streams, namely
stdout and stderr, for BPF programs. The idea is that these streams will
be written to by BPF programs and the kernel, and serve as standard
interfaces for informing user space of any BPF runtime violations. Users
can also utilize them for printing normal messages for debugging usage,
as is the case with bpf_printk() and trace pipe interface.

BPF programs and the kernel can use these streams to output messages.
User space can dump these messages using bpftool.

The stream interface itself is implemented using a lockless list, so
that we can queue messages from any context. Every printk statement into
the stream leads to memory allocation. Allocation itself relies on
try_alloc_pages() to construct a bespoke bump allocator to carve out
elements. If this fails, we finally give up and drop the message.

See commit logs for more details.

Three scenarios are covered:
 - Deadlocks and timeouts in rqspinlock.
 - Arena page faults.
 - Timeouts for may_goto.

In each we provide the stack trace and source information for the
offending BPF programs. Both the C source line and the file and line
numbers are printed. The output format is as follows:

ERROR: AA or ABBA deadlock detected for bpf_res_spin_lock
Attempted lock   = 0xff11000108f3a5e0
Total held locks = 1
Held lock[ 0] = 0xff11000108f3a5e0
CPU: 48 UID: 0 PID: 786 Comm: test_progs
Call trace:
bpf_stream_stage_dump_stack+0xb0/0xd0
bpf_prog_report_rqspinlock_violation+0x10b/0x130
bpf_res_spin_lock+0x8c/0xa0
bpf_prog_3699ea119d1f6ed8_foo+0xe5/0x140
  if (!bpf_res_spin_lock(&v2->lock)) @ stream_bpftool.c:62
bpf_prog_9b324ec4a1b2a5c0_stream_bpftool_dump_prog_stream+0x7e/0x2d0
  foo(stream); @ stream_bpftool.c:93
bpf_prog_test_run_syscall+0x102/0x240
__sys_bpf+0xd68/0x2bf0
__x64_sys_bpf+0x1e/0x30
do_syscall_64+0x68/0x140
entry_SYSCALL_64_after_hwframe+0x76/0x7e

ERROR: Arena READ access at unmapped address 0xdeadbeef
CPU: 48 UID: 0 PID: 786 Comm: test_progs
Call trace:
bpf_stream_stage_dump_stack+0xb0/0xd0
bpf_prog_report_arena_violation+0x90/0xb0
ex_handler_bpf+0x4a/0xa0
fixup_exception+0xde/0x310
kernelmode_fixup_or_oops.constprop.0+0x2f/0x70
exc_page_fault+0xdd/0x1d0
asm_exc_page_fault+0x26/0x30
bpf_prog_3699ea119d1f6ed8_foo+0x10c/0x140
  *(u64 __arena *)0xfaceb00c = *(u64 __arena *)0xdeadbeef; @ stream_bpftool.c:68
bpf_prog_9b324ec4a1b2a5c0_stream_bpftool_dump_prog_stream+0x7e/0x2d0
  foo(stream); @ stream_bpftool.c:93
bpf_prog_test_run_syscall+0x102/0x240
__sys_bpf+0xd68/0x2bf0
__x64_sys_bpf+0x1e/0x30
do_syscall_64+0x68/0x140
entry_SYSCALL_64_after_hwframe+0x76/0x7e

ERROR: Arena WRITE access at unmapped address 0xfaceb00c
CPU: 48 UID: 0 PID: 786 Comm: test_progs
Call trace:
bpf_stream_stage_dump_stack+0xb0/0xd0
bpf_prog_report_arena_violation+0x90/0xb0
ex_handler_bpf+0x4a/0xa0
fixup_exception+0xde/0x310
kernelmode_fixup_or_oops.constprop.0+0x2f/0x70
exc_page_fault+0xdd/0x1d0
asm_exc_page_fault+0x26/0x30
bpf_prog_3699ea119d1f6ed8_foo+0x111/0x140
  *(u64 __arena *)0xfaceb00c = *(u64 __arena *)0xdeadbeef; @ stream_bpftool.c:68
bpf_prog_9b324ec4a1b2a5c0_stream_bpftool_dump_prog_stream+0x7e/0x2d0
  foo(stream); @ stream_bpftool.c:93
bpf_prog_test_run_syscall+0x102/0x240
__sys_bpf+0xd68/0x2bf0
__x64_sys_bpf+0x1e/0x30
do_syscall_64+0x68/0x140
entry_SYSCALL_64_after_hwframe+0x76/0x7e

ERROR: Timeout detected for may_goto instruction
CPU: 48 UID: 0 PID: 786 Comm: test_progs
Call trace:
bpf_stream_stage_dump_stack+0xb0/0xd0
bpf_prog_report_may_goto_violation+0x6a/0x90
bpf_check_timed_may_goto+0x4d/0xa0
arch_bpf_timed_may_goto+0x21/0x40
bpf_prog_3699ea119d1f6ed8_foo+0x12f/0x140
  while (can_loop) @ stream_bpftool.c:71
bpf_prog_9b324ec4a1b2a5c0_stream_bpftool_dump_prog_stream+0x7e/0x2d0
  foo(stream); @ stream_bpftool.c:93
bpf_prog_test_run_syscall+0x102/0x240
__sys_bpf+0xd68/0x2bf0
__x64_sys_bpf+0x1e/0x30
do_syscall_64+0x68/0x140
entry_SYSCALL_64_after_hwframe+0x76/0x7e

Changelog:
----------
RFC v1 -> v1
RFC v1: https://lore.kernel.org/bpf/20250414161443.1146103-1-memx...

 * Rebase on bpf-next/master.
 * Change output in dump_stack to also print source line. (Alexei)
 * Simplify API to single pop() operation. (Eduard, Alexei)
 * Add kdoc for bpf_dynptr_from_mem_slice.
 * Fix -EINVAL returned from prog_dump_stream. (Eduard)
 * Split dump_stack() patch into multiple commits.
 * Add macro wrapping stream staging API.
 * Change bpftool command from dump to tracelog. (Quentin)
 * Add bpftool documentation and bash completion. (Quentin)
 * Change license of bpftool to Dual BSD/GPL.
 * Simplify memory allocator (Alexei).
   * No overflow into second page.
   * Remove bpf_mem_alloc() fallback.
 * Symlink bpftool BPF program and exercise as selftest. (Eduard)
 * Verify output after dumping from ringbuf. (Eduard)
 * More failure cases to check API invariants.
 * Remove patches for dynptr lifetime fixes (split into separate set).
 * Limit maximum error messages, and add stream capacity (Eduard).

Kumar Kartikeya Dwivedi (11):
  bpf: Introduce bpf_dynptr_from_mem_slice
  bpf: Introduce BPF standard streams
  bpf: Add function to extract program source info
  bpf: Add function to find program from stack trace
  bpf: Add dump_stack() analogue to print to BPF stderr
  bpf: Report may_goto timeout to BPF stderr
  bpf: Report rqspinlock deadlocks/timeout to BPF stderr
  bpf: Report arena faults to BPF stderr
  libbpf: Add bpf_stream_printk() macro
  bpftool: Add support for dumping streams
  selftests/bpf: Add tests for prog streams

 arch/x86/net/bpf_jit_comp.c                   |  22 +-
 include/linux/bpf.h                           |  91 ++-
 kernel/bpf/Makefile                           |   2 +-
 kernel/bpf/arena.c                            |  14 +
 kernel/bpf/core.c                             |  95 ++-
 kernel/bpf/helpers.c                          |  63 +-
 kernel/bpf/rqspinlock.c                       |  22 +
 kernel/bpf/stream.c                           | 552 ++++++++++++++++++
 kernel/bpf/syscall.c                          |   2 +-
 kernel/bpf/verifier.c                         |  21 +-
 .../bpftool/Documentation/bpftool-prog.rst    |   6 +
 tools/bpf/bpftool/Makefile                    |   2 +-
 tools/bpf/bpftool/bash-completion/bpftool     |  16 +-
 tools/bpf/bpftool/prog.c                      |  88 ++-
 tools/bpf/bpftool/skeleton/stream.bpf.c       |  69 +++
 tools/lib/bpf/bpf_helpers.h                   |  44 +-
 .../testing/selftests/bpf/prog_tests/stream.c |  95 +++
 tools/testing/selftests/bpf/progs/stream.c    | 127 ++++
 .../selftests/bpf/progs/stream_bpftool.c      |   1 +
 .../testing/selftests/bpf/progs/stream_fail.c |  90 +++
 20 files changed, 1383 insertions(+), 39 deletions(-)
 create mode 100644 kernel/bpf/stream.c
 create mode 100644 tools/bpf/bpftool/skeleton/stream.bpf.c
 create mode 100644 tools/testing/selftests/bpf/prog_tests/stream.c
 create mode 100644 tools/testing/selftests/bpf/progs/stream.c
 create mode 120000 tools/testing/selftests/bpf/progs/stream_bpftool.c
 create mode 100644 tools/testing/selftests/bpf/progs/stream_fail.c


base-commit: 43745d11bfd9683abdf08ad7a5cc403d6a9ffd15
-- 
2.47.1




Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds