2019-05-19 16:51:55 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2008-01-30 15:32:53 +03:00
/*
* test_kprobes . c - simple sanity test for * probes
*
* Copyright IBM Corp . 2008
*/
2014-08-09 01:19:48 +04:00
# define pr_fmt(fmt) "Kprobe smoke test: " fmt
2008-01-30 15:32:53 +03:00
# include <linux/kernel.h>
# include <linux/kprobes.h>
# include <linux/random.h>
# define div_factor 3
2017-10-06 02:15:17 +03:00
static u32 rand1 , preh_val , posth_val ;
2008-01-30 15:32:53 +03:00
static int errors , handler_errors , num_tests ;
2009-01-07 01:41:47 +03:00
static u32 ( * target ) ( u32 value ) ;
2009-01-07 01:41:48 +03:00
static u32 ( * target2 ) ( u32 value ) ;
2008-01-30 15:32:53 +03:00
static noinline u32 kprobe_target ( u32 value )
{
return ( value / div_factor ) ;
}
static int kp_pre_handler ( struct kprobe * p , struct pt_regs * regs )
{
2017-09-19 12:59:00 +03:00
if ( preemptible ( ) ) {
handler_errors + + ;
pr_err ( " pre-handler is preemptible \n " ) ;
}
2008-01-30 15:32:53 +03:00
preh_val = ( rand1 / div_factor ) ;
return 0 ;
}
static void kp_post_handler ( struct kprobe * p , struct pt_regs * regs ,
unsigned long flags )
{
2017-09-19 12:59:00 +03:00
if ( preemptible ( ) ) {
handler_errors + + ;
pr_err ( " post-handler is preemptible \n " ) ;
}
2008-01-30 15:32:53 +03:00
if ( preh_val ! = ( rand1 / div_factor ) ) {
handler_errors + + ;
2014-08-09 01:19:48 +04:00
pr_err ( " incorrect value in post_handler \n " ) ;
2008-01-30 15:32:53 +03:00
}
posth_val = preh_val + div_factor ;
}
static struct kprobe kp = {
. symbol_name = " kprobe_target " ,
. pre_handler = kp_pre_handler ,
. post_handler = kp_post_handler
} ;
static int test_kprobe ( void )
{
int ret ;
ret = register_kprobe ( & kp ) ;
if ( ret < 0 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " register_kprobe returned %d \n " , ret ) ;
2008-01-30 15:32:53 +03:00
return ret ;
}
2009-01-07 01:41:47 +03:00
ret = target ( rand1 ) ;
2008-01-30 15:32:53 +03:00
unregister_kprobe ( & kp ) ;
if ( preh_val = = 0 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " kprobe pre_handler not called \n " ) ;
2008-01-30 15:32:53 +03:00
handler_errors + + ;
}
if ( posth_val = = 0 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " kprobe post_handler not called \n " ) ;
2008-01-30 15:32:53 +03:00
handler_errors + + ;
}
return 0 ;
}
2009-01-07 01:41:48 +03:00
static noinline u32 kprobe_target2 ( u32 value )
{
return ( value / div_factor ) + 1 ;
}
static int kp_pre_handler2 ( struct kprobe * p , struct pt_regs * regs )
{
preh_val = ( rand1 / div_factor ) + 1 ;
return 0 ;
}
static void kp_post_handler2 ( struct kprobe * p , struct pt_regs * regs ,
unsigned long flags )
{
if ( preh_val ! = ( rand1 / div_factor ) + 1 ) {
handler_errors + + ;
2014-08-09 01:19:48 +04:00
pr_err ( " incorrect value in post_handler2 \n " ) ;
2009-01-07 01:41:48 +03:00
}
posth_val = preh_val + div_factor ;
}
static struct kprobe kp2 = {
. symbol_name = " kprobe_target2 " ,
. pre_handler = kp_pre_handler2 ,
. post_handler = kp_post_handler2
} ;
static int test_kprobes ( void )
{
int ret ;
struct kprobe * kps [ 2 ] = { & kp , & kp2 } ;
2010-10-14 07:10:24 +04:00
/* addr and flags should be cleard for reusing kprobe. */
kp . addr = NULL ;
kp . flags = 0 ;
2009-01-07 01:41:48 +03:00
ret = register_kprobes ( kps , 2 ) ;
if ( ret < 0 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " register_kprobes returned %d \n " , ret ) ;
2009-01-07 01:41:48 +03:00
return ret ;
}
preh_val = 0 ;
posth_val = 0 ;
ret = target ( rand1 ) ;
if ( preh_val = = 0 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " kprobe pre_handler not called \n " ) ;
2009-01-07 01:41:48 +03:00
handler_errors + + ;
}
if ( posth_val = = 0 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " kprobe post_handler not called \n " ) ;
2009-01-07 01:41:48 +03:00
handler_errors + + ;
}
preh_val = 0 ;
posth_val = 0 ;
ret = target2 ( rand1 ) ;
if ( preh_val = = 0 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " kprobe pre_handler2 not called \n " ) ;
2009-01-07 01:41:48 +03:00
handler_errors + + ;
}
if ( posth_val = = 0 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " kprobe post_handler2 not called \n " ) ;
2009-01-07 01:41:48 +03:00
handler_errors + + ;
}
unregister_kprobes ( kps , 2 ) ;
return 0 ;
}
2008-01-30 15:32:53 +03:00
# ifdef CONFIG_KRETPROBES
static u32 krph_val ;
2008-02-06 12:38:22 +03:00
static int entry_handler ( struct kretprobe_instance * ri , struct pt_regs * regs )
{
2017-09-19 12:59:00 +03:00
if ( preemptible ( ) ) {
handler_errors + + ;
pr_err ( " kretprobe entry handler is preemptible \n " ) ;
}
2008-02-06 12:38:22 +03:00
krph_val = ( rand1 / div_factor ) ;
return 0 ;
}
2008-01-30 15:32:53 +03:00
static int return_handler ( struct kretprobe_instance * ri , struct pt_regs * regs )
{
unsigned long ret = regs_return_value ( regs ) ;
2017-09-19 12:59:00 +03:00
if ( preemptible ( ) ) {
handler_errors + + ;
pr_err ( " kretprobe return handler is preemptible \n " ) ;
}
2008-01-30 15:32:53 +03:00
if ( ret ! = ( rand1 / div_factor ) ) {
handler_errors + + ;
2014-08-09 01:19:48 +04:00
pr_err ( " incorrect value in kretprobe handler \n " ) ;
2008-01-30 15:32:53 +03:00
}
2008-02-06 12:38:22 +03:00
if ( krph_val = = 0 ) {
handler_errors + + ;
2014-08-09 01:19:48 +04:00
pr_err ( " call to kretprobe entry handler failed \n " ) ;
2008-02-06 12:38:22 +03:00
}
2008-01-30 15:32:53 +03:00
2008-02-06 12:38:22 +03:00
krph_val = rand1 ;
2008-01-30 15:32:53 +03:00
return 0 ;
}
static struct kretprobe rp = {
. handler = return_handler ,
2008-02-06 12:38:22 +03:00
. entry_handler = entry_handler ,
2008-01-30 15:32:53 +03:00
. kp . symbol_name = " kprobe_target "
} ;
static int test_kretprobe ( void )
{
int ret ;
ret = register_kretprobe ( & rp ) ;
if ( ret < 0 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " register_kretprobe returned %d \n " , ret ) ;
2008-01-30 15:32:53 +03:00
return ret ;
}
2009-01-07 01:41:47 +03:00
ret = target ( rand1 ) ;
2008-01-30 15:32:53 +03:00
unregister_kretprobe ( & rp ) ;
2008-02-06 12:38:22 +03:00
if ( krph_val ! = rand1 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " kretprobe handler not called \n " ) ;
2008-01-30 15:32:53 +03:00
handler_errors + + ;
}
return 0 ;
}
2009-01-07 01:41:48 +03:00
static int return_handler2 ( struct kretprobe_instance * ri , struct pt_regs * regs )
{
unsigned long ret = regs_return_value ( regs ) ;
if ( ret ! = ( rand1 / div_factor ) + 1 ) {
handler_errors + + ;
2014-08-09 01:19:48 +04:00
pr_err ( " incorrect value in kretprobe handler2 \n " ) ;
2009-01-07 01:41:48 +03:00
}
if ( krph_val = = 0 ) {
handler_errors + + ;
2014-08-09 01:19:48 +04:00
pr_err ( " call to kretprobe entry handler failed \n " ) ;
2009-01-07 01:41:48 +03:00
}
krph_val = rand1 ;
return 0 ;
}
static struct kretprobe rp2 = {
. handler = return_handler2 ,
. entry_handler = entry_handler ,
. kp . symbol_name = " kprobe_target2 "
} ;
static int test_kretprobes ( void )
{
int ret ;
struct kretprobe * rps [ 2 ] = { & rp , & rp2 } ;
2010-10-14 07:10:24 +04:00
/* addr and flags should be cleard for reusing kprobe. */
rp . kp . addr = NULL ;
rp . kp . flags = 0 ;
2009-01-07 01:41:48 +03:00
ret = register_kretprobes ( rps , 2 ) ;
if ( ret < 0 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " register_kretprobe returned %d \n " , ret ) ;
2009-01-07 01:41:48 +03:00
return ret ;
}
krph_val = 0 ;
ret = target ( rand1 ) ;
if ( krph_val ! = rand1 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " kretprobe handler not called \n " ) ;
2009-01-07 01:41:48 +03:00
handler_errors + + ;
}
krph_val = 0 ;
ret = target2 ( rand1 ) ;
if ( krph_val ! = rand1 ) {
2014-08-09 01:19:48 +04:00
pr_err ( " kretprobe handler2 not called \n " ) ;
2009-01-07 01:41:48 +03:00
handler_errors + + ;
}
unregister_kretprobes ( rps , 2 ) ;
return 0 ;
}
2008-01-30 15:32:53 +03:00
# endif /* CONFIG_KRETPROBES */
int init_test_probes ( void )
{
int ret ;
2009-01-07 01:41:47 +03:00
target = kprobe_target ;
2009-01-07 01:41:48 +03:00
target2 = kprobe_target2 ;
2009-01-07 01:41:47 +03:00
2008-01-30 15:32:53 +03:00
do {
2013-04-30 03:21:30 +04:00
rand1 = prandom_u32 ( ) ;
2008-01-30 15:32:53 +03:00
} while ( rand1 < = div_factor ) ;
2014-08-09 01:19:48 +04:00
pr_info ( " started \n " ) ;
2008-01-30 15:32:53 +03:00
num_tests + + ;
ret = test_kprobe ( ) ;
if ( ret < 0 )
errors + + ;
2009-01-07 01:41:48 +03:00
num_tests + + ;
ret = test_kprobes ( ) ;
if ( ret < 0 )
errors + + ;
2008-01-30 15:32:53 +03:00
# ifdef CONFIG_KRETPROBES
num_tests + + ;
ret = test_kretprobe ( ) ;
if ( ret < 0 )
errors + + ;
2009-01-07 01:41:48 +03:00
num_tests + + ;
ret = test_kretprobes ( ) ;
if ( ret < 0 )
errors + + ;
2008-01-30 15:32:53 +03:00
# endif /* CONFIG_KRETPROBES */
if ( errors )
2014-08-09 01:19:48 +04:00
pr_err ( " BUG: %d out of %d tests failed \n " , errors , num_tests ) ;
2008-01-30 15:32:53 +03:00
else if ( handler_errors )
2014-08-09 01:19:48 +04:00
pr_err ( " BUG: %d error(s) running handlers \n " , handler_errors ) ;
2008-01-30 15:32:53 +03:00
else
2014-08-09 01:19:48 +04:00
pr_info ( " passed successfully \n " ) ;
2008-01-30 15:32:53 +03:00
return 0 ;
}