usar stackoverflow que pila linea historia espanol error desbordamiento como c linux stack segmentation-fault setrlimit

stackoverflow - stack overflow wikipedia



Establezca el tamaƱo de pila con setrlimit() y provoque un desbordamiento de pila/segfault (2)

Creo que setrlimit mueve los "punteros de recursos" pero no aplica los nuevos límites hasta que exec una nueva copia del programa.

#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/resource.h> void foo(int chk) { unsigned ints[2048]; ints[2047] = 42; printf("foo %d: %u/n", chk, ints[2047]); } int main(int argc, char **argv) { char *newarg[] = { "argv[0]", "one", "two" }; char *newenv[] = { NULL }; struct rlimit lim; newarg[0] = argv[0]; getrlimit(RLIMIT_STACK, &lim); printf("lim: %d / %d/n", (int)lim.rlim_cur, (int)lim.rlim_max); switch (argc) { case 1: /* first call from command line */ lim.rlim_cur = 65536; lim.rlim_max = 65536; if (setrlimit(RLIMIT_STACK, &lim) == -1) return EXIT_FAILURE; newarg[2] = NULL; foo(1); execve(argv[0], newarg, newenv); break; case 2: /* second call */ lim.rlim_cur = 1024; lim.rlim_max = 1024; if (setrlimit(RLIMIT_STACK, &lim) == -1) return EXIT_FAILURE; foo(2); execve(argv[0], newarg, newenv); break; default: /* third call */ foo(3); break; } return 0; }

Y una prueba de ejecución:

$ ./a.out lim: 8388608 / -1 foo 1: 42 lim: 65536 / 65536 foo 2: 42 Killed

Por qué el proceso se mata antes de imprimir los límites (y antes de llamar a foo), no lo sé.

En el siguiente ejemplo, intento establecer el tamaño de pila en 1kb.

¿Por qué ahora es posible asignar una matriz de entradas en la pila con tamaño 8kb en foo() ?

#include <stdio.h> #include <sys/resource.h> void foo(void); int main() { struct rlimit lim = {1024, 1024}; if (setrlimit(RLIMIT_STACK, &lim) == -1) return 1; foo(); return 0; } void foo() { unsigned ints[2048]; printf("foo: %u/n", ints[2047]=42); }


El límite se establece de inmediato, pero solo se verifica cuando se intenta asignar una nueva pila o tratar de hacer crecer la pila existente. Un grep para RLIMIT_STACK ( o una búsqueda de identificador LXR ) en las fuentes del kernel debería indicarlo.

Aparentemente, el tamaño inicial de la pila es el que se necesita para el nombre de archivo + env strings + arg strings más algunas páginas adicionales asignadas en setup_arg_pages (20 páginas en 2.6.33 1 , 2 , 128 Kb en 2.6.34 3 ).

En resumen:

initial stack size = MIN(size for filename + arg strings + env strings + extra pages, MAX(size for filename + arg strings + env strings, RLIMIT_STACK))

dónde

size for filename + arg strings + env strings <= MAX(ARG_MAX(32 pages), RLIMIT_STACK/4)

Además, los núcleos con el parche de exec-shield Ingo Molnar (Fedora, Ubuntu, ...) tienen un EXEC_STACK_BIAS " adicional (2 MB más para cubrir los efectos de aleatorización)" , consulte la llamada a la nueva función over_stack_limit() de acct_stack_growth() ( [Ubuntu1] , [Ubuntu2] , [Ubuntu3] ).

He editado el programa original para mostrar esto:

#include <stdio.h> #include <sys/resource.h> void foo(void); int main(int argc, char *argv[]) { struct rlimit lim = {1, 1}; if (argc > 1 && argv[1][0] == ''-'' && argv[1][8]==''l'') { printf("limiting stack size/n"); if (setrlimit(RLIMIT_STACK, &lim) == -1) { printf("rlimit failed/n"); return 1; } } foo(); return 0; } void foo() { unsigned ints[32768]; printf("foo: %u/n", ints[2047]=42); }

Lo que resulta en:

$./rl foo: 42 $./rl -l limiting stack size Segmentation fault $