定位可动态加载的内核模块的OOPS代码行


1. 从vmlinux获取具体的代码行

    文章中albcamus版主也提到了,需要有自己编译的vmlinux,而且编译时打开compile with debug info. 这个选项打开之后会使vmlinux文件比不加调试信息大一些。我这里代调试信息的是49M。建议如果学习的时候,想使用gdb的方式获取出错代码行的 话,就加上这个编译条件。

    然后就可以按照具体的方法去操作,可以定位到具体的C 代码行。

    2. 从自己编译的内核模块出错信息中获取代码行以ldd3中提供的misc-modules/faulty.c为例。主要以faulty_write函数作分析。

    (1)由于作者提供的函数代码就一样,过于简单,我这里简单加上一些代码(也就是判断和赋值),如下:

    ssize_t faulty_write (struct file *filp, const char __user *buf, size_t count,

    loff_t *pos)

    {

    /* make a simple fault by dereferencing a NULL pointer */

    if(count > 0x100)

    count = 0x100;

    *(int *)0 = 0;

    return count;

    }

    (2)编译该模块,并且mknod /dev/faulty(3)向该模块写入数据:echo 1 > /dev/faulty, 内核OOPS,信息如下:

    <1>BUG: unable to handle kernel NULL pointer dereference at virtual address 00000000

    printing eip:

    f8e8000e

    *pde = 00000000

    Oops: 0002 [#3]

    SMP

    Modules linked in: faulty autofs4 hidp rfcomm l2cap ...... //此处省略若干字符

    CPU: 1

    EIP: 0060:[<f8e8000e>] Not tainted VLI

    EFLAGS: 00010283   (2.6.18.3 #2)

    EIP is at faulty_write+0xe/0x19 [faulty]

    eax: 00000001 ebx: f4f6ca40 ecx: 00000001 edx: b7c2d000

    esi: f8e80000 edi: b7c2d000 ebp: 00000001 esp: f4dc5f84

    ds: 007b es: 007b ss: 0068

    Process bash (pid: 6084, ti=f4dc5000 task=f7c8d4d0 task.ti=f4dc5000)

    Stack: c1065914 f4dc5fa4 f4f6ca40 fffffff7 b7c2d000 f4dc5000 c1065f06 f4dc5fa4

    00000000 00000000 00000000 00000001 00000001 c1003d0b 00000001 b7c2d000

    00000001 00000001 b7c2d000 bfd40aa8 ffffffda 0000007b c100007b 00000004

    Call Trace:

    [<c1065914>] vfs_write+0xa1/0x143

    [<c1065f06>] sys_write+0x3c/0x63

    [<c1003d0b>] syscall_call+0x7/0xb

    Code:  Bad EIP value.

    EIP: [<f8e8000e>] faulty_write+0xe/0x19 [faulty] SS:ESP 0068:f4dc5f84

    其中,我们应该关注的信息是第一行红色标出部分:告诉我们操作了NULL指针。其次,就是第二行红色部分:EIP is at faulty_write+0xe/0x19。这个出错信息告诉我们EIP指针出现问题的地方时faulty_write函数,而且指出了是faulty 模块。

    同时,faulty_write+0xe/0x19的后半部分0xe/0x19,说明该函数的大小时0x019,出错位置是在0x0e。这两个值应该值得都是汇编代码的值。

    (4)将faulty模块反汇编出汇编代码:

    objdump -d faulty.ko > faulty.s

    或

    objdump -d faulty.o > faulty.s然后,我们打开faulty.s文件。由于我们需要关注的部分正好在文件的前面,因此我这里只贴出文件的前面一部分内容:

    faulty.o:     file format elf32-i386

    Disassembly of section .text:

    00000000 <faulty_write>:

    0:        81 f9 00 01 00 00            cmp    {GetProperty(Content)}x100,%ecx 6:        b8 00 01 00 00               mov    {GetProperty(Content)}x100,%eax b:        0f 46 c1                     cmovbe %ecx,%eax e:        c7 05 00 00 00 00 00         movl   {GetProperty(Content)}x0,0x0

    15: 00 00 00

    18: c3 ret

    00000019 <cleanup_module>:

    19:        a1 00 00 00 00               mov    0x0,%eax 1e:        ba 00 00 00 00               mov    {GetProperty(Content)}x0,%edx

    23: e9 fc ff ff ff jmp 24 <cleanup_module+0xb>

    00000028 <faulty_init>:

    28:        a1 00 00 00 00               mov    0x0,%eax 2d:        b9 00 00 00 00               mov    {GetProperty(Content)}x0,%ecx 32:        ba 00 00 00 00               mov    {GetProperty(Content)}x0,%edx

    37: e8 fc ff ff ff call 38 <faulty_init+0x10>

    3c:        85 c0                        test   %eax,%eax

    3e: 78 13 js 53 <faulty_init+0x2b>

    40:        83 3d 00 00 00 00 00         cmpl   {GetProperty(Content)}x0,0x0

    47: 74 03 je 4c <faulty_init+0x24>

    49:        31 c0                        xor    %eax,%eax

    4b: c3 ret

    4c:        a3 00 00 00 00               mov    %eax,0x0 51:        31 c0                        xor    %eax,%eax

    53: c3 ret

    由以上汇编代码可以看出,faulty_write函数的大小确实是0x18 -0x00 +1 = 0x19. 那么EIP指针出问题的地方是0x0e处,代码为:

    e:        c7 05 00 00 00 00 00         movl   {GetProperty(Content)}x0,0x0

    这行汇编代码就是将0值保存到0地址的位置。那么很显然是非法的。这一行对应的C 代码应该就是:

    *(int *)0 = 0;

    (5)以上是对模块出错信息的分析。不过也有一定的局限。

    首先就是EIP出错的位置正好在本模块内部,这样可以在本模块定位问题;其次,要求一定的汇编基础,特别是当一个函数的代码比较多时,对应的汇编代码也比较大,如何准确定位到C代码行需要一定的经验和时间。

    实际运用中,可以将内核代码行的定位和可动态加载的内核模块代码行的定位结合起来使用,应该可以较快的定位问题。

    分析中有纰漏或者不妥的地方希望大家指出,也希望有网友分享更有效的方法



相关阅读:
Linux中关于driver的编写
jquery photoFrame 图片边框美化显示插件
Javascript select下拉框操作常用方法
“不能执行已释放的Script代码”错误的原因及解决办法
CSS控制input标签需要注意的问题
ASP之处理用Javascript动态添加的表单元素数据的代码
asp.net javascript 文件无刷新上传实例代码
不用图片作背景CSS做的小灯笼效果_练习用
使用参数化和块语句来提高批处理SQL语句的执行效率
google suggest 下拉菜单实现代码(asp.net版本)
WinXP/2003 禁止U盘和移动硬盘的方法
触发器对SQL Server数据库进行备份
制作高质量的JQuery Plugin 插件的方法
用CSS样式描述表格Table边框
快速导航

Copyright © 2016 phpStudy |