2012-02-28 17 views
5

Espero que debido a la aleatorización de diseño de espacio de direcciones (ALSR) un proceso bifurcado de otro proceso tenga direcciones diferentes devueltas al llamar al mmap. Pero como descubrí, ese no era el caso. Hice el siguiente programa de prueba para ese propósito. Todas las direcciones devueltas por malloc son exactamente iguales para el padre y el hijo. Tenga en cuenta que la malloc para CL1, Cl2, PL1, PL2 utiliza internamente mmap porque son grandes bloques.Aleación de diseño de espacio de direcciones (ALSR) y mmap

Entonces, mi pregunta es, ¿por qué mmap no devuelve direcciones diferentes, incluso en presencia de ALSR. Tal vez sea porque la semilla para la aleatorización aquí es la misma para el proceso original y bifurcado. ¿O hay alguna otra razón?

int main() 
{ 
    pid = fork(); 

    if (pid == 0)    // child 
    { 
    void * c1 = malloc(4096); 
    void * c2 = malloc(4096); 

    void * cl1 = malloc((long)512e3); // internally uses mmap 
    void * cl2 = malloc((long)512e3); // internally uses mmap 

    printf("c1 = %p, c2 = %p, cl1 = %p, cl2 = %p!\n", c1, c2, cl1, cl2); 
    } 
    else 
    { 
    void * p1 = malloc(4096); 
    void * p2 = malloc(4096); 

    void * pl1 = malloc((long)512e3); // internally uses mmap 
    void * pl2 = malloc((long)512e3); // internally uses mmap 

    printf("p1 = %p, p2 = %p, pl1 = %p, pl2 = %p!\n", p1, p2, pl1, pl2); 
    } 

    return 0; 
} 
+0

No estoy seguro de que ASLR requiera que 'mmap' devuelva direcciones diferentes; solo significa que * puede * devolver otros diferentes. Y quizás (¡solo una suposición!) Se desencadena más por 'execve' que por' fork'. Por supuesto, si comienzo dos veces seguidas su programa, obtendré direcciones diferentes. Y esto podría cambiar con los kernels futuros, o quizás con los habilitados para SELinux ... –

+2

puede que le resulte útil: http://xorl.wordpress.com/2011/01/16/linux-kernel-aslr-implementation/ – Necrolis

+0

@ Basile: Claro, obtendrá diferentes direcciones para cada ejecución, pero para una ejecución, ¿difieren alguna vez las direcciones de los dos procesos (padre e hijo)? – MetallicPriest

Respuesta

4

No se puede volver a cambiar aleatoriamente el espacio de direcciones del niño - todos los punteros tendrían que ser retocado, y eso es técnicamente imposible (el entorno de ejecución ni siquiera sabe qué parte de sus datos son punteros).

El resultado que está viendo es el esperado, el elemento secundario del tenedor tiene una copia exacta del espacio de direcciones principal en el momento de la bifurcación, incluido el diseño de la dirección virtual.

Necesitará una llamada exec* para obtener un nuevo diseño de espacio de direcciones.

$ cat t.c 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 

int main(int argc, char **argv) 
{ 
    printf("%p\n", malloc((long)512e3)); 
    if ((argc > 1) && fork()) { 
     execl("./a.out", "./a.out", NULL); 
    } 
    return 0; 
} 
$ gcc -Wall t.c 
$ ./a.out 1 
0x7f5bf6962010 
0x7f3483044010 
$ ./a.out 1 
0x7f1ce7462010 
0x7feb2adc2010 

(y asegúrese de /proc/sys/kernel/randomize_va_space no es cero también.)

+0

OP no parece querer que las asignaciones creadas antes de la horquilla cambien las direcciones, solo para nuevas asignaciones después de la horquilla para obtener direcciones aleatorias independientes. Esto no es técnicamente imposible, pero como se describe en mi respuesta, es una mala idea. –

+0

Entonces, ¿quiere decir que todos los futuros mmap, sbrk, malloc, etc. devolverán las mismas direcciones para los procesos padre e hijo? – MetallicPriest

+1

@MetallicPriest: si los haces en el mismo orden, para las mismas cantidades, y no entran en juego factores externos (límites de recursos, OOM normal, etc.), probablemente sí con un kernel Linux simple. Pueden existir algunos parches para aleatorizar asignaciones dinámicas, pero no el núcleo base. Ver la respuesta de R .. para más sobre esto. – Mat

5

ASLR aleatoriza principalmente la distancia desde la parte superior del espacio de usuario espacio de direcciones a la pila, y la distancia desde la parte inferior de stack- espacio reservado para el primer mmap (que es probablemente el mapeo del enlazador dinámico). Cualquier aleatorización adicional tendría graves efectos de fragmentación en el espacio de la memoria virtual, y por lo tanto rompería los programas que necesitan hacer grandes mmap s (por ejemplo, un mapeo de 1-2 GB en una máquina de 32 bits).

He visto algunas distribuciones de Linux enviar kernels reparados que realizan mucha más aleatorización en las direcciones devueltas por mmap. Algunos de ellos incluso te dan asignaciones que se superponen con el espacio reservado para que la pila se expanda, y luego cuando crece la pila obtura tu mapeo (lo que resulta en un enorme agujero de seguridad, mucho más grande que cualquier asignación de direcciones no aleatorias) . Mantente alejado de estos hacks.

+0

Entonces, ¿podemos suponer que mmap en un proceso bifurcado no siempre devolverá la misma dirección que en el padre? ¿derecho? – MetallicPriest

+0

Es (por lo general) cierto hoy, pero no lo asumiré para los kernels futuros. Nada especifica eso, es solo la implementación actual. Y la gente del kernel podría querer mejorarlo. –

+0

Evitaría hacer suposiciones de una manera u otra. Por ejemplo, probablemente sea seguro/razonable agregar una pequeña cantidad de relleno aleatorio (páginas no asignadas) antes de mapeos muy grandes (ya que la sobrecarga/fragmentación porcentual sería necesariamente muy pequeña). –

Cuestiones relacionadas