You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kprobe挂钩getdents64系统调用时count参数读取异常求助

解决kprobe挂钩getdents64系统调用时count参数返回-1的问题

问题背景

在XUbuntu 22.04(内核版本5.15.0-107-generic x86_64)环境下,使用kprobe挂钩__x64_sys_getdents64系统调用入口,尝试读取第三个参数count时,内核日志始终输出-1,但该参数应为用户态传入的正整数值。

核心原因

你混淆了kprobe handler中struct pt_regs的含义:

  • __x64_sys_getdents64的实际原型是long __x64_sys_getdents64(const struct pt_regs *user_regs),它接收的是用户态触发系统调用时的寄存器快照指针,而非直接的系统调用参数。
  • 你当前代码中直接访问的regs->dx是进入内核函数__x64_sys_getdents64时的CPU寄存器状态,并非用户态传递给getdents64的count参数。

解决方案

修改kprobe的预处理函数,先获取__x64_sys_getdents64的第一个参数(即用户态寄存器快照指针),再从该快照中提取正确的系统调用参数:

  • x86_64用户态系统调用参数传递规则:第1个参数存于rdi,第2个存于rsi,第3个存于rdx。

修改后的关键代码如下:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
#include <linux/syscalls.h>  // 确保包含pt_regs相关定义

static struct kprobe kp;

static int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
    // 获取__x64_sys_getdents64的第一个参数:用户态寄存器快照指针
    const struct pt_regs *user_regs = (const struct pt_regs *)regs->di;
    
    // 从用户态寄存器快照中提取系统调用参数
    int fd = user_regs->di;
    unsigned long dirp = user_regs->si;
    int count = user_regs->dx;
    
    printk(KERN_INFO "kprobe: getdents64 called, fd=%d, count=%d\n", fd, count);
    return 0;
}

// 其余模块初始化/退出代码保持不变
static int __init kprobe_init(void)
{
    kp.pre_handler = handler_pre;
    kp.symbol_name = "__x64_sys_getdents64";

    if (register_kprobe(&kp) < 0) {
        printk(KERN_ERR "register_kprobe failed\n");
        return -1;
    }
    printk(KERN_INFO "kprobe registered\n");
    return 0;
}

static void __exit kprobe_exit(void)
{
    unregister_kprobe(&kp);
    printk(KERN_INFO "kprobe unregistered\n");
}

module_init(kprobe_init)
module_exit(kprobe_exit)
MODULE_LICENSE("GPL");

验证步骤

  1. 保持原Makefile不变,重新编译模块:
make clean && make
  1. 加载模块并查看内核日志:
sudo insmod hidproc.ko
tail -f /var/log/kern.log

此时你应该能看到正确的count参数值(通常为用户态传入的缓冲区大小,如4096)。

额外注意事项

  • 确保挂钩的系统调用入口正确:x86_64系统下,64位程序调用getdents64会进入__x64_sys_getdents64,32位兼容程序会进入__ia32_sys_getdents64,根据你的需求选择对应入口。
  • 内核日志打印建议使用KERN_INFO/KERN_ERR等级别宏,便于区分日志类型。

内容的提问来源于stack exchange,提问作者Jelal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:17:32