为了模拟某些行为,我想将探测器附加到系统调用并在传递某些参数时修改返回值。或者,在函数成为进程之前修改函数的参数也足够了。
这可以用 BPF 实现吗?
最佳答案
在内核探测 (kprobes) 中,eBPF 虚拟机对系统调用参数和返回值具有只读访问权限。
然而,eBPF 程序将有自己的返回码。可以应用捕获 BPF(不是 eBPF;感谢@qeole)返回代码并在执行期间中断系统调用的 seccomp 配置文件。
允许的运行时修改是:
SECCOMP_RET_KILL
:使用SIGSYS
立即终止SECCOMP_RET_TRAP
:发送一个可捕捉的SIGSYS
,给模拟系统调用一个机会SECCOMP_RET_ERRNO
:强制errno
值SECCOMP_RET_TRACE
:对 ptracer 做出决定或将errno
设置为-ENOSYS
SECCOMP_RET_ALLOW
:允许
https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt
SECCOMP_RET_TRACE
方法可以修改执行的系统调用、参数或返回值。这是依赖于体系结构的,强制外部引用的修改可能会导致 ENOSYS 错误。
它通过将执行传递给等待的用户空间 ptrace 来实现,它能够修改跟踪的进程内存、寄存器和文件描述符。
tracer 需要调用ptrace,然后调用waitpid。一个例子:
ptrace(PTRACE_SETOPTIONS, tracee_pid, 0, PTRACE_O_TRACESECCOMP);
waitpid(tracee_pid, &status, 0);
http://man7.org/linux/man-pages/man2/ptrace.2.html
当 waitpid
返回时,根据 status
的内容,可以使用 PTRACE_GETEVENTMSG
ptrace 操作检索 seccomp 返回值。这将检索 seccomp SECCOMP_RET_DATA
值,这是由 BPF 程序设置的 16 位字段。示例:
ptrace(PTRACE_GETEVENTMSG, tracee_pid, 0, &data);
系统调用参数可以在继续操作之前在内存中修改。您可以使用 PTRACE_SYSCALL
步骤执行单个系统调用进入或退出。在恢复执行之前,可以在用户空间修改系统调用返回值;底层程序将无法看到系统调用返回值已被修改。
一个示例实现: Filter and Modify System Calls with seccomp and ptrace
关于linux - eBPF 可以修改系统调用的返回值或参数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43003805/