kfree部分内存是否有效?

时间:2016-03-08 09:10:23

标签: c linux linux-kernel linux-device-driver

我正在调试内存损坏问题,并发现Linux内核似乎接受用户来免费部分缓冲区"。教科书总是教我们成对调用alloc / free。我有点迷惑不解了!所以我写了一个在Linux内核中运行的小测试。

char *p_buf, *p_buf2;

p_buf = kmalloc(1024, GFP_KERNEL);     //alloc 1024
printk("malloc(1024) = %p\n", p_buf); 

kfree(p_buf+256);                      //free from offset 256(equals to free 768)
printk("kfree(%p)\n", p_buf+256);

p_buf2 = kmalloc(1024-256, GFP_KERNEL);  // alloc 768
printk("malloc(%d) = %p\n", 1024-256, p_buf2);

kfree(p_buf);
kfree(p_buf2);

结果(在Linux 3.16上运行)

malloc(1024) = ce52b800   //alloc 1024
kfree(ce52b900)           //free 768  ---(1)
malloc(768) = ce52b900    //alloc 768 ---(2)

您可以看到(1)和(2)地址相同。这是对的吗?这是否意味着Linux将缓冲区划分为两个部分,如我所料? 我知道这段代码肯定是错的,但我只是想知道Linux内核如何处理它 - Linux如何释放一个与alloc不同的地址。

先谢谢。

1 个答案:

答案 0 :(得分:2)

操作系统内核可能会决定安全地假设模块开发人员知道他们在做什么(而不是应用程序开发,它永远不能破坏操作系统)。

显然,Linux已决定(可能出于运行时效率的原因)不检查移交给 kfree()的地址是否最初由 kmalloc()(强烈暗示 kfree()的签名甚至不允许它返回错误代码)。

内核中分配的所有内存都需要在某处进行监控(最常见的是在它回送给你的内存块之前的某种块头中),以便能够正确释放记忆了。 kmalloc()初始化此某处(包含已分配块的大小,用法,属于哪个实例等信息)。如果 kfree()未被 kmalloc()分配的内容,则某处将根本不存在,并会使内核解释任意区域内存为某处 - 导致各种未定义的行为,最后是内核崩溃。这种行为不端的代码迟早会崩溃,只取决于运行内核中的动态数量。它可能会工作,直到有人决定卸载你的模块,甚至只是因为内核内存越来越紧。

并且我的(不可否认的是旧)手册页面向kfree明确说明了

  

没有最初由kmalloc分配的空闲内存,否则你将遇到麻烦。

如果要释放缓冲区的一部分(最后),则应使用 krealloc(),但始终,并使用返回的原始指针的kmalloc()

BTW:找到这种误用的快速方法是使用定义kmymalloc()和kmyfree()的宏来定义源代码,这些宏将分配更多内存,并在开头设置内存保护。分配区域如

void  *kmymalloc(...)
    unsigned long *area = kmalloc (...<size+sizeof (unsigned long)>)
    *area = 0xdeadbeef;
    return (void*) &(area[1]);
}
void *kmyfree(...){
    unsigned long *area = *(ptr - sizeof (unsigned long));
    if (*area != 0xdeadbeef)
        ... print a stack trace, shutdown system, or whatever
    else
       kfree (area)
}