File Index
Files and directories
Sign in
FILE

test_ubsan.c

File preview with syntax highlighting.

linux-6.19.14/lib/test_ubsan.c C
  1// SPDX-License-Identifier: GPL-2.0
  2#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_INTEGER_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_INTEGER_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_INTEGER_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_INTEGER_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_truncate_signed(void)
 57{
 58	volatile long val = LONG_MAX;
 59	volatile int val2 = 0;
 60
 61	UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP);
 62	val2 = val;
 63}
 64
 65static void test_ubsan_shift_out_of_bounds(void)
 66{
 67	volatile int neg = -1, wrap = 4;
 68	volatile int val1 = 10;
 69	volatile int val2 = INT_MAX;
 70
 71	UBSAN_TEST(CONFIG_UBSAN_SHIFT, "negative exponent");
 72	val1 <<= neg;
 73
 74	UBSAN_TEST(CONFIG_UBSAN_SHIFT, "left overflow");
 75	val2 <<= wrap;
 76}
 77
 78static void test_ubsan_out_of_bounds(void)
 79{
 80	int i = 4, j = 4, k = -1;
 81	volatile struct {
 82		char above[4]; /* Protect surrounding memory. */
 83		int arr[4];
 84		char below[4]; /* Protect surrounding memory. */
 85	} data;
 86
 87	OPTIMIZER_HIDE_VAR(i);
 88	OPTIMIZER_HIDE_VAR(j);
 89	OPTIMIZER_HIDE_VAR(k);
 90
 91	UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "above");
 92	data.arr[j] = i;
 93
 94	UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "below");
 95	data.arr[k] = i;
 96}
 97
 98enum ubsan_test_enum {
 99	UBSAN_TEST_ZERO = 0,
100	UBSAN_TEST_ONE,
101	UBSAN_TEST_MAX,
102};
103
104static void test_ubsan_load_invalid_value(void)
105{
106	volatile char *dst, *src;
107	bool val, val2, *ptr;
108	enum ubsan_test_enum eval, eval2, *eptr;
109	unsigned char c = 0xff;
110
111	UBSAN_TEST(CONFIG_UBSAN_BOOL, "bool");
112	dst = (char *)&val;
113	src = &c;
114	*dst = *src;
115
116	ptr = &val2;
117	val2 = val;
118
119	UBSAN_TEST(CONFIG_UBSAN_ENUM, "enum");
120	dst = (char *)&eval;
121	src = &c;
122	*dst = *src;
123
124	eptr = &eval2;
125	eval2 = eval;
126}
127
128static void test_ubsan_misaligned_access(void)
129{
130	volatile char arr[5] __aligned(4) = {1, 2, 3, 4, 5};
131	volatile int *ptr, val = 6;
132
133	UBSAN_TEST(CONFIG_UBSAN_ALIGNMENT);
134	ptr = (int *)(arr + 1);
135	*ptr = val;
136}
137
138static const test_ubsan_fp test_ubsan_array[] = {
139	test_ubsan_add_overflow,
140	test_ubsan_sub_overflow,
141	test_ubsan_mul_overflow,
142	test_ubsan_negate_overflow,
143	test_ubsan_truncate_signed,
144	test_ubsan_shift_out_of_bounds,
145	test_ubsan_out_of_bounds,
146	test_ubsan_load_invalid_value,
147	test_ubsan_misaligned_access,
148};
149
150/* Excluded because they Oops the module. */
151static __used const test_ubsan_fp skip_ubsan_array[] = {
152	test_ubsan_divrem_overflow,
153};
154
155static int __init test_ubsan_init(void)
156{
157	unsigned int i;
158
159	for (i = 0; i < ARRAY_SIZE(test_ubsan_array); i++)
160		test_ubsan_array[i]();
161
162	return 0;
163}
164module_init(test_ubsan_init);
165
166static void __exit test_ubsan_exit(void)
167{
168	/* do nothing */
169}
170module_exit(test_ubsan_exit);
171
172MODULE_AUTHOR("Jinbum Park <jinb.park7@gmail.com>");
173MODULE_DESCRIPTION("UBSAN unit test");
174MODULE_LICENSE("GPL v2");
~/ Read-only file preview.