2010-07-29 179 views
1

我的系統(Linux內核2.6.32-24)正在實現一個名爲地址空間佈局隨機化(ASLR)的功能。 ASLR似乎改變了堆棧大小:可變堆棧大小

void f(int n) 
{ 
    printf(" %d ", n); 
    f(n + 1); 
} 

int main(...) 
{ 
    f(0); 
} 

很明顯,如果你執行程序,你會得到一個堆棧溢出。問題是分段錯誤在每次執行時發生在不同的「n」值上。這很明顯是由ASLR引起的(如果你禁用它,程序始終以相同的值「n」退出)。

我有兩個問題:

  1. 豈不是ASLR使堆棧大小略有變化?
  2. 如果是這樣,您是否看到這個事實存在問題?可能是內核錯誤?
+1

令人驚訝的是,編譯器並沒有將該函數優化爲簡單的無限循環。 – caf 2010-07-29 13:46:51

回答

1

這可能意味着在一個實例中堆棧恰好流入其他分配的塊,而在另一個實例中,它會在未分配的地址空間上跳轉。

+0

我一開始也這麼想過,但我一直在試圖看看/ proc//maps文件。堆棧段永遠不會接近另一個映射,並且它的大小在它的段錯誤發生之前比堆棧的rlimit(rlim_cur)大得多(超過一頁)。 – jdizzle 2010-07-29 10:35:47

+0

你的意思是說,如果默認堆棧大小爲8192k,那麼在超過此限制之後,分段故障會發生很多? 您能否發佈說明以檢查此行爲? – agori 2010-07-29 10:44:31

+0

我只是有一個循環捕獲/ proc//maps文件,並查看proc崩潰之前打印的最後一件事情。分配給堆棧的內存範圍在崩潰時間一直大於rlimit的金額(在開始無限遞歸之前,我得到/打印rlimit值) – jdizzle 2010-07-29 11:47:05

1

ASLR代表「地址空間佈局隨機化」。它所做的是在每次運行時更改不同的段/段起始地址,是的,這包括堆棧。

這不是一個bug;這是設計。它的目的部分是讓溢出緩衝區難以獲得訪問權限,因爲爲了執行任意代碼,您需要誘使CPU「返回」到堆棧中某個點或運行時庫中。合法的代碼會知道要返回的位置,但是某些罐頭式利用不會 - 每次都可能是不同的地址。至於爲什麼表觀堆棧大小發生變化,堆棧空間是以頁面分配的,而不是以字節分配的。調整堆棧指針,特別是如果它不是頁面大小的倍數,則會改變您看到的可用空間量。

+0

您確定ASLR可以更改段/段大小嗎?你有這方面的參考嗎? – agori 2010-07-29 09:58:14

+0

除了這是它的整個生活目的(因此名稱),請參閱http://en.wikipedia.org/wiki/Address_space_layout_randomization或http://netsecurity.about.com/od/quicktips/qt/whatisaslr.htm一些更多的信息。 – cHao 2010-07-29 10:02:56

+0

ASLR肯定會更改地址,但我看不到任何有關更改堆棧大小的文檔。 – agori 2010-07-29 10:05:47