Linux内核源码编译
内核编译
可以首先搜索一下当前电脑上可以使用apt-get下载的linux-source版本
1
| sudo apt-cache search linux-source
|
要下载的是5.15.0版本的内核,首先执行sudo apt-get install linux-source-5.15.0来将内核源码给下载到/usr/src/linux-source-5.15.0文件夹下。
之后对当前文件夹执行sudo chmod 777 -R .来赋予当前目录写的权限。就可以对源码包进行解压tar xf linux-source-5.15.0.tar.bz2
然后将cp -R debin ./linux-source-5.15.0复制进去,然后cp /boot/config-$(uname -r) .config
就可以进入linux-source-5.15.0目录下执行make来编译了。
内核工具编译
在源码目录下其实存在很多linux自带的工具,比如perf,可以尝试对其进行编译。进入到/usr/src/linux-source-5.15.0/linux-source-5.15.0/tools/perf目录下直接执行make。
traceFS
监测点详解
1 2
| sudo cat /sys/kernel/debug/tracing/available_filter_functions | wc -l
|
- available_events文件
- 在/sys/kernel/debug/tracing目录下存在available_events文件,用来表示该操作系统中可用的挂载点,是在available_filter_functions文件中挑选过的非常稳定的挂载点。

该目录下存放了所有可以被监测的Hook点,并用目录对其进行了分类。比如存在power目录或者syscalls目录,这些目录下都存放的是对应的很多个Hook点。并且在events目录下是存在一个enable文件,该文件是所有监测点的总开关,如果将该文件的内容设置为1的时候,该目录下的所有监测点就会被激活。

但是如果将子文件夹下的enable文件设置为1的话,那么只有该子文件夹下的监测点会被激活。并且如果只想要激活某一个监测点的话,就可以只激活该监测点文件夹下的enable文件。
1 2 3 4 5 6
| red256@maomao:~$ sudo ls /sys/kernel/debug/tracing/events/raw_syscalls enable filter sys_enter sys_exit
red256@maomao:~$ sudo ls /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter enable filter format hist id inject trigger
|
在每一个特定的监测点下都会有个format文件,其中的内容是关于该监测点的字段信息,描述了参数、返回值、参数类型等等。
1 2 3 4 5 6 7 8 9 10 11 12 13
| red256@maomao:~$ sudo cat /sys/kernel/debug/tracing/events/raw_syscalls/sys_enter/format name: sys_enter ID: 24 format: field:unsigned short common_type; offset:0; size:2; signed:0; field:unsigned char common_flags; offset:2; size:1; signed:0; field:unsigned char common_preempt_count; offset:3; size:1; signed:0; field:int common_pid; offset:4; size:4; signed:1;
field:long id; offset:8; size:8; signed:1; field:unsigned long args[6]; offset:16; size:48; signed:0;
print fmt: "NR %ld (%lx, %lx, %lx, %lx, %lx, %lx)", REC->id, REC->args[0], REC->args[1], REC->args[2], REC->args[3], REC->args[4], REC->args[5]
|
激活uprobes
针对/bin/bash中的readline方法进行uprobe的监测。首先使用readelf来找到readline方法的偏移地址是0x00000000000d2190
1 2 3 4 5 6 7
| red256@red256-virtual-machine:~$ readelf -s /bin/bash | grep readline | grep FUNC 348: 00000000000d1dc0 968 FUNC GLOBAL DEFAULT 13 readline_interna[...] 851: 00000000000d0d60 620 FUNC GLOBAL DEFAULT 13 readline_interna[...] 901: 0000000000097364 264 FUNC GLOBAL DEFAULT 13 posix_readline_i[...] 922: 00000000000d5700 208 FUNC GLOBAL DEFAULT 13 readline 1293: 00000000000948d0 24 FUNC GLOBAL DEFAULT 13 initialize_readline 2111: 00000000000d0fd0 776 FUNC GLOBAL DEFAULT 13 readline_interna[...]
|
之后对文件内容进行更新
1
| sudo bash -c 'echo p:readline /bin/bash:0x00000000000d5700 %ip %ax > /sys/kernel/debug/tracing/uprobe_events'
|
可以查询一下该文件中的内容
1 2
| red256@red256-virtual-machine:~$ sudo cat /sys/kernel/debug/tracing/uprobe_events p:uprobes/readline /bin/bash:0x00000000000d5700 arg1=%ip arg2=%ax
|
并且当这个文件中存在内容的时候,在/sys/kernel/debug/tracing/events/uprobes目录下就会存在对应的监测点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| red256@red256-virtual-machine:~$ sudo ls /sys/kernel/debug/tracing/events/uprobes enable filter readline red256@red256-virtual-machine:~$ sudo ls /sys/kernel/debug/tracing/events/uprobes/readline enable filter format hist id inject trigger red256@red256-virtual-machine:~$ sudo ls /sys/kernel/debug/tracing/events/uprobes/readline/format /sys/kernel/debug/tracing/events/uprobes/readline/format red256@red256-virtual-machine:~$ sudo cat /sys/kernel/debug/tracing/events/uprobes/readline/format name: readline ID: 1634 format: field:unsigned short common_type; offset:0; size:2; signed:0; field:unsigned char common_flags; offset:2; size:1; signed:0; field:unsigned char common_preempt_count; offset:3; size:1; signed:0; field:int common_pid; offset:4; size:4; signed:1;
field:unsigned long __probe_ip; offset:8; size:8; signed:0; field:u64 arg1; offset:16; size:8; signed:0; field:u64 arg2; offset:24; size:8; signed:0;
print fmt: "(%lx) arg1=0x%Lx arg2=0x%Lx", REC->__probe_ip, REC->arg1, REC->arg2tr
|
新建好了监测点之后需要启用监测点,执行以下指令
1 2
| sudo bash -c 'echo 1 > /sys/kernel/debug/tracing/events/uprobes/readline/enbale' sudo bash -c 'echo 1 > /sys/kernel/debug/tracing/tracing_on'
|
可以通过查看/sys/kernel/debug/tracing/trace_pipe文件来查看一下管道输入。每当readline方法被调用的时候这里就会出现一个输出,这里并没有记录真实的字符串,但是记录的是参数的指针等等。
1 2 3 4 5 6
| red256@red256-virtual-machine:~$ sudo cat /sys/kernel/debug/tracing/trace_pipe bash-2171 [000] DNZff 4535.880055: readline: (0x5828a3d8a700) arg1=0x5828a3d8a700 arg2=0x5828a3ddc1bd bash-2171 [001] DNZff 4577.061549: readline: (0x5828a3d8a700) arg1=0x5828a3d8a700 arg2=0x5828a3ddc1bd bash-2171 [001] DNZff 4615.412384: readline: (0x5828a3d8a700) arg1=0x5828a3d8a700 arg2=0x5828a3ddc1bd <...>-4556 [000] DNZff 4621.275109: readline: (0x5dc7ef96c700) arg1=0x5dc7ef96c700 arg2=0x5dc7ef9be1bd bash-4556 [000] DNZff 4624.673064: readline: (0x5dc7ef96c700) arg1=0x5dc7ef96c700 arg2=0x5dc7ef9be1bd
|
当不需要的时候需要对监测点进行关闭
1 2 3 4
| sudo bash -c 'echo > /sys/kernel/debug/tracing/kprobe_events' sudo bash -c 'echo > /sys/kernel/debug/tracing/uprobe_events' sudo bash -c 'echo 0 > /proc/sys/kernel/ftrace_enabled' sudo bash -c 'echo 0 > /sys/kernel/debug/tracing/tracing_on'
|
perf工具使用
perf在ebpf流行起来之前,是在linux系统中常用的性能监测工具,那么现在perf涉及到的perf_event_open这个系统调用,被ebpf广泛的使用。
使用sudo apt-get install linux-tools-${uname -r}来安装perf
perf top
使用sudo pref top指令可以实现top指令的效果。会列举现在的程序使用的系统调用。
perf ftrace
perf工具针对ftrace也做了对应的封装,首先是可以执行sudo perf ftrace -F就可以打印所有的可以被探测的函数。实际上是读取了/sys/kernel/debug/tracing/available_filter_functions文件中的内容来打印出来的。
1 2 3 4
| red256@red256-virtual-machine:~/Desktop$ sudo perf ftrace -F | wc -l 59699 red256@red256-virtual-machine:~/Desktop$ sudo cat /sys/kernel/debug/tracing/available_filter_functions | wc -l 59699
|
perf record
当想使用perf来统计2秒中sys_enter_openat系统调用的次数的话,可以使用record指令
1
| sudo perf record -e 'syscalls:sys_enter_openat' -aR sleep 2
|
ebpf指令集
ebpf指令集规范
官方文档:https://docs.kernel.org/bpf/standardization/instruction-set.html