[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
=====================================================
- Re: stack bounds,
Bruno Haible <=