bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: stack bounds


From: Bruno Haible
Subject: Re: stack bounds
Date: Sat, 10 Oct 2020 14:08:49 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-189-generic; KDE/5.18.0; x86_64; ; )

Hi Paul,

you wrote on 2020-09-22:
> I am thinking of some combination of gcc -fstack-check and/or 
> -fstack-clash-protection and/or related ideas (not that I've looked into all 
> the 
> details). That is, I'm expecting help from the hardware, the kernel, and from 
> GCC. Stack-exhaustion checking should "just work". I realize it's a 
> nontrivial ask.

gcc -fstack-clash-protection does exactly what most people expect; as you say,
with the help from the hardware, the kernel, and GCC.
  - The hardware provides the MMU and the concept of page tables, which are
    the basis of mprotect().
  - The kernel provides mprotect; organizes a guard page at the bottom of the
    stack; and grows the stack if an access to the guard page is made.
  - 'gcc -fstack-clash-protection' arranges that a stack frame that is larger
    than one page is accessed in single-page steps, from top to bottom, so
    that the kernel will grow the stack and not report a SIGSEGV. Test code
    below.
This is how it's done on Windows.

On Linux, the kernel allows the stack to grow by any amount, if it does not
become closer than 1 MB to another VMA and does not violate the set limits.
See linux/mm/mmap.c:expand_downwards and linux/mm/mmap.c:acct_stack_growth.
Therefore on Linux, there is no need for a guard page and no need for
'gcc -fstack-clash-protection'.

In both cases, it "just works". What other features around stack bounds checking
are you thinking of?

gcc -fstack-check is unrelated: It merely adds a canary word in each stack
frame and checks that this word is still present upon return. So, it's merely
a defense against buffer overflows on the stack.

Bruno

========================= foo.c =====================
void bar (int *array);

void foo (int n)
{
  int array[n];
  for (int i = 0; i < n; i++)
    array[i] = i*i;
  bar (array);
}
=====================================================

gcc -fstack-clash-protection -O2 -S foo.c
========================= foo.s =====================
        .file   "foo.c"
        .text
        .p2align 4
        .globl  foo
        .type   foo, @function
foo:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movslq  %edi, %rcx
        leaq    15(,%rcx,4), %rax
        movq    %rcx, %rdx
        movq    %rax, %rsi
        andq    $-4096, %rax
        movq    %rsp, %rdi
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        andq    $-16, %rsi
        subq    %rax, %rdi
        cmpq    %rdi, %rsp
        je      .L3
.L13:
        subq    $4096, %rsp
        orq     $0, 4088(%rsp)
        cmpq    %rdi, %rsp
        jne     .L13
.L3:
        andl    $4095, %esi
        subq    %rsi, %rsp
        testq   %rsi, %rsi
        jne     .L14
.L4:
        movq    %rsp, %rdi
        testl   %edx, %edx
        jle     .L5
        xorl    %eax, %eax
        .p2align 4,,10
        .p2align 3
.L6:
        movl    %eax, %edx
        imull   %eax, %edx
        movl    %edx, (%rdi,%rax,4)
        addq    $1, %rax
        cmpq    %rcx, %rax
        jne     .L6
.L5:
        call    bar
        leave
        .cfi_remember_state
        .cfi_def_cfa 7, 8
        ret
        .p2align 4,,10
        .p2align 3
.L14:
        .cfi_restore_state
        orq     $0, -8(%rsp,%rsi)
        jmp     .L4
        .cfi_endproc
.LFE0:
        .size   foo, .-foo
        .ident  "GCC: (GNU) 10.2.0"
        .section        .note.GNU-stack,"",@progbits
=====================================================




reply via email to

[Prev in Thread] Current Thread [Next in Thread]