stat系列系统调用混淆及kprobe挂载相关技术问询
问题描述
我尝试为stat系统调用设置kprobe以捕获相关信息,但查看/proc/kallsyms时发现大量相似名称的符号,难以确定正确的挂载目标。我的需求是找到对应stat filename或stat dir输出数据的系统调用。
我首先尝试挂载__x64_sys_stat,但处理函数未被触发;随后尝试__do_sys_stat、__x64_sys_newstat,同样无响应。/proc/kallsyms相关输出如下:
user@xubun2204:~$ cat /proc/kallsyms | grep newstat 0000000000000000 t __do_sys_newstat 0000000000000000 T __x64_sys_newstat 0000000000000000 T __ia32_sys_newstat 0000000000000000 t __do_compat_sys_newstat 0000000000000000 T __ia32_compat_sys_newstat 0000000000000000 T __x64_compat_sys_newstat 0000000000000000 d event_exit__newstat 0000000000000000 d event_enter__newstat 0000000000000000 d __syscall_meta__newstat 0000000000000000 d args__newstat 0000000000000000 d types__newstat 0000000000000000 d __event_exit__newstat 0000000000000000 d __event_enter__newstat 0000000000000000 d __p_syscall_meta__newstat 0000000000000000 d _eil_addr___x64_compat_sys_newstat 0000000000000000 d _eil_addr___ia32_compat_sys_newstat 0000000000000000 d _eil_addr___ia32_sys_newstat 0000000000000000 d _eil_addr___x64_sys_newstat user@xubun2204:~$ cat /proc/kallsyms | grep do_stat 0000000000000000 T proc_do_static_key 0000000000000000 T do_statx 0000000000000000 t do_statfs_native 0000000000000000 t do_statfs64 user@xubun2204:~$ cat /proc/kallsyms | grep sys_stat 0000000000000000 t __do_sys_stat 0000000000000000 T __x64_sys_stat 0000000000000000 T __ia32_sys_stat 0000000000000000 T __x64_sys_statx 0000000000000000 T __ia32_sys_statx 0000000000000000 t __do_sys_statfs 0000000000000000 T __x64_sys_statfs 0000000000000000 T __ia32_sys_statfs 0000000000000000 t __do_sys_statfs64 0000000000000000 T __x64_sys_statfs64 0000000000000000 T __ia32_sys_statfs64 0000000000000000 t __do_compat_sys_statfs 0000000000000000 T __ia32_compat_sys_statfs 0000000000000000 T __x64_compat_sys_statfs 0000000000000000 T kcompat_sys_statfs64 0000000000000000 T __ia32_compat_sys_statfs64 0000000000000000 T __x64_compat_sys_statfs64 0000000000000000 d _eil_addr___ia32_sys_statx 0000000000000000 d _eil_addr___x64_sys_statx 0000000000000000 d _eil_addr___ia32_sys_stat 0000000000000000 d _eil_addr___x64_sys_stat 0000000000000000 d _eil_addr___x64_compat_sys_statfs64 0000000000000000 d _eil_addr___ia32_compat_sys_statfs64 0000000000000000 d _eil_addr___x64_compat_sys_statfs 0000000000000000 d _eil_addr___ia32_compat_sys_statfs 0000000000000000 d _eil_addr___ia32_sys_statfs64 0000000000000000 d _eil_addr___x64_sys_statfs64 0000000000000000 d _eil_addr___ia32_sys_statfs 0000000000000000 d _eil_addr___x64_sys_statfs
之后我尝试__x64_sys_statfs,处理函数成功被触发!我原本理解sys_stat用于获取文件/目录信息,sys_statfs用于获取文件系统信息,但无论我对stat命令传入文件、目录还是文件系统路径,__x64_sys_statfs都会被调用。现在我疑惑该syscall返回的是struct kstat还是struct statfs?
以下是我成功触发kretprobe处理函数的代码:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/kprobes.h> #include <linux/statfs.h> #include <linux/slab.h> #include <linux/fs.h> static struct kretprobe my_kretprobe; static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { printk("entry_handler\n"); return 0; } static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs) { printk("ret_handler\n"); return 0; } static int __init my_module_init(void) { int ret; my_kretprobe.kp.symbol_name = "__x64_sys_statfs"; my_kretprobe.entry_handler = entry_handler; my_kretprobe.handler = ret_handler; my_kretprobe.maxactive = 20; ret = register_kretprobe(&my_kretprobe); if (ret < 0) { printk(KERN_INFO "register_kretprobe failed, returned %d\n", ret); return ret; } printk(KERN_INFO "Kretprobe registered for __x64_sys_statfs\n"); return 0; } static void __exit my_module_exit(void) { unregister_kretprobe(&my_kretprobe); printk(KERN_INFO "Kretprobe unregistered\n"); } module_init(my_module_init); module_exit(my_module_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("jelal"); MODULE_DESCRIPTION("simple kret lkm");
以及Makefile:
obj-m += statdata.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
我的实验目标是从内核中获取stat命令展示的数据,现存在以下疑问:
- sys_stat、sys_statfs、sys_newstat和sys_statx之间有何区别?
- 如何确定应挂载探针的正确系统调用?
- sys_stat未被调用的原因是什么?
解答
1. sys_stat、sys_statfs、sys_newstat和sys_statx的区别
- sys_stat:早期的系统调用,对应旧版
struct stat结构,字段长度和布局受32位/64位架构限制,属于被淘汰的旧接口,仅用于兼容老旧程序。 - sys_newstat:sys_stat的过渡改进版,解决了32位系统中
struct stat字段溢出问题,但仍为架构相关接口,现在已被新接口替代。 - sys_statfs:专门用于获取文件系统层面的信息,比如总容量、可用空间、块大小等,返回
struct statfs结构。stat命令会触发它,是因为默认会输出挂载点等文件系统相关信息。 - sys_statx:Linux 4.11+引入的新一代统一接口,支持扩展属性、高精度时间戳,兼容32/64位架构,是当前用户态工具(包括stat命令)实际调用的核心系统调用。
2. 确定正确系统调用的方法
- 直接跟踪用户态调用:用
strace stat filename查看stat命令实际触发的系统调用,这是最精准的方式,会发现现代系统中stat实际调用的是statx。 - 分析内核符号:关注带
statx的符号(比如__x64_sys_statx)以及内核内部处理函数do_statx,这些是当前stat命令的实际依赖点。 - 验证探针触发:先通过strace确认目标syscall,再挂载对应的kprobe,避免盲目尝试旧接口。
3. sys_stat未被调用的原因
现代Linux发行版中的stat命令(基于GNU coreutils)已默认使用statx系统调用,不再直接调用旧的sys_stat或sys_newstat。这些旧接口仅为兼容几十年前的程序保留,新工具不会主动使用,所以挂载__x64_sys_stat时不会被触发。
内容的提问来源于stack exchange,提问作者Jelal
相关产品推荐
相关产品推荐

