Linux

程序堆棧大小

  • November 28, 2017

我了解到每個程序的預設堆棧大小限制為 8MB,並且 mmap_base 是根據 rlimit 中的堆棧大小和隨機值計算的。下面的程式碼是 mmap_base 函式,它計算 x86 中的 mmap_base 地址(linux/include/uapi/asm-generic/resource.h)。

static unsigned long mmap_base(unsigned long rnd)
{
   unsigned long gap = rlimit(RLIMIT_STACK);

   if (gap < MIN_GAP)
       gap = MIN_GAP;
   else if (gap > MAX_GAP)
       gap = MAX_GAP;

   return PAGE_ALIGN(TASK_SIZE - gap - rnd);
}

我想知道如果程序堆棧大小大於 8MB+rnd 值怎麼辦?我的意思是如果堆棧大小增長到 mmap_base 以上怎麼辦?如果我分配超過 8MB 的堆棧記憶體,它是否會因分段錯誤而失敗?如果核心自動擴大堆棧大小,是否可以將 mmap_base 中的內容移動到其他空間?

程序主執行緒堆棧大小不能增長大於設置的限制。此限制的預設值為 8 MB。超過此限制將導致分段錯誤,並且該程序將被發送一個SIGSEGV信號,預設情況下將其終止。ulimit -s在啟動程序之前可以更改堆棧的最大大小。程序啟動後,核心不會在記憶體區域(如 mmap 區域)中移動,也不能這樣做,因為通常有指向該區域的指針在移動後會指向錯誤的地址。

但是,堆棧溢出的檢查是在訪問堆棧記憶體時執行的,因此只是在堆棧上執行大分配,或者以其他方式更改堆棧指針的值,並不一定會觸發故障。

2017 年夏天有一些關於利用這種行為的可能性的討論。如果某些攻擊者可以欺騙程序分配大量記憶體,這可能導致堆棧指針跳過保護區並指向有效但不同的區域。這為一些巧妙的技巧提供了機會來控制該過程。有關該問題的討論,請參閱此 lwn.net 文章

引用自:https://unix.stackexchange.com/questions/407204