目录

使用bpf trace来trace什么进程在读取/etc/passw

使用bpf trace来trace追踪/etc/passwd的进程从而读取/etc/passw,具体步骤为:1、创建bpf trace脚本;2、解释脚本;3、执行脚本,等待输出。创建bpf trace脚本是指创建一个bpftrace脚本以便进行后续操作。

一、使用bpf trace来trace什么进程在读取/etc/passw

1、创建bpf trace脚本

首先创建一个bpf trace脚本以便进行后续操作,下面是代码示例:

sudo bpftrace -e 'tracepoint:syscalls:sys_enter_openat /arg1 == "0x0" && strstr(arg2->filename, "/etc/passwd")/{ printf("%d %s\n", pid, comm); }'

2、解释脚本

  • tracepoint:syscalls:sys_enter_openat:表示跟踪系统调用 openat 的开始执行;
  • /arg1 == “0x0” && strstr(arg2->filename, “/etc/passwd”)/:表示过滤条件,只需要捕捉 filename 为 /etc/passwd 的系统调用;
  • { printf(“%d %s\n”, pid, comm); }:表示当满足上述条件时,输出该进程的pid和进程名。

3、执行脚本,等待输出

当有进程读取/etc/passwd文件时,命令行会输出该进程的pid和进程名,可以从输出中找到目标进程。

二、bpf trace介绍

1、简介

在v21.07 release发布版本中,SPDK提供了对BPF追踪(tracing)的支持。BPF追踪指一组定义在 SPDK 库的脚本和静态探针,为用户提供了检查 SPDK 应用程序的另一种方法。SPDK很久以前就建立过一个名为libtrace的追踪库。支持BPF追踪并不是要取代libtrace,而是要对它进行补充。这两个库的功能略有不同:libtrace的开销很低,但灵活性较差。BPF追踪的成本较高(请求CPU核trap陷阱),但功能更全面,甚至可以动态链接,不必在代码中定义探针。

2、用户态追踪

首先,我们来探讨什么是BPF追踪,以及SPDK是如何利用它的。BPF,即Berkeley Packet Filter(伯克利包过滤器),是一项最初为分析和过滤网络流量而开发的技术。用户可以借此在专门的BPF虚拟机的操作系统内核运行用户提供的程序。随后BPF在Linux中得到扩展(扩展后的BPF简称为eBPF),可支持更多用例,其中也包括追踪。

用户能够利用Linux 追踪子系统在程序的特定地方附加探针,一旦触发后会运行附加在该探针的eBPF程序。在用户态应用程序中,BPF会放置一条指令(x86的int3指令),生成SIGTRAP,被CPU核捕获后,即触发执行eBPF程序。

SPDK使用BPF trace(https://github.com/iovisor/bpftrace)来定义和附加探针。BPF追踪工具使用高级脚本语言(作者称是awk和C语言的结合)来描述特定探针被触发时的操作。探针可以分为静态定义和动态定义两种。静态探针也称为USDT(User Statically-Defined Tracing用户静态定义的探针),由程序员放置在代码的各个关键位置(使用一种SPDK_DTRACE_PROBE*宏)。动态探针可以在任何函数开始时启用,不需要更改代码或重新编译应用程序。但有一点需要注意:一些静态函数调用可能会使编译器产生inline,在这种情况下,不会照常执行探针追踪。

3、追踪工具

为了编译静态探针,SPDK必须配置–with-usdt。我们在Ubuntu 20.04和Fedora 33的数据包版本追踪时都遇到了一些问题,因此建议从源码构建最新版本的bpftrace。可以使用scripts/bpftrace.sh来附加和显示追踪。运行scripts/bpftrace.sh需要两个参数:支持追踪的进程参数PID和支持附加的bpftrace脚本。这些脚本能够收集和显示各种不同的信息和统计数据。例如,可以输出某个函数每次被调用时的参数,计算某个代码路径被执行的次数,甚至可以创建并显示一组数据的直方图。SPDK 提供了几个可用脚本,位于 scripts/bpf 目录。

接下来我们来讨论scripts/bpf/send_msg.bt脚本,应该如何用它来检查SPDK应用程序呢?该脚本通过spdk_thread_send_msg()和spdk_for_each_channel()计算某函数的执行次数。脚本的内容简单明了:

uprobe:__EXE__:spdk_thread_send_msg {

                       @send_msg[usym(arg1)] = count();
}

uprobe:__EXE__:spdk_for_each_channel {
                      @for_each_channel[usym(arg1)] = count();
}

scripts/bpf/send_msg.bt脚本通过uprobe关键字定义了两个动态探针,分别为send_msg和for_each_channel,将每个函数的调用次数存在映射。名列前茅个参数arg1是映射的密钥之一,在这两种探针下arg1指的都是待执行函数的指针。该脚本使用了两个辅助函数:usym()函数负责返回给定地址的符号名称,count()函数负责计算某个函数被调用的次数。

还有一个特殊变量是SPDK 特有的__EXE__。 scripts/bpftrace.sh 以可执行文件的名称来代替该变量(即符合 bpftrace预期)。__PID__变量由追踪进程的PID参数代替。这两个变量都提供了更便捷的方法,在不同的应用程序中可使用相同的脚本。

4、SPDK和BPF追踪

如前所述,SPDK追踪库其中一个目的是将开销减至最小。这意味着每个追踪点只能记录最关键的数据。做到在I/O路径中放置追踪点,同时不对性能产生重大影响。但有了BPF追踪,我们可以把bpftrace探针放在对象创建的位置,收集其属性,然后用这些数据来辅助SPDK追踪。

例如,在NVMe/RDMA I/O路径中记录指针,指向可执行请求的qpair。然后可以用bpftrace来记录qpair的信息,比如它的队列ID、线程ID、子系统NQN和主机NQN,SPDK显示追踪时与指针一同显示。这就是scripts/bpf/trace.py脚本的功能。

5、总结

总而言之,现在SPDK可以使用更全面更有效的方法实现BPF追踪以检查应用程序。BPF追踪由一组bpftrace程序、定义在SPDK库的USDT探针和几个脚本组成,这些脚本能够简化BPF追踪,和常规的SPDK追踪代码结合使用。

延伸阅读1:trace简介

trace是一个计算机术语。TRACE和TRACK是用来调试web服务器连接的HTTP方式。TRACE宏对于VC下程序调试来说是很有用的东西,有着类似printf的功能。在MATLAB中,trace用于求二维方阵的迹,即该方阵对角线上元素之和。在Flex中,用作调试信息显示函数,用于在debug(调试)模式下输出。在SQL Server中有Default Trace默认跟踪,数据库记录信息到log.trc文件,可以查看trace_event_id,46表示Create对象(Object:Created),47表示Drop对象(Object:Deleted),93表示日志文件自动增长(Log File Auto Grow),164表示Alter对象(Object:Altered),20表示错误日志(Audit Login Failed)。

一站式研发项目管理平台 PingCode

一站式研发项目管理平台 PingCode

支持敏捷\瀑布、知识库、迭代计划&跟踪、需求、缺陷、测试管理,同时满足非研发团队的流程规划、项目管理和在线办公需要。