1、首届中国首届中国eBPFeBPF研讨会研讨会框架开发经验分享杨润青华为Linux Tracing System浅析&首届中国首届中国eBPFeBPF研讨会研讨会Linux Tracing System浅析“Kprobe,Tracepoint,Linux Auditing subsystem(auditd),SystemTap,LTTng,perf,trace-cmd,eBPF,bpftrace,BCC“这些专业词语是什么意思?它们之间有什么关系?每种tracing技术的优缺点是什么?为什么eBPF会从中脱颖而出,近年来得到广泛关注?首届中国首届中国eBPFeBPF研讨会研讨会*Figure i
2、nspired by https:/ 框架:负责对接数据源,采集解析发送数据,并对用户态提供接口前端工具/库:对接Tracing框架,直接与用户交互,负责采集配置和数据分析Linux Tracing System浅析首届中国首届中国eBPFeBPF研讨会研讨会*Figure inspired by https:/ Tracing System浅析#trace-cmdrecord-esched_process_exec#trace-cmdreportps-4243.947402:sched_process_exec:filename=/usr/bin/pspid=18447
3、8old_pid=184478grep-4243.947596:sched_process_exec:filename=/usr/bin/egreppid=184479old_pid=184479grep-4243.947681:sched_process_exec:filename=/usr/bin/greppid=184480old_pid=184480awk-4243.947783:sched_process_exec:filename=/usr/bin/awkpid=184481old_pid=184481grep-18
4、4479005154243.948385:sched_process_exec:filename=/usr/bin/greppid=184479old_pid=184479cat-4244.970658:sched_process_exec:filename=/usr/bin/catpid=184482old_pid=184482使用前端工具trace-cmd,通过tracefs 框架,对接数据源tracepoint,实现进程exec行为的数据采集和分析工作首届中国首届中国eBPFeBPF研讨会研讨会*Figure inspired by https:/ 框架:负责对接数
5、据源,采集解析发送数据,并对用户态提供接口前端工具/库:对接Tracing框架,直接与用户交互,负责采集配置和数据分析Linux Tracing System浅析首届中国首届中国eBPFeBPF研讨会研讨会Linux Tracing System 发展历程1999年,LTT(Linux Trace Toolkit)发布(没有被引入内核)2004年4月,Linux Auditing subsystem(auditd)被引入内核2.6.6-rc1通过修改内核代码,添加工具专用的数据源Linux Auditing Subsystem通过在syscall和文件操作等内核源代码上插入自定义的hook函数
6、(通常以audit_开头)来实现syscall和文件行为的监控内核源码:2.6.6-rc1首届中国首届中国eBPFeBPF研讨会研讨会Linux Tracing System 发展历程1999年,LTT(Linux Trace Toolkit)发布2004年4月,Linux Auditing subsystem(auditd)被引入内核2.6.6-rc1通过修改内核代码,添加工具专用的数据源Tracing框架和数据源解耦,数据源由专用演进为通用2005年4月,动态探针技术 Kprobe被引入内核(v2.6.11.7)2008年10月,静态探针技术 Tracepoint 被引入内核(v2.6.2
7、8)However,statically declaring an instrumentation site for dynamic activation typically incurs a non-zero performance overhead due to the test and branch required to skip the instrumentation call.性能差强耦合I identified the need to decouple instrumentation from the tracer.The idea is that adding instrume
8、ntation to the Linux kernel is a task better performed by contributors and experts of each individual kernel subsystem.LTTng和Tracepoint的作者,Mathieu Desnoyers的2009年毕业论文首届中国首届中国eBPFeBPF研讨会研讨会可以Hook几乎所有的内核函数不稳定(函数的变更可能导致程序失效)性能相对Tracepoint更差Tracepoint VS KprobeTRACE_EVENT(sched_process_exec,TP_PROTO(str
9、ucttask_struct*p,pid_told_pid,structlinux_binprm*bprm),.);staticintexec_binprm(structlinux_binprm*bprm)/*.*/trace_sched_process_exec(current,old_pid,bprm);return0;2012年新的Tracepoint sched_process_exec被引入内核 1稳定(内核子系统开发者会负责维护该函数的稳定性)性能好 需要修改内核代码来添加新的Tracepoint点。内核支持的Tracepoint数量有限1 https:/ 工作原理示意图指令1跳转
10、指令内核函数自定义代码首届中国首届中国eBPFeBPF研讨会研讨会Linux Tracing System 发展历程1999年,LTT(Linux Trace Toolkit)发布2004年4月,Linux Auditing subsystem(auditd)被引入内核2.6.6-rc1通过修改内核代码,添加工具专用的数据源Tracing框架和数据源解耦,数据源由专用演进为通用2005年4月,Kprobe被引入内核2.6.11.72008年10月,Kernel Tracepoint 被引入内核(v2.6.28)。涌现了一批基于通用数据源的Tracing框架和工具2006年,LTTng发布(没有
11、合入内核)2009年,perf被引入内核性能差强耦合首届中国首届中国eBPFeBPF研讨会研讨会Linux Tracing System 发展历程1999年,LTT(Linux Trace Toolkit)发布(没有被引入内核)2004年4月,Linux Auditing subsystem(auditd)被引入内核2.6.6-rc1通过修改内核代码,添加工具专用的数据源Tracing框架和数据源解耦,数据源由专用演进为通用2005年4月,Kprobe被引入内核2.6.11.72008年10月,Kernel Tracepoint 被引入内核(v2.6.28)。2009年,SystemTap 1
12、.0 发布(至今没有合入内核)涌现了一批基于通用数据源的Tracing框架和工具2006年,LTTng发布(没有合入内核)2009年,perf被引入内核Tracing框架支持内核编程eBPF:支持用户自定义代码在内核中更安全地运行2014年,Alexei Starovoitov将eBPF引入内核不支持内核编程安全性差性能差强耦合首届中国首届中国eBPFeBPF研讨会研讨会eBPF的优势:l安全性:通过验证器,防止用户编写的程序导致内核崩溃。p相比内核模块,eBPF的安全性更容易被产品线接受。l免安装:eBPF内置于Linux内核,无需安装额外依赖,开箱即用。l内核编程:支持开发者插入自定义的代
13、码逻辑(包括数据采集、分析和过滤)到内核中运行采集框架安全性Linux内核内置内核编程性能Linux Auditing SubsystemSystemTapLTTngperf/ftraceeBPFTracing内核框架对比首届中国首届中国eBPFeBPF研讨会研讨会eBPF目前正在高速发展,很多坑和解决办法缺乏官方文档,在eBPF开发实践中经常遇到的问题,包括1.eBPF开发框架的选择2.eBPF如何跨内核版本运行(可移植性)3.如何为低版本内核生成BTF文件4.eBPF验证机制与编译器优化机制的不一致问题5.eBPF在ARM架构遇到的问题6.eBPF框架开发经验分享首届中国首届中国eBPFe
14、BPF研讨会研讨会*Photo from ebpf.ioLibraries:libbpf/bcc/other third-part onesbpf()eBPF 用户态程序用户态程序加载加载eBPF程序到内核程序到内核Tracepoints/Krpobes监控主机上运行的进程监控主机上运行的进程编译eBPF源代码 内核验证并运行eBPF程序触发eBPF程序执行eBPF程序分为两部分:用户态和内核态代码。eBPF背景介绍工作流程首届中国首届中国eBPFeBPF研讨会研讨会SEC(kprobe/do_unlinkat)intBPF_KPROBE(do_unlinkat,intdfd,structfi
15、lename*name)/获取一个数组指针array(数组MAX_SIZE为16个字节)u32key=0;char*array=bpf_map_lookup_elem(&array_map,&key);if(array=NULL)return0;/获取当前运行程序的CPU编号(当前机器的CPU有16个核)unsignedintpos=bpf_get_smp_processor_id();/根据下标修改数组的值arraypos=1;return0;eBPF会被LLVM编译为eBPF字节码 eBPF字节码需要通过eBPF verifier的(静态)验证后,才能真正运行 边界检查是eBPF veri
16、fy的重点工作,防止eBPF程序内存越界访问eBPF验证器边界检查案例首届中国首届中国eBPFeBPF研讨会研讨会0000000000000000:;intBPF_KPROBE(do_unlinkat,intdfd,structfilename*name)0:r1=0;u32key=0;1:*(u32*)(r10-4)=r12:r2=r103:r2+=-4;char*array=bpf_map_lookup_elem(&array_map,&key);4:r1=0ll6:call17:r6=r0;if(array=NULL)8:ifr6=0goto+6;unsignedintpos=bpf_g
17、et_smp_processor_id();9:call8;arraypos=1;10:r0=3212:r6+=r013:r1=1;arraypos=1;14:*(u8*)(r6+0)=r114行无法通过验证因为R6寄存器(变量pos)没有进行边界检查eBPF验证器边界检查案例首届中国首届中国eBPFeBPF研讨会研讨会0000000000000000:;intBPF_KPROBE(do_unlinkat,intdfd,structfilename*name)0:r1=0;u32key=0;1:*(u32*)(r10-4)=r12:r2=r103:r2+=-4;char*array=bpf_m
18、ap_lookup_elem(&array_map,&key);4:r1=0ll6:call17:r6=r0;if(array=NULL)8:ifr6=0goto+7;unsignedintpos=bpf_get_smp_processor_id();9:call810:r0=32;if(pos15goto+3;arraypos=1;13:r6+=r014:r1=1;arraypos=1;15:*(u8*)(r6+0)=r1通过验证,可以运行解决方案:添加边界检查代码eBPF验证器边界检查案例首届中国首届中国eBPFeBPF研讨会研讨会SEC(kprobe/do_unlinkat)intBPF
19、_KPROBE(do_unlinkat,intdfd,structfilename*name)/获取一个数组指针array(数组MAX_SIZE为16个字节)u32key=0;char*array=bpf_map_lookup_elem(&array_map,&key);if(array=NULL)return0;/获取当前运行程序的CPU编号(当前机器的CPU有16个核)unsignedintpos=bpf_get_smp_processor_id();/修改数值if(pos32,bpf_get_current_pid_tgid(),array1);/修改数值if(posMAX_SIZE)a
20、rraypos=1;return0;通过验证,可以运行代码测试环境均为:1.LLVM 112.Ubuntu 5.8.0内核版本3.libbpf commit 9c44c8a一个print引发的惨案首届中国首届中国eBPFeBPF研讨会研讨会SEC(kprobe/do_unlinkat)intBPF_KPROBE(do_unlinkat,intdfd,structfilename*name)/获取一个数组指针array(数组MAX_SIZE为16个字节)u32key=0;char*array=bpf_map_lookup_elem(&array_map,&key);if(array=NULL)r
21、eturn0;/获取当前运行程序的CPU编号(当前机器的CPU有16个核)unsignedintpos=bpf_get_smp_processor_id();/修改数值if(pos32,bpf_get_current_pid_tgid(),array1);/修改数值if(posMAX_SIZE)arraypos=1;return0;无法通过验证因为R0寄存器(变量pos)没有进行边界检查仅仅删除源码中的print代码,导致无法通过验证一个print引发的惨案首届中国首届中国eBPFeBPF研讨会研讨会Page 19;if(pos15goto+9;arraypos=1;14:r3=r615:r3
22、+=r116:r2=117:*(u8*)(r3+0)=r2编译器存在自身的代码优化机制,逻辑相似的代码可能会生成完全不同的eBPF字节码;if(posMAX_SIZE)18:ifr1=15goto+4;arraypos=1;19:r0=32;pos+=1;21:r0+=r6;arraypos=1;22:*(u8*)(r0+1)=r2根本原因:编译优化导致eBPF verifier无法获得完整的上下文信息if(posMAX_SIZE)arraypos=1;pos+=1;if(posMAX_SIZE)arraypos=1;对r1进行了边界检查,并用r1来访问了数组array对r1进行了边界检查,但
23、却用r0+1来访问了数组array通过验证,可以运行无法通过验证,寄存器r0没有边界检查源代码eBPF字节码eBPF验证机制与编译器优化机制的不一致问题(1)首届中国首届中国eBPFeBPF研讨会研讨会SEC(kprobe/do_unlinkat)intBPF_KPROBE(do_unlinkat,intdfd,structfilename*name)/获取一个数组指针array(数组MAX_SIZE为16个字节)u32key=0;char*array=bpf_map_lookup_elem(&array_map,&key);if(array=NULL)return0;/获取当前运行程序的CP
24、U编号(当前机器的CPU有16个核)unsignedlongpos=bpf_get_smp_processor_id();/修改数值if(posMAX_SIZE)arraypos=1;return0;通过验证,可以运行eBPF验证机制与编译器优化机制的不一致问题(2)首届中国首届中国eBPFeBPF研讨会研讨会SEC(kprobe/do_unlinkat)intBPF_KPROBE(do_unlinkat,intdfd,structfilename*name)/获取一个数组指针array(数组MAX_SIZE为16个字节)u32key=0;char*array=bpf_map_lookup_e
25、lem(&array_map,&key);if(array=NULL)return0;/获取当前运行程序的CPU编号(当前机器的CPU有16个核)unsignedlongpos=bpf_get_smp_processor_id();/修改数值if(posMAX_SIZE)for(unsignedlongi=0;i32,bpf_get_current_pid_tgid(),arrayi);arraypos=1;return0;仅仅在源码中添加了print代码,导致无法通过验证无法通过验证因为R1寄存器(变量pos)没有进行边界检查eBPF验证机制与编译器优化机制的不一致问题(2)首届中国首届中国
26、eBPFeBPF研讨会研讨会;if(pos15goto+3;arraypos=1;13:r6+=r014:r1=1;arraypos=1;15:*(u8*)(r6+0)=r1;if(pos15goto+2413:*(u64*)(r10-16)=r0.;arraypos=1;33:r1=*(u64*)(r10-16)34:r7+=r135:r1=136:*(u8*)(r7+0)=r1根本原因:寄存器溢出/重加载后,状态丢失if(posMAX_SIZE)arraypos=1;if(posMAX_SIZE)for()bpf_printk();arraypos=1;通过验证,可以运行无法通过验证,寄存
27、器r1没有边界检查源代码eBPF字节码eBPF验证机制与编译器优化机制的不一致问题(2)首届中国首届中国eBPFeBPF研讨会研讨会eBPF验证机制与编译器优化机制的不一致问题 的缓解思路1.在源码中加入&=操作符,引导编译器生成理想的eBPF字节码arraypos&=MAX_SIZE-1=1;2.如果上述方法失效,无法引导编译器,那么针对出错的部分源代码人工编写eBPF字节码,替代编译器生成的字节码#defineSTR(s)#s#defineXSTR(s)STR(s)#defineasm_variable_bound_check(variable)(asmvolatile(%tmp&=XSTR(MAX_SIZE-1)n:tmp+&r(variable);)asm_check(pos);arraypos=1;首届中国首届中国eBPFeBPF研讨会研讨会