2011-04-04 13 views
7

Esta pregunta está relacionada pero es diferente de this one sobre las matrices de longitud variable en C99.¿Cuántas páginas de memoria usan los compiladores de C en sistemas operativos de escritorio para detectar desbordamientos de pila?

Las respuestas señalan que un peligro al asignar matrices de longitud variable (o solo grandes matrices de un tamaño fijo) en la pila es que la asignación puede fallar silenciosamente, en oposición a, por ejemplo, llamar al malloc, que explícitamente informa al llamante si la asignación tuvo éxito.

Las plataformas de compilación no incorporadas modernas usan una zona de memoria no válida para detectar algunos desbordamientos de pila sin costo adicional (las comprobaciones son solo las comprobaciones que la MMU ha realizado de forma gratuita). Esto no protege al 100% del problema anterior porque una matriz local muy grande puede hacer que el puntero de la pila salte sobre el área no válida.

¿Alguien sabe cuántas páginas se suelen asignar para esta detección? Supongo que sería al menos 4KiB, pero podría ser más. ¿Es una elección hecha por el compilador o el sistema operativo, y en ambos casos, hay una manera de cambiarlo?

+1

Buena pregunta, pero uno debe comentar que malloc no dice explícitamente en todos los sistemas si la asignación tuvo éxito. Todavía puede fallar después en el primer acceso (al menos en algunos sistemas: consulte asignación optimizada o compromiso excesivo de memoria). – flolo

+0

@flolo Casi comento sobre eso, pero luego decidí omitirlo porque el exceso de memoria es realmente un problema de sistema operativo, no de lenguaje. Como tal, no causa un comportamiento indefinido, causa que el proceso de asignación, u otro proceso, sea asesinado limpiamente. –

+0

Consulte también [Aviso de seguridad de Qualys: The Stack Clash] (http://www.openwall.com/lists/oss-security/2017/06/19/1) en la lista de correo de OSS-Security. Muestra algunos buenos trucos, y es bastante condenatorio de la página de guardia. Es sorprendente la cantidad de OS que arrastraron con él. – jww

Respuesta

6

En Windows, es una página de 4 KB (al menos en x86): Consulte Description of the stack checking for Windows NT-based applications.

Este método utiliza un crecimiento automático página guardia, a,, página de memoria reservada no comprometidos que linda con la parte comprometida de memoria. Cuando la aplicación toca la página de guard , el sistema operativo confirma esa página y la siguiente página no confirmada se convierte en la nueva página de protección. El crecimiento automático de la pila solo funciona para la página de guardia y la memoria de la pila deben crecer en incrementos de 4K o de una página. Si la aplicación toca a otro página reservada pero no comprometida de pila de memoria antes de que toque la página de protección , una página normal excepción culpa se produce un comportamiento impredecible y puede resultado.

...

Para evitar que el fallo, el compilador llama al __chkstk() de cada tiempo de la asignación local supera 4K. La función __chkstk() de Windows NT no comprueba explícitamente el desbordamiento de la pila como lo hace la versión de MS-DOS. Simplemente toca las direcciones de memoria cada 4K desde la pila actual ubicación del puntero a la asignación solicitada. Esto desencadena las páginas de protección en la secuencia correcta y confirma la memoria adicional a la pila según sea necesario.

para GCC, GCC Stack checking

No estoy seguro de cómo/si de VLA de C99 cambiaría el comportamiento de WinNT.

7

Estoy bastante seguro de que la práctica más común es usar una sola página, generalmente 4k. Un buen compilador, sin embargo, intentará secuencialmente acceder a cada página de un marco de pila más grande que el tamaño de página en la entrada de funciones (o en la asignación VLA/alloca) para garantizar que se golpee una página de protección. GCC puede opcionalmente hacer esto; ver: http://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options y la opción -fstack-check.

Cuestiones relacionadas