eBPF可以修改系统调用的返回值或参数吗?

Geo*_*lly 5 linux system-calls bpf ebpf

为了模拟某些行为,我想将探测附加到系统调用,并在传递某些参数时修改返回值.或者,在函数处理之前修改函数的参数也就足够了.

这可能与BPF有关吗?

Ben*_*her 7

在内核探测器(kprobes)中,eBPF虚拟机具有对syscall参数和返回值的只读访问权限.

但是,eBPF程序将拥有自己的返回代码.可以应用一个seccomp配置文件来捕获BPF(NOT eBPF;感谢@qeole)返回码并在执行期间中断系统调用.

允许的运行时修改是:

  • SECCOMP_RET_KILL:立即杀死 SIGSYS
  • SECCOMP_RET_TRAP:发送一个catlecble 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来实现,ptrace能够修改跟踪的进程内存,寄存器和文件描述符.

跟踪器需要调用ptrace然后调用waitpid.一个例子:

ptrace(PTRACE_SETOPTIONS, tracee_pid, 0, PTRACE_O_TRACESECCOMP);
waitpid(tracee_pid, &status, 0);
Run Code Online (Sandbox Code Playgroud)

http://man7.org/linux/man-pages/man2/ptrace.2.html

waitpid返回时,根据的内容status,可以通过检索返回的Seccomp值PTRACE_GETEVENTMSGptrace的操作.这将检索seccomp SECCOMP_RET_DATA值,该值是BPF程序设置的16位字段.例:

ptrace(PTRACE_GETEVENTMSG, tracee_pid, 0, &data);
Run Code Online (Sandbox Code Playgroud)

在继续操作之前,可以在内存中修改Syscall参数.您可以使用该PTRACE_SYSCALL步骤执行单个系统调用条目或退出.在恢复执行之前,可以在用户空间中修改Syscall返回值; 底层程序将无法看到系统调用返回值已被修改.

示例实现: 使用seccomp和ptrace过滤和修改系统调用

  • 次要更正:seccomp仅支持BPF的"经典"版本.目前不支持**e**BPF("扩展BPF"). (3认同)

Qeo*_*ole 5

我相信将 eBPF 附加到 kprobes/kretprobes 可以让你读取函数参数和返回值,但你不能篡改它们。我不是 100% 确定;要求确认的好地方是 IO Visor 项目邮件列表或 IRC 频道(irc.oftc.net 上的#iovisor)。

作为替代解决方案,我知道您至少可以使用strace-e选项更改系统调用的返回值。引用手册页

-e inject=set[:error=errno|:retval=value][:signal=sig][:when=expr]
       Perform syscall tampering for the specified set of syscalls.
Run Code Online (Sandbox Code Playgroud)

此外,如果您感兴趣的话,在 Fosdem 2017 上有一个关于此的演示和故障注入。这是幻灯片中的一个示例命令:

strace -P precious.txt -efault=unlink:retval=0 unlink precious.txt
Run Code Online (Sandbox Code Playgroud)

编辑:正如 Ben 所说,kprobes 和跟踪点上的 eBPF 绝对是只读的,用于跟踪和监控用例。我也在 IRC 上得到了确认。