From 71166900c7ab552fec678cb77beed5c5762f76cf Mon Sep 17 00:00:00 2001 From: David Smith Date: Mon, 25 Nov 2013 14:00:51 -0600 Subject: [PATCH] PR16207 partial fix: Fix the 'dup' [nd_]syscall.exp tests on rawhide. * tapset/linux/syscalls.stp: Split the syscall.dup2 probe into syscall.dup2 and syscall.dup3. * tapset/linux/nd_syscalls.stp: Split the nd_syscall.dup2 probe into nd_syscall.dup2 and nd_syscall.dup3. * runtime/linux/compat_unistd.h: Added the __NR_compat_dup3 define. * testsuite/buildok/syscalls-detailed.stp: Added dup3 test. * testsuite/buildok/nd_syscalls-detailed.stp: Ditto. --- runtime/linux/compat_unistd.h | 5 + tapset/linux/nd_syscalls.stp | 105 ++++----------------- tapset/linux/syscalls.stp | 46 +++------ testsuite/buildok/nd_syscalls-detailed.stp | 4 +- testsuite/buildok/syscalls-detailed.stp | 4 +- 5 files changed, 38 insertions(+), 126 deletions(-) diff --git a/runtime/linux/compat_unistd.h b/runtime/linux/compat_unistd.h index 0138ec5e0..47e259dac 100644 --- a/runtime/linux/compat_unistd.h +++ b/runtime/linux/compat_unistd.h @@ -15,6 +15,9 @@ // On older kernels (like RHEL5), we have to define our own 32-bit // syscall numbers. +#ifndef __NR_ia32_dup3 +#define __NR_ia32_dup3 330 +#endif #ifndef __NR_ia32_faccessat #define __NR_ia32_faccessat 307 #endif @@ -34,6 +37,7 @@ #define __NR_ia32_symlinkat 304 #endif +#define __NR_compat_dup3 __NR_ia32_dup3 #define __NR_compat_faccessat __NR_ia32_faccessat #define __NR_compat_fchmodat __NR_ia32_fchmodat #define __NR_compat_fchownat __NR_ia32_fchownat @@ -48,6 +52,7 @@ // On the ppc64 and s390x, the 32-bit syscalls use the same number // as the 64-bit syscalls. +#define __NR_compat_dup3 __NR_dup3 #define __NR_compat_faccessat __NR_faccessat #define __NR_compat_fchmodat __NR_fchmodat #define __NR_compat_fchownat __NR_fchownat diff --git a/tapset/linux/nd_syscalls.stp b/tapset/linux/nd_syscalls.stp index 3d2aa69b0..a55e3f23e 100644 --- a/tapset/linux/nd_syscalls.stp +++ b/tapset/linux/nd_syscalls.stp @@ -690,122 +690,51 @@ probe nd_syscall.dup.return = kprobe.function("sys_dup").return ? # dup2 _______________________________________________________ # long sys_dup2(unsigned int oldfd, unsigned int newfd) -# Only handles corner case, others handled by dup3. probe nd_syscall.dup2 = kprobe.function("sys_dup2") { - // if ($oldfd != $newfd) next; - // name = "dup2" + name = "dup2" // oldfd = $oldfd // newfd = $newfd + // # The dup2 syscall doesn't have a 'flags' argument. But, the + // # syscall.dup2 and syscall.dup3 probes used to be combined, so + // # both probes need a 'flags' variable. // flags = 0 // argstr = sprintf("%d, %d", $oldfd, $newfd) asmlinkage() oldfd = int_arg(1) newfd = int_arg(2) - if (oldfd != newfd) next; - - name = "dup2" + # The dup2 syscall doesn't have a 'flags' argument. But, the + # syscall.dup2 and syscall.dup3 probes used to be combined, so + # both probes need a 'flags' variable. flags = 0 argstr = sprintf("%d, %d", oldfd, newfd) } probe nd_syscall.dup2.return = kprobe.function("sys_dup2").return { - // if ($oldfd != $newfd) next; - // name = "dup2" - // retstr = return_str(1, $return) - if (@entry(__asmlinkage_int_arg(1)) != @entry(int_arg(2))) next; name = "dup2" retstr = returnstr(1) } -# dup3 (handles both dup2 and dup3 except for corner case)___________ -# long sys_dup2(unsigned int oldfd, unsigned int newfd) +# dup3 _______________________________________________________ # SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags) -probe nd_syscall.dup2 = __nd_syscall.dup3 !, __nd_syscall.dup2 -{ -} -probe __nd_syscall.dup3 = kprobe.function("sys_dup3") +probe nd_syscall.dup3 = kprobe.function("sys_dup3") ? { + @__syscall_compat_gate(%{ __NR_dup3 %}, %{ __NR_compat_dup3 %}) + name = "dup3"; // oldfd = $oldfd // newfd = $newfd - // flags = @defined($flags) ? $flags : 0; + // flags = $flags + // argstr = sprintf("%d, %d, %s", $oldfd, $newfd, _dup3_flag_str(flags)); asmlinkage() oldfd = int_arg(1) newfd = int_arg(2) flags = int_arg(3) - - # Corner case handled by dup2 - // if ($oldfd == $newfd && flags == 0) next - if (oldfd == newfd && flags == 0) next - - // if (flags == 0) { - // name = "dup2"; - // argstr = sprintf("%d, %d", $oldfd, $newfd); - // } else { - // name = "dup3"; - // argstr = sprintf("%d, %d, %s", $oldfd, $newfd, - // _dup3_flag_str(flags)); - // } - if (flags == 0) { - name = "dup2"; - argstr = sprintf("%d, %d", oldfd, newfd); - } else { - name = "dup3"; - argstr = sprintf("%d, %d, %s", oldfd, newfd, - _dup3_flag_str(flags)); - } + argstr = sprintf("%d, %d, %s", oldfd, newfd, _dup3_flag_str(flags)); } -probe __nd_syscall.dup2 = kprobe.function("sys_dup2") +probe nd_syscall.dup3.return = kprobe.function("sys_dup3").return ? { - // oldfd = $oldfd - // newfd = $newfd - // flags = @defined($flags) ? $flags : 0; - asmlinkage() - oldfd = int_arg(1) - newfd = int_arg(2) - flags = 0 - - # Corner case handled by dup2 - // if ($oldfd == $newfd && flags == 0) next - if (oldfd == newfd) next - - // if (flags == 0) { - // name = "dup2"; - // argstr = sprintf("%d, %d", $oldfd, $newfd); - // } else { - // name = "dup3"; - // argstr = sprintf("%d, %d, %s", $oldfd, $newfd, - // _dup3_flag_str(flags)); - // } - name = "dup2"; - argstr = sprintf("%d, %d", oldfd, newfd); -} -probe nd_syscall.dup2.return = __nd_syscall.dup3.return !, - __nd_syscall.dup2.return -{ -} -probe __nd_syscall.dup3.return = kprobe.function("sys_dup3").return -{ - // flags = @defined($flags) ? $flags : 0; - flags = @entry(__asmlinkage_int_arg(3)) - - # Corner case handled by dup2 - // if ($oldfd == $newfd && flags == 0) next - if (@entry(int_arg(1)) == @entry(int_arg(2)) && flags == 0) next - - name = flags == 0 ? "dup2" : "dup3"; - // retstr = return_str(1, $return) - retstr = returnstr(1) -} -probe __nd_syscall.dup2.return = kprobe.function("sys_dup2").return -{ - # Corner case handled by dup2 - // if ($oldfd == $newfd && flags == 0) next - if (@entry(__asmlinkage_int_arg(1)) == @entry(int_arg(2))) next - - // name = flags == 0 ? "dup2" : "dup3"; - // retstr = return_str(1, $return) - name = "dup2" + @__syscall_compat_gate(%{ __NR_dup3 %}, %{ __NR_compat_dup3 %}) + name = "dup3" retstr = returnstr(1) } diff --git a/tapset/linux/syscalls.stp b/tapset/linux/syscalls.stp index e2fd8dabe..40495ca1e 100644 --- a/tapset/linux/syscalls.stp +++ b/tapset/linux/syscalls.stp @@ -553,62 +553,40 @@ probe syscall.dup.return = kernel.function("sys_dup").return retstr = return_str(1, $return) } -# Notice there are two syscall.dup2 probe aliases. This is -# intentional, to handle dup2/dup3 properly (and all their corner -# cases). See commit 816395 for details (and a testcase). -# # dup2 _______________________________________________________ # long sys_dup2(unsigned int oldfd, unsigned int newfd) -# Only handles corner case, others handled by dup3. probe syscall.dup2 = kernel.function("sys_dup2").call { - if ($oldfd != $newfd) next; - name = "dup2" oldfd = $oldfd newfd = $newfd + # The dup2 syscall doesn't have a 'flags' argument. But, the + # syscall.dup2 and syscall.dup3 probes used to be combined, so + # both probes need a 'flags' variable. flags = 0 argstr = sprintf("%d, %d", $oldfd, $newfd) } probe syscall.dup2.return = kernel.function("sys_dup2").return { - if ($oldfd != $newfd) next; - name = "dup2" retstr = return_str(1, $return) } -# dup3 (handles both dup2 and dup3 except for corner case)___________ -# long sys_dup2(unsigned int oldfd, unsigned int newfd) +# dup3 _______________________________________________________ # SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags) -probe syscall.dup2 = kernel.function("sys_dup3").call !, - kernel.function("sys_dup2").call +probe syscall.dup3 = kernel.function("sys_dup3").call ? { + @__syscall_compat_gate(%{ __NR_dup3 %}, %{ __NR_compat_dup3 %}) + name = "dup3"; oldfd = $oldfd newfd = $newfd - flags = @choose_defined($flags, 0); - - # Corner case handled by dup2 - if ($oldfd == $newfd && flags == 0) next - - if (flags == 0) { - name = "dup2"; - argstr = sprintf("%d, %d", $oldfd, $newfd); - } else { - name = "dup3"; - argstr = sprintf("%d, %d, %s", $oldfd, $newfd, - _dup3_flag_str(flags)); - } + flags = $flags + argstr = sprintf("%d, %d, %s", $oldfd, $newfd, _dup3_flag_str(flags)); } -probe syscall.dup2.return = kernel.function("sys_dup3").return !, - kernel.function("sys_dup2").return +probe syscall.dup3.return = kernel.function("sys_dup3").return ? { - flags = @choose_defined($flags, 0); - - # Corner case handled by dup2 - if ($oldfd == $newfd && flags == 0) next - - name = flags == 0 ? "dup2" : "dup3"; + @__syscall_compat_gate(%{ __NR_dup3 %}, %{ __NR_compat_dup3 %}) + name = "dup3" retstr = return_str(1, $return) } diff --git a/testsuite/buildok/nd_syscalls-detailed.stp b/testsuite/buildok/nd_syscalls-detailed.stp index 8152f8d5f..b3489e16e 100755 --- a/testsuite/buildok/nd_syscalls-detailed.stp +++ b/testsuite/buildok/nd_syscalls-detailed.stp @@ -231,12 +231,12 @@ probe nd_syscall.dup.return printf("%s, %s\n", name, retstr) } -probe nd_syscall.dup2 +probe nd_syscall.dup2, nd_syscall.dup3 ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", oldfd, newfd, flags) } -probe nd_syscall.dup2.return +probe nd_syscall.dup2.return, nd_syscall.dup3.return ? { printf("%s, %s\n", name, retstr) } diff --git a/testsuite/buildok/syscalls-detailed.stp b/testsuite/buildok/syscalls-detailed.stp index e1c626c74..1d47d623d 100755 --- a/testsuite/buildok/syscalls-detailed.stp +++ b/testsuite/buildok/syscalls-detailed.stp @@ -231,12 +231,12 @@ probe syscall.dup.return printf("%s, %s\n", name, retstr) } -probe syscall.dup2 +probe syscall.dup2, syscall.dup3 ? { printf("%s, %s\n", name, argstr) printf("%d, %d, %d\n", oldfd, newfd, flags) } -probe syscall.dup2.return +probe syscall.dup2.return, syscall.dup3.return ? { printf("%s, %s\n", name, retstr) } -- 2.43.5