2016-03-08 81 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) 
} 
相關問題