我正在调试内存损坏问题,发现 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 不同的地址。
提前致谢。
最佳答案
操作系统内核可能会安全地假设模块开发人员知道他们在做什么(与应用程序开发相反,应用程序开发应该永远无法损害操作系统)。
显然,Linux 已经决定(可能是出于运行时效率的原因)不检查交给kfree() 的地址是否最初由kmalloc()(一个强烈的暗示是 kfree() 的签名甚至不允许它返回错误代码)。
内核中分配的所有内存都需要在某处进行监控(最典型的是在某种 block 头中,就在它返回给你的那 block 内存之前),以便能够正确释放再次记忆。 kmalloc() 在某处 初始化这个(使用分配 block 的大小、用途、属于哪个实例等信息)。如果您 kfree() 一些东西不是由 kmalloc() 分配的,那么这个某处 将根本不存在并且将使内核解释任意区域内存作为某处 - 导致各种未定义的行为,最终导致内核崩溃。这种行为不当的代码迟早会崩溃,仅取决于您运行的内核中的动态量。它可能会一直有效,直到有人决定卸载您的模块,或者甚至只是因为内核内存越来越紧张。
我的(公认的旧)kfree 手册页清楚地说明了
Don't free memory not originally allocated by kmalloc or you will run into trouble.
如果你想释放缓冲区的一部分(在最后),你应该使用 krealloc(),但是总是 返回的原始指针kmalloc()
顺便说一句:找到此类误用的一种快速方法是使用定义 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)
}
关于c - 内存的 kfree 部分是否有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35863207/