// 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
#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
// 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
# 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)
}
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)
}
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)
}
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)
}