2012-02-28 7 views
5

Spodziewam się, że z powodu Randomization Layout przestrzeni adresowej (ALSR) proces rozwidlony z innego procesu będzie miał inne adresy zwrócone podczas wywoływania mmap. Ale jak się dowiedziałem, tak nie było. W tym celu wykonałem następujący program testowy. Wszystkie adresy zwrócone przez malloc są dokładnie takie same dla rodzica i dziecka. Zauważ, że malloc dla CL1, CL2, PL1, PL2 wewnętrznie używa mmap bo są duże bloki.Randomizacja układu adresu (ALSR) i mmap

Moje pytanie brzmi, dlaczego mmap nie zwraca różnych adresów nawet w obecności ALSR. Może to dlatego, że nasiono do randomizacji jest takie samo dla oryginalnego i rozwidlonego procesu. Czy jest jakiś inny powód?

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

Nie jestem pewien, czy ASLR wymaga, aby 'mmap' zwracał różne adresy; oznacza to tylko, że * może * zwrócić różne. I być może (po prostu przypuszczenie!) Jest on uruchamiany bardziej przez 'execve' niż przez' fork'. Na pewno, jeśli uruchomię dwa razy z rzędu twój program, otrzymuję różne adresy. A to może się zmienić w przyszłych jądrach, lub może z włączonymi SELinux ... –

+2

może ci się przydać: http://xorl.wordpress.com/2011/01/16/linux-kernel-aslr-implementation/ – Necrolis

+0

@ Basile: Oczywiście, otrzymasz różne adresy dla każdego biegu, ale czy w jednym biegu adresy obu procesów (rodzic i dziecko) różnią się od siebie? – MetallicPriest

Odpowiedz

4

Nie można ponownie losowo przestrzeń adresową dziecka - wszystkie wskaźniki będą musiały być dotykane, a to technicznie niemożliwe (środowisko uruchomieniowe nawet nie wie, jaka część Twoich danych to wskaźniki).

Zatem oczekiwany wynik jest oczekiwany, dziecko z widelca ma dokładną kopię swojej przestrzeni adresowej w momencie rozwidlania, łącznie z jego układem adresów wirtualnych.

Będziesz potrzebował wywołania exec*, aby uzyskać nowy układ przestrzeni adresowej.

$ 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 

(I upewnij /proc/sys/kernel/randomize_va_space nie jest zbyt zerowy).

+0

OP wydaje się nie chcieć mapowania stworzonego przed widelcem, aby zmienić adresy, tylko dla nowych mapowań po widelcu, aby uzyskać niezależnie losowe adresy. Nie jest to technicznie niemożliwe, ale jak opisano w mojej odpowiedzi, jest to zły pomysł. –

+0

Masz na myśli, że każdy przyszły mmap, sbrk, malloc itd. Zwróci te same adresy dla procesów nadrzędnych i podrzędnych? – MetallicPriest

+1

@MetallicPriest: jeśli robisz je w dokładnie tej samej kolejności, dla tych samych ilości i nie ma żadnych zewnętrznych czynników (limity zasobów, zwykły OOM, itp.), Prawdopodobnie tak z prostym jądrem Linux. Niektóre łatki mogą istnieć, aby losowo alokować dynamiczne alokacje, ale nie podstawowe jądro. Zobacz odpowiedź R .. więcej na ten temat. – Mat

5

ASLR losuje głównie odległość od góry przestrzeni użytkownika do przestrzeni adresowej w dół stosu, a odległość od dna stack- zarezerwowane miejsce na pierwszy mmap (który jest prawdopodobnie mapowaniem dynamicznego linkera). Jakakolwiek dalsza randomizacja miałaby poważne efekty fragmentacji na wirtualnej przestrzeni pamięci, a zatem przerwałaby programy, które muszą wykonać duże mmap s (np. Mapowanie 1-2 GB na 32-bitowym komputerze).

Widziałem kilka linuksowych dystrybucji łatek, które wykonują znacznie większą losowość na adresach zwróconych przez mmap. Niektóre z nich dają nawet odwzorowania pokrywające się z miejscem zarezerwowanym dla stosu, a następnie, gdy rośnie stos, odkłada mapowanie (co skutkuje ogromną luką w zabezpieczeniach, znacznie większą niż wszystko, co mogło spowodować przypadkowe przypisanie adresu) . Trzymaj się z daleka od tych hacków.

+0

Więc możemy założyć, że mmap w rozwidlonym procesie nie zawsze zwróci ten sam adres, co w rodzicu? dobrze? – MetallicPriest

+0

Jest (zwykle) prawdziwe dzisiaj, ale nie będę zakładać, że dla przyszłych ziaren. Nic nie precyzuje, że jest to tylko obecna implementacja. I ludzie jądra mogą chcieć go ulepszyć. –

+0

Unikałbym przyjmowania założeń w taki czy inny sposób. Na przykład prawdopodobnie byłoby bezpieczne/uzasadnione dodanie niewielkiej ilości losowego wypełnienia (niezmapowane strony) przed bardzo dużymi mapowaniami (ponieważ procentowe obciążenie/fragmentacja musiałaby być bardzo mała). –