Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1587992
  • 博文数量: 77
  • 博客积分: 1205
  • 博客等级: 少尉
  • 技术积分: 4476
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-22 21:48
文章分类
文章存档

2018年(1)

2017年(1)

2015年(1)

2014年(18)

2013年(12)

2012年(44)

分类: LINUX

2012-05-02 23:32:57

kprobe可以动态跟踪某一内核函数的执行情况而无需修改内核,当然为了达到这样目的,我们需要自己写一个小的内核模块,不过这也要比修改内核源码要来得方便的多,我觉得这种方法可以形象地称之为“无损探测”。
下面是利用<>中的一小段代码,经过适当改写完善,来探测一个U盘加入系统时,do_execve所执行的环境参数。kprobe的原理大约是在执行被探测函数前先行获得控制权,执行内核模块所注册的回调函数,之后再把控制权转给被探测的函数,这个原理很有意思,有进一步分析的必要。

以下是内核模块代码:

  1. #include <linux/module.h>
  2. #include <linux/kprobes.h>
  3. #include <linux/kallsyms.h>

  4. struct kprobe kp;

  5. int handler_pre(struct kprobe *p, struct pt_regs *regs)
  6. {
  7.         printk(KERN_INFO "|pid: %6d |comm: %10s |filename = %10s|\n",
  8.                 current->pid, current->comm, (char *)regs->di);
  9.         return 0;
  10. }

  11. static __init int init_kprobe_sample(void)
  12. {
  13.         kp.symbol_name = "do_execve";
  14.         kp.pre_handler = handler_pre;
  15.         register_kprobe(&kp);
  16.         printk(KERN_INFO "---------------kprobe for execve--------------\n");
  17.         return 0;
  18. }

  19. static __exit void cleanup_kprobe_sample(void)
  20. {
  21.         unregister_kprobe(&kp);
  22. }

  23. module_init(init_kprobe_sample);
  24. module_exit(cleanup_kprobe_sample);

  25. MODULE_LICENSE("GPL");
insmod这个模块之后,探测活动就正式开始了,下面是往系统插入一个U盘时,kprobe回调函数的输出:

  1. root@build-server:/home/dennis/debug/kprobe# dmesg -c
  2. [10370.912471] usb 1-1.3: new high-speed USB device number 9 using ehci_hcd
  3. [10370.988796] |pid: 3296 |comm: kworker/u:3 |filename = /sbin/myhotplug|
  4. [10370.989038] |pid: 3297 |comm: kworker/u:3 |filename = /sbin/myhotplug|
  5. [10370.989146] |pid: 3298 |comm: udevd |filename = /lib/udev/mtp-probe|
  6. [10370.989192] |pid: 3299 |comm: myhotplug |filename = /bin/touch|
  7. [10370.989496] |pid: 3300 |comm: myhotplug |filename = /bin/touch|
  8. [10370.989730] scsi11 : usb-storage 1-1.3:1.0
  9. [10370.989768] |pid: 3303 |comm: kworker/u:3 |filename = /sbin/myhotplug|
  10. [10370.989861] |pid: 3304 |comm: kworker/u:3 |filename = /sbin/myhotplug|
  11. [10370.990137] |pid: 3305 |comm: myhotplug |filename = /bin/touch|
  12. [10370.990212] |pid: 3306 |comm: myhotplug |filename = /bin/touch|
  13. [10371.249360] |pid: 3307 |comm: udevd |filename = /lib/udev/usb_id|
  14. [10371.992667] scsi 11:0:0:0: Direct-Access TOSHIBA TransMemory 1.00 PQ: 0 ANSI: 2
  15. [10371.992972] |pid: 3309 |comm: kworker/u:3 |filename = /sbin/myhotplug|
  16. [10371.993341] |pid: 3310 |comm: myhotplug |filename = /bin/touch|
  17. [10371.993360] |pid: 3311 |comm: kworker/u:3 |filename = /sbin/myhotplug|
  18. [10371.993636] |pid: 3312 |comm: udevd |filename = /sbin/modprobe|
  19. [10371.993712] |pid: 3313 |comm: myhotplug |filename = /bin/touch|
  20. [10371.993777] |pid: 3314 |comm: kworker/u:3 |filename = /sbin/myhotplug|
  21. [10371.994364] |pid: 3316 |comm: kworker/u:2 |filename = /sbin/myhotplug|
  22. [10371.994563] |pid: 3317 |comm: myhotplug |filename = /bin/touch|
  23. [10371.994797] |pid: 3318 |comm: kworker/u:2 |filename = /sbin/myhotplug|
  24. [10371.994830] sd 11:0:0:0: Attached scsi generic sg3 type 0
  25. [10371.994886] |pid: 3319 |comm: kworker/u:2 |filename = /sbin/myhotplug|
  26. [10371.995249] |pid: 3320 |comm: myhotplug |filename = /bin/touch|
  27. [10371.995506] |pid: 3321 |comm: myhotplug |filename = /bin/touch|
  28. [10371.995538] |pid: 3322 |comm: myhotplug |filename = /bin/touch|
  29. [10371.995786] sd 11:0:0:0: [sdc] 15654848 512-byte logical blocks: (8.01 GB/7.46 GiB)
  30. [10371.996281] sd 11:0:0:0: [sdc] Write Protect is off
  31. [10371.996282] sd 11:0:0:0: [sdc] Mode Sense: 65 44 09 30
  32. [10371.996788] sd 11:0:0:0: [sdc] No Caching mode page present
  33. [10371.996862] sd 11:0:0:0: [sdc] Assuming drive cache: write through
  34. [10371.996996] |pid: 3323 |comm: kworker/u:2 |filename = /sbin/myhotplug|
  35. [10371.997387] |pid: 3324 |comm: myhotplug |filename = /bin/touch|
  36. [10371.999537] sd 11:0:0:0: [sdc] No Caching mode page present
  37. [10371.999609] sd 11:0:0:0: [sdc] Assuming drive cache: write through
  38. [10372.000283] sdc: sdc1
  39. [10372.000358] |pid: 3325 |comm: kworker/u:2 |filename = /sbin/myhotplug|
  40. [10372.000458] |pid: 3326 |comm: kworker/u:2 |filename = /sbin/myhotplug|
  41. [10372.000711] |pid: 3327 |comm: myhotplug |filename = /bin/touch|
  42. [10372.000820] |pid: 3328 |comm: myhotplug |filename = /bin/touch|
  43. [10372.000865] |pid: 3329 |comm: udevd |filename = /lib/udev/usb_id|
  44. [10372.001676] |pid: 3330 |comm: udevd |filename = /lib/udev/path_id|
  45. [10372.002411] sd 11:0:0:0: [sdc] No Caching mode page present
  46. [10372.002459] |pid: 3331 |comm: udevd |filename = /sbin/blkid|
  47. [10372.002484] sd 11:0:0:0: [sdc] Assuming drive cache: write through
  48. [10372.002564] sd 11:0:0:0: [sdc] Attached SCSI removable disk
  49. [10372.066849] |pid: 3332 |comm: udevd |filename = /lib/udev/udisks-part-id|
  50. [10372.070023] |pid: 3333 |comm: udevd |filename = /lib/udev/hdparm|
  51. [10372.070633] |pid: 3334 |comm: hdparm |filename = /bin/grep|
  52. [10372.071212] |pid: 3335 |comm: hdparm |filename = /bin/egrep|
  53. [10372.071930] |pid: 3337 |comm: hdparm |filename = /bin/egrep|
  54. [10372.073162] |pid: 3339 |comm: udevd |filename = /sbin/blkid|
  55. [10372.127677] |pid: 3341 |comm: udevd |filename = /lib/udev/udisks-part-id|
  56. [10373.752620] |pid: 3342 |comm: bash |filename = /bin/dmesg|
如果仔细分析上面的输出,会发现不少有趣的信息,比如udevd与mtp-probe,hdparm等等。

这时候,do_execve就要抱怨了,因为它的隐私全被人家给窥视了,如果遇到再狠一点的角色,估计连底裤都不剩下了,呵呵,kprobe就是这样一个具有窥私癖的东西。


阅读(7133) | 评论(10) | 转发(7) |
给主人留下些什么吧!~~

alex-huang2012-05-07 23:22:27

其实kprobe又称为指令断点,与hw_breakpoint(数据断点)相对应。kprobe的原理就是将你要监控的指令先保存起来,并解码译码,然后,在原指令的位置替换为非法指令,这样,你的程序运行到你要监控的指令时,就会产生一个数据访问异常,这个时候会执行异常处理程序,而你注册的处理程序在这个时候就会被调用,然后,解码译码后的那条指令重新执行,最后,kprobe会把那条非法指令替换为正常的指令,执行pc+4,就返回了。过程其实是很复杂的。而且,kprobe也有限制,很多内核函数不能使用,另外,由于原理上的原因,不能够大量使用,否则,影响性能。在这种情况下,使用数据断点更好,效率更高,而且,也支持指令监控

3089389692012-05-07 17:24:44

MagicBoy2010: 需要吗?
以上代码在3.2.9 x86-64环境下编译没有任何问题。.....
呵呵,我的是2.6.35.6

十七岁的回忆2012-05-06 10:58:13

kprobe回调函数的输出怎么看不懂。。

MagicBoy20102012-05-05 22:31:31

308938969: #include <linux/sched.h>少个头文件.....
需要吗?
以上代码在3.2.9 x86-64环境下编译没有任何问题。

3089389692012-05-05 09:41:31

#include <linux/sched.h>少个头文件