forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
KFuzzTest PR v4 #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ethangraham2001
wants to merge
6
commits into
master
Choose a base branch
from
kfuzztest_pr_v4
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
KFuzzTest PR v4 #17
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
38e2cd1
kfuzztest: add user-facing API and data structures
ethangraham2001 aeb7608
kfuzztest: implement core module and input processing
ethangraham2001 8db4ec6
kfuzztest: add ReST documentation
ethangraham2001 1a67b07
kfuzztest: add KFuzzTest sample fuzz targets
ethangraham2001 727713d
crypto: implement KFuzzTest targets for PKCS7 and RSA parsing
ethangraham2001 a8fa42f
MAINTAINERS: add maintainer information for KFuzzTest
ethangraham2001 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,152 @@ | ||
| .. SPDX-License-Identifier: GPL-2.0 | ||
| .. Copyright 2025 Google LLC | ||
|
|
||
| ========================================= | ||
| Kernel Fuzz Testing Framework (KFuzzTest) | ||
| ========================================= | ||
|
|
||
| Overview | ||
| ======== | ||
|
|
||
| The Kernel Fuzz Testing Framework (KFuzzTest) is a framework designed to expose | ||
| internal kernel functions to a userspace fuzzing engine. | ||
|
|
||
| It is intended for testing stateless or low-state functions that are difficult | ||
| to reach from the system call interface, such as routines involved in file | ||
| format parsing or complex data transformations. This provides a method 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. | ||
|
|
||
| The framework consists of two main components: | ||
|
|
||
| 1. An API, based on the ``FUZZ_TEST_SIMPLE`` macro, for defining test targets | ||
| directly in the kernel tree. | ||
| 2. A ``debugfs`` interface through which a userspace fuzzer submits raw | ||
| binary test inputs. | ||
|
|
||
| .. warning:: | ||
| KFuzzTest is a debugging and testing tool. It exposes internal kernel | ||
| functions to userspace with minimal sanitization and is designed for | ||
| use in controlled test environments only. It must **NEVER** be enabled | ||
| in production kernels. | ||
|
|
||
| Supported Architectures | ||
| ======================= | ||
|
|
||
| KFuzzTest is designed for generic architecture support. It has only been | ||
| explicitly tested on x86_64. | ||
|
|
||
| Usage | ||
| ===== | ||
|
|
||
| To enable KFuzzTest, configure the kernel with:: | ||
|
|
||
| CONFIG_KFUZZTEST=y | ||
|
|
||
| which depends on ``CONFIG_DEBUGFS`` for receiving userspace inputs, and | ||
| ``CONFIG_DEBUG_KERNEL`` as an additional guardrail for preventing KFuzzTest | ||
| from finding its way into a production build accidentally. | ||
|
|
||
| The KFuzzTest sample fuzz targets can be built in with | ||
| ``CONFIG_SAMPLE_KFUZZTEST``. | ||
|
|
||
| KFuzzTest currently only supports targets that are built into the kernel, as the | ||
| core module's startup process discovers fuzz targets from a dedicated ELF | ||
| section during startup. | ||
|
|
||
| Defining a KFuzzTest target | ||
| --------------------------- | ||
|
|
||
| A fuzz target should be defined in a .c file. The recommended place to define | ||
| this is under the subsystem's ``/tests`` directory in a ``<file-name>_kfuzz.c`` | ||
| file, following the convention used by KUnit. The only strict requirement is | ||
| that the function being fuzzed is visible to the fuzz target. | ||
|
|
||
| Use the ``FUZZ_TEST_SIMPLE`` macro to define a fuzz target. This macro is | ||
| designed for functions that accept a buffer and its length (e.g., | ||
| ``(const char *data, size_t datalen)``). | ||
|
|
||
| This macro provides ``data`` and ``datalen`` variables implicitly to the test | ||
| body. | ||
|
|
||
| .. code-block:: c | ||
|
|
||
| /* 1. The kernel function that we want to fuzz. */ | ||
| int process_data(const char *data, size_t len); | ||
|
|
||
| /* 2. Define the fuzz target with the FUZZ_TEST_SIMPLE macro. */ | ||
| FUZZ_TEST_SIMPLE(test_process_data) | ||
| { | ||
| /* 3. Call the kernel function with the provided input. */ | ||
| process_data(data, datalen); | ||
| } | ||
|
|
||
| A ``FUZZ_TEST_SIMPLE`` target creates a debugfs directory | ||
| (``/sys/kernel/debug/kfuzztest/<test-name>``) containing a single write-only | ||
| file ``input_simple``: writing a raw blob to this file will invoke the fuzz | ||
| target, passing the blob as ``(data, datalen)``. | ||
|
|
||
| Basic Usage | ||
| ^^^^^^^^^^^ | ||
|
|
||
| Because the interface accepts raw binary data, targets can be smoke-tested or | ||
| fuzzed naively using standard command-line tools without any external | ||
| dependencies. | ||
|
|
||
| For example, to feed 128 bytes of random data to the target defined above: | ||
|
|
||
| .. code-block:: sh | ||
|
|
||
| head -c 128 /dev/urandom > \ | ||
| /sys/kernel/debug/kfuzztest/test_process_data/input_simple | ||
|
|
||
| Integration with Fuzzers | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| The simple interface makes it easy to integrate with userspace fuzzers (e.g., | ||
| LibFuzzer, AFL++, honggfuzz). A LibFuzzer, for example, harness may look like | ||
| so: | ||
|
|
||
| .. code-block:: c | ||
|
|
||
| /* Path to the simple target's input file */ | ||
| const char *filepath = "/sys/kernel/debug/kfuzztest/test_process_data/input_simple"; | ||
|
|
||
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { | ||
| FILE *f = fopen(filepath, "w"); | ||
| if (!f) { | ||
| return 0; /* Fuzzer should not stop. */ | ||
| } | ||
| /* Write the raw fuzzer input directly. */ | ||
| fwrite(Data, 1, Size, f); | ||
| fclose(f); | ||
| return 0; | ||
| } | ||
|
|
||
| Note that while it is simple to feed inputs to KFuzzTest targets, kernel | ||
| coverage collection is key for the effectiveness of a coverage-guided fuzzer; | ||
| setup of KCOV or other coverage mechanisms is outside of KFuzzTest's scope. | ||
|
|
||
| Metadata | ||
| -------- | ||
|
|
||
| The ``FUZZ_TEST_SIMPLE`` macro embeds metadata into a dedicated section within | ||
| the main ``.data`` section of the final ``vmlinux`` binary: | ||
| ``.kfuzztest_simple_target``, delimited by ``__kfuzztest_simple_targets_start`` | ||
| and ``__kfuzztest_simple_targets_end``. | ||
|
|
||
| The metadata serves two purposes: | ||
|
|
||
| 1. The core module uses the ``.kfuzztest_simple_target`` section at boot to | ||
| discover every test instance and create its ``debugfs`` directory and | ||
| ``input_simple`` file. | ||
| 2. Tooling can use this section for offline discovery. While available fuzz | ||
| targets can be trivially enumerated at runtime by listing the directories | ||
| under ``/sys/kernel/debug/kfuzztest``, the metadata allows fuzzing | ||
| orchestrators to index available fuzz targets directly from the ``vmlinux`` | ||
| binary without needing to boot the kernel. | ||
|
|
||
| This metadata consists of an array of ``struct kfuzztest_simple_target``. The | ||
| ``name`` field within this struct references data in other locations of the | ||
| ``vmlinux`` binary, and therefore a userspace tool that parses the ELF must | ||
| resolve these pointers to read the underlying data. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| pkcs7-kfuzz-y := $(and $(CONFIG_KFUZZTEST),$(filter y, $(CONFIG_PKCS7_MESSAGE_PARSER))) | ||
| rsa-helper-kfuzz-y := $(and $(CONFIG_KFUZZTEST),$(filter y, $(CONFIG_CRYPTO_RSA))) | ||
| obj-$(pkcs7-kfuzz-y) += pkcs7_kfuzz.o | ||
| obj-$(rsa-helper-kfuzz-y) += rsa_helper_kfuzz.o |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
| /* | ||
| * PKCS#7 parser KFuzzTest target. | ||
| * | ||
| * Copyright 2025 Google LLC | ||
| */ | ||
| #include <crypto/pkcs7.h> | ||
| #include <linux/kfuzztest.h> | ||
|
|
||
| FUZZ_TEST_SIMPLE(test_pkcs7_parse_message) | ||
| { | ||
| struct pkcs7_message *msg; | ||
|
|
||
| msg = pkcs7_parse_message(data, datalen); | ||
| if (msg && !IS_ERR(msg)) | ||
| pkcs7_free_message(msg); | ||
| return 0; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
| /* | ||
| * RSA key extract helper KFuzzTest targets. | ||
| * | ||
| * Copyright 2025 Google LLC | ||
| */ | ||
| #include <crypto/internal/rsa.h> | ||
| #include <linux/kfuzztest.h> | ||
|
|
||
| FUZZ_TEST_SIMPLE(test_rsa_parse_pub_key) | ||
| { | ||
| struct rsa_key out; | ||
|
|
||
| rsa_parse_pub_key(&out, data, datalen); | ||
| return 0; | ||
| } | ||
|
|
||
| FUZZ_TEST_SIMPLE(test_rsa_parse_priv_key) | ||
| { | ||
| struct rsa_key out; | ||
ethangraham2001 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| rsa_parse_priv_key(&out, data, datalen); | ||
| return 0; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| // SPDX-License-Identifier: GPL-2.0 | ||
| /* | ||
| * The Kernel Fuzz Testing Framework (KFuzzTest) API for defining fuzz targets | ||
| * for internal kernel functions. | ||
| * | ||
| * For more information please see Documentation/dev-tools/kfuzztest.rst. | ||
| * | ||
| * Copyright 2025 Google LLC | ||
| */ | ||
| #ifndef KFUZZTEST_H | ||
| #define KFUZZTEST_H | ||
|
|
||
| #include <linux/fs.h> | ||
| #include <linux/printk.h> | ||
| #include <linux/types.h> | ||
|
|
||
| #define KFUZZTEST_MAX_INPUT_SIZE (PAGE_SIZE * 16) | ||
|
|
||
| /* Common code for receiving inputs from userspace. */ | ||
| int kfuzztest_write_cb_common(struct file *filp, const char __user *buf, size_t len, loff_t *off, void **test_buffer); | ||
|
|
||
| struct kfuzztest_simple_target { | ||
| const char *name; | ||
| ssize_t (*write_input_cb)(struct file *filp, const char __user *buf, size_t len, loff_t *off); | ||
| }; | ||
|
|
||
| /** | ||
| * FUZZ_TEST_SIMPLE - defines a KFuzzTest target | ||
| * | ||
| * @test_name: the unique identifier for the fuzz test, which is used to name | ||
| * the debugfs entry. | ||
| * | ||
| * This macro defines a fuzz target entry point that accepts raw byte buffers | ||
| * from userspace. It registers a struct kfuzztest_simple_target which the | ||
| * framework exposes via debugfs. | ||
| * | ||
| * When userspace writes to the corresponding debugfs file, the framework | ||
| * allocates a kernel buffer, copies the user data, and passes it to the | ||
| * logic defined in the macro body. | ||
| * | ||
| * User-provided Logic: | ||
| * The developer must provide the body of the fuzz test logic within the curly | ||
| * braces following the macro invocation. Within this scope, the framework | ||
| * implicitly defines the following variables: | ||
| * | ||
| * - `char *data`: A pointer to the raw input data. | ||
| * - `size_t datalen`: The length of the input data. | ||
| * | ||
| * Example Usage: | ||
| * | ||
| * // 1. The kernel function that we want to fuzz. | ||
| * int process_data(const char *data, size_t datalen); | ||
| * | ||
| * // 2. Define a fuzz target using the FUZZ_TEST_SIMPLE macro. | ||
| * FUZZ_TEST_SIMPLE(test_process_data) | ||
| * { | ||
| * // Call the function under test using the `data` and `datalen` | ||
| * // variables. | ||
| * process_data(data, datalen); | ||
| * } | ||
| * | ||
| */ | ||
| #define FUZZ_TEST_SIMPLE(test_name) \ | ||
| static ssize_t kfuzztest_simple_write_cb_##test_name(struct file *filp, const char __user *buf, size_t len, \ | ||
| loff_t *off); \ | ||
| static ssize_t kfuzztest_simple_logic_##test_name(char *data, size_t datalen); \ | ||
| static const struct kfuzztest_simple_target __fuzz_test_simple__##test_name __section( \ | ||
| ".kfuzztest_simple_target") __used = { \ | ||
| .name = #test_name, \ | ||
| .write_input_cb = kfuzztest_simple_write_cb_##test_name, \ | ||
| }; \ | ||
| static ssize_t kfuzztest_simple_write_cb_##test_name(struct file *filp, const char __user *buf, size_t len, \ | ||
| loff_t *off) \ | ||
| { \ | ||
| void *buffer; \ | ||
| int ret; \ | ||
| \ | ||
| ret = kfuzztest_write_cb_common(filp, buf, len, off, &buffer); \ | ||
| if (ret < 0) \ | ||
| goto out; \ | ||
| ret = kfuzztest_simple_logic_##test_name(buffer, len); \ | ||
| if (ret == 0) \ | ||
| ret = len; \ | ||
| kfree(buffer); \ | ||
| out: \ | ||
| return ret; \ | ||
| } \ | ||
| static ssize_t kfuzztest_simple_logic_##test_name(char *data, size_t datalen) | ||
|
|
||
| #endif /* KFUZZTEST_H */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| # SPDX-License-Identifier: GPL-2.0-only | ||
|
|
||
| config KFUZZTEST | ||
| bool "KFuzzTest - enable support for internal fuzz targets" | ||
| depends on DEBUG_FS && DEBUG_KERNEL | ||
| help | ||
| Enables support for the kernel fuzz testing framework (KFuzzTest), an | ||
| interface for exposing internal kernel functions to a userspace fuzzing | ||
| engine. KFuzzTest targets are exposed via a debugfs interface that | ||
| accepts raw binary inputs from userspace, and is designed to make it | ||
| easier to fuzz deeply nested kernel code that is hard to reach from | ||
| the system call boundary. Using a simple macro-based API, developers | ||
| can add a new fuzz target with minimal boilerplate code. | ||
|
|
||
| WARNING: This exposes internal kernel functions directly to userspace | ||
| and must NEVER be enabled in production builds. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # SPDX-License-Identifier: GPL-2.0 | ||
|
|
||
| obj-$(CONFIG_KFUZZTEST) += kfuzztest.o | ||
| kfuzztest-objs := main.o input.o |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.