Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jprobe没有';t监控所有的'do_execve'呼叫_C_Linux Kernel_Jprobe - Fatal编程技术网

Jprobe没有';t监控所有的'do_execve'呼叫

Jprobe没有';t监控所有的'do_execve'呼叫,c,linux-kernel,jprobe,C,Linux Kernel,Jprobe,我知道过去有一个问题,但我没有找到解决办法 我正在编写下一个内核模块来跟踪do\u exec调用。AFAIK每个新的进程映像(不是创建)都应该这样加载,所以我想我可以用这个jprobe跟踪所有的执行情况 不幸的是,此jprobe的唯一输出是: execve通过kworker/u8:3调用/usr/lib/systemd/systemd cgroups代理 我的模块代码如下: #include <linux/kernel.h> #include <linux/module.h&g

我知道过去有一个问题,但我没有找到解决办法

我正在编写下一个内核模块来跟踪
do\u exec
调用。AFAIK每个新的进程映像(不是创建)都应该这样加载,所以我想我可以用这个
jprobe
跟踪所有的执行情况

不幸的是,此
jprobe的唯一输出是:

execve通过kworker/u8:3调用/usr/lib/systemd/systemd cgroups代理

我的模块代码如下:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/fs.h>

static long jdo_execve(struct filename *filename, 
        const char __user *const __user __argv, 
        const char __user *const __user __envp)
{
    const char *name = filename->name;
    printk("execve called %s by %s\n", name, current->comm);
    jprobe_return();
    return 0;
}

static struct jprobe execve_jprobe = {
    .entry          = jdo_execve,
    .kp = {
        .symbol_name    = "do_execve",
    },
};

static int __init jprobe_init(void)
{
    int ret;

    ret = register_jprobe(&execve_jprobe);
    if (ret < 0) {
        printk(KERN_INFO "register_jprobe failed, returned %d\n", ret);
        return -1;
    }
    return 0;
}

static void __exit jprobe_exit(void)
{
    unregister_jprobe(&execve_jprobe);
    printk(KERN_INFO "jprobe at %p unregistered\n", write_jprobe.kp.addr);
}

module_init(jprobe_init)
module_exit(jprobe_exit)
MODULE_LICENSE("GPL");
#包括
#包括
#包括
#包括
静态长jdo_execve(结构文件名*文件名,
常量字符*常量用户*常量用户,
常量字符用户*常量用户环境)
{
常量字符*名称=文件名->名称;
printk(“execve由%s调用%s\n”,名称,当前->通信);
jprobe_return();
返回0;
}
静态结构jprobe execve\u jprobe={
.entry=jdo_execve,
.kp={
.symbol\u name=“do\u execve”,
},
};
静态整数初始化jprobe初始化(无效)
{
int ret;
ret=寄存器(register_jprobe)(&execve_jprobe);
如果(ret<0){
printk(KERN_INFO“register_jprobe失败,返回%d\n”,ret);
返回-1;
}
返回0;
}
静态void\uuu退出jprobe\u退出(void)
{
取消注册\u jprobe(&execve\u jprobe);
printk(KERN_INFO“jprobe at%p unregistered\n”,write_jprobe.kp.addr);
}
模块初始化(jprobe初始化)
模块出口(jprobe出口)
模块许可证(“GPL”);
我使用的是CentOS 7,内核版本3.10.0-514.el7.x86_64

感谢您的帮助

手边的代码是:

SYSCALL_DEFINE3(execve,
                const char __user *, filename,
                const char __user *const __user *, argv,
                const char __user *const __user *, envp)
{
        return do_execve(getname(filename), argv, envp);
}
以及:

考虑到函数有多短,第一个明显的怀疑是它内联到了execve入口点。他证实了这一怀疑:

0xffffffff811e6e20 <sys_execve>:        nopl   0x0(%rax,%rax,1) [FTRACE NOP]
0xffffffff811e6e25 <sys_execve+0x5>:    push   %rbp
0xffffffff811e6e26 <sys_execve+0x6>:    mov    %rsp,%rbp
0xffffffff811e6e29 <sys_execve+0x9>:    push   %r12
0xffffffff811e6e2b <sys_execve+0xb>:    mov    %rdx,%r12
0xffffffff811e6e2e <sys_execve+0xe>:    push   %rbx
0xffffffff811e6e2f <sys_execve+0xf>:    mov    %rsi,%rbx
0xffffffff811e6e32 <sys_execve+0x12>:   callq  0xffffffff811ef380 <getname>
0xffffffff811e6e37 <sys_execve+0x17>:   mov    %r12,%r8
0xffffffff811e6e3a <sys_execve+0x1a>:   mov    %rbx,%rdx
0xffffffff811e6e3d <sys_execve+0x1d>:   xor    %ecx,%ecx
0xffffffff811e6e3f <sys_execve+0x1f>:   xor    %esi,%esi
0xffffffff811e6e41 <sys_execve+0x21>:   mov    %rax,%rdi
0xffffffff811e6e44 <sys_execve+0x24>:   callq  0xffffffff811e6520 <do_execve_common>
0xffffffff811e6e49 <sys_execve+0x29>:   pop    %rbx
0xffffffff811e6e4a <sys_execve+0x2a>:   pop    %r12
0xffffffff811e6e4c <sys_execve+0x2c>:   cltq   
0xffffffff811e6e4e <sys_execve+0x2e>:   pop    %rbp
0xffffffff811e6e4f <sys_execve+0x2f>:   retq   
0xFFFFFF811E6E20:nopl 0x0(%rax,%rax,1)[FTRACE NOP]
0xFF811E6E25:推送%rbp
0xFFFF811E6E26:mov%rsp,%rbp
0xFF811E6E29:推送%r12
0xFFFF811E6E2B:mov%rdx,%r12
0xFFFF811E6E2E:推送%rbx
0xFFFF811E6E2F:mov%rsi,%rbx
0xFFFFFF811E6E32:调用0xffffffff811ef380
0xFFFF811E6E37:mov%r12,%r8
0xFFFF811E6E3A:mov%rbx,%rdx
0xFFFF811E6E3D:xor%ecx,%ecx
0xFFFF811E6E3F:xor%esi,%esi
0xFFFF811E6E41:mov%rax,%rdi
0xFFFFFF811E6E44:调用0xffffffff811e6520
0xFFFF811E6E49:弹出%rbx
0xFFFF811E6E4A:弹出%r12
0xFFFF811E6E4C:cltq
0xFFFF811E6E4E:弹出%rbp
0xFFFF811E6E4F:retq
因此,您看不到大多数要执行的“调用”,因为在您感兴趣的代码路径中没有任何调用

另一种调试方法是尝试在堆栈中更深或更高的位置放置探测器


我不得不问你为什么要玩jprobes或者内核。到目前为止,您似乎是一个初学者程序员,现在还不应该玩它。特别是,您不太可能编写遵循所有规则的内核代码(包括jprobes),并且能够解释为什么会这样做。创建代码太容易了,因为在测试不足的情况下,代码似乎可以工作,但却被破坏了。

AFAIK每个新的进程映像(不是创建)都应该这样加载
-例如,从32位环境执行的进程不使用此函数,它们使用
compat\u do\u execve
。尝试钩住
do\u execve\u common
,这样你也会截获32位进程创建。当然,忘了提到我正在运行一个64位内核,这个内核中没有
compat\u do\u execve
符号(请参阅文章中的确切版本)符号
compat\u execve
(以及其他“compat”符号)当系统调用由32位应用程序发出时,是专门针对64位内核的(是的,我在您的帖子中注意到了内核版本)。换句话说,您有64位内核,64位操作系统,但它可以运行32位应用程序,它将使用“compat”系统调用[root@localhost3.10.0-514.el7.x86_64]#grep-R do_execve*include/linux/sched.h:extern int do_execve(结构文件名*,System.map:ffffffffff81205ac0 t do_execve\u common.isra.25 System.map:ffffffffff81206150 t do_execve[root@localhost3.10.0-514.el7.x86_64]#grep-R compat_do_execve*[root@localhost3.10.0-514.el7.x86_64]35;
0xffffffff811e6e20 <sys_execve>:        nopl   0x0(%rax,%rax,1) [FTRACE NOP]
0xffffffff811e6e25 <sys_execve+0x5>:    push   %rbp
0xffffffff811e6e26 <sys_execve+0x6>:    mov    %rsp,%rbp
0xffffffff811e6e29 <sys_execve+0x9>:    push   %r12
0xffffffff811e6e2b <sys_execve+0xb>:    mov    %rdx,%r12
0xffffffff811e6e2e <sys_execve+0xe>:    push   %rbx
0xffffffff811e6e2f <sys_execve+0xf>:    mov    %rsi,%rbx
0xffffffff811e6e32 <sys_execve+0x12>:   callq  0xffffffff811ef380 <getname>
0xffffffff811e6e37 <sys_execve+0x17>:   mov    %r12,%r8
0xffffffff811e6e3a <sys_execve+0x1a>:   mov    %rbx,%rdx
0xffffffff811e6e3d <sys_execve+0x1d>:   xor    %ecx,%ecx
0xffffffff811e6e3f <sys_execve+0x1f>:   xor    %esi,%esi
0xffffffff811e6e41 <sys_execve+0x21>:   mov    %rax,%rdi
0xffffffff811e6e44 <sys_execve+0x24>:   callq  0xffffffff811e6520 <do_execve_common>
0xffffffff811e6e49 <sys_execve+0x29>:   pop    %rbx
0xffffffff811e6e4a <sys_execve+0x2a>:   pop    %r12
0xffffffff811e6e4c <sys_execve+0x2c>:   cltq   
0xffffffff811e6e4e <sys_execve+0x2e>:   pop    %rbp
0xffffffff811e6e4f <sys_execve+0x2f>:   retq