Jprobes

【用途】

类似于Kprobes和Return Probes,区别在于,Kprobes可以在任意指令处插入探针,Jprobes只在函数入口插入探针,而Return Probes则是在函数返回时插入探针。

【接口说明】【参考samples/kprobes/jprobe_example.c】

#include <linux/kprobes.h>

int register_jprobe(struct jprobe *jp);

void unregister_jprobe(struct jprobe *jp);

int enable_jprobe(struct jprobe *jp);

int disable_jprobe(struct jprobe *jp);

【番外篇】

我这篇也就写点儿使用Kprobe和Jprobe的注意事项:

用Kprobe和retprobe注册的handler运行于原子(atomic)上下文,因为它们都是运行在int3的异常处理函数或调试(debug)中断的处理函数中,并且两者都是在关闭当前cpu中断的前提下执行的。相比之下,Jprobe就灵活得多了,用它注册的handler的执行环境和原始的执行环境并没有两样,堆栈环境和cpu寄存器都是相同的。

因为Jprobe执行用户注册的handler之前有保存现场(主要是int3之前的CPU寄存器的值)的工作,所以Jprobe的handler是没有办法破坏寄存器的值的,但是可以改变堆栈中的变量的值,Kprobe将没有这些限制,它对系统具有完全的访问权限,另一方面,Kprobe也比Jprobe危险得多,如果只是简单的打印一些系统信息,推荐用Jprobe,不要冒险!

Jprobe机制和用户空间的setjmp和longjmp的实现比较类似,事实上,它的内核代码的注释部分也是如此作类比的,所以用register_jprobe注册的代码段,最后必须要用jprobe_return进行返回,当然,如果你想让它一去不复返除外。这点就象用kprobe注册的handler必须是可以返回的函数一样。目前,能想到的就这么多了。

BTW: 看kprobe的内核代码的时侯,发现有的地方还是有些缺陷的,比如说某些地方用preempt_disable()关闭了抢占,但是当函数出错返回的时侯,并没有打开抢占。不知道最新的内核有没有修复这些细节,懒得去看了,应该没有哪个正式的发型版会打开这个选项的。所以文章标题中所提到的注入的可能性也就比较小了,本来这个东西出现的背景就是为了方便内核开发者的调试工作!

【实例】

/*jprobe_test.c */

#include <linux/kernel.h>

#include <linux/module.h>

#include <linux/fs.h>

#include <linux/uio.h>

#include <linux/kprobes.h>

#include <linux/kallsyms.h>

/*

* Jumper probe for do_fork.

* Mirror principle enables access to arguments of the probed routine

* from the probe handler.

*/

/* Proxy routine having the same arguments as actual do_fork() routine */

long jdo_fork(

  unsigned long clone_flags,

  unsigned long stack_start,

struct pt_regs *regs,

  unsigned long stack_size,

  int __user * parent_tidptr,

  int __user * child_tidptr) {

  printk("jprobe: clone_flags=0x%lx, stack_size=0x%lx, regs=0x%p\n",       clone_flags, stack_size, regs);

  /* Always end with a call to jprobe_return(). */

  jprobe_return();

  /*NOTREACHED*/

  return 0;

}

static struct jprobe my_jprobe = {

.entry = (kprobe_opcode_t *) jdo_fork

};

int init_module(void) {

int ret;

my_jprobe.kp.addr = (kprobe_opcode_t *) kallsyms_lookup_name("do_fork");

if (!my_jprobe.kp.addr) {

printk("Couldn't find %s to plant jprobe\n", "do_fork");

return -1;

}

if ((ret = register_jprobe(&my_jprobe)) <0) {

printk("register_jprobe failed, returned %d\n", ret);

return -1;

}

printk("Planted jprobe at %p, handler addr %p\n",       my_jprobe.kp.addr, my_jprobe.entry);

return 0;

}

void cleanup_module(void) {   unregister_jprobe(&my_jprobe);   printk("jprobe unregistered\n"); }

MODULE_LICENSE("GPL");

Linux内核调试方法总结之Jprobes的更多相关文章

  1. Linux内核调试方法总结

    Linux内核调试方法总结 一  调试前的准备 二  内核中的bug 三  内核调试配置选项 1  内核配置 2  调试原子操作 四  引发bug并打印信息 1  BUG()和BUG_ON() 2   ...

  2. Linux内核调试方法总结【转】

    转自:http://my.oschina.net/fgq611/blog/113249 内核开发比用户空间开发更难的一个因素就是内核调试艰难.内核错误往往会导致系统宕机,很难保留出错时的现场.调试内核 ...

  3. 【转】Linux内核调试方法总结

    目录[-] 一  调试前的准备 二  内核中的bug 三  内核调试配置选项 1  内核配置 2  调试原子操作 四  引发bug并打印信息 1  BUG()和BUG_ON() 2  dump_sta ...

  4. Linux内核调试方法【转】

    转自:http://www.cnblogs.com/shineshqw/articles/2359114.html kdb:只能在汇编代码级进行调试: 优点是不需要两台机器进行调试. gdb:在调试模 ...

  5. Linux内核调试方法总结之反汇编

    Linux反汇编调试方法 Linux内核模块或者应用程序经常因为各种各样的原因而崩溃,一般情况下都会打印函数调用栈信息,那么,这种情况下,我们怎么去定位问题呢?本文档介绍了一种反汇编的方法辅助定位此类 ...

  6. Linux内核调试方法总结之栈帧

    栈帧 栈帧和指针可以说是C语言的精髓.栈帧是一种特殊的数据结构,在C语言函数调用时,栈帧用来保存当前函数的父一级函数的栈底指针,当前函数的局部变量以及被调用函数返回后下一条汇编指令的地址.如下图所示: ...

  7. Linux内核调试方法总结之序言

    本系列主要介绍Linux内核死机.异常重启类稳定性问题的调试方法. 在Linux系统中,一切皆为文件,而系统运行的载体,是一类特殊的文件,即进程.因此,我尝试从进程的角度分析Linux内核的死机.异常 ...

  8. Linux内核调试方法总结之ddebug

    [用途] Linux内核动态调试特性,适用于驱动和内核各子系统调试.动态调试的主要功能就是允许你动态的打开或者关闭内核代码中的各种提示信息.适用于驱动和内核线程功能调试. [使用方法] 依赖于CONF ...

  9. Linux内核调试方法总结之调试宏

    本文介绍的内核调试宏属于静态调试方法,通过调试宏主动触发oops从而打印出函数调用栈信息. 1) BUG_ON 查看bug处堆栈内容,主动制造oops Linux中BUG_ON,WARN_ON用于调试 ...

随机推荐

  1. 万万没想到,Spring Boot 竟然这么耗内存!

    Spring Boot总体来说,搭建还是比较容易的,特别是Spring Cloud全家桶,简称亲民微服务. 但在发展趋势中,容器化技术已经成熟,面对巨耗内存的Spring Boot,小公司表示用不起. ...

  2. 并发编程时守护进程在pycharm与python shell中的运行结果不同

    原代码如下 from multiprocessing import Process import time import random def task(name): print('%s is run ...

  3. C/C++ 递归

    递归 当一个函数调用它自己来定义时称它为递归函数.(什么叫它自己调用它自己呢?) 1.1.引出递归 从一个简单的问题考虑递归,求0,1,2, 3,4,5......n的和. 首先定义一个求和公式:su ...

  4. java体系中OOP,OOD,OOA分别代表什么含义,以及OA,CRM,ERP

    OOP:Object Oriented Programming 面向对象程序设计. OOD:Object Oriented Design 面向对象设计. OOA:Object Oriented Ana ...

  5. 自己制作 Android Vector Asset 矢量图

    版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/c5138891/article/deta ...

  6. CentOS上安装Git及配置远程仓库

    首先登陆CentOS服务器,连接上服务器之后我们使用yum remove git 命令删除已安装的Git,若之前没安装过Git则不需要这一步.注意前提是你的CentOS服务器上安装了yum,这是Cen ...

  7. Mongo --01 介绍、安装、优化报警

    目录 一 . NoSQL 介绍 二.MongoDB简介 三.MongoDB特点 四. mongo应用场景 五. 安装配置mongodb 六.优化报警 一 . NoSQL 介绍 NoSQL,指的是非关系 ...

  8. Educational Codeforces Round 55 (Rated for Div. 2) C. Multi-Subject Competition (实现,贪心,排序)

    C. Multi-Subject Competition time limit per test2 seconds memory limit per test256 megabytes inputst ...

  9. 64bit机器编译32bit汇编

    sudo apt-get install gcc-multilib sudo apt-get install g++-multilib gcc -m32  -S a.c -o a.s gcc -m64 ...

  10. Zookeeper学习笔记(中)

    Zookeeper学习笔记(中) Zookeeper的基本原理和基本实现 深入了解ZK的基本原理 ZK的一致性: ZAB 协议: Zookeeper 原子消息广播协议 ZK通过选举保证 leader ...