程式堆疊大小

程式堆疊大小

我了解到每個進程的預設堆疊大小限制為 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 中的內容移動到其他空間?

答案1

進程主執行緒堆疊大小不能成長到大於設定的限制。此限制的預設值為 8 MB。超過此限制將導致分段錯誤,並且進程將被發送訊號SIGSEGV,預設將其殺死。堆疊的最大大小可以ulimit -s在啟動程式之前更改。程式啟動後,核心不會在記憶體區域(如 mmap 區域)移動,也無法這樣做,因為通常有指向該區域的指標在移動後會指向錯誤的位址。

但是,堆疊溢位檢查是在存取堆疊記憶體時執行的,因此僅在堆疊上執行大量分配或以其他方式更改堆疊指標的值並不一定會觸發故障。

2017 年夏天,有人討論過利用這種行為的可能性。如果某些攻擊者可以欺騙程式分配大量內存,則可能會導致堆疊指標跳過保護區並指向有效但不同的區域。這為一些巧妙的技巧來控制流程提供了機會。看這篇 lwn.net 文章來討論這個問題。

相關內容