这个题目好像起得有些坏,因为类似于正规的名字都被人占用了,没有办法,只有退而求其次了,这个题目也不赖,不是吗?
初识Jprobe是在写的drcom代码的内核部分,不过当时并没有仔细研究,只是简单的知道这个东西的存在,如果换成某些同学的简历,又该说成是“熟悉”了,还好我还没有无耻的那种地步。最近,从一本杂志上再次看到关于Kprobe和Jprobe的介绍,遂静下心来,学习了如何利用它进行编程,并粗略地分析了一下其实现,感叹于其精巧的设计。一时兴起,又要挥毫泼墨,涂鸦。动笔之前,小心地google了一下,感动啊!互联网上已经有成文的篇章存在,且质量较高,也就不用劳烦我老人家在这里浪费口水了,至于详细内容,请见本文结尾处的链接。
我这篇也就写点儿使用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()关闭了抢占,但是当函数出错返回的时侯,并没有打开抢占。不知道最新的内核有没有修复这些细节,懒得去看了,应该没有哪个正式的发型版会打开这个选项的。所以文章标题中所提到的注入的可能性也就比较小了,本来这个东西出现的背景就是为了方便内核开发者的调试工作!
参考链接:http://www-128.ibm.com/developerworks/cn/linux/l-kprobes.html
阅读(2894) | 评论(2) | 转发(0) |