From 2f0d9ada4f887f28118904b87de9552b47d10d0f Mon Sep 17 00:00:00 2001 From: Di Chen Date: Tue, 15 Feb 2022 17:39:29 +0800 Subject: [PATCH] Add support for new syscall memfd_secret Linux 5.14 added the memfd_secret syscall, adding tapset support. memfd_secret() was disabled by default and a command-line option was added to enable it at boot time. $ cat /proc/cmdline [...] secretmem.enable=y https://sourceware.org/bugzilla/show_bug.cgi?id=28418 https://lwn.net/Articles/865256/ Signed-off-by: Di Chen --- runtime/linux/compat_unistd.h | 4 + tapset/linux/aux_syscalls.stp | 3 + tapset/linux/sysc_memfd_secret.stp | 102 +++++++++++++++++++++ testsuite/systemtap.syscall/memfd_secret.c | 22 +++++ 4 files changed, 131 insertions(+) create mode 100644 tapset/linux/sysc_memfd_secret.stp create mode 100644 testsuite/systemtap.syscall/memfd_secret.c diff --git a/runtime/linux/compat_unistd.h b/runtime/linux/compat_unistd.h index 5a932cc17..2bbb0bac5 100644 --- a/runtime/linux/compat_unistd.h +++ b/runtime/linux/compat_unistd.h @@ -920,6 +920,9 @@ #ifndef __NR_ia32_memfd_create #define __NR_ia32_memfd_create 356 #endif +#ifndef __NR_ia32_memfd_secret +#define __NR_ia32_memfd_secret 447 +#endif #ifndef __NR_ia32_migrate_pages #define __NR_ia32_migrate_pages 294 #endif @@ -1999,6 +2002,7 @@ #define __NR_compat_mbind __NR_mbind #define __NR_compat_membarrier __NR_membarrier #define __NR_compat_memfd_create __NR_memfd_create +#define __NR_compat_memfd_secret __NR_memfd_secret #define __NR_compat_migrate_pages __NR_migrate_pages #define __NR_compat_mincore __NR_mincore #define __NR_compat_mkdir __NR_mkdir diff --git a/tapset/linux/aux_syscalls.stp b/tapset/linux/aux_syscalls.stp index 3313fb441..4a4bac4df 100644 --- a/tapset/linux/aux_syscalls.stp +++ b/tapset/linux/aux_syscalls.stp @@ -1703,6 +1703,9 @@ static const _stp_val_array _stp_mfd_flags_list[] = { #endif #ifdef MFD_ALLOW_SEALING V(MFD_ALLOW_SEALING), +#endif +#ifdef O_CLOEXEC + V(O_CLOEXEC), #endif {0, NULL} }; diff --git a/tapset/linux/sysc_memfd_secret.stp b/tapset/linux/sysc_memfd_secret.stp new file mode 100644 index 000000000..396077c9d --- /dev/null +++ b/tapset/linux/sysc_memfd_secret.stp @@ -0,0 +1,102 @@ +# memfd_secret _____________________________________________________ +# long sys_memfd_secret (unsigned int flags) + +/* kernel 5.14+ */ +@define _SYSCALL_MEMFD_SECRET_NAME +%( + name = "memfd_secret" +%) + +@define _SYSCALL_MEMFD_SECRET_ARGSTR +%( + argstr = sprintf("%s", flags_str) +%) + +@define _SYSCALL_MEMFD_SECRET_REGARGS +%( + flags = uint_arg(1) + flags_str = _mfd_flags_str(uint_arg(1)) +%) + +@define _SYSCALL_MEMFD_SECRET_REGARGS_STORE +%( + if (@probewrite(flags)) + set_uint_arg(1, flags) +%) + +probe syscall.memfd_secret = dw_syscall.memfd_secret !, nd_syscall.memfd_secret ? {} +probe syscall.memfd_secret.return = dw_syscall.memfd_secret.return !, nd_syscall.memfd_secret.return ? {} + +# dw_memfd_secret _____________________________________________________ + +probe dw_syscall.memfd_secret = kernel.function("sys_memfd_secret").call ? +{ + @_SYSCALL_MEMFD_SECRET_NAME + flags = $flags + flags_str = _mfd_flags_str($flags) + @_SYSCALL_MEMFD_SECRET_ARGSTR +} +probe dw_syscall.memfd_secret.return = kernel.function("sys_memfd_secret").return ? +{ + @_SYSCALL_MEMFD_SECRET_NAME + @SYSC_RETVALSTR($return) +} + +# nd_memfd_secret _____________________________________________________ + +probe nd_syscall.memfd_secret = nd1_syscall.memfd_secret!, nd2_syscall.memfd_secret!, tp_syscall.memfd_secret + { } + +probe nd1_syscall.memfd_secret = kprobe.function("sys_memfd_secret") ? +{ + @_SYSCALL_MEMFD_SECRET_NAME + asmlinkage() + @_SYSCALL_MEMFD_SECRET_REGARGS + @_SYSCALL_MEMFD_SECRET_ARGSTR +} + +probe nd2_syscall.memfd_secret = kprobe.function(@arch_syscall_prefix "sys_memfd_secret") ? +{ + __set_syscall_pt_regs(pointer_arg(1)) + @_SYSCALL_MEMFD_SECRET_NAME + @_SYSCALL_MEMFD_SECRET_REGARGS + @_SYSCALL_MEMFD_SECRET_ARGSTR +}, +{ + %( @_IS_SREG_KERNEL %? @_SYSCALL_MEMFD_SECRET_REGARGS_STORE %) +} + +probe tp_syscall.memfd_secret = kernel.trace("sys_enter") +{ + __set_syscall_pt_regs($regs) + @__syscall_compat_gate(@const("__NR_memfd_secret"), @const("__NR_compat_memfd_secret")) + @_SYSCALL_MEMFD_SECRET_NAME + @_SYSCALL_MEMFD_SECRET_REGARGS + @_SYSCALL_MEMFD_SECRET_ARGSTR +}, +{ + %( @_IS_SREG_KERNEL %? @_SYSCALL_MEMFD_SECRET_REGARGS_STORE %) +} + +probe nd_syscall.memfd_secret.return = nd1_syscall.memfd_secret.return!, nd2_syscall.memfd_secret.return!, tp_syscall.memfd_secret.return + { } + +probe nd1_syscall.memfd_secret.return = kprobe.function("sys_memfd_secret").return ? +{ + @_SYSCALL_MEMFD_SECRET_NAME + @SYSC_RETVALSTR(returnval()) +} + +probe nd2_syscall.memfd_secret.return = kprobe.function(@arch_syscall_prefix "sys_memfd_secret").return ? +{ + @_SYSCALL_MEMFD_SECRET_NAME + @SYSC_RETVALSTR(returnval()) +} + +probe tp_syscall.memfd_secret.return = kernel.trace("sys_exit") +{ + __set_syscall_pt_regs($regs) + @__syscall_compat_gate(@const("__NR_memfd_secret"), @const("__NR_compat_memfd_secret")) + @_SYSCALL_MEMFD_SECRET_NAME + @SYSC_RETVALSTR($ret) +} diff --git a/testsuite/systemtap.syscall/memfd_secret.c b/testsuite/systemtap.syscall/memfd_secret.c new file mode 100644 index 000000000..9a467db86 --- /dev/null +++ b/testsuite/systemtap.syscall/memfd_secret.c @@ -0,0 +1,22 @@ +/* COVERAGE: memfd_secret */ + +/* + * Glibc doesn't support memfd_secret yet, so we have to use syscall(2) + */ +#define _GNU_SOURCE +#include +#include +#include + +#ifdef __NR_memfd_secret + +int main() +{ + int fd; + fd = syscall(__NR_memfd_secret, O_CLOEXEC); + //staptest// memfd_secret (O_CLOEXEC) = NNNN + + close(fd); +} + +#endif -- 2.34.1