From: Ethan Graham <ethan.w.s.graham@gmail.com>
To: ethan.w.s.graham@gmail.com, glider@google.com
Cc: akpm@linux-foundation.org, andreyknvl@gmail.com, andy@kernel.org,
andy.shevchenko@gmail.com, brauner@kernel.org,
brendan.higgins@linux.dev, davem@davemloft.net,
davidgow@google.com, dhowells@redhat.com, dvyukov@google.com,
ebiggers@kernel.org, elver@google.com,
gregkh@linuxfoundation.org, herbert@gondor.apana.org.au,
ignat@cloudflare.com, jack@suse.cz, jannh@google.com,
johannes@sipsolutions.net, kasan-dev@googlegroups.com,
kees@kernel.org, kunit-dev@googlegroups.com,
linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, lukas@wunner.de, mcgrof@kernel.org,
rmoar@google.com, shuah@kernel.org, sj@kernel.org,
skhan@linuxfoundation.org, tarasmadan@google.com,
wentaoz5@illinois.edu
Subject: [PATCH v4 1/6] kfuzztest: add user-facing API and data structures
Date: Mon, 12 Jan 2026 20:28:22 +0100 [thread overview]
Message-ID: <20260112192827.25989-2-ethan.w.s.graham@gmail.com> (raw)
In-Reply-To: <20260112192827.25989-1-ethan.w.s.graham@gmail.com>
Add the foundational user-facing components for the KFuzzTest framework.
This includes the main API header <linux/kfuzztest.h>, the Kconfig
option to enable the feature, and the required linker script changes
which introduce a new ELF section in vmlinux.
Note that KFuzzTest is intended strictly for debug builds only, and
should never be enabled in a production build. The fact that it exposes
internal kernel functions and state directly to userspace may constitute
a serious security vulnerability if used for any reason other than
testing.
The header defines:
- The FUZZ_TEST_SIMPLE() macro for creating test targets.
- The `struct kfuzztest_simple_target` structure used to register tests.
- The linker section (.kfuzztest_simple_target) where test metadata is
stored for discovery by the framework.
This patch only adds the public interface and build integration; no
runtime logic is included.
Signed-off-by: Ethan Graham <ethan.w.s.graham@gmail.com>
---
PR v4:
- Remove the complex FUZZ_TEST macro and associated dependencies,
including domain constraints, annotations, and de-serialization,
dramatically simplifying the flow.
- Drop unused ELF sections (.kfuzztest_constraint, etc...) from the
linker script, keeping only .kfuzztest_simple_target.
PR v3:
- Reorder definitions in kfuzztest.h for better flow and readability.
- Introduce __KFUZZTEST_CONSTRAINT macro in preparation for the
introduction of the FUZZ_TEST_SIMPLE macro in the following patch,
which uses it for manually emitting constraint metadata.
PR v1:
- Move KFuzzTest metadata definitions to generic vmlinux linkage so that
the framework isn't bound to x86_64.
- Return -EFAULT when simple_write_to_buffer returns a value not equal
to the input length in the main FUZZ_TEST macro.
- Enforce a maximum input size of 64KiB in the main FUZZ_TEST macro,
returning -EINVAL when it isn't respected.
- Refactor KFUZZTEST_ANNOTATION_* macros.
- Taint the kernel with TAINT_TEST inside the FUZZ_TEST macro when a
fuzz target is invoked for the first time.
---
---
include/asm-generic/vmlinux.lds.h | 14 ++++-
include/linux/kfuzztest.h | 88 +++++++++++++++++++++++++++++++
lib/Kconfig.debug | 1 +
lib/kfuzztest/Kconfig | 16 ++++++
4 files changed, 118 insertions(+), 1 deletion(-)
create mode 100644 include/linux/kfuzztest.h
create mode 100644 lib/kfuzztest/Kconfig
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index ae2d2359b79e..5aa46dbbc9b2 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -373,7 +373,8 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG)
TRACE_PRINTKS() \
BPF_RAW_TP() \
TRACEPOINT_STR() \
- KUNIT_TABLE()
+ KUNIT_TABLE() \
+ KFUZZTEST_TABLE()
/*
* Data section helpers
@@ -966,6 +967,17 @@ defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG)
BOUNDED_SECTION_POST_LABEL(.kunit_init_test_suites, \
__kunit_init_suites, _start, _end)
+#ifdef CONFIG_KFUZZTEST
+#define KFUZZTEST_TABLE() \
+ . = ALIGN(PAGE_SIZE); \
+ __kfuzztest_simple_targets_start = .; \
+ KEEP(*(.kfuzztest_simple_target)); \
+ __kfuzztest_simple_targets_end = .; \
+
+#else /* CONFIG_KFUZZTEST */
+#define KFUZZTEST_TABLE()
+#endif /* CONFIG_KFUZZTEST */
+
#ifdef CONFIG_BLK_DEV_INITRD
#define INIT_RAM_FS \
. = ALIGN(4); \
diff --git a/include/linux/kfuzztest.h b/include/linux/kfuzztest.h
new file mode 100644
index 000000000000..62fce9267761
--- /dev/null
+++ b/include/linux/kfuzztest.h
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * The Kernel Fuzz Testing Framework (KFuzzTest) API for defining fuzz targets
+ * for internal kernel functions.
+ *
+ * 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 */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index dc0e0c6ed075..49a1748b9f24 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1947,6 +1947,7 @@ endmenu
menu "Kernel Testing and Coverage"
source "lib/kunit/Kconfig"
+source "lib/kfuzztest/Kconfig"
config NOTIFIER_ERROR_INJECTION
tristate "Notifier error injection"
diff --git a/lib/kfuzztest/Kconfig b/lib/kfuzztest/Kconfig
new file mode 100644
index 000000000000..d8e9caaac108
--- /dev/null
+++ b/lib/kfuzztest/Kconfig
@@ -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.
--
2.51.0
next prev parent reply other threads:[~2026-01-12 19:28 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-12 19:28 [PATCH v4 0/6] KFuzzTest: a new kernel fuzzing framework Ethan Graham
2026-01-12 19:28 ` Ethan Graham [this message]
2026-01-12 19:28 ` [PATCH v4 2/6] kfuzztest: implement core module and input processing Ethan Graham
2026-01-12 19:28 ` [PATCH v4 3/6] kfuzztest: add ReST documentation Ethan Graham
2026-01-12 19:28 ` [PATCH v4 4/6] kfuzztest: add KFuzzTest sample fuzz targets Ethan Graham
2026-01-12 19:28 ` [PATCH v4 5/6] crypto: implement KFuzzTest targets for PKCS7 and RSA parsing Ethan Graham
2026-01-12 19:28 ` [PATCH v4 6/6] MAINTAINERS: add maintainer information for KFuzzTest Ethan Graham
2026-01-12 19:43 ` [PATCH v4 0/6] KFuzzTest: a new kernel fuzzing framework Ethan Graham
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260112192827.25989-2-ethan.w.s.graham@gmail.com \
--to=ethan.w.s.graham@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=andreyknvl@gmail.com \
--cc=andy.shevchenko@gmail.com \
--cc=andy@kernel.org \
--cc=brauner@kernel.org \
--cc=brendan.higgins@linux.dev \
--cc=davem@davemloft.net \
--cc=davidgow@google.com \
--cc=dhowells@redhat.com \
--cc=dvyukov@google.com \
--cc=ebiggers@kernel.org \
--cc=elver@google.com \
--cc=glider@google.com \
--cc=gregkh@linuxfoundation.org \
--cc=herbert@gondor.apana.org.au \
--cc=ignat@cloudflare.com \
--cc=jack@suse.cz \
--cc=jannh@google.com \
--cc=johannes@sipsolutions.net \
--cc=kasan-dev@googlegroups.com \
--cc=kees@kernel.org \
--cc=kunit-dev@googlegroups.com \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lukas@wunner.de \
--cc=mcgrof@kernel.org \
--cc=rmoar@google.com \
--cc=shuah@kernel.org \
--cc=sj@kernel.org \
--cc=skhan@linuxfoundation.org \
--cc=tarasmadan@google.com \
--cc=wentaoz5@illinois.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox