Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/init.h>
0003 #include <linux/kernel.h>
0004 #include <linux/module.h>
0005 
0006 typedef void(*test_ubsan_fp)(void);
0007 
0008 #define UBSAN_TEST(config, ...) do {                    \
0009         pr_info("%s " __VA_ARGS__ "%s(%s=%s)\n", __func__,  \
0010             sizeof(" " __VA_ARGS__) > 2 ? " " : "",     \
0011             #config, IS_ENABLED(config) ? "y" : "n");   \
0012     } while (0)
0013 
0014 static void test_ubsan_divrem_overflow(void)
0015 {
0016     volatile int val = 16;
0017     volatile int val2 = 0;
0018 
0019     UBSAN_TEST(CONFIG_UBSAN_DIV_ZERO);
0020     val /= val2;
0021 }
0022 
0023 static void test_ubsan_shift_out_of_bounds(void)
0024 {
0025     volatile int neg = -1, wrap = 4;
0026     int val1 = 10;
0027     int val2 = INT_MAX;
0028 
0029     UBSAN_TEST(CONFIG_UBSAN_SHIFT, "negative exponent");
0030     val1 <<= neg;
0031 
0032     UBSAN_TEST(CONFIG_UBSAN_SHIFT, "left overflow");
0033     val2 <<= wrap;
0034 }
0035 
0036 static void test_ubsan_out_of_bounds(void)
0037 {
0038     volatile int i = 4, j = 5, k = -1;
0039     volatile char above[4] = { }; /* Protect surrounding memory. */
0040     volatile int arr[4];
0041     volatile char below[4] = { }; /* Protect surrounding memory. */
0042 
0043     above[0] = below[0];
0044 
0045     UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "above");
0046     arr[j] = i;
0047 
0048     UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "below");
0049     arr[k] = i;
0050 }
0051 
0052 enum ubsan_test_enum {
0053     UBSAN_TEST_ZERO = 0,
0054     UBSAN_TEST_ONE,
0055     UBSAN_TEST_MAX,
0056 };
0057 
0058 static void test_ubsan_load_invalid_value(void)
0059 {
0060     volatile char *dst, *src;
0061     bool val, val2, *ptr;
0062     enum ubsan_test_enum eval, eval2, *eptr;
0063     unsigned char c = 0xff;
0064 
0065     UBSAN_TEST(CONFIG_UBSAN_BOOL, "bool");
0066     dst = (char *)&val;
0067     src = &c;
0068     *dst = *src;
0069 
0070     ptr = &val2;
0071     val2 = val;
0072 
0073     UBSAN_TEST(CONFIG_UBSAN_ENUM, "enum");
0074     dst = (char *)&eval;
0075     src = &c;
0076     *dst = *src;
0077 
0078     eptr = &eval2;
0079     eval2 = eval;
0080 }
0081 
0082 static void test_ubsan_misaligned_access(void)
0083 {
0084     volatile char arr[5] __aligned(4) = {1, 2, 3, 4, 5};
0085     volatile int *ptr, val = 6;
0086 
0087     UBSAN_TEST(CONFIG_UBSAN_ALIGNMENT);
0088     ptr = (int *)(arr + 1);
0089     *ptr = val;
0090 }
0091 
0092 static const test_ubsan_fp test_ubsan_array[] = {
0093     test_ubsan_shift_out_of_bounds,
0094     test_ubsan_out_of_bounds,
0095     test_ubsan_load_invalid_value,
0096     test_ubsan_misaligned_access,
0097 };
0098 
0099 /* Excluded because they Oops the module. */
0100 static const test_ubsan_fp skip_ubsan_array[] = {
0101     test_ubsan_divrem_overflow,
0102 };
0103 
0104 static int __init test_ubsan_init(void)
0105 {
0106     unsigned int i;
0107 
0108     for (i = 0; i < ARRAY_SIZE(test_ubsan_array); i++)
0109         test_ubsan_array[i]();
0110 
0111     return 0;
0112 }
0113 module_init(test_ubsan_init);
0114 
0115 static void __exit test_ubsan_exit(void)
0116 {
0117     /* do nothing */
0118 }
0119 module_exit(test_ubsan_exit);
0120 
0121 MODULE_AUTHOR("Jinbum Park <jinb.park7@gmail.com>");
0122 MODULE_LICENSE("GPL v2");