brintos

brintos / linux-shallow public Read only

0
0
Text · 3.1 KiB · 5d7b10e Raw
161 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <linux/init.h>3#include <linux/kernel.h>4#include <linux/module.h>5 6typedef void(*test_ubsan_fp)(void);7 8#define UBSAN_TEST(config, ...)	do {					\9		pr_info("%s " __VA_ARGS__ "%s(%s=%s)\n", __func__,	\10			sizeof(" " __VA_ARGS__) > 2 ? " " : "",		\11			#config, IS_ENABLED(config) ? "y" : "n");	\12	} while (0)13 14static void test_ubsan_add_overflow(void)15{16	volatile int val = INT_MAX;17 18	UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);19	val += 2;20}21 22static void test_ubsan_sub_overflow(void)23{24	volatile int val = INT_MIN;25	volatile int val2 = 2;26 27	UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);28	val -= val2;29}30 31static void test_ubsan_mul_overflow(void)32{33	volatile int val = INT_MAX / 2;34 35	UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);36	val *= 3;37}38 39static void test_ubsan_negate_overflow(void)40{41	volatile int val = INT_MIN;42 43	UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);44	val = -val;45}46 47static void test_ubsan_divrem_overflow(void)48{49	volatile int val = 16;50	volatile int val2 = 0;51 52	UBSAN_TEST(CONFIG_UBSAN_DIV_ZERO);53	val /= val2;54}55 56static void test_ubsan_shift_out_of_bounds(void)57{58	volatile int neg = -1, wrap = 4;59	volatile int val1 = 10;60	volatile int val2 = INT_MAX;61 62	UBSAN_TEST(CONFIG_UBSAN_SHIFT, "negative exponent");63	val1 <<= neg;64 65	UBSAN_TEST(CONFIG_UBSAN_SHIFT, "left overflow");66	val2 <<= wrap;67}68 69static void test_ubsan_out_of_bounds(void)70{71	volatile int i = 4, j = 5, k = -1;72	volatile char above[4] = { }; /* Protect surrounding memory. */73	volatile int arr[4];74	volatile char below[4] = { }; /* Protect surrounding memory. */75 76	above[0] = below[0];77 78	UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "above");79	arr[j] = i;80 81	UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "below");82	arr[k] = i;83}84 85enum ubsan_test_enum {86	UBSAN_TEST_ZERO = 0,87	UBSAN_TEST_ONE,88	UBSAN_TEST_MAX,89};90 91static void test_ubsan_load_invalid_value(void)92{93	volatile char *dst, *src;94	bool val, val2, *ptr;95	enum ubsan_test_enum eval, eval2, *eptr;96	unsigned char c = 0xff;97 98	UBSAN_TEST(CONFIG_UBSAN_BOOL, "bool");99	dst = (char *)&val;100	src = &c;101	*dst = *src;102 103	ptr = &val2;104	val2 = val;105 106	UBSAN_TEST(CONFIG_UBSAN_ENUM, "enum");107	dst = (char *)&eval;108	src = &c;109	*dst = *src;110 111	eptr = &eval2;112	eval2 = eval;113}114 115static void test_ubsan_misaligned_access(void)116{117	volatile char arr[5] __aligned(4) = {1, 2, 3, 4, 5};118	volatile int *ptr, val = 6;119 120	UBSAN_TEST(CONFIG_UBSAN_ALIGNMENT);121	ptr = (int *)(arr + 1);122	*ptr = val;123}124 125static const test_ubsan_fp test_ubsan_array[] = {126	test_ubsan_add_overflow,127	test_ubsan_sub_overflow,128	test_ubsan_mul_overflow,129	test_ubsan_negate_overflow,130	test_ubsan_shift_out_of_bounds,131	test_ubsan_out_of_bounds,132	test_ubsan_load_invalid_value,133	test_ubsan_misaligned_access,134};135 136/* Excluded because they Oops the module. */137static __used const test_ubsan_fp skip_ubsan_array[] = {138	test_ubsan_divrem_overflow,139};140 141static int __init test_ubsan_init(void)142{143	unsigned int i;144 145	for (i = 0; i < ARRAY_SIZE(test_ubsan_array); i++)146		test_ubsan_array[i]();147 148	return 0;149}150module_init(test_ubsan_init);151 152static void __exit test_ubsan_exit(void)153{154	/* do nothing */155}156module_exit(test_ubsan_exit);157 158MODULE_AUTHOR("Jinbum Park <jinb.park7@gmail.com>");159MODULE_DESCRIPTION("UBSAN unit test");160MODULE_LICENSE("GPL v2");161