linux/lib/fortify_kunit.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Runtime test cases for CONFIG_FORTIFY_SOURCE. For additional memcpy()
 * testing see FORTIFY_MEM_* tests in LKDTM (drivers/misc/lkdtm/fortify.c).
 *
 * For corner cases with UBSAN, try testing with:
 *
 * ./tools/testing/kunit/kunit.py run --arch=x86_64 \
 *	--kconfig_add CONFIG_FORTIFY_SOURCE=y \
 *	--kconfig_add CONFIG_UBSAN=y \
 *	--kconfig_add CONFIG_UBSAN_TRAP=y \
 *	--kconfig_add CONFIG_UBSAN_BOUNDS=y \
 *	--kconfig_add CONFIG_UBSAN_LOCAL_BOUNDS=y \
 *	--make_options LLVM=1 fortify
 */
#define pr_fmt(fmt)

/* We don't need to fill dmesg with the fortify WARNs during testing. */
#ifdef DEBUG
#define FORTIFY_REPORT_KUNIT
#define FORTIFY_WARN_KUNIT
#else
#define FORTIFY_REPORT_KUNIT(x...)
#define FORTIFY_WARN_KUNIT(x...)
#endif

/* Redefine fortify_panic() to track failures. */
void fortify_add_kunit_error(int write);
#define fortify_panic(func, write, avail, size, retfail)

/* Redefine fortify_warn_once() to track memcpy() failures. */
#define fortify_warn_once(chk_func, x...)

#include <kunit/device.h>
#include <kunit/test.h>
#include <kunit/test-bug.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/vmalloc.h>

/* Handle being built without CONFIG_FORTIFY_SOURCE */
#ifndef __compiletime_strlen
#define __compiletime_strlen
#endif

static struct kunit_resource read_resource;
static struct kunit_resource write_resource;
static int fortify_read_overflows;
static int fortify_write_overflows;

static const char array_of_10[] =;
static const char *ptr_of_11 =;
static char array_unknown[] =;

void fortify_add_kunit_error(int write)
{}

static void fortify_test_known_sizes(struct kunit *test)
{}

/* This is volatile so the optimizer can't perform DCE below. */
static volatile int pick;

/* Not inline to keep optimizer from figuring out which string we want. */
static noinline size_t want_minus_one(int pick)
{}

static void fortify_test_control_flow_split(struct kunit *test)
{}

#define KUNIT_EXPECT_BOS(test, p, expected, name)

#if !__has_builtin(__builtin_dynamic_object_size)
#define KUNIT_EXPECT_BDOS
#else
#define KUNIT_EXPECT_BDOS(test, p, expected, name)
#endif

/* If the execpted size is a constant value, __bos can see it. */
#define check_const(_expected, alloc, free)

/* If the execpted size is NOT a constant value, __bos CANNOT see it. */
#define check_dynamic(_expected, alloc, free)

/* Assortment of constant-value kinda-edge cases. */
#define CONST_TEST_BODY(TEST_alloc)

static volatile size_t zero_size;
static volatile size_t unknown_size =;

#if !__has_builtin(__builtin_dynamic_object_size)
#define DYNAMIC_TEST_BODY
#else
#define DYNAMIC_TEST_BODY(TEST_alloc)
#endif

#define DEFINE_ALLOC_SIZE_TEST_PAIR(allocator)

#define TEST_kmalloc(checker, expected_size, alloc_size)
DEFINE_ALLOC_SIZE_TEST_PAIR()

/* Sizes are in pages, not bytes. */
#define TEST_vmalloc(checker, expected_pages, alloc_pages)
DEFINE_ALLOC_SIZE_TEST_PAIR()

/* Sizes are in pages (and open-coded for side-effects), not bytes. */
#define TEST_kvmalloc(checker, expected_pages, alloc_pages)
DEFINE_ALLOC_SIZE_TEST_PAIR()

#define TEST_devm_kmalloc(checker, expected_size, alloc_size)
DEFINE_ALLOC_SIZE_TEST_PAIR()

static const char * const test_strs[] =;

#define TEST_realloc(checker)
static void fortify_test_realloc_size(struct kunit *test)
{}

/*
 * We can't have an array at the end of a structure or else
 * builds without -fstrict-flex-arrays=3 will report them as
 * being an unknown length. Additionally, add bytes before
 * and after the string to catch over/underflows if tests
 * fail.
 */
struct fortify_padding {};
/* Force compiler into not being able to resolve size at compile-time. */
static volatile int unconst;

static void fortify_test_strlen(struct kunit *test)
{}

static void fortify_test_strnlen(struct kunit *test)
{}

static void fortify_test_strcpy(struct kunit *test)
{}

static void fortify_test_strncpy(struct kunit *test)
{}

static void fortify_test_strscpy(struct kunit *test)
{}

static void fortify_test_strcat(struct kunit *test)
{}

static void fortify_test_strncat(struct kunit *test)
{}

static void fortify_test_strlcat(struct kunit *test)
{}

/* Check for 0-sized arrays... */
struct fortify_zero_sized {};

#define __fortify_test(memfunc)
__fortify_test()
__fortify_test()

static void fortify_test_memscan(struct kunit *test)
{}

static void fortify_test_memchr(struct kunit *test)
{}

static void fortify_test_memchr_inv(struct kunit *test)
{}

static void fortify_test_memcmp(struct kunit *test)
{}

static void fortify_test_kmemdup(struct kunit *test)
{}

static int fortify_test_init(struct kunit *test)
{}

static struct kunit_case fortify_test_cases[] =;

static struct kunit_suite fortify_test_suite =;

kunit_test_suite();

MODULE_DESCRIPTION();
MODULE_LICENSE();