2016-03-08 58 views
1

我调试了一个内存破坏问题,并发现Linux内核似乎接受用户“缓冲的免费部分”。教科书总是教我们拨号/免费成对。我有点迷惑不解了!所以我写了一个在Linux内核中运行的小测试。内存的kfree部分是否有效?

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如何释放与a​​lloc不同的地址。

在先进的感谢。

+0

kfree'的'文档不说“的缓冲区的部分可以被释放”。在你的第二个例子中,你混合了'malloc'(没有'k')和'kfree'。您可能会遇到未定义的行为。 –

+0

你说得对。问题是,我仍然可以做“免费”如果不立即错误(恐慌或任何消息),我可以分配是从“无错先前的”返回的缓冲区。稍后,内存损坏发生在某处。 – acolor

+0

@acolor:那不会使任何方式的码是否正确。 –

回答

2

操作系统内核可以决定安全地假定模块开发人员知道他们在做什么(而不是应用程序的开发从未应该能够危及OS)。

显然,Linux已经决定(可能是运行时效率原因)不检查地址是否移交给kfree()最初由用kmalloc(分配)(A强烈的暗示是, 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) 
} 
相关问题