0

In my program I create simple pthread to explore how it will look like in memory and what system calls will be called:

void *foo() {
    printf("test");
}
int main() {
    pthread_t a;
    pthread_create(&a, NULL, foo, NULL);
    pthread_join(a, NULL);
    while(true);
}

Using strace I see that it leaves little space before stack without any permissions:

mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7fc67e53e000
mprotect(0x7fc67e53f000, 8388608, PROT_READ|PROT_WRITE) = 0
clone(child_stack=0x7fc67ed3dfb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7fc67ed3e9d0, tls=0x7fc67ed3e700, child_tidptr=0x7fc67ed3e9d0) = 9020

In /proc/[pid]/maps it looks like that:

7fc67e53e000-7fc67e53f000 ---p 00000000 00:00 0 
7fc67e53f000-7fc67ed3f000 rw-p 00000000 00:00 0 

My question is for what purpose os using this ---p segment?

  • Hint: Stacks, on most processor architectures and systems, grow *downwards*. – EOF Nov 22 '20 at 21:19
  • 2
    The operating system uses this as a guard [page](https://en.wikipedia.org/wiki/Page_(computer_memory)) to detect when the stack is full and must expand. The CPU will trigger an exception when trying to access this page, and the operating system will handle this exception by growing the stack. – Andreas Wenzel Nov 22 '20 at 21:35
  • @AndreasWenzel: Expansion is not actually possible unless you already reserved space to ensure that nothing is adjacent, in which case you didn't need to trap and expand to begin with - you could just have mapped it all right to begin with. `MAP_GROWSDOWN` was a historical mistake by folks who didnt think this through. – R.. GitHub STOP HELPING ICE Nov 22 '20 at 21:54
  • After further investigation, it seems that my previous comment is correct for [how Microsoft Windows handles the stack](https://geidav.wordpress.com/tag/stack-probing/). However, Linux does not grow the stack in this way. It uses the guard page only for security reasons, to detect [stack overflows](https://en.wikipedia.org/wiki/Stack_overflow), and not for detecting when to grow the stack. – Andreas Wenzel Nov 23 '20 at 11:03

1 Answers1

1

This is called a guard page, and the purpose of putting it below the stack is so that, in event of a stack overflow, you get a fault that will trap and terminate the process (or that could be intercepted to do dubious things) rather than having the stack pointer continue growing across whatever memory happens to be adjacent. This only works if the stack advances in increments of at most a page at a time without an intervening memory access, though. This was understood by security community since the 90s, but was apparently unknown to compiler engineers until 2017 when it gained notoriety as Stack Clash and got GCC to add the -fstack-clash-protection option, which should be on by default in any hardened environment.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711