From 66db7d43abaa0b08415c28fe1eee422a58ca0ba4 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Mon, 11 Oct 2021 16:46:02 -0400 Subject: [PATCH] Add various tapset/bpf files (and links) to support syscall_any for BPF --- tapset/bpf/aux_syscalls.stp | 12 ++++++++ tapset/bpf/compatdefs.stp | 9 ++++++ tapset/bpf/syscall_any.stp | 49 ++++++++++++++++++++++++++++++ tapset/bpf/syscall_num_arm.stp | 1 + tapset/bpf/syscall_num_arm64.stp | 1 + tapset/bpf/syscall_num_mips.stp | 1 + tapset/bpf/syscall_num_powerpc.stp | 1 + tapset/bpf/syscall_num_s390.stp | 1 + tapset/bpf/syscall_num_x86_64.stp | 1 + tapset/bpf/syscall_table.stp | 47 ++++++++++++++++++++++++++++ 10 files changed, 123 insertions(+) create mode 100644 tapset/bpf/aux_syscalls.stp create mode 100644 tapset/bpf/compatdefs.stp create mode 100644 tapset/bpf/syscall_any.stp create mode 120000 tapset/bpf/syscall_num_arm.stp create mode 120000 tapset/bpf/syscall_num_arm64.stp create mode 120000 tapset/bpf/syscall_num_mips.stp create mode 120000 tapset/bpf/syscall_num_powerpc.stp create mode 120000 tapset/bpf/syscall_num_s390.stp create mode 120000 tapset/bpf/syscall_num_x86_64.stp create mode 100644 tapset/bpf/syscall_table.stp diff --git a/tapset/bpf/aux_syscalls.stp b/tapset/bpf/aux_syscalls.stp new file mode 100644 index 000000000..bc0922cf0 --- /dev/null +++ b/tapset/bpf/aux_syscalls.stp @@ -0,0 +1,12 @@ +function _stp_bpf_syscall_get_nr:long(regs:long) +{ + return @choose_defined( @cast(regs, "struct pt_regs", "kernel")->orig_ax, // STAPCONF_X86_UNIREGS + @choose_defined(@cast(regs, "struct pt_regs", "kernel")->orig_rax, // __x86_64__ + @choose_defined(@cast(regs, "struct pt_regs", "kernel")->orig_eax, // __i386__ + @choose_defined(@cast(regs, "struct pt_regs", "kernel")->ARM_r7, // __arm__ + @choose_defined(@cast(regs, "struct pt_regs", "kernel")->regs[2], //__mips__ + @choose_defined(@cast(regs, "struct pt_regs", "kernel")->gpr[0], //__powerpc__ + @choose_defined(@cast(regs, "struct pt_regs", "kernel")->gprs[2], // __s390__ || __s390x__ + @choose_defined(@cast(regs, "struct pt_regs", "kernel")->syscallno, // __aarch64__ + @cast(regs, "struct pt_regs", "kernel")->a7)))))))); // __riscv__ +} diff --git a/tapset/bpf/compatdefs.stp b/tapset/bpf/compatdefs.stp new file mode 100644 index 000000000..2a1cbeb0d --- /dev/null +++ b/tapset/bpf/compatdefs.stp @@ -0,0 +1,9 @@ +function _stp_is_compat_task2:long (task:long) { + // FIXME does not currently handle compatibility mode + return 0; +} + +function _stp_is_compat_task:long(void) +{ + _stp_is_compat_task2(task_current()) +} diff --git a/tapset/bpf/syscall_any.stp b/tapset/bpf/syscall_any.stp new file mode 100644 index 000000000..8607d70a4 --- /dev/null +++ b/tapset/bpf/syscall_any.stp @@ -0,0 +1,49 @@ +/** + * equivalent to linux module syscall_any - Record entry into a syscall + * + * @syscall_nr: number of the syscall + * @name: name of the syscall + * + * Context: The process performing the syscall + * + * The syscall_any probe point is designed to be a low overhead + * that monitors all the syscalls entered via a kernel tracepoint. + * Because of the breadth of syscalls it monitors it provides + * no information about the syscall arguments or argstr string + * representation of those arguments. + * + * This requires kernel 3.5+ and newer which have the + * kernel.trace("sys_enter") probe point. + */ +probe syscall_any = kernel.trace("sys_enter") +{ + syscall_nr = $id + name = syscall_name($id) +} + + +/** + * equivalent to linux module syscall_any.return - Record exit from a syscall + * + * @syscall_nr: number of the syscall + * @name: name of the syscall + * @retval: return value of the syscall + * + * Context: The process performing the syscall + * + * The syscall_any.return probe point is designed to be a low overhead + * that monitors all the syscalls returns via a kernel tracepoint. + * Because of the breadth of syscalls it monitors it provides + * no information about the syscall arguments, argstr string + * representation of those arguments, or a string interpretation + * of the return value (retval). + * + * This requires kernel 3.5+ and newer which have the + * kernel.trace("sys_exit") probe point. + */ +probe syscall_any.return = kernel.trace("sys_exit") +{ + syscall_nr = _stp_bpf_syscall_get_nr($regs) + name = syscall_name(_stp_bpf_syscall_get_nr($regs)) + retval = $ret +} diff --git a/tapset/bpf/syscall_num_arm.stp b/tapset/bpf/syscall_num_arm.stp new file mode 120000 index 000000000..a5b8d49b4 --- /dev/null +++ b/tapset/bpf/syscall_num_arm.stp @@ -0,0 +1 @@ +../linux/arm/syscall_num.stp \ No newline at end of file diff --git a/tapset/bpf/syscall_num_arm64.stp b/tapset/bpf/syscall_num_arm64.stp new file mode 120000 index 000000000..4a7992e69 --- /dev/null +++ b/tapset/bpf/syscall_num_arm64.stp @@ -0,0 +1 @@ +../linux/arm64/syscall_num.stp \ No newline at end of file diff --git a/tapset/bpf/syscall_num_mips.stp b/tapset/bpf/syscall_num_mips.stp new file mode 120000 index 000000000..8743774a6 --- /dev/null +++ b/tapset/bpf/syscall_num_mips.stp @@ -0,0 +1 @@ +../linux/mips/syscall_num.stp \ No newline at end of file diff --git a/tapset/bpf/syscall_num_powerpc.stp b/tapset/bpf/syscall_num_powerpc.stp new file mode 120000 index 000000000..11c471201 --- /dev/null +++ b/tapset/bpf/syscall_num_powerpc.stp @@ -0,0 +1 @@ +../linux/powerpc/syscall_num.stp \ No newline at end of file diff --git a/tapset/bpf/syscall_num_s390.stp b/tapset/bpf/syscall_num_s390.stp new file mode 120000 index 000000000..ac6aba04a --- /dev/null +++ b/tapset/bpf/syscall_num_s390.stp @@ -0,0 +1 @@ +../linux/s390/syscall_num.stp \ No newline at end of file diff --git a/tapset/bpf/syscall_num_x86_64.stp b/tapset/bpf/syscall_num_x86_64.stp new file mode 120000 index 000000000..972de0085 --- /dev/null +++ b/tapset/bpf/syscall_num_x86_64.stp @@ -0,0 +1 @@ +../linux/x86_64/syscall_num.stp \ No newline at end of file diff --git a/tapset/bpf/syscall_table.stp b/tapset/bpf/syscall_table.stp new file mode 100644 index 000000000..b6e3d16fd --- /dev/null +++ b/tapset/bpf/syscall_table.stp @@ -0,0 +1,47 @@ +# This is syscall_table tapset providing namely syscall_name() and syscall_num() +# functions. It uses architecture specific data contained in other arch +# specific tapsets. Helper scripts/dump-syscalls.sh is used to generate those. + +function syscall_name(num) { + //%( CONFIG_COMPAT == "y" %? + // if (@__compat_task) + // return __syscall_32_num2name[num] + //%) +%( CONFIG_64BIT == "y" %? + return __syscall_64_num2name[num] +%: + return __syscall_32_num2name[num] +%) +} + +# Systemtap is benevolent when an associative array is being queried for an +# unexisting key. If we call e.g. __syscall_64_name2num["unexisting_syscall"], +# the result is zero. But at the same time zero is a valid syscall number, so +# we really need to return some other value in this case to indicate that +# syscall with given name doesn't exist. Let's use following +# @return_sanitized macro. +# +# The other way round, when evaluating e.g. __syscall_64_num2name[-123], stap +# is benevolent too - we'll get an empty string. But that is sufficiently +# unique, so we are good at this front. + +@define return_sanitized(indexable, key) +%( + if (@key in @indexable) + return @indexable[@key] + else + return -1 +%) + +function syscall_num(name) { +%( CONFIG_COMPAT == "y" %? + if (@__compat_task) + @return_sanitized(__syscall_32_name2num, name) +%) +%( CONFIG_64BIT == "y" %? + @return_sanitized(__syscall_64_name2num, name) +%: + @return_sanitized(__syscall_32_name2num, name) +%) +} + -- 2.43.5