2018-04-11 02:32:58 +03:00
// SPDX-License-Identifier: GPL-2.0
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/module.h>
typedef void ( * test_ubsan_fp ) ( void ) ;
2020-12-16 07:46:43 +03:00
# 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 )
2018-04-11 02:32:58 +03:00
static void test_ubsan_divrem_overflow ( void )
{
volatile int val = 16 ;
volatile int val2 = 0 ;
2020-12-16 07:46:43 +03:00
UBSAN_TEST ( CONFIG_UBSAN_DIV_ZERO ) ;
2018-04-11 02:32:58 +03:00
val / = val2 ;
}
static void test_ubsan_shift_out_of_bounds ( void )
{
2020-12-16 07:46:43 +03:00
volatile int neg = - 1 , wrap = 4 ;
int val1 = 10 ;
int val2 = INT_MAX ;
UBSAN_TEST ( CONFIG_UBSAN_SHIFT , " negative exponent " ) ;
val1 < < = neg ;
2018-04-11 02:32:58 +03:00
2020-12-16 07:46:43 +03:00
UBSAN_TEST ( CONFIG_UBSAN_SHIFT , " left overflow " ) ;
val2 < < = wrap ;
2018-04-11 02:32:58 +03:00
}
static void test_ubsan_out_of_bounds ( void )
{
2020-12-16 07:46:43 +03:00
volatile int i = 4 , j = 5 , k = - 1 ;
volatile char above [ 4 ] = { } ; /* Protect surrounding memory. */
2019-03-08 03:28:21 +03:00
volatile int arr [ 4 ] ;
2020-12-16 07:46:43 +03:00
volatile char below [ 4 ] = { } ; /* Protect surrounding memory. */
2018-04-11 02:32:58 +03:00
2020-12-16 07:46:43 +03:00
above [ 0 ] = below [ 0 ] ;
UBSAN_TEST ( CONFIG_UBSAN_BOUNDS , " above " ) ;
2018-04-11 02:32:58 +03:00
arr [ j ] = i ;
2020-12-16 07:46:43 +03:00
UBSAN_TEST ( CONFIG_UBSAN_BOUNDS , " below " ) ;
arr [ k ] = i ;
2018-04-11 02:32:58 +03:00
}
2020-12-16 07:46:43 +03:00
enum ubsan_test_enum {
UBSAN_TEST_ZERO = 0 ,
UBSAN_TEST_ONE ,
UBSAN_TEST_MAX ,
} ;
2018-04-11 02:32:58 +03:00
static void test_ubsan_load_invalid_value ( void )
{
volatile char * dst , * src ;
bool val , val2 , * ptr ;
2020-12-16 07:46:43 +03:00
enum ubsan_test_enum eval , eval2 , * eptr ;
unsigned char c = 0xff ;
2018-04-11 02:32:58 +03:00
2020-12-16 07:46:43 +03:00
UBSAN_TEST ( CONFIG_UBSAN_BOOL , " bool " ) ;
2018-04-11 02:32:58 +03:00
dst = ( char * ) & val ;
src = & c ;
* dst = * src ;
ptr = & val2 ;
val2 = val ;
2020-12-16 07:46:43 +03:00
UBSAN_TEST ( CONFIG_UBSAN_ENUM , " enum " ) ;
dst = ( char * ) & eval ;
src = & c ;
* dst = * src ;
eptr = & eval2 ;
eval2 = eval ;
2018-04-11 02:32:58 +03:00
}
2018-04-11 02:33:02 +03:00
static void test_ubsan_misaligned_access ( void )
2018-04-11 02:32:58 +03:00
{
volatile char arr [ 5 ] __aligned ( 4 ) = { 1 , 2 , 3 , 4 , 5 } ;
volatile int * ptr , val = 6 ;
2020-12-16 07:46:43 +03:00
UBSAN_TEST ( CONFIG_UBSAN_ALIGNMENT ) ;
2018-04-11 02:32:58 +03:00
ptr = ( int * ) ( arr + 1 ) ;
* ptr = val ;
}
static const test_ubsan_fp test_ubsan_array [ ] = {
test_ubsan_shift_out_of_bounds ,
test_ubsan_out_of_bounds ,
test_ubsan_load_invalid_value ,
test_ubsan_misaligned_access ,
} ;
2020-12-16 07:46:43 +03:00
/* Excluded because they Oops the module. */
static const test_ubsan_fp skip_ubsan_array [ ] = {
test_ubsan_divrem_overflow ,
} ;
2018-04-11 02:32:58 +03:00
static int __init test_ubsan_init ( void )
{
unsigned int i ;
for ( i = 0 ; i < ARRAY_SIZE ( test_ubsan_array ) ; i + + )
test_ubsan_array [ i ] ( ) ;
return 0 ;
}
module_init ( test_ubsan_init ) ;
static void __exit test_ubsan_exit ( void )
{
/* do nothing */
}
module_exit ( test_ubsan_exit ) ;
MODULE_AUTHOR ( " Jinbum Park <jinb.park7@gmail.com> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;