首页 > 解决方案 > Linux x86-64 系统调用挂钩,路径名乱码

问题描述

我一直在尝试在 x86_64 Linux 系统上挂接 Linux 系统调用,sys_call_table遵循/proc/kallsyms.

然而,在我的蹦床上,特别是对于解析文件路径(如 openat、makedir)的系统调用,我似乎正在检索非人类可读的文件路径printk(path),其中路径是传递给被拦截的系统调用的确切形式参数。

如此处所见

有人可以解释为什么我无法从系统调用中截取人类可读的路径名吗?例如/usr/home/file.txt

问题绕道:

asmlinkage int sys_access_trampoline(const char __user *path, int mode)
{
    char buffer[STR_MAX];
    strncpy_from_user(buffer, path, strnlen_user(path, PATH_MAX+1));
    printk(buffer);  // prints \xe1\xaa\xff\xff\ etc...
    STUB_ORIGIN();
    return sys_access(path, mode);
}

标签: clinuxlinux-kernelsystem-callskernel-module

解决方案


正如 Tsyvarev 所暗示的,对于较新的内核版本( > 4.17 ),传递系统调用参数的方式已经改变,并且要求拦截蹦床具有以下签名:

asmlinkage __type__ sys_foobar(const struct pt_regs * regs).

然后通过相应的寄存器访问各个参数,即 (x86_64)

        arg1   arg2   arg3   arg4    arg5   arg6 
regs->  (di)   (si)   (dx)   (r10)   (r8)   (r9)

因此,要获取访问系统调用的路径字符串,您可以使用regs->di.

asmlinkage int sys_access_trampoline(const struct pt_regs * regs)
{
    char buffer[STR_MAX];
    strncpy_from_user(buffer, regs->di, strnlen_user(path, PATH_MAX+1));
    printk(buffer);  
    STUB_ORIGIN();
    return sys_access(path, mode);
}

我现在收到正确的 ASCII 路径名。

感谢大家的帮助!


推荐阅读