Why is the stack size different in different runs of the same program?

Consider the following program. It takes an argument from the command line and then expands the recursive function to that limit.

#include <stdio.h>
#include <stdlib.h>

int rec(int x, int limit) {
  if (x == limit) {
    return limit;
  }
  int r = rec(x + 1, limit);
  return r - 1;
}

int main(int arc, char* argv[]) {
  int result, limit;
  limit = atoi(argv[1]);
  printf("stack: %p\n", &result);
  result = rec(0, limit);
  printf("%d\n", result);
}

If I compile it, I expect it to finish stacks to limit a fixed input argument. Something else is happening.

dejan@raven:~/test/stack$ gcc stack.c
dejan@raven:~/test/stack$ ./a.out 174580
stack: 0x7fff42fd58f0
Segmentation fault (core dumped)
dejan@raven:~/test/stack$ ./a.out 174580
stack: 0x7ffdd2dd8b20
0

In two different runs, the stack size seems different. This does not seem to be a problem with the compiler, since the same thing happens with clang, and disassembling does not affect anything strange.

Why is the stack size different in different swings?

+4
source share
2 answers

/proc/self/maps ( , @AndrewHenle, pmap):

char* get_stack_bounds() {
    FILE* maps = fopen("/proc/self/maps", "r");
    static char line[256];

    while(!feof(maps)) {
        fgets(line, 255, maps);
        if(strstr(line, "[stack]")) {
            char* space = strchr(line, ' ');
            *space = '\0';
            fclose(maps);
            return line;
        }
    }

    fclose(maps);
    return NULL;
}

unsigned long get_stack_right() {
    char* bounds = get_stack_bounds();
    bounds = strchr(bounds, '-') + 1;
    return strtol(bounds, NULL, 16);
}

main():

printf("&result: %p delta: %ld\n", &result, 
     get_stack_right() - ((unsigned long) &result));

:

> ./a.out 104747
&result: 0x7fff3347c7f8 delta: 6152
0
> ./a.out 174580
&result: 0x7fffe43c9b38 delta: 5320
0
> ./a.out 174580
&result: 0x7fff26ad2b28 delta: 9432
Segmentation fault (core dumped)
> ./a.out 174580
&result: 0x7fff145aa5a8 delta: 6744
0
> ./a.out 174580
&result: 0x7fff74fff0b8 delta: 12104
Segmentation fault (core dumped)

, delta ( result ) .


, main() , , _start() crt1.o( - ), .

. fs/binfmt_elf_fdpic.c :

/* In some cases (e.g. Hyper-Threading), we want to avoid L1 evictions
 * by the processes running on the same package. One thing we can do is
 * to shuffle the initial stack for them, so we give the architecture
 * an opportunity to do so here.
 */
sp = arch_align_stack(bprm->p);

arch_align_stack() x86:

unsigned long arch_align_stack(unsigned long sp)
{
    if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
        sp -= get_random_int() % 8192;
    return sp & ~0xf;
}
+2

SIGSEGV:

void handler( int sig )
{
    char buffer[ 1024 ]
    sprintf( buffer, "/path/to/pmap %d", getpid() );
    system( buffer );
    exit( 0 );
}

int main( int argc, char *argv[] )
{
    signal( SIGSEGV, handler );
       .
       .
       .

, , SEGVs.

, -. . , .

0

All Articles