From 1354362089d2c745c00f6b10b5526055f14c4c81 Mon Sep 17 00:00:00 2001 From: David Smith Date: Fri, 28 Mar 2014 14:10:01 -0500 Subject: [PATCH] PR16716 partial fix: Fix 'syscall.{recv,recvfrom}' on 32-bit platforms. * tapset/uconversions.stp (user_ulong): New function. (user_ulong_warn): Ditto. * tapset/linux/syscalls2.stp: Change all calls to user_uint64() to user_ulong(), so that 32-bit platforms are handled correctly. * tapset/linux/nd_syscalls2.stp: Ditto. Also added asmlinkage() calls to 'nd_syscall.{recv,recvfrom}'. * testsuite/buildok/conversions-embedded.stp: Added build tests for user_ulong() and user_ulong_warn(). * testsuite/buildok/conversions.stp: Ditto. --- tapset/linux/nd_syscalls2.stp | 29 ++++++++------- tapset/linux/syscalls2.stp | 22 ++++++------ tapset/uconversions.stp | 42 ++++++++++++++++++++++ testsuite/buildok/conversions-embedded.stp | 2 ++ testsuite/buildok/conversions.stp | 2 ++ 5 files changed, 74 insertions(+), 23 deletions(-) diff --git a/tapset/linux/nd_syscalls2.stp b/tapset/linux/nd_syscalls2.stp index b3be45aca..e9889d019 100644 --- a/tapset/linux/nd_syscalls2.stp +++ b/tapset/linux/nd_syscalls2.stp @@ -921,25 +921,28 @@ probe nd_syscall.recv = __nd_syscall.socketcall.recv ?, } probe __nd_syscall.socketcall.recv = kprobe.function("sys_socketcall").call ? { + asmlinkage() if (int_arg(1) != %{ SYS_RECV %}) next; __args = pointer_arg(2) - s = user_int32(&@cast(__args, "ulong")[0]) - buf_uaddr = user_uint64(&@cast(__args, "ulong")[1]) - len = user_uint64(&@cast(__args, "ulong")[2]) + s = user_int(&@cast(__args, "ulong")[0]) + buf_uaddr = user_ulong(&@cast(__args, "ulong")[1]) + len = user_ulong(&@cast(__args, "ulong")[2]) flags = user_uint32(&@cast(__args, "ulong")[3]) } probe __nd_syscall.compat_socketcall.recv = kprobe.function("compat_sys_socketcall").call ? { + asmlinkage() if (int_arg(1) != %{ SYS_RECV %}) next; __args = pointer_arg(2) - s = user_int32(&@cast(__args, "unsigned int")[0]) + s = user_int(&@cast(__args, "unsigned int")[0]) buf_uaddr = user_uint32(&@cast(__args, "unsigned int")[1]) len = user_uint32(&@cast(__args, "unsigned int")[2]) flags = user_uint32(&@cast(__args, "unsigned int")[3]) } probe __nd_syscall.recv = kprobe.function("sys_recv").call ? { + asmlinkage() @__syscall_gate(%{ __NR_recv %}) s = int_arg(1) buf_uaddr = pointer_arg(2) @@ -956,7 +959,7 @@ probe __nd_syscall.socketcall.recv.return = kprobe.function("sys_socketcall").return ?, kprobe.function("compat_sys_socketcall").return ? { - if (@entry(int_arg(1)) != %{ SYS_RECV %}) next; + if (@entry(__asmlinkage_int_arg(1)) != %{ SYS_RECV %}) next; } probe __nd_syscall.recv.return = kprobe.function("sys_recv").return ? { @@ -988,21 +991,23 @@ probe nd_syscall.recvfrom = __nd_syscall.socketcall.recvfrom ?, probe __nd_syscall.socketcall.recvfrom = kprobe.function("sys_socketcall").call ? { + asmlinkage() if (int_arg(1) != %{ SYS_RECVFROM %}) next __args = pointer_arg(2) - s = user_int32(&@cast(__args, "ulong")[0]) - buf_uaddr = user_uint64(&@cast(__args, "ulong")[1]) - len = user_uint64(&@cast(__args, "ulong")[2]) + s = user_int(&@cast(__args, "ulong")[0]) + buf_uaddr = user_ulong(&@cast(__args, "ulong")[1]) + len = user_ulong(&@cast(__args, "ulong")[2]) flags = user_uint32(&@cast(__args, "ulong")[3]) - addr_uaddr = user_uint64(&@cast(__args, "ulong")[4]) - addrlen_uaddr = user_uint64(&@cast(__args, "ulong")[5]) + addr_uaddr = user_ulong(&@cast(__args, "ulong")[4]) + addrlen_uaddr = user_ulong(&@cast(__args, "ulong")[5]) } probe __nd_syscall.compat_socketcall.recvfrom = kprobe.function("compat_sys_socketcall").call ? { + asmlinkage() if (int_arg(1) != %{ SYS_RECVFROM %}) next __args = pointer_arg(2) - s = user_int32(&@cast(__args, "unsigned int")[0]) + s = user_int(&@cast(__args, "unsigned int")[0]) buf_uaddr = user_uint32(&@cast(__args, "unsigned int")[1]) len = user_uint32(&@cast(__args, "unsigned int")[2]) flags = user_uint32(&@cast(__args, "unsigned int")[3]) @@ -1145,7 +1150,7 @@ probe nd_syscall.compat_sys_recvmsg = if (int_arg(1) != %{ SYS_RECVMSG %}) next; name = "recvmsg" __args = pointer_arg(2) - s = user_int32(&@cast(__args, "unsigned int")[0]) + s = user_int(&@cast(__args, "unsigned int")[0]) msg_uaddr = user_uint32(&@cast(__args, "unsigned int")[1]) flags = user_uint32(&@cast(__args, "unsigned int")[2]) flags_str = _msg_flags_str(flags) diff --git a/tapset/linux/syscalls2.stp b/tapset/linux/syscalls2.stp index c37e4cb05..50b8358a4 100644 --- a/tapset/linux/syscalls2.stp +++ b/tapset/linux/syscalls2.stp @@ -973,16 +973,16 @@ probe syscall.recv = __syscall.socketcall.recv ?, probe __syscall.socketcall.recv = kernel.function("sys_socketcall").call ? { if ($call != %{ SYS_RECV %}) next; - s = user_int32(&@cast($args, "ulong")[0]) - buf_uaddr = user_uint64(&@cast($args, "ulong")[1]) - len = user_uint64(&@cast($args, "ulong")[2]) + s = user_int(&@cast($args, "ulong")[0]) + buf_uaddr = user_ulong(&@cast($args, "ulong")[1]) + len = user_ulong(&@cast($args, "ulong")[2]) flags = user_uint32(&@cast($args, "ulong")[3]) } probe __syscall.compat_socketcall.recv = kernel.function("compat_sys_socketcall").call ? { if ($call != %{ SYS_RECV %}) next; - s = user_int32(&@cast($args, "unsigned int")[0]) + s = user_int(&@cast($args, "unsigned int")[0]) buf_uaddr = user_uint32(&@cast($args, "unsigned int")[1]) len = user_uint32(&@cast($args, "unsigned int")[2]) flags = user_uint32(&@cast($args, "unsigned int")[3]) @@ -1036,18 +1036,18 @@ probe syscall.recvfrom = __syscall.socketcall.recvfrom ?, probe __syscall.socketcall.recvfrom = kernel.function("sys_socketcall").call ? { if ($call != %{ SYS_RECVFROM %}) next - s = user_int32(&@cast($args, "ulong")[0]) - buf_uaddr = user_uint64(&@cast($args, "ulong")[1]) - len = user_uint64(&@cast($args, "ulong")[2]) + s = user_int(&@cast($args, "ulong")[0]) + buf_uaddr = user_ulong(&@cast($args, "ulong")[1]) + len = user_ulong(&@cast($args, "ulong")[2]) flags = user_uint32(&@cast($args, "ulong")[3]) - addr_uaddr = user_uint64(&@cast($args, "ulong")[4]) - addrlen_uaddr = user_uint64(&@cast($args, "ulong")[5]) + addr_uaddr = user_ulong(&@cast($args, "ulong")[4]) + addrlen_uaddr = user_ulong(&@cast($args, "ulong")[5]) } probe __syscall.compat_socketcall.recvfrom = kernel.function("compat_sys_socketcall").call ? { if ($call != %{ SYS_RECVFROM %}) next - s = user_int32(&@cast($args, "unsigned int")[0]) + s = user_int(&@cast($args, "unsigned int")[0]) buf_uaddr = user_uint32(&@cast($args, "unsigned int")[1]) len = user_uint32(&@cast($args, "unsigned int")[2]) flags = user_uint32(&@cast($args, "unsigned int")[3]) @@ -1182,7 +1182,7 @@ probe syscall.compat_sys_recvmsg = { if ($call != %{ SYS_RECVMSG %}) next; name = "recvmsg" - s = user_int32(&@cast($args, "unsigned int")[0]) + s = user_int(&@cast($args, "unsigned int")[0]) msg_uaddr = user_uint32(&@cast($args, "unsigned int")[1]) flags = user_uint32(&@cast($args, "unsigned int")[2]) flags_str = _msg_flags_str(flags) diff --git a/tapset/uconversions.stp b/tapset/uconversions.stp index 0980823cc..089d0d7e0 100644 --- a/tapset/uconversions.stp +++ b/tapset/uconversions.stp @@ -519,6 +519,48 @@ function user_long_warn:long (addr:long) %{ /* pure */ /* myproc-unprivileged */ STP_GET_USER_WARN(long); %} +/** + * sfunction user_ulong - Retrieves an unsigned long value stored in user space + * + * @addr: the user space address to retrieve the unsigned long from + * + * Description: Returns the unsigned long value from a given user + * space address. Returns zero when user space data is not + * accessible. Note that the size of the unsigned long depends on the + * architecture of the current user space task (for those + * architectures that support both 64/32 bit compat tasks). + */ +function user_ulong:long (addr:long) +%{ /* pure */ /* myproc-unprivileged */ +#ifdef CONFIG_COMPAT + if (_stp_is_compat_task()) + STP_GET_USER(compat_ulong_t); + else +#endif + STP_GET_USER(unsigned long); +%} + +/** + * sfunction user_ulong_warn - Retrieves an unsigned long value stored in user space + * + * @addr: the user space address to retrieve the unsigned long from + * + * Description: Returns the unsigned long value from a given user + * space address. Returns zero when user space and warns (but does not + * abort) about the failure. Note that the size of the unsigned long + * depends on the architecture of the current user space task (for + * those architectures that support both 64/32 bit compat tasks). + */ +function user_ulong_warn:long (addr:long) +%{ /* pure */ /* myproc-unprivileged */ +#ifdef CONFIG_COMPAT + if (_stp_is_compat_task()) + STP_GET_USER_WARN(compat_ulong_t); + else +#endif + STP_GET_USER_WARN(unsigned long); +%} + /** * sfunction user_int8 - Retrieves a 8-bit integer value stored in user space * diff --git a/testsuite/buildok/conversions-embedded.stp b/testsuite/buildok/conversions-embedded.stp index 20fd5d3e2..a239c6c3b 100755 --- a/testsuite/buildok/conversions-embedded.stp +++ b/testsuite/buildok/conversions-embedded.stp @@ -31,6 +31,8 @@ probe begin { print (user_int_warn(0)) print (user_long(0)) print (user_long_warn(0)) + print (user_ulong(0)) + print (user_ulong_warn(0)) print (user_char(0)) print (user_char_warn(0)) diff --git a/testsuite/buildok/conversions.stp b/testsuite/buildok/conversions.stp index 28997947f..25bb9546c 100755 --- a/testsuite/buildok/conversions.stp +++ b/testsuite/buildok/conversions.stp @@ -30,6 +30,8 @@ probe begin { print (user_int_warn(2342)) print (user_long(2342)) print (user_long_warn(2342)) + print (user_ulong(2342)) + print (user_ulong_warn(2342)) print (user_char(2342)) print (user_char_warn(2342)) -- 2.43.5