[PATCH v2 0/10] KFuzzTest: a new kernel fuzzing framework

Ethan Graham posted 10 patches 1 week, 5 days ago
Documentation/dev-tools/index.rst             |   1 +
Documentation/dev-tools/kfuzztest.rst         | 385 ++++++++++++++
MAINTAINERS                                   |   8 +
crypto/asymmetric_keys/Makefile               |   2 +
crypto/asymmetric_keys/tests/Makefile         |   4 +
crypto/asymmetric_keys/tests/pkcs7_kfuzz.c    |  26 +
.../asymmetric_keys/tests/rsa_helper_kfuzz.c  |  38 ++
drivers/auxdisplay/charlcd.c                  |   8 +
drivers/auxdisplay/tests/charlcd_kfuzz.c      |  20 +
fs/binfmt_script.c                            |   8 +
fs/tests/binfmt_script_kfuzz.c                |  58 ++
include/asm-generic/vmlinux.lds.h             |  22 +-
include/linux/kasan.h                         |  11 +
include/linux/kfuzztest.h                     | 497 ++++++++++++++++++
lib/Kconfig.debug                             |   1 +
lib/Makefile                                  |   2 +
lib/kfuzztest/Kconfig                         |  20 +
lib/kfuzztest/Makefile                        |   4 +
lib/kfuzztest/main.c                          | 242 +++++++++
lib/kfuzztest/parse.c                         | 204 +++++++
mm/kasan/shadow.c                             |  34 ++
samples/Kconfig                               |   7 +
samples/Makefile                              |   1 +
samples/kfuzztest/Makefile                    |   3 +
samples/kfuzztest/overflow_on_nested_buffer.c |  71 +++
samples/kfuzztest/underflow_on_buffer.c       |  59 +++
tools/Makefile                                |  18 +-
tools/testing/kfuzztest-bridge/.gitignore     |   2 +
tools/testing/kfuzztest-bridge/Build          |   6 +
tools/testing/kfuzztest-bridge/Makefile       |  49 ++
tools/testing/kfuzztest-bridge/bridge.c       | 115 ++++
tools/testing/kfuzztest-bridge/byte_buffer.c  |  85 +++
tools/testing/kfuzztest-bridge/byte_buffer.h  |  31 ++
tools/testing/kfuzztest-bridge/encoder.c      | 390 ++++++++++++++
tools/testing/kfuzztest-bridge/encoder.h      |  16 +
tools/testing/kfuzztest-bridge/input_lexer.c  | 256 +++++++++
tools/testing/kfuzztest-bridge/input_lexer.h  |  58 ++
tools/testing/kfuzztest-bridge/input_parser.c | 425 +++++++++++++++
tools/testing/kfuzztest-bridge/input_parser.h |  82 +++
tools/testing/kfuzztest-bridge/rand_stream.c  |  77 +++
tools/testing/kfuzztest-bridge/rand_stream.h  |  57 ++
41 files changed, 3399 insertions(+), 4 deletions(-)
create mode 100644 Documentation/dev-tools/kfuzztest.rst
create mode 100644 crypto/asymmetric_keys/tests/Makefile
create mode 100644 crypto/asymmetric_keys/tests/pkcs7_kfuzz.c
create mode 100644 crypto/asymmetric_keys/tests/rsa_helper_kfuzz.c
create mode 100644 drivers/auxdisplay/tests/charlcd_kfuzz.c
create mode 100644 fs/tests/binfmt_script_kfuzz.c
create mode 100644 include/linux/kfuzztest.h
create mode 100644 lib/kfuzztest/Kconfig
create mode 100644 lib/kfuzztest/Makefile
create mode 100644 lib/kfuzztest/main.c
create mode 100644 lib/kfuzztest/parse.c
create mode 100644 samples/kfuzztest/Makefile
create mode 100644 samples/kfuzztest/overflow_on_nested_buffer.c
create mode 100644 samples/kfuzztest/underflow_on_buffer.c
create mode 100644 tools/testing/kfuzztest-bridge/.gitignore
create mode 100644 tools/testing/kfuzztest-bridge/Build
create mode 100644 tools/testing/kfuzztest-bridge/Makefile
create mode 100644 tools/testing/kfuzztest-bridge/bridge.c
create mode 100644 tools/testing/kfuzztest-bridge/byte_buffer.c
create mode 100644 tools/testing/kfuzztest-bridge/byte_buffer.h
create mode 100644 tools/testing/kfuzztest-bridge/encoder.c
create mode 100644 tools/testing/kfuzztest-bridge/encoder.h
create mode 100644 tools/testing/kfuzztest-bridge/input_lexer.c
create mode 100644 tools/testing/kfuzztest-bridge/input_lexer.h
create mode 100644 tools/testing/kfuzztest-bridge/input_parser.c
create mode 100644 tools/testing/kfuzztest-bridge/input_parser.h
create mode 100644 tools/testing/kfuzztest-bridge/rand_stream.c
create mode 100644 tools/testing/kfuzztest-bridge/rand_stream.h
[PATCH v2 0/10] KFuzzTest: a new kernel fuzzing framework
Posted by Ethan Graham 1 week, 5 days ago
From: Ethan Graham <ethangraham@google.com>

This patch series introduces KFuzzTest, a lightweight framework for
creating in-kernel fuzz targets for internal kernel functions.

The primary motivation for KFuzzTest is to simplify the fuzzing of
low-level, relatively stateless functions (e.g., data parsers, format
converters) that are difficult to exercise effectively from the syscall
boundary. It is intended for in-situ fuzzing of kernel code without
requiring that it be built as a separate userspace library or that its
dependencies be stubbed out. Using a simple macro-based API, developers
can add a new fuzz target with minimal boilerplate code.

The core design consists of three main parts:
1. A `FUZZ_TEST(name, struct_type)` macro that allows developers to
   easily define a fuzz test.
2. A binary input format that allows a userspace fuzzer to serialize
   complex, pointer-rich C structures into a single buffer.
3. Metadata for test targets, constraints, and annotations, which is
   emitted into dedicated ELF sections to allow for discovery and
   inspection by userspace tools. These are found in
   ".kfuzztest_{targets, constraints, annotations}".

To demonstrate this framework's viability, support for KFuzzTest has been
prototyped in a development fork of syzkaller, enabling coverage-guided
fuzzing. To validate its end-to-end effectiveness, we performed an
experiment by manually introducing an off-by-one buffer over-read into
pkcs7_parse_message, like so:

- ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
+ ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen + 1);

A syzkaller instance fuzzing the new test_pkcs7_parse_message target
introduced in patch 7 successfully triggered the bug inside of
asn1_ber_decoder in under 30 seconds from a cold start. Similar
experiements on the other new fuzz targets (patches 8-9) also
successfully identified injected bugs, proving that KFuzzTest is
effective when paired with a coverage-guided fuzzing engine.

A note on build system integration: several new fuzz targets (patches
7-9) are included by conditionally importing a .c file when
CONFIG_KFUZZTEST=y. While this may seem unusual, it follows a pattern
used by some KUnit tests (e.g., in /fs/binfmt_elf.c). We considered
defining macros like VISIBLE_IF_KFUZZTEST, but believe the final
integration approach is best decided by subsystem maintainers. This
avoids creating a one-size-fits-all abstraction prematurely.

The patch series is structured as follows:
- Patch 1 adds and exposes kasan_poison_range for poisoning memory
  ranges with an unaligned start address and KASAN_GRANULE_SIZE aligned
  end address.
- Patch 2 introduces the core KFuzzTest API and data structures.
- Patch 3 adds the runtime implementation for the framework.
- Patch 4 adds a tool for sending structured inputs into a fuzz target.
- Patch 5 adds documentation.
- Patch 6 provides sample fuzz targets.
- Patch 7 defines fuzz targets for several functions in /crypto.
- Patch 8 defines a fuzz target for parse_xy in /drivers/auxdisplay.
- Patch 9 defines a fuzz target for load_script in /fs.
- Patch 10 adds maintainer information for KFuzzTest.

Changes since PR v1:
- Per feedback from SeongJae Park, move kfuzztest-bridge into the
  testing/tools directory, and update the Makefile accordingly.
- Per review from Alexander Potapenko, address some cleanup issues and
  nits.
- Fix build issues identified by the kernel test robot <lkp@intel.com>.

Ethan Graham (10):
  mm/kasan: implement kasan_poison_range
  kfuzztest: add user-facing API and data structures
  kfuzztest: implement core module and input processing
  tools: add kfuzztest-bridge utility
  kfuzztest: add ReST documentation
  kfuzztest: add KFuzzTest sample fuzz targets
  crypto: implement KFuzzTest targets for PKCS7 and RSA parsing
  drivers/auxdisplay: add a KFuzzTest for parse_xy()
  fs/binfmt_script: add KFuzzTest target for load_script
  MAINTAINERS: add maintainer information for KFuzzTest

 Documentation/dev-tools/index.rst             |   1 +
 Documentation/dev-tools/kfuzztest.rst         | 385 ++++++++++++++
 MAINTAINERS                                   |   8 +
 crypto/asymmetric_keys/Makefile               |   2 +
 crypto/asymmetric_keys/tests/Makefile         |   4 +
 crypto/asymmetric_keys/tests/pkcs7_kfuzz.c    |  26 +
 .../asymmetric_keys/tests/rsa_helper_kfuzz.c  |  38 ++
 drivers/auxdisplay/charlcd.c                  |   8 +
 drivers/auxdisplay/tests/charlcd_kfuzz.c      |  20 +
 fs/binfmt_script.c                            |   8 +
 fs/tests/binfmt_script_kfuzz.c                |  58 ++
 include/asm-generic/vmlinux.lds.h             |  22 +-
 include/linux/kasan.h                         |  11 +
 include/linux/kfuzztest.h                     | 497 ++++++++++++++++++
 lib/Kconfig.debug                             |   1 +
 lib/Makefile                                  |   2 +
 lib/kfuzztest/Kconfig                         |  20 +
 lib/kfuzztest/Makefile                        |   4 +
 lib/kfuzztest/main.c                          | 242 +++++++++
 lib/kfuzztest/parse.c                         | 204 +++++++
 mm/kasan/shadow.c                             |  34 ++
 samples/Kconfig                               |   7 +
 samples/Makefile                              |   1 +
 samples/kfuzztest/Makefile                    |   3 +
 samples/kfuzztest/overflow_on_nested_buffer.c |  71 +++
 samples/kfuzztest/underflow_on_buffer.c       |  59 +++
 tools/Makefile                                |  18 +-
 tools/testing/kfuzztest-bridge/.gitignore     |   2 +
 tools/testing/kfuzztest-bridge/Build          |   6 +
 tools/testing/kfuzztest-bridge/Makefile       |  49 ++
 tools/testing/kfuzztest-bridge/bridge.c       | 115 ++++
 tools/testing/kfuzztest-bridge/byte_buffer.c  |  85 +++
 tools/testing/kfuzztest-bridge/byte_buffer.h  |  31 ++
 tools/testing/kfuzztest-bridge/encoder.c      | 390 ++++++++++++++
 tools/testing/kfuzztest-bridge/encoder.h      |  16 +
 tools/testing/kfuzztest-bridge/input_lexer.c  | 256 +++++++++
 tools/testing/kfuzztest-bridge/input_lexer.h  |  58 ++
 tools/testing/kfuzztest-bridge/input_parser.c | 425 +++++++++++++++
 tools/testing/kfuzztest-bridge/input_parser.h |  82 +++
 tools/testing/kfuzztest-bridge/rand_stream.c  |  77 +++
 tools/testing/kfuzztest-bridge/rand_stream.h  |  57 ++
 41 files changed, 3399 insertions(+), 4 deletions(-)
 create mode 100644 Documentation/dev-tools/kfuzztest.rst
 create mode 100644 crypto/asymmetric_keys/tests/Makefile
 create mode 100644 crypto/asymmetric_keys/tests/pkcs7_kfuzz.c
 create mode 100644 crypto/asymmetric_keys/tests/rsa_helper_kfuzz.c
 create mode 100644 drivers/auxdisplay/tests/charlcd_kfuzz.c
 create mode 100644 fs/tests/binfmt_script_kfuzz.c
 create mode 100644 include/linux/kfuzztest.h
 create mode 100644 lib/kfuzztest/Kconfig
 create mode 100644 lib/kfuzztest/Makefile
 create mode 100644 lib/kfuzztest/main.c
 create mode 100644 lib/kfuzztest/parse.c
 create mode 100644 samples/kfuzztest/Makefile
 create mode 100644 samples/kfuzztest/overflow_on_nested_buffer.c
 create mode 100644 samples/kfuzztest/underflow_on_buffer.c
 create mode 100644 tools/testing/kfuzztest-bridge/.gitignore
 create mode 100644 tools/testing/kfuzztest-bridge/Build
 create mode 100644 tools/testing/kfuzztest-bridge/Makefile
 create mode 100644 tools/testing/kfuzztest-bridge/bridge.c
 create mode 100644 tools/testing/kfuzztest-bridge/byte_buffer.c
 create mode 100644 tools/testing/kfuzztest-bridge/byte_buffer.h
 create mode 100644 tools/testing/kfuzztest-bridge/encoder.c
 create mode 100644 tools/testing/kfuzztest-bridge/encoder.h
 create mode 100644 tools/testing/kfuzztest-bridge/input_lexer.c
 create mode 100644 tools/testing/kfuzztest-bridge/input_lexer.h
 create mode 100644 tools/testing/kfuzztest-bridge/input_parser.c
 create mode 100644 tools/testing/kfuzztest-bridge/input_parser.h
 create mode 100644 tools/testing/kfuzztest-bridge/rand_stream.c
 create mode 100644 tools/testing/kfuzztest-bridge/rand_stream.h

-- 
2.51.0.470.ga7dc726c21-goog
Re: [PATCH v2 0/10] KFuzzTest: a new kernel fuzzing framework
Posted by Johannes Berg 1 week ago
On Fri, 2025-09-19 at 14:57 +0000, Ethan Graham wrote:
> 
> This patch series introduces KFuzzTest, a lightweight framework for
> creating in-kernel fuzz targets for internal kernel functions.
> 
> The primary motivation for KFuzzTest is to simplify the fuzzing of
> low-level, relatively stateless functions (e.g., data parsers, format
> converters) that are difficult to exercise effectively from the syscall
> boundary. It is intended for in-situ fuzzing of kernel code without
> requiring that it be built as a separate userspace library or that its
> dependencies be stubbed out. Using a simple macro-based API, developers
> can add a new fuzz target with minimal boilerplate code.

So ... I guess I understand the motivation to make this easy for
developers, but I'm not sure I'm happy to have all of this effectively
depend on syzkaller.

You spelled out the process to actually declare a fuzz test, but you
never spelled out the process to actually run fuzzing against it. For
the record, and everyone else who might be reading, here's my
understanding:

 - the FUZZ_TEST() macro declares some magic in the Linux binary,
   including the name of the struct that describes the necessary input

 - there's a parser in syzkaller (and not really usable standalone) that
   can parse the vmlinux binary (and doesn't handle modules) and
   generates descriptions for the input from it

 - I _think_ that the bridge tool uses these descriptions, though the
   example you have in the documentation just says "use this command for
   this test" and makes no representation as to how the first argument
   to the bridge tool is created, it just appears out of thin air

 - the bridge tool will then parse the description and use some random
   data to create the serialised data that's deserialized in the kernel
   and then passed to the test

   - side note: did that really have to be a custom serialization
     format? I don't see any discussion on that, there are different
     formats that exist already, I'd think?

 - the test runs now, and may or may not crash, as you'd expect


I was really hoping to integrate this with ARCH=um and other fuzzers[1],
but ... I don't really think it's entirely feasible. I can basically
only require hard-coding the input description like the bridge tool
does, but that doesn't scale, or attempt to extract a few thousand lines
of code from syzkaller to extract the data...

[1] in particular honggfuzz as I wrote earlier, due to the coverage
    feedback format issues with afl++, but if I were able to use clang
    right now I could probably also make afl++ work in a similar way
    by adding support for --fsanitize-coverage=trace-pc-guard first.


I'm not even saying that you had many choices here, but it's definitely
annoying, at least to me, that all this infrastructure is effectively
dependent on syzkaller due to all of this. At the same time, yes, I get
that parsing dwarf and getting a description out is not an easy feat,
and without the infrastructure already in syzkaller it'd take more than
the ~1.1kLOC (and even that is not small) it has now.


I guess the biggest question to me is ultimately why all that is
necessary? Right now, there's only the single example kfuzztest that
even uses this infrastructure beyond a single linear buffer [2]. Where
is all that complexity even worth it? It's expressly intended for
simpler pieces of code that parse something ("data parsers, format
converters").

[2] admittedly the auxdisplay one is slightly different and uses a
    string, but that's pretty much equivalent

johannes
Re: [PATCH v2 0/10] KFuzzTest: a new kernel fuzzing framework
Posted by Alexander Potapenko 1 week, 5 days ago
On Fri, Sep 19, 2025 at 4:58 PM Ethan Graham <ethan.w.s.graham@gmail.com> wrote:
>
> From: Ethan Graham <ethangraham@google.com>
>
> This patch series introduces KFuzzTest, a lightweight framework for
> creating in-kernel fuzz targets for internal kernel functions.

Hi Shuah,
Since these are all fundamentally test code, I was wondering if the
selftests tree would be the appropriate path for merging them?

If you agree, would you be open to picking them up once the review is done?

Thank you!