diff options
Diffstat (limited to 'lib/test_ubsan.c')
| -rw-r--r-- | lib/test_ubsan.c | 96 |
1 files changed, 63 insertions, 33 deletions
diff --git a/lib/test_ubsan.c b/lib/test_ubsan.c index 280f4979d00e..a4b6f52b9c57 100644 --- a/lib/test_ubsan.c +++ b/lib/test_ubsan.c @@ -5,10 +5,17 @@ typedef void(*test_ubsan_fp)(void); +#define UBSAN_TEST(config, ...) do { \ + pr_info("%s " __VA_ARGS__ "%s(%s=%s)\n", __func__, \ + sizeof(" " __VA_ARGS__) > 2 ? " " : "", \ + #config, IS_ENABLED(config) ? "y" : "n"); \ + } while (0) + static void test_ubsan_add_overflow(void) { volatile int val = INT_MAX; + UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP); val += 2; } @@ -17,6 +24,7 @@ static void test_ubsan_sub_overflow(void) volatile int val = INT_MIN; volatile int val2 = 2; + UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP); val -= val2; } @@ -24,6 +32,7 @@ static void test_ubsan_mul_overflow(void) { volatile int val = INT_MAX / 2; + UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP); val *= 3; } @@ -31,6 +40,7 @@ static void test_ubsan_negate_overflow(void) { volatile int val = INT_MIN; + UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP); val = -val; } @@ -39,53 +49,80 @@ static void test_ubsan_divrem_overflow(void) volatile int val = 16; volatile int val2 = 0; + UBSAN_TEST(CONFIG_UBSAN_DIV_ZERO); val /= val2; } -static void test_ubsan_vla_bound_not_positive(void) +static void test_ubsan_truncate_signed(void) { - volatile int size = -1; - char buf[size]; + volatile long val = LONG_MAX; + volatile int val2 = 0; - (void)buf; + UBSAN_TEST(CONFIG_UBSAN_INTEGER_WRAP); + val2 = val; } static void test_ubsan_shift_out_of_bounds(void) { - volatile int val = -1; - int val2 = 10; + volatile int neg = -1, wrap = 4; + volatile int val1 = 10; + volatile int val2 = INT_MAX; - val2 <<= val; + UBSAN_TEST(CONFIG_UBSAN_SHIFT, "negative exponent"); + val1 <<= neg; + + UBSAN_TEST(CONFIG_UBSAN_SHIFT, "left overflow"); + val2 <<= wrap; } static void test_ubsan_out_of_bounds(void) { - volatile int i = 4, j = 5; - volatile int arr[i]; - - arr[j] = i; + int i = 4, j = 4, k = -1; + volatile struct { + char above[4]; /* Protect surrounding memory. */ + int arr[4]; + char below[4]; /* Protect surrounding memory. */ + } data; + + OPTIMIZER_HIDE_VAR(i); + OPTIMIZER_HIDE_VAR(j); + OPTIMIZER_HIDE_VAR(k); + + UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "above"); + data.arr[j] = i; + + UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "below"); + data.arr[k] = i; } +enum ubsan_test_enum { + UBSAN_TEST_ZERO = 0, + UBSAN_TEST_ONE, + UBSAN_TEST_MAX, +}; + static void test_ubsan_load_invalid_value(void) { volatile char *dst, *src; bool val, val2, *ptr; - char c = 4; + enum ubsan_test_enum eval, eval2, *eptr; + unsigned char c = 0xff; + UBSAN_TEST(CONFIG_UBSAN_BOOL, "bool"); dst = (char *)&val; src = &c; *dst = *src; ptr = &val2; val2 = val; -} -static void test_ubsan_null_ptr_deref(void) -{ - volatile int *ptr = NULL; - int val; + UBSAN_TEST(CONFIG_UBSAN_ENUM, "enum"); + dst = (char *)&eval; + src = &c; + *dst = *src; - val = *ptr; + eptr = &eval2; + eval2 = eval; } static void test_ubsan_misaligned_access(void) @@ -93,33 +130,26 @@ static void test_ubsan_misaligned_access(void) volatile char arr[5] __aligned(4) = {1, 2, 3, 4, 5}; volatile int *ptr, val = 6; + UBSAN_TEST(CONFIG_UBSAN_ALIGNMENT); ptr = (int *)(arr + 1); *ptr = val; } -static void test_ubsan_object_size_mismatch(void) -{ - /* "((aligned(8)))" helps this not into be misaligned for ptr-access. */ - volatile int val __aligned(8) = 4; - volatile long long *ptr, val2; - - ptr = (long long *)&val; - val2 = *ptr; -} - static const test_ubsan_fp test_ubsan_array[] = { test_ubsan_add_overflow, test_ubsan_sub_overflow, test_ubsan_mul_overflow, test_ubsan_negate_overflow, - test_ubsan_divrem_overflow, - test_ubsan_vla_bound_not_positive, + test_ubsan_truncate_signed, test_ubsan_shift_out_of_bounds, test_ubsan_out_of_bounds, test_ubsan_load_invalid_value, - //test_ubsan_null_ptr_deref, /* exclude it because there is a crash */ test_ubsan_misaligned_access, - test_ubsan_object_size_mismatch, +}; + +/* Excluded because they Oops the module. */ +static __used const test_ubsan_fp skip_ubsan_array[] = { + test_ubsan_divrem_overflow, }; static int __init test_ubsan_init(void) @@ -129,7 +159,6 @@ static int __init test_ubsan_init(void) for (i = 0; i < ARRAY_SIZE(test_ubsan_array); i++) test_ubsan_array[i](); - (void)test_ubsan_null_ptr_deref; /* to avoid unsed-function warning */ return 0; } module_init(test_ubsan_init); @@ -141,4 +170,5 @@ static void __exit test_ubsan_exit(void) module_exit(test_ubsan_exit); MODULE_AUTHOR("Jinbum Park <jinb.park7@gmail.com>"); +MODULE_DESCRIPTION("UBSAN unit test"); MODULE_LICENSE("GPL v2"); |
