首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Linux 内核内存检测工具 - Kmemcheck(4)

Linux 内核内存检测工具 - Kmemcheck(4)

清单 8. kmemchk_unallocated.c 部分代码示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

static int __init kmemchk_unallocated_init(void)
{
        …
        /* create a slab cache */
        cachep  = kmem_cache_create(
                      "kmemchk_test_cache", /* the name of slab cache */
                      1024,  /* object size */
                      0,
                      SLAB_HWCACHE_ALIGN,    /* without SLAB_NOTRACK specifed,  \
                                     or else there would be kmemcheck warning messages */
                      NULL   /* no constructor */  
                      );
       …
        /* allocate a object */
        object = kmem_cache_alloc(cachep,GFP_KERNEL);
        if(object) {
           offset = 1500;

           /* access unallocated memory, objects are allocated from high */
           /* addr to low addr, so we minus the offset to access the memory */
           /* with no objects allocated yet */
        if(*((char*)object - offset) == 'a')
             printk("You hit a random char \n");
        }         
      …
}





加载模块后就会出现 kmemcheck 的警告信息(完整 log 信息请参阅附件 1):
清单 9. Unallocated 警告日志
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
WARNING: kmemcheck: Caught 8-bit read from freed memory (c14000dc)
ffffffff636f6e7374616e745f746573745f6269740000000000000061000000
f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f f
                                                                  ^
Pid: 13144, comm: rsyslogd Tainted: G      D W  (2.6.31.1 #2) V71
EIP: 0060:[<d0a5b044>] EFLAGS: 00010282 CPU: 0
EIP is at kmemchk_freed_exit+0x44/0x5b [kmemchk_freed]
EAX: c1400000 EBX: 00000000 ECX: 00000092 EDX: 00885000
ESI: d0a5b4a0 EDI: 00000000 EBP: cfb9ff4c ESP: c09e29bc
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
CR0: 8005003b CR2: cf432070 CR3: 0eff0000 CR4: 000006d0
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff4ff0 DR7: 00000400
[<c046fe62>] sys_delete_module+0x152/0x1f0
[<c0403b14>] sysenter_do_call+0x12/0x28
[<ffffffff>] 0xffffffff




对清单 9 的分析可以参考清单 6。
3.  本例中(完整代码请参阅附件 1 中的 kmemchk_free.c),我们先用 kmalloc 分配内存,完毕后释放该内存,然后再去访问被释放了的内存空间,我们会发现 kmemcheck 会发出访问内存已释放警告信息(即 KMEMCHECK_SHADOW_FREED 类型的错误信息)
清单 10. Freed 警告日志
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

static int __init kmemchk_freed_init(void)
{
        …
        /* using kmalloc to allocate 4KB memory without GFP_NOTRACK flag*/
        kmalloc_base = kmalloc(4*1024*1024,GFP_KERNEL);  
        …
}

static void __exit kmemchk_freed_exit(void)
{
        int offset; /* offset to the kmalloc base address */
         
        if(kmalloc_base) {
          kfree(kmalloc_base); /* free the memory */
          offset = 220;
        printk("checkpoint:access mem -base: %p offset: %d \n\n",kmalloc_base,offset);
         if(*(kmalloc_base + offset) == 'a') /*access freed memory */
            printk("You hit a random char \n");
        }

}





该模块在卸载时会出现如下 kmemcheck 的警告信息(完整 log 信息请参阅附件 2):
清单 9. Freed 警告日志
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
WARNING: kmemcheck: Caught 8-bit read from unallocated memory (cef2c624)
53050000000604a8040000103331000008070b7c0500000ef5440000070cfc00
a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a
        ^
Pid: 1490, comm: bash Tainted: G      D W  (2.6.31.1 #2) V71
EIP: 0060:[<d0aca04e>] EFLAGS: 00010286 CPU: 0
EIP is at 0xd0aca04e
EAX: cef2cc00 EBX: d0aca000 ECX: 00000000 EDX: c1001000
ESI: 00000000 EDI: b7efffc0 EBP: cf2a0f5c ESP: c09e2ae0
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
CR0: 8005003b CR2: 08100118 CR3: 0ec01000 CR4: 000006d0
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff4ff0 DR7: 00000400
[<c0401123>] do_one_initcall+0x23/0x180
[<c0471b71>] sys_init_module+0xb1/0x1f0
[<c0403b14>] sysenter_do_call+0x12/0x28
[<ffffffff>] 0xffffffff




在该例中,由于 kmalloc 是基于 slab cache 机制的,对一个对象的释放不会马上释放该对象所在的页面,因而会出现非法访问警告信息(但是如果对象所在的数据页面也被释放了,则不会出现警告,因为影子页面也同时被释放了)。
返回列表