Skip to content

Conversation

@ethangraham2001
Copy link
Owner

@ethangraham2001 ethangraham2001 commented Jun 23, 2025

WIP

This PR adds a macro for defining a KFuzztest case, which is exposed as a debufs entry under /sys/kernel/debug/kftf/<test-case>. Usage of this is demonstrated in this syzkaller PR ethangraham2001/syzkaller#1 that leverages it to fuzz the two simple test cases exposed here.

Ethan Graham added 5 commits June 18, 2025 10:02
binary representation down. Correctly causes a KASAN repot when passing a
buggy input to it.
Added support for this for x86 arch, but it is probably fragile because
we aren't guarding with a #ifdef yet

static struct kftf_simple_fuzzer_state st;

// XXX: allows everyone to write - correct flags?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Single-line C-style comments are discouraged in the kernel.
Unfortunately this is never mentioned in https://www.kernel.org/doc/html/latest/process/coding-style.html.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the flags, this is a good question.
We are letting the developers expose arbitrary kernel functions to the user, so the security of the kernel under test is already severely compromised.
We can probably start with only allowing root access for now, although no one should be enabling fuzz tests on production machines anyway.

#define KEXEC_RELOCATE_KERNEL
#endif

#define KFTF_TABLE \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's more or less up to you to pick a name for this subsystem, and it's not too late to change it if you prefer something different from "KFTF" :)

.write_callback = _write_callback_##func, \
}; \
/* user-defined write callback */ \
static ssize_t _write_callback_##func(struct file *filp, \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The common part of the write callback that is handling writes probably doesn't need to be duplicated for each test case.

Ethan Graham added 7 commits June 23, 2025 13:45
the argument type that the function takes so that the user can use tools
like pahole to generate a syzkaller definition of the argument and thus
fuzz the function more easily.
files. It works, and the function is exposed correctly!
* {
* // arg is provided by the macro, and is of type `struct func_arg_type`
* ret = func(arg.arg1, ..., arg.argn);
* validate(ret);
Copy link
Owner Author

@ethangraham2001 ethangraham2001 Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

I think it would be great to have some kind of KFTF_BUG_ON(condition) or similar so that a bug is reported in a consistent way in the case that a fuzz tests fails.

Copy link
Owner Author

@ethangraham2001 ethangraham2001 Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could look something like

#define KFTF_BUG_ON(condition) if (condition) pr_warn("some output to indicate failure")

Or perhaps ASSERT_TRUE(condition) as is the case in libFuzzer

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, some sort of an assertion would be good to have.

Comment on lines +14 to +15
extern const struct kftf_test_case __kftf_start[];
extern const struct kftf_test_case __kftf_end[];
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: these aren't being linked against properly if we build with CONFIG_KFTF=M (I.e. as a module). It seems a little too restrictive to enforce that the fuzz test targets always be exposed as a built-in.

That being said, not sure how to link against the fuzz targets if the module is built separately from the kernel.

Ethan Graham added 3 commits July 1, 2025 06:35
pointer to function argument type. This should remove the need for a
mutex guarding a shared buffer entirely, and ultimately will likely
perform better.
variable, and extract common input reading functionality into a separate
function.
@@ -0,0 +1,130 @@
#ifndef KFTF_H

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to the include guard, every kernel file should contain an SPDX license header (/* SPDX-License-Identifier: GPL-2.0 */) and a short comment explaining what it is doing.

Check include/linux/kfence.h for an example (drop (C) per go/copyright).

* - A mutex to protect the input buffer
* - A `struct kftf_test_case` instance
*
* Example usagea:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: usagea

* TN argn;
* };
*
* // Define the test case

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: single-line comments should end with a period.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By the way, maybe change them to C-style? I don't insist though, as they are inside a comment anyway.

* }
*/
#define FUZZ_TEST(func, func_arg_type) \
/* input buffer. Size 2 for now, but we may support batching */ \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: single-line comments should start with a capital letter (unless that's a name of an identifier) and end with a period.

*/
#define FUZZ_TEST(func, func_arg_type) \
/* input buffer. Size 2 for now, but we may support batching */ \
static func_arg_type input_buf_##func[2]; \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need two elements, do you use them?

source "lib/Kconfig.kasan"
source "lib/Kconfig.kfence"
source "lib/Kconfig.kmsan"
source "lib/Kconfig.kftf"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest moving it one line above, so that the source directive are sorted.

@@ -0,0 +1,151 @@
#include <linux/debugfs.h>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file also needs an SPDX header

* @func_arg_type: the input type of func. If func takes multiple arguments,
* then one should wrap that inside of a multi-fielded struct. See usage
* example below.
*

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: extra newline.

size_t num_test_cases;

/*
* To avoid kmalloc entirely, we enforce a maximum number of fuzz tests

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want to avoid kmalloc?

* {
* // arg is provided by the macro, and is of type `struct func_arg_type`
* ret = func(arg.arg1, ..., arg.argn);
* validate(ret);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, some sort of an assertion would be good to have.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants