[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260112192827.25989-2-ethan.w.s.graham@gmail.com>
Date: Mon, 12 Jan 2026 20:28:22 +0100
From: Ethan Graham <ethan.w.s.graham@...il.com>
To: ethan.w.s.graham@...il.com,
glider@...gle.com
Cc: akpm@...ux-foundation.org,
andreyknvl@...il.com,
andy@...nel.org,
andy.shevchenko@...il.com,
brauner@...nel.org,
brendan.higgins@...ux.dev,
davem@...emloft.net,
davidgow@...gle.com,
dhowells@...hat.com,
dvyukov@...gle.com,
ebiggers@...nel.org,
elver@...gle.com,
gregkh@...uxfoundation.org,
herbert@...dor.apana.org.au,
ignat@...udflare.com,
jack@...e.cz,
jannh@...gle.com,
johannes@...solutions.net,
kasan-dev@...glegroups.com,
kees@...nel.org,
kunit-dev@...glegroups.com,
linux-crypto@...r.kernel.org,
linux-kernel@...r.kernel.org,
linux-mm@...ck.org,
lukas@...ner.de,
mcgrof@...nel.org,
rmoar@...gle.com,
shuah@...nel.org,
sj@...nel.org,
skhan@...uxfoundation.org,
tarasmadan@...gle.com,
wentaoz5@...inois.edu
Subject: [PATCH v4 1/6] kfuzztest: add user-facing API and data structures
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@...il.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
Powered by blists - more mailing lists