2021-06-29 05:34:33 +03:00
// SPDX-License-Identifier: GPL-2.0
# include <kunit/test.h>
# include <linux/mm.h>
# include <linux/slab.h>
# include <linux/module.h>
# include <linux/kernel.h>
# include "../mm/slab.h"
static struct kunit_resource resource ;
static int slab_errors ;
static void test_clobber_zone ( struct kunit * test )
{
struct kmem_cache * s = kmem_cache_create ( " TestSlub_RZ_alloc " , 64 , 0 ,
2022-04-06 09:00:03 +03:00
SLAB_RED_ZONE | SLAB_NO_USER_FLAGS , NULL ) ;
2021-06-29 05:34:33 +03:00
u8 * p = kmem_cache_alloc ( s , GFP_KERNEL ) ;
kasan_disable_current ( ) ;
p [ 64 ] = 0x12 ;
validate_slab_cache ( s ) ;
KUNIT_EXPECT_EQ ( test , 2 , slab_errors ) ;
kasan_enable_current ( ) ;
kmem_cache_free ( s , p ) ;
kmem_cache_destroy ( s ) ;
}
# ifndef CONFIG_KASAN
static void test_next_pointer ( struct kunit * test )
{
struct kmem_cache * s = kmem_cache_create ( " TestSlub_next_ptr_free " , 64 , 0 ,
2022-04-06 09:00:03 +03:00
SLAB_POISON | SLAB_NO_USER_FLAGS , NULL ) ;
2021-06-29 05:34:33 +03:00
u8 * p = kmem_cache_alloc ( s , GFP_KERNEL ) ;
unsigned long tmp ;
unsigned long * ptr_addr ;
kmem_cache_free ( s , p ) ;
ptr_addr = ( unsigned long * ) ( p + s - > offset ) ;
tmp = * ptr_addr ;
p [ s - > offset ] = 0x12 ;
/*
* Expecting three errors .
* One for the corrupted freechain and the other one for the wrong
* count of objects in use . The third error is fixing broken cache .
*/
validate_slab_cache ( s ) ;
KUNIT_EXPECT_EQ ( test , 3 , slab_errors ) ;
/*
* Try to repair corrupted freepointer .
* Still expecting two errors . The first for the wrong count
* of objects in use .
* The second error is for fixing broken cache .
*/
* ptr_addr = tmp ;
slab_errors = 0 ;
validate_slab_cache ( s ) ;
KUNIT_EXPECT_EQ ( test , 2 , slab_errors ) ;
/*
* Previous validation repaired the count of objects in use .
* Now expecting no error .
*/
slab_errors = 0 ;
validate_slab_cache ( s ) ;
KUNIT_EXPECT_EQ ( test , 0 , slab_errors ) ;
kmem_cache_destroy ( s ) ;
}
static void test_first_word ( struct kunit * test )
{
struct kmem_cache * s = kmem_cache_create ( " TestSlub_1th_word_free " , 64 , 0 ,
2022-04-06 09:00:03 +03:00
SLAB_POISON | SLAB_NO_USER_FLAGS , NULL ) ;
2021-06-29 05:34:33 +03:00
u8 * p = kmem_cache_alloc ( s , GFP_KERNEL ) ;
kmem_cache_free ( s , p ) ;
* p = 0x78 ;
validate_slab_cache ( s ) ;
KUNIT_EXPECT_EQ ( test , 2 , slab_errors ) ;
kmem_cache_destroy ( s ) ;
}
static void test_clobber_50th_byte ( struct kunit * test )
{
struct kmem_cache * s = kmem_cache_create ( " TestSlub_50th_word_free " , 64 , 0 ,
2022-04-06 09:00:03 +03:00
SLAB_POISON | SLAB_NO_USER_FLAGS , NULL ) ;
2021-06-29 05:34:33 +03:00
u8 * p = kmem_cache_alloc ( s , GFP_KERNEL ) ;
kmem_cache_free ( s , p ) ;
p [ 50 ] = 0x9a ;
validate_slab_cache ( s ) ;
KUNIT_EXPECT_EQ ( test , 2 , slab_errors ) ;
kmem_cache_destroy ( s ) ;
}
# endif
static void test_clobber_redzone_free ( struct kunit * test )
{
struct kmem_cache * s = kmem_cache_create ( " TestSlub_RZ_free " , 64 , 0 ,
2022-04-06 09:00:03 +03:00
SLAB_RED_ZONE | SLAB_NO_USER_FLAGS , NULL ) ;
2021-06-29 05:34:33 +03:00
u8 * p = kmem_cache_alloc ( s , GFP_KERNEL ) ;
kasan_disable_current ( ) ;
kmem_cache_free ( s , p ) ;
p [ 64 ] = 0xab ;
validate_slab_cache ( s ) ;
KUNIT_EXPECT_EQ ( test , 2 , slab_errors ) ;
kasan_enable_current ( ) ;
kmem_cache_destroy ( s ) ;
}
static int test_init ( struct kunit * test )
{
slab_errors = 0 ;
kunit_add_named_resource ( test , NULL , NULL , & resource ,
" slab_errors " , & slab_errors ) ;
return 0 ;
}
static struct kunit_case test_cases [ ] = {
KUNIT_CASE ( test_clobber_zone ) ,
# ifndef CONFIG_KASAN
KUNIT_CASE ( test_next_pointer ) ,
KUNIT_CASE ( test_first_word ) ,
KUNIT_CASE ( test_clobber_50th_byte ) ,
# endif
KUNIT_CASE ( test_clobber_redzone_free ) ,
{ }
} ;
static struct kunit_suite test_suite = {
. name = " slub_test " ,
. init = test_init ,
. test_cases = test_cases ,
} ;
kunit_test_suite ( test_suite ) ;
MODULE_LICENSE ( " GPL " ) ;