Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crypto/asymmetric_keys/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ obj-$(CONFIG_PKCS7_TEST_KEY) += pkcs7_test_key.o
pkcs7_test_key-y := \
pkcs7_key_type.o

obj-y += tests/

#
# Signed PE binary-wrapped key handling
#
Expand Down
2 changes: 1 addition & 1 deletion crypto/asymmetric_keys/pkcs7_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
ctx->ppsinfo = &ctx->msg->signed_infos;

/* Attempt to decode the signature */
ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen + 1 /* Intentional bug! */ );
if (ret < 0) {
msg = ERR_PTR(ret);
goto out;
Expand Down
4 changes: 4 additions & 0 deletions crypto/asymmetric_keys/tests/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pkcs7-test-y := $(and $(CONFIG_KUNIT),$(filter y, $(CONFIG_PKCS7_MESSAGE_PARSER)))
rsa-helper-test-y := $(and $(CONFIG_KUNIT),$(filter y, $(CONFIG_CRYPTO_RSA)))
obj-$(pkcs7-test-y) += pkcs7_test.o
obj-$(rsa-helper-test-y) += rsa_helper_test.o
24 changes: 24 additions & 0 deletions crypto/asymmetric_keys/tests/pkcs7_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <crypto/pkcs7.h>
#include <kunit/test.h>

static void fuzz_pkcs7_parse_message(struct kunit *test, char *data,
size_t datalen)
{
struct pkcs7_message *msg;

msg = pkcs7_parse_message(data, datalen);
if (msg && !IS_ERR(msg))
pkcs7_free_message(msg);
}

static struct kunit_case pkcs7_test_cases[] = {
KUNIT_CASE_FUZZ(fuzz_pkcs7_parse_message),
{}
};

static struct kunit_suite pkcs7_test_suite = {
.name = "pkcs7",
.test_cases = pkcs7_test_cases,
};

kunit_test_suites(&pkcs7_test_suite);
31 changes: 31 additions & 0 deletions crypto/asymmetric_keys/tests/rsa_helper_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <crypto/internal/rsa.h>
#include <kunit/test.h>

static void fuzz_rsa_parse_pub_key(struct kunit *test, char *data,
size_t datalen)
{
struct rsa_key out;

rsa_parse_priv_key(&out, data, datalen);
}

static void fuzz_rsa_parse_priv_key(struct kunit *test, char *data,
size_t datalen)
{
struct rsa_key out;

rsa_parse_priv_key(&out, data, datalen);
}

static struct kunit_case rsa_helper_test_cases[] = {
KUNIT_CASE_FUZZ(fuzz_rsa_parse_pub_key),
KUNIT_CASE_FUZZ(fuzz_rsa_parse_priv_key),
{}
};

static struct kunit_suite rsa_helper_test_suite = {
.name = "rsa_helper",
.test_cases = rsa_helper_test_cases,
};

kunit_test_suites(&rsa_helper_test_suite);
26 changes: 21 additions & 5 deletions include/kunit/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,15 @@ enum kunit_speed {
KUNIT_SPEED_MAX = KUNIT_SPEED_NORMAL,
};

enum kunit_case_type {
KUNIT_NORMAL,
KUNIT_FUZZ,
};

/* Holds attributes for each test case and suite */
struct kunit_attributes {
enum kunit_speed speed;
enum kunit_case_type type;
};

/**
Expand Down Expand Up @@ -127,6 +133,7 @@ struct kunit_attributes {
*/
struct kunit_case {
void (*run_case)(struct kunit *test);
void (*fuzz_case)(struct kunit *test, char *input, size_t input_len);
const char *name;
const void* (*generate_params)(struct kunit *test,
const void *prev, char *desc);
Expand Down Expand Up @@ -161,9 +168,16 @@ static inline char *kunit_status_to_ok_not_ok(enum kunit_status status)
* &struct kunit_case object from it. See the documentation for
* &struct kunit_case for an example on how to use it.
*/
#define KUNIT_CASE(test_name) \
{ .run_case = test_name, .name = #test_name, \
.module_name = KBUILD_MODNAME}
#define KUNIT_CASE(test_name) \
{ .run_case = test_name, \
.name = #test_name, \
.module_name = KBUILD_MODNAME }
Comment on lines -164 to +174
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

My formatter got excited and git add -p wouldn't let me split this.


#define KUNIT_CASE_FUZZ(test_name) \
{ .fuzz_case = test_name, \
.name = #test_name, \
.attr.type = KUNIT_FUZZ, \
.module_name = KBUILD_MODNAME }

/**
* KUNIT_CASE_ATTR - A helper for creating a &struct kunit_case
Expand Down Expand Up @@ -285,6 +299,8 @@ struct kunit_suite {
struct string_stream *log;
int suite_init_err;
bool is_init;
char *fuzz_input;
size_t fuzz_input_len;
};

/* Stores an array of suites, end points one past the end */
Expand Down Expand Up @@ -464,8 +480,8 @@ static inline int kunit_run_all_tests(void)
#define kunit_test_init_section_suite(suite) \
kunit_test_init_section_suites(&suite)

#define kunit_suite_for_each_test_case(suite, test_case) \
for (test_case = suite->test_cases; test_case->run_case; test_case++)
#define kunit_suite_for_each_test_case(suite, test_case) \
for (test_case = suite->test_cases; test_case->name; test_case++)

enum kunit_status kunit_suite_has_succeeded(struct kunit_suite *suite);

Expand Down
144 changes: 131 additions & 13 deletions lib/kunit/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@
* Author: Alan Maguire <alan.maguire@oracle.com>
*/

#include "test_internal.h"
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/ioctl.h>

#define KFUZZ_IOC_MAGIC 'K'
#define KFUZZ_IOC_RUN _IO(KFUZZ_IOC_MAGIC, 1)

#include <kunit/test.h>
#include <kunit/test-bug.h>

#include "string-stream.h"
#include "debugfs.h"

#define KUNIT_DEBUGFS_ROOT "kunit"
#define KUNIT_DEBUGFS_RESULTS "results"
#define KUNIT_DEBUGFS_RUN "run"
#define KUNIT_DEBUGFS_ROOT "kunit"
#define KUNIT_DEBUGFS_RESULTS "results"
#define KUNIT_DEBUGFS_RUN "run"
#define KUNIT_DEBUGFS_FUZZ "fuzz"

/*
* Create a debugfs representation of test suites:
Expand Down Expand Up @@ -114,8 +120,29 @@ static int debugfs_print_run(struct seq_file *seq, void *v)
struct kunit_suite *suite = (struct kunit_suite *)seq->private;

seq_puts(seq, "Write to this file to trigger the test suite to run.\n");
seq_printf(seq, "usage: echo \"any string\" > /sys/kernel/debugfs/kunit/%s/run\n",
suite->name);
seq_printf(
seq,
"usage: echo \"any string\" > /sys/kernel/debugfs/kunit/%s/run\n",
suite->name);
return 0;
}

static int debugfs_print_fuzz(struct seq_file *seq, void *v)
{
struct kunit_case *test_case;
struct kunit_suite *suite;

suite = (struct kunit_suite *)seq->private;

size_t i = 0;
seq_puts(seq, "available fuzz harnesses:\n");
kunit_suite_for_each_test_case(suite, test_case) {
if (test_case->attr.type != KUNIT_FUZZ)
continue;
seq_printf(seq, " %zu: %s\n", i, test_case->name);
i++;
}

return 0;
}

Expand All @@ -139,17 +166,91 @@ static int debugfs_run_open(struct inode *inode, struct file *file)
*
* Note: what is written to this file will not be saved.
*/
static ssize_t debugfs_run(struct file *file,
const char __user *buf, size_t count, loff_t *ppos)
static ssize_t debugfs_run(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct inode *f_inode = file->f_inode;
struct kunit_suite *suite = (struct kunit_suite *) f_inode->i_private;
struct kunit_suite *suite = (struct kunit_suite *)f_inode->i_private;

__kunit_test_suites_init(&suite, 1, true);

return count;
}

static ssize_t debugfs_fuzz(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
void *input_buff;

struct inode *f_inode = file->f_inode;
struct kunit_suite *suite = (struct kunit_suite *)f_inode->i_private;

input_buff = kzalloc(count, GFP_KERNEL);
if (!input_buff)
return -ENOMEM;

if (copy_from_user(input_buff, buf, count)) {
kfree(input_buff);
return -EFAULT;
}

/* Free the previously allocated input buffer if it exists. */
if (suite->fuzz_input)
kfree(suite->fuzz_input);
suite->fuzz_input = input_buff;
suite->fuzz_input_len = count;
return count;
}

static struct kunit_case *find_nth_fuzz_harness(struct kunit_suite *suite,
unsigned int n)
{
struct kunit_case *test_case;
unsigned int i = 0;

kunit_suite_for_each_test_case(suite, test_case) {
if (test_case->attr.type != KUNIT_FUZZ)
continue;
if (i == n)
return test_case;
i++;
}
return NULL;
}

static long kfuzz_unlocked_ioctl_invoke(struct file *file, unsigned int cmd,
unsigned long arg)
{
/* XXX: not sure this is the correct way to do this? */
struct kunit test = { .param_value = NULL, .param_index = 0 };

struct kunit_case *harness;
size_t harness_id;

struct inode *f_inode = file->f_inode;
struct kunit_suite *suite = (struct kunit_suite *)f_inode->i_private;

if (cmd != KFUZZ_IOC_RUN)
return -ENOTTY;

harness_id = arg;

harness = find_nth_fuzz_harness(suite, harness_id);
if (!harness)
return -EINVAL;

kunit_init_test(&test, harness->name, harness->log);
kunit_run_case_catch_errors(suite, harness, &test);

return 0;
}

static int debugfs_fuzz_open(struct inode *inode, struct file *file)
{
struct kunit_suite *suite = (struct kunit_suite *)inode->i_private;
return single_open(file, debugfs_print_fuzz, suite);
}

static const struct file_operations debugfs_results_fops = {
.open = debugfs_results_open,
.read = seq_read,
Expand All @@ -165,10 +266,20 @@ static const struct file_operations debugfs_run_fops = {
.release = debugfs_release,
};

static const struct file_operations debugfs_fuzz_fops = {
.open = debugfs_fuzz_open,
.read = seq_read,
.write = debugfs_fuzz,
.llseek = seq_lseek,
.release = debugfs_release,
.unlocked_ioctl = kfuzz_unlocked_ioctl_invoke,
};

void kunit_debugfs_create_suite(struct kunit_suite *suite)
{
struct kunit_case *test_case;
struct string_stream *stream;
bool has_fuzz_harness = false;

/* If suite log already allocated, do not create new debugfs files. */
if (suite->log)
Expand All @@ -194,19 +305,26 @@ void kunit_debugfs_create_suite(struct kunit_suite *suite)

string_stream_set_append_newlines(stream, true);
test_case->log = stream;
if (test_case->attr.type == KUNIT_FUZZ)
has_fuzz_harness = true;
}

suite->debugfs = debugfs_create_dir(suite->name, debugfs_rootdir);

debugfs_create_file(KUNIT_DEBUGFS_RESULTS, S_IFREG | 0444,
suite->debugfs,
suite, &debugfs_results_fops);
suite->debugfs, suite, &debugfs_results_fops);

/* Do not create file to re-run test if test runs on init */
/*
* Do not create file to re-run test if test runs on init, or if the
* suite represents a set of fuzzing harnesses.
*/
Comment on lines +317 to +320
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Oops - this comment is from another attempt. Behavior is unchanged here, ignore the comment.

if (!suite->is_init) {
debugfs_create_file(KUNIT_DEBUGFS_RUN, S_IFREG | 0644,
suite->debugfs,
suite, &debugfs_run_fops);
suite->debugfs, suite, &debugfs_run_fops);
}
if (has_fuzz_harness) {
debugfs_create_file(KUNIT_DEBUGFS_FUZZ, S_IFREG | 0644,
suite->debugfs, suite, &debugfs_fuzz_fops);
}
return;

Expand Down
22 changes: 22 additions & 0 deletions lib/kunit/kunit-example-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,26 @@ static void example_params_test_with_init_dynamic_arr(struct kunit *test)
KUNIT_EXPECT_EQ(test, param_val - param_val, 0);
}

static void example_fuzz_harness_always_fails(struct kunit *test, char *data,
size_t datalen)
{
kunit_info(test, "i am a fuzz harness and got %zu bytes of data!",
datalen);
KUNIT_ASSERT_EQ(test, true, false);
}

static void example_fuzz_harness_oob(struct kunit *test, char *data,
size_t datalen)
{
size_t i;
volatile char c;

for (i = 0; i < datalen; i++)
READ_ONCE(data[i]);

c = *(data - 1);
}

/*
* Here we make a list of all the test cases we want to add to the test suite
* below.
Expand All @@ -514,6 +534,8 @@ static struct kunit_case example_test_cases[] = {
kunit_array_gen_params, example_param_init_dynamic_arr,
example_param_exit_dynamic_arr),
KUNIT_CASE_SLOW(example_slow_test),
KUNIT_CASE_FUZZ(example_fuzz_harness_always_fails),
KUNIT_CASE_FUZZ(example_fuzz_harness_oob),
{}
};

Expand Down
Loading