test_ubsan.c (2498B)
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_divrem_overflow(void) 15{ 16 volatile int val = 16; 17 volatile int val2 = 0; 18 19 UBSAN_TEST(CONFIG_UBSAN_DIV_ZERO); 20 val /= val2; 21} 22 23static void test_ubsan_shift_out_of_bounds(void) 24{ 25 volatile int neg = -1, wrap = 4; 26 int val1 = 10; 27 int val2 = INT_MAX; 28 29 UBSAN_TEST(CONFIG_UBSAN_SHIFT, "negative exponent"); 30 val1 <<= neg; 31 32 UBSAN_TEST(CONFIG_UBSAN_SHIFT, "left overflow"); 33 val2 <<= wrap; 34} 35 36static void test_ubsan_out_of_bounds(void) 37{ 38 volatile int i = 4, j = 5, k = -1; 39 volatile char above[4] = { }; /* Protect surrounding memory. */ 40 volatile int arr[4]; 41 volatile char below[4] = { }; /* Protect surrounding memory. */ 42 43 above[0] = below[0]; 44 45 UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "above"); 46 arr[j] = i; 47 48 UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "below"); 49 arr[k] = i; 50} 51 52enum ubsan_test_enum { 53 UBSAN_TEST_ZERO = 0, 54 UBSAN_TEST_ONE, 55 UBSAN_TEST_MAX, 56}; 57 58static void test_ubsan_load_invalid_value(void) 59{ 60 volatile char *dst, *src; 61 bool val, val2, *ptr; 62 enum ubsan_test_enum eval, eval2, *eptr; 63 unsigned char c = 0xff; 64 65 UBSAN_TEST(CONFIG_UBSAN_BOOL, "bool"); 66 dst = (char *)&val; 67 src = &c; 68 *dst = *src; 69 70 ptr = &val2; 71 val2 = val; 72 73 UBSAN_TEST(CONFIG_UBSAN_ENUM, "enum"); 74 dst = (char *)&eval; 75 src = &c; 76 *dst = *src; 77 78 eptr = &eval2; 79 eval2 = eval; 80} 81 82static void test_ubsan_misaligned_access(void) 83{ 84 volatile char arr[5] __aligned(4) = {1, 2, 3, 4, 5}; 85 volatile int *ptr, val = 6; 86 87 UBSAN_TEST(CONFIG_UBSAN_ALIGNMENT); 88 ptr = (int *)(arr + 1); 89 *ptr = val; 90} 91 92static const test_ubsan_fp test_ubsan_array[] = { 93 test_ubsan_shift_out_of_bounds, 94 test_ubsan_out_of_bounds, 95 test_ubsan_load_invalid_value, 96 test_ubsan_misaligned_access, 97}; 98 99/* Excluded because they Oops the module. */ 100static const test_ubsan_fp skip_ubsan_array[] = { 101 test_ubsan_divrem_overflow, 102}; 103 104static int __init test_ubsan_init(void) 105{ 106 unsigned int i; 107 108 for (i = 0; i < ARRAY_SIZE(test_ubsan_array); i++) 109 test_ubsan_array[i](); 110 111 return 0; 112} 113module_init(test_ubsan_init); 114 115static void __exit test_ubsan_exit(void) 116{ 117 /* do nothing */ 118} 119module_exit(test_ubsan_exit); 120 121MODULE_AUTHOR("Jinbum Park <jinb.park7@gmail.com>"); 122MODULE_LICENSE("GPL v2");