Rust for Linux List
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/6] kcov: per-task dataflow extraction at kernel function boundaries
@ 2026-06-03 17:43 Yunseong Kim
  2026-06-03 17:43 ` [RFC PATCH v2 1/6] kcov: add per-task dataflow tracking for function arguments/return values Yunseong Kim
                   ` (8 more replies)
  0 siblings, 9 replies; 20+ messages in thread
From: Yunseong Kim @ 2026-06-03 17:43 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra, Juri Lelli, Vincent Guittot,
	Dietmar Eggemann, Steven Rostedt, Ben Segall, Mel Gorman,
	Valentin Schneider, K Prateek Nayak, Dmitry Vyukov,
	Andrey Konovalov, Andrew Morton, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt, Nicolas Schier,
	Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Danilo Krummrich, Jonathan Corbet, Shuah Khan
  Cc: Yunseong Kim, linux-kernel, kasan-dev, llvm, linux-kbuild,
	rust-for-linux, workflows, linux-doc, Yunseong Kim

Introduces a new KCOV exetened feature that captures function arguments and
return values at kernel function boundaries, enabling per-process visibility
into runtime dataflow.

Motivation
==========

Even for highly experienced developers, it is not straightforward to
determine, at any given moment, which specific kernel paths a user
process is executing or how function arguments and return values evolve
during execution. This lack of visibility makes debugging and security
auditing significantly more challenging.

Limitations of existing tools in per-task dataflow extraction:

  - ftrace/kprobes provide dynamic tracing at specific probe points
  - eBPF enables programmable in-kernel analysis but requires manual
    specification of struct layouts rather than automatic extraction
    from compiler debug metadata
  - perf provides statistical sampling of hardware/software events,
    inherently lossy and designed for performance profiling rather
    than deterministic data-flow capture

This is NOT a performance tool. The purpose is auditing and contract
verification — confirming that kernel functions receive and return
expected values at runtime.

Real-World Result: Android Binder Vulnerabilities
=================================================

Using kcov-dataflow with CONFIG_KCOV_DATAFLOW_INSTRUMENT_ALL, I
audited the Android binder driver (both C and Rust implementations)
and discovered two exploitable logic bugs:

Bug 1: BINDER_SET_MAX_THREADS accepts 0xFFFFFFFF without validation.
  kcov-dataflow showed: set_max_threads(max=0xffffffff) → return 0
  Impact: bypasses RLIMIT_NPROC, OOM from unprivileged userspace.

Bug 2: BC_ENTER_LOOPER accepted twice without error.
  kcov-dataflow showed: looper_enter() called with ENTERED already set,
  no rejection, return=0 on both calls.
  Impact: thread pool state corruption.

These bugs are invisible to:
  - KASAN: no memory corruption occurs
  - Edge coverage: same code paths for valid/invalid values
  - ftrace: shows "function called" but not argument values

Only by capturing the actual runtime values at function boundaries
could I detect that 0xFFFFFFFF passes through without rejection, or
that the same state-mutating command succeeds twice.

The fixes are submitted separately:
  [PATCH 1/4] binder: cap BINDER_SET_MAX_THREADS at RLIMIT_NPROC
  [PATCH 2/4] binder: reject duplicate BC_ENTER_LOOPER commands
  [PATCH 3/4] rust_binder: cap set_max_threads at RLIMIT_NPROC
  [PATCH 4/4] rust_binder: reject duplicate BC_ENTER_LOOPER in looper_enter

Approach
========

Rather than tracing individual probe points, this patch set enables
continuous per-task extraction of data flow across all instrumented
function boundaries — capturing how argument values enter and return
values exit each function as execution progresses through a subsystem.

The key insight is that function boundaries are natural observation
points: arguments at entry reveal what data enters a subsystem, and
return values reveal what comes out.

The compiler (clang with a SanitizerCoverage extension) inserts
callbacks at function entry/exit that record argument values into a
per-task mmap'd buffer. The kernel backend reads struct fields safely
via copy_from_kernel_nofault(). When not enabled for a task, the
overhead is a single boolean check per instrumented function.

Design
======

- Completely independent from legacy /sys/kernel/debug/kcov
- Separate device: /sys/kernel/debug/kcov_dataflow
- Separate ioctl namespace ('d'), separate per-task buffer
- Per-module opt-in: KCOV_DATAFLOW_file.o := y
- Optional global enablement: CONFIG_KCOV_DATAFLOW_INSTRUMENT_ALL
- Supports both C and Rust kernel modules
- Safe in process context; rejects interrupt/NMI via in_task() guard
- Recursion guard via sequence counter bit 31
- Requires clang with -fsanitize-coverage=dataflow-args,dataflow-ret
  (Kconfig uses cc-option to verify compiler support)

Performance Note
================

This feature is designed for auditing and security analysis, NOT for
production use or performance measurement. It should not be compared
to runtime tracing tools optimized for low overhead.

Per-module instrumentation (recording active):
  ~27ns per callback (dominated by LOCK XADD + copy_from_kernel_nofault)

Global instrumentation (INSTRUMENT_ALL, recording disabled):
  .text: +9.5%, .data: +44%, boot: +71%, syscall latency: +133%

CONFIG_KCOV_DATAFLOW_INSTRUMENT_ALL instruments every function in the
kernel. This incurs significant overhead comparable to KMSAN and is
intended exclusively for:
  - Fuzzer-driven whole-kernel auditing (syzkaller integration)
  - Full-subsystem contract verification (as demonstrated with binder)
  - Capturing complete call-flow data for post-mortem analysis

For targeted auditing, use per-module opt-in (KCOV_DATAFLOW_file.o := y)
which limits overhead to the specific subsystem under investigation.

Patches
=======

1/6: Core kernel implementation (kernel/kcov.c, sched.h, Kconfig)
2/6: Build system support (Makefile.kcov, Makefile.lib)
3/6: CONFIG_KCOV_DATAFLOW_INSTRUMENT_ALL and NO_INLINE
4/6: Userspace tools and test modules
5/6: Harden kcov_df_write() against interrupt reentry
6/6: Recursion guard and documentation

Prerequisites / Toolchain
=========================

This kernel patch relies on a custom LLVM SanitizerCoverage pass that
emits __sanitizer_cov_trace_args() and __sanitizer_cov_trace_ret()
callbacks at function boundaries, extracting struct field layouts from
DWARF debug metadata at compile time.

To build and test this patchset, compile the kernel using the modified
toolchain:

1. LLVM/Clang (adds -fsanitize-coverage=dataflow-args,dataflow-ret):
   https://github.com/llvm/llvm-project/pull/201410

2. Rust (rustc 1.98 built against the above LLVM 23, for Rust module support):
   https://github.com/yskzalloc/rust

Build instructions:

  # Build the modified clang
  cd llvm-project && cmake -G Ninja -S llvm -B build \
    -DLLVM_ENABLE_PROJECTS="clang;lld" -DCMAKE_BUILD_TYPE=Release
  ninja -C build clang

  # Build the kernel with dataflow support
  export PATH=$HOME/llvm-project/build/bin:$PATH
  export RUSTC=$HOME/rust/build/x86_64-unknown-linux-gnu/stage1/bin/rustc
  export RUST_LIB_SRC=$HOME/rust/library

  make LLVM=1 defconfig
  scripts/config --enable KCOV \
                 --enable KCOV_DATAFLOW_ARGS \
                 --enable KCOV_DATAFLOW_RET
  make LLVM=1 olddefconfig
  make LLVM=1 -j$(nproc)

Note: CONFIG_KCOV_DATAFLOW_ARGS and CONFIG_KCOV_DATAFLOW_RET depend on
CONFIG_KCOV and use $(cc-option) to verify the compiler supports the
new flags. With standard (unpatched) clang, these options will not
appear in menuconfig and silently remain disabled.

Optional configs:
  --enable KCOV_DATAFLOW_INSTRUMENT_ALL  (instrument entire kernel)
  --enable KCOV_DATAFLOW_NO_INLINE       (enabled by default)
  --set-val FRAME_WARN 4096             (needed for INSTRUMENT_ALL)
  --disable KASAN                        (conflicts with INSTRUMENT_ALL)

Testing
=======

Tested on linux-next 7.1.0-rc5 with custom clang/LLVM 23 and
rustc 1.98-nightly (built against the same LLVM). Verified under
virtme-ng (QEMU/KVM, 1GB RAM):
- Per-module C (eight_args_mod): all 8 functions captured
- Per-module C (deep_chain_mod): 10-deep call chain captured
- Per-module Rust (eight_args_rust): all 8 rfunc functions captured
- Interrupt safety: in_task() + recursion guard prevents corruption
- Binder auditing: discovered 2 exploitable bugs (patches separate)
- Standard clang (without patch): Kconfig options correctly hidden
- Global enablement (INSTRUMENT_ALL): kernel boots, 104K records
  captured during single copy.fail exploit reproduction
  
    https://github.com/yskzalloc/kcov-dataflow/blob/main/copy.fail/origin/converted.txt

Signed-off-by: Yunseong Kim <yunseong.kim@est.tech>
---
Changes in v2:
- EDITME: describe what is new in this series revision.
- EDITME: use bulletpoints and terse descriptions.
- Link to v1: https://patch.msgid.link/20260603-kcov-dataflow-next-20260603-v1-0-e64300bf17cf@est.tech

To: Ingo Molnar <mingo@redhat.com>
To: Peter Zijlstra <peterz@infradead.org>
To: Juri Lelli <juri.lelli@redhat.com>
To: Vincent Guittot <vincent.guittot@linaro.org>
To: Dietmar Eggemann <dietmar.eggemann@arm.com>
To: Steven Rostedt <rostedt@goodmis.org>
To: Ben Segall <bsegall@google.com>
To: Mel Gorman <mgorman@suse.de>
To: Valentin Schneider <vschneid@redhat.com>
To: K Prateek Nayak <kprateek.nayak@amd.com>
To: Dmitry Vyukov <dvyukov@google.com>
To: Andrey Konovalov <andreyknvl@gmail.com>
To: Andrew Morton <akpm@linux-foundation.org>
To: Nathan Chancellor <nathan@kernel.org>
To: Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
To: Bill Wendling <morbo@google.com>
To: Justin Stitt <justinstitt@google.com>
To: Nicolas Schier <nsc@kernel.org>
To: Miguel Ojeda <ojeda@kernel.org>
To: Boqun Feng <boqun@kernel.org>
To: Gary Guo <gary@garyguo.net>
To: Björn Roy Baron <bjorn3_gh@protonmail.com>
To: Benno Lossin <lossin@kernel.org>
To: Andreas Hindborg <a.hindborg@kernel.org>
To: Alice Ryhl <aliceryhl@google.com>
To: Trevor Gross <tmgross@umich.edu>
To: Danilo Krummrich <dakr@kernel.org>
To: Jonathan Corbet <corbet@lwn.net>
To: Shuah Khan <skhan@linuxfoundation.org>
Cc: linux-kernel@vger.kernel.org
Cc: kasan-dev@googlegroups.com
Cc: llvm@lists.linux.dev
Cc: linux-kbuild@vger.kernel.org
Cc: rust-for-linux@vger.kernel.org
Cc: workflows@vger.kernel.org
Cc: linux-doc@vger.kernel.org

---
Yunseong Kim (6):
      kcov: add per-task dataflow tracking for function arguments/return values
      kcov: add build system support for dataflow instrumentation
      kcov: add CONFIG_KCOV_DATAFLOW_INSTRUMENT_ALL and NO_INLINE
      tools/kcov-dataflow: add userspace consumer and test modules
      kcov: add interrupt context guard to kcov_df_write()
      kcov: add recursion guard and documentation for kcov-dataflow

 Documentation/dev-tools/kcov-dataflow.rst          | 282 +++++++++++++++++++
 include/linux/sched.h                              |   8 +
 kernel/Makefile                                    |   3 +
 kernel/kcov.c                                      | 307 +++++++++++++++++++++
 lib/Kconfig.debug                                  |  43 +++
 rust/Makefile                                      |   1 +
 scripts/Makefile.kcov                              |   6 +
 scripts/Makefile.lib                               |   7 +
 tools/kcov-dataflow/.gitignore                     |  12 +
 tools/kcov-dataflow/deep_module/Makefile           |   2 +
 tools/kcov-dataflow/deep_module/deep_chain_mod.c   | 224 +++++++++++++++
 tools/kcov-dataflow/eight_args_c/Makefile          |   3 +
 tools/kcov-dataflow/eight_args_c/eight_args_mod.c  |  95 +++++++
 tools/kcov-dataflow/eight_args_rust/Makefile       |   2 +
 .../eight_args_rust/eight_args_rust.rs             | 114 ++++++++
 tools/kcov-dataflow/kcov-view.py                   | 272 ++++++++++++++++++
 tools/kcov-dataflow/trigger.c                      | 125 +++++++++
 17 files changed, 1506 insertions(+)
---
base-commit: f7af91adc230aa99e23330ecf85bc9badd9780ad
change-id: 20260603-kcov-dataflow-next-20260603-8bf628f98086

Best regards,
--  
Yunseong Kim <yunseong.kim@est.tech>


^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2026-06-05 17:23 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-03 17:43 [RFC PATCH v2 0/6] kcov: per-task dataflow extraction at kernel function boundaries Yunseong Kim
2026-06-03 17:43 ` [RFC PATCH v2 1/6] kcov: add per-task dataflow tracking for function arguments/return values Yunseong Kim
2026-06-03 19:25   ` Nicolas Schier
2026-06-04  8:41   ` Peter Zijlstra
2026-06-05 16:05   ` Alexander Potapenko
2026-06-03 17:43 ` [RFC PATCH v2 2/6] kcov: add build system support for dataflow instrumentation Yunseong Kim
2026-06-04  8:45   ` Peter Zijlstra
2026-06-04 21:48     ` Nathan Chancellor
2026-06-05 15:29   ` Alexander Potapenko
2026-06-03 17:43 ` [RFC PATCH v2 3/6] kcov: add CONFIG_KCOV_DATAFLOW_INSTRUMENT_ALL and NO_INLINE Yunseong Kim
2026-06-04  8:46   ` Peter Zijlstra
2026-06-03 17:43 ` [RFC PATCH v2 4/6] tools/kcov-dataflow: add userspace consumer and test modules Yunseong Kim
2026-06-05 15:19   ` Alexander Potapenko
2026-06-03 17:43 ` [RFC PATCH v2 5/6] kcov: add interrupt context guard to kcov_df_write() Yunseong Kim
2026-06-04  8:48   ` Peter Zijlstra
2026-06-03 17:43 ` [RFC PATCH v2 6/6] kcov: add recursion guard and documentation for kcov-dataflow Yunseong Kim
2026-06-04  8:52   ` Peter Zijlstra
2026-06-04  8:40 ` [RFC PATCH v2 0/6] kcov: per-task dataflow extraction at kernel function boundaries Peter Zijlstra
2026-06-04  9:29 ` Yunseong Kim
2026-06-05 16:20 ` Alexander Potapenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox