From be4bfe018e1dd0dc54d7ba9f9e48b04208301f97 Mon Sep 17 00:00:00 2001 From: Martin Cermak Date: Tue, 23 Sep 2014 09:03:02 +0200 Subject: [PATCH] PR16716 partial fix: Fix types and compat support in timer syscalls family * tapset/linux/syscalls2.stp: syscall.timer_{delete,getoverrun,gettime,settime}: Fix types syscall.timer_gettime: Add compat support * tapset/linux/nd_syscalls2.stp (timer_gettime): Add compat support * tapset/linux/aux_syscalls.stp: Print the pointer value when _stp_copy_from_user() fails instead of reporting "UNKNOWN" * testsuite/systemtap.syscall/test.tcl: Link with -lrt to allow using glibc wrappers for timer syscalls family * testsuite/systemtap.syscall/timer.c: Add more tests --- tapset/linux/aux_syscalls.stp | 6 +- tapset/linux/nd_syscalls2.stp | 25 ++++++- tapset/linux/syscalls2.stp | 48 +++++++++---- testsuite/systemtap.syscall/test.tcl | 3 +- testsuite/systemtap.syscall/timer.c | 101 +++++++++++++++++++++++---- 5 files changed, 150 insertions(+), 33 deletions(-) diff --git a/tapset/linux/aux_syscalls.stp b/tapset/linux/aux_syscalls.stp index c489afe9d..792fd86b6 100644 --- a/tapset/linux/aux_syscalls.stp +++ b/tapset/linux/aux_syscalls.stp @@ -362,7 +362,8 @@ function _struct_itimerspec_u:string(uaddr:long) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if(_stp_copy_from_user((char *)&its, ptr,sizeof(struct itimerspec))) - strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); + snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", + (unsigned long)ptr); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d.%06d,%d.%06d]", (int)its.it_interval.tv_sec, (int)its.it_interval.tv_nsec, @@ -379,7 +380,8 @@ function _struct_compat_itimerspec_u:string(uaddr:long) strlcpy (STAP_RETVALUE, "NULL", MAXSTRINGLEN); else { if (_stp_copy_from_user((char *)&its, ptr, sizeof(its))) - strlcpy (STAP_RETVALUE, "UNKNOWN", MAXSTRINGLEN); + snprintf(STAP_RETVALUE, MAXSTRINGLEN, "0x%lx", + (unsigned long)ptr); else snprintf(STAP_RETVALUE, MAXSTRINGLEN, "[%d.%06d,%d.%06d]", diff --git a/tapset/linux/nd_syscalls2.stp b/tapset/linux/nd_syscalls2.stp index cbaa5cfab..59a8ff024 100644 --- a/tapset/linux/nd_syscalls2.stp +++ b/tapset/linux/nd_syscalls2.stp @@ -3816,20 +3816,41 @@ probe nd_syscall.timer_getoverrun.return = kprobe.function("sys_timer_getoverrun # # long sys_timer_gettime(timer_t timer_id, # struct itimerspec __user *setting) +# long compat_sys_timer_gettime(timer_t timer_id, +# struct itimerspec __user *setting) # -probe nd_syscall.timer_gettime = kprobe.function("sys_timer_gettime") ? +probe nd_syscall.timer_gettime = __nd_syscall.timer_gettime, + __nd_syscall.compat_timer_gettime ? { name = "timer_gettime" +} + +probe __nd_syscall.timer_gettime = kprobe.function("sys_timer_gettime") +{ + @__syscall_gate(%{ __NR_timer_gettime %}) + asmlinkage() + timerid = int_arg(1) + value_uaddr = pointer_arg(2) + argstr = sprintf("%d, %p", timerid, value_uaddr) +} +probe __nd_syscall.compat_timer_gettime = kprobe.function("compat_sys_timer_gettime") ? +{ asmlinkage() timerid = int_arg(1) value_uaddr = pointer_arg(2) argstr = sprintf("%d, %p", timerid, value_uaddr) } -probe nd_syscall.timer_gettime.return = kprobe.function("sys_timer_gettime").return ? +probe nd_syscall.timer_gettime.return = + __nd_syscall.timer_gettime.return, + kprobe.function("compat_sys_timer_gettime").return ? { name = "timer_gettime" retstr = returnstr(1) } +probe __nd_syscall.timer_gettime.return = kprobe.function("sys_timer_gettime").return +{ + @__syscall_gate(%{ __NR_timer_gettime %}) +} # timer_settime ______________________________________________ # diff --git a/tapset/linux/syscalls2.stp b/tapset/linux/syscalls2.stp index 80f0e3c5e..c21562586 100644 --- a/tapset/linux/syscalls2.stp +++ b/tapset/linux/syscalls2.stp @@ -3641,8 +3641,8 @@ probe __syscall.timer_create.return = kernel.function("sys_timer_create").return probe syscall.timer_delete = kernel.function("sys_timer_delete").call { name = "timer_delete" - timerid = $timer_id - argstr = sprint($timer_id) + timerid = __int32($timer_id) + argstr = sprint(__int32($timer_id)) } probe syscall.timer_delete.return = kernel.function("sys_timer_delete").return { @@ -3657,8 +3657,8 @@ probe syscall.timer_delete.return = kernel.function("sys_timer_delete").return probe syscall.timer_getoverrun = kernel.function("sys_timer_getoverrun").call { name = "timer_getoverrun" - timerid = $timer_id - argstr = sprint($timer_id) + timerid = __int32($timer_id) + argstr = sprint(__int32($timer_id)) } probe syscall.timer_getoverrun.return = kernel.function("sys_timer_getoverrun").return { @@ -3670,19 +3670,39 @@ probe syscall.timer_getoverrun.return = kernel.function("sys_timer_getoverrun"). # # long sys_timer_gettime(timer_t timer_id, # struct itimerspec __user *setting) +# long compat_sys_timer_gettime(timer_t timer_id, +# struct itimerspec __user *setting) # -probe syscall.timer_gettime = kernel.function("sys_timer_gettime").call +probe syscall.timer_gettime = __syscall.timer_gettime, + __syscall.compat_timer_gettime ? { name = "timer_gettime" - timerid = $timer_id +} +probe __syscall.timer_gettime = kernel.function("sys_timer_gettime").call +{ + @__syscall_gate(%{ __NR_timer_gettime %}) + timerid = __int32($timer_id) + value_uaddr = $setting + argstr = sprintf("%d, %p", __int32($timer_id), $setting) +} +probe __syscall.compat_timer_gettime = + kernel.function("compat_sys_timer_gettime").call ? +{ + timerid = __int32($timer_id) value_uaddr = $setting - argstr = sprintf("%d, %p", $timer_id, $setting) + argstr = sprintf("%d, %p", __int32($timer_id), $setting) } -probe syscall.timer_gettime.return = kernel.function("sys_timer_gettime").return +probe syscall.timer_gettime.return = + __syscall.timer_gettime.return, + kernel.function("compat_sys_timer_gettime").return ? { name = "timer_gettime" retstr = return_str(1, $return) } +probe __syscall.timer_gettime.return = kernel.function("sys_timer_gettime").return +{ + @__syscall_gate(%{ __NR_timer_gettime %}) +} # timer_settime ______________________________________________ # @@ -3702,21 +3722,21 @@ probe syscall.timer_settime = __syscall.timer_settime, probe __syscall.timer_settime = kernel.function("sys_timer_settime").call { @__syscall_gate(%{ __NR_timer_settime %}) - timerid = $timer_id - flags = $flags + timerid = __int32($timer_id) + flags = __int32($flags) value_uaddr = $new_setting ovalue_uaddr = $old_setting - argstr = sprintf("%d, %d, %s, %p", $timer_id, $flags, + argstr = sprintf("%d, %d, %s, %p", __int32($timer_id), __int32($flags), _struct_itimerspec_u($new_setting), $old_setting) } probe __syscall.compat_timer_settime = kernel.function("compat_sys_timer_settime").call ? { - timerid = $timer_id - flags = $flags + timerid = __int32($timer_id) + flags = __int32($flags) value_uaddr = $new ovalue_uaddr = $old - argstr = sprintf("%d, %d, %s, %p", $timer_id, $flags, + argstr = sprintf("%d, %d, %s, %p", __int32($timer_id), __int32($flags), _struct_compat_itimerspec_u($new), $old) } probe syscall.timer_settime.return = diff --git a/testsuite/systemtap.syscall/test.tcl b/testsuite/systemtap.syscall/test.tcl index ff376911c..f048d8d86 100644 --- a/testsuite/systemtap.syscall/test.tcl +++ b/testsuite/systemtap.syscall/test.tcl @@ -41,7 +41,8 @@ proc run_one_test {filename flags bits suite} { return } - set res [target_compile $filename $syscall_dir/$testname executable $flags] + set flags "$flags additional_flags=-lrt" + set res [target_compile $filename $syscall_dir/$testname executable $flags ] if { $res != "" } { send_log "$bits-bit $testname $suite : no corresponding devel environment found\n" untested "$bits-bit $testname $suite" diff --git a/testsuite/systemtap.syscall/timer.c b/testsuite/systemtap.syscall/timer.c index 9a55b2e81..13bc407c1 100644 --- a/testsuite/systemtap.syscall/timer.c +++ b/testsuite/systemtap.syscall/timer.c @@ -9,24 +9,97 @@ int main() { - timer_t tid=0; - struct itimerspec val, oval; + timer_t tid=0; + struct itimerspec val, oval; - syscall(SYS_timer_create, CLOCK_REALTIME, NULL, &tid); - //staptest// timer_create (CLOCK_REALTIME, 0x[0]+, XXXX) - syscall(SYS_timer_gettime, tid, &val); - //staptest// timer_gettime (NNNN, XXXX) + // SYSCALL timer_create ----- - syscall(SYS_timer_settime, 0, tid, &val, &oval); - //staptest// timer_settime (0, NNNN, \[0.000000,0.000000\], XXXX) + syscall(__NR_timer_create, -1, NULL, &tid); + //staptest// timer_create (0x[f]+, 0x0, XXXX) = NNNN (EINVAL) - syscall(SYS_timer_getoverrun, tid); - //staptest// timer_getoverrun (NNNN) + syscall(__NR_timer_create, CLOCK_REALTIME, -1, &tid); +#ifdef __s390__ + //staptest// timer_create (CLOCK_REALTIME, 0x[7]?[f]+, XXXX) = NNNN (EFAULT) +#else + //staptest// timer_create (CLOCK_REALTIME, 0x[f]+, XXXX) = NNNN (EFAULT) +#endif - syscall(SYS_timer_delete, tid); - //staptest// timer_delete (NNNN) + syscall(__NR_timer_create, CLOCK_REALTIME, NULL, -1); +#ifdef __s390__ + //staptest// timer_create (CLOCK_REALTIME, 0x0, 0x[7]?[f]+) = NNNN (EFAULT) +#else + //staptest// timer_create (CLOCK_REALTIME, 0x0, 0x[f]+) = NNNN (EFAULT) +#endif - return 0; + timer_create(CLOCK_REALTIME, NULL, &tid); + //staptest// timer_create (CLOCK_REALTIME, XXXX, XXXX) = 0 + + + // SYSCALL timer_gettime ----- + + syscall(__NR_timer_gettime, -1, &val); + //staptest// timer_gettime (-1, XXXX) = NNNN (EINVAL) + + syscall(__NR_timer_gettime, tid, -1); +#ifdef __s390__ + //staptest// timer_gettime (NNNN, 0x[7]?[f]+) = NNNN (EINVAL) +#else + //staptest// timer_gettime (NNNN, 0x[f]+) = NNNN (EINVAL) +#endif + + timer_gettime(tid, &val); + //staptest// timer_gettime (NNNN, XXXX) = 0 + + + // SYSCALL timer_settime ----- + + val.it_value.tv_sec = 0; + val.it_value.tv_nsec = 0; + val.it_interval.tv_sec = 0; + val.it_interval.tv_nsec = 0; + + syscall(__NR_timer_settime, -1, 0, &val, &oval); + //staptest// timer_settime (-1, 0, \[0.000000,0.000000\], XXXX) = NNNN (EINVAL) + + syscall(__NR_timer_settime, 0, -1, &val, &oval); + //staptest// timer_settime (0, -1, \[0.000000,0.000000\], XXXX) = NNNN + + syscall(__NR_timer_settime, tid, 0, -1, &oval); +#ifdef __s390__ + //staptest// timer_settime (NNNN, 0, 0x[7]?[f]+, XXXX) = NNNN (EFAULT) +#else + //staptest// timer_settime (NNNN, 0, 0x[f]+, XXXX) = NNNN (EFAULT) +#endif + + syscall(__NR_timer_settime, tid, 0, &val, -1); +#ifdef __s390__ + //staptest// timer_settime (NNNN, 0, \[0.000000,0.000000\], 0x[7]?[f]+) = NNNN (EINVAL) +#else + //staptest// timer_settime (NNNN, 0, \[0.000000,0.000000\], 0x[f]+) = NNNN (EINVAL) +#endif + + timer_settime(tid, -1, &val, &oval); + //staptest// timer_settime (NNNN, -1, \[0.000000,0.000000\], XXXX) = 0 + + + // SYSCALL timer_getoverrun ----- + + syscall(__NR_timer_getoverrun, -1); + //staptest// timer_getoverrun (-1) = NNNN (EINVAL) + + timer_getoverrun(tid); + //staptest// timer_getoverrun (NNNN) = 0 + + + // SYSCALL timer_delete ----- + + syscall(__NR_timer_delete, -1); + //staptest// timer_delete (-1) = NNNN (EINVAL) + + timer_delete(tid); + //staptest// timer_delete (NNNN) = 0 + + return 0; } - + -- 2.43.5