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. 为什么 Java 线程没有 Running 状态?

    Java虚拟机层面所暴露给我们的状态,与操作系统底层的线程状态是两个不同层面的事.具体而言,这里说的 Java 线程状态均来自于 Thread 类下的 State 这一内部枚举类中所定义的状态: 什么 ...

  2. C#中的委托和事件(一)——delegate

    前言 来说一说委托(delegate)和事件(event),本篇采取的形式是翻译微软Delegate的docs中的重要部分(不要问我为什么微软的docs有中文还要读英文,因为读中文感觉自己有阅读障碍- ...

  3. NOIP赛前集训备忘录(含每日总结)(日更?。。。)

    NOIP赛前集训备忘录(含每日考试总结) 标签: 有用的东西~(≧▽≦)/~啦啦啦 阅读体验:https://zybuluo.com/Junlier/note/1279194 考试每日总结(这个东西是 ...

  4. redis学习之旅-初识Redis

    定义: redis是一种支持Key-Value等多种数据结构的存储系统.可用于缓存,事件发布或订阅,高速队列等场景.该数据库使用ANSI C语言编写,支持网络,提供字符串,哈希,列表,队列,集合结构直 ...

  5. 05: 常用反扒机制 & 解决方法

    1.1 常用反扒机制   参考博客:https://blog.csdn.net/python36/article/details/90174300 1.header  浏览器的请求头 header中添 ...

  6. package.json的所有配置项及其用法,你都熟悉么

    写在前面 在前端开发中,npm已经是必不可少的工具了.使用npm,不可避免的就要和package.json打交道.平时package.json用得挺多,但是没有认真看过官方文档.本文结合npm官方文档 ...

  7. 划水日记之大哥带我走渗透I

    5/24/19 周五 access注入 先测试是否有漏洞 or nor and 1=1 and 1=2 2. Order by 猜字表端,发现一共有22个 3..然后使用 union select 1 ...

  8. 把excel中的数据导入到Oracle数据库中

    从事工作以来,数据库一直使用oracle,却不知道excel导入oracle,今天看了一篇文章,分享给大家,希望对大家有用. https://jingyan.baidu.com/article/0f5 ...

  9. 牛客练习赛14 E - 无向图中的最短距离 (bfs+bitset)

    一个链接:https://ac.nowcoder.com/acm/contest/82/E来源:牛客网 无向图中的最短距离 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144 ...

  10. GUI学习之二十九—QInputDialog学习总结

    最后一种对话框是QInputDialog,,用来提供个输入的窗口. 一常用的静态方法 由于输入的类型不同,QInputDialog分为多种静态方法使用 #有步长调节器的整形数据,step为步长调节器的 ...