2012-02-28 5 views
5

주소 공간 레이아웃 무작위 화 (ALSR) 때문에 다른 프로세스에서 분기 된 프로세스는 mmap을 호출 할 때 다른 주소가 반환 될 것으로 예상합니다. 그러나 내가 알았 듯이 그것은 사실이 아닙니다. 그 목적을 위해 다음 테스트 프로그램을 만들었습니다. malloc에 의해 반환 된 모든 주소는 부모와 자식에 대해 정확히 동일합니다. 그들은 큰 블록이 있기 때문에 mallocPL2, CL1, CL2, PL1 내부적으로 mmap를 사용 참고.주소 공간 레이아웃 무작위 화 (ALSR) 및 mmap

내 질문은 왜 mmap이 ALSR이있는 경우에도 다른 주소를 반환하지 않는 이유입니다. 어쩌면 그것의 무작위 화를위한 씨앗은 원래의 갈래 과정에서 동일하기 때문일 수도 있습니다. 아니면 다른 이유가 있습니까? 모든 포인터가 접촉되어야 할 것이다, 그것은 (런타임 환경도 포인터입니다 데이터의 어떤 부분 모른다) 기술적으로 불가능 -

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

ASLR에서 'mmap'이 다른 주소를 반환하도록 요구하는지 확신 할 수 없습니다. 그것은 단지 다른 것들을 반환 할 수도 있음을 의미합니다. 아마도 (아마도 추측!)'fork'보다는'execve'에 의해 더 많이 트리거됩니다. 물론 두 번 연속해서 프로그램을 시작하면 다른 주소를 얻게됩니다. 그리고 이것은 미래의 커널이나 아마도 SELinux가 활성화 된 것들로 바뀔 수도 있습니다 ... –

+2

당신은 이것을 유용 할 것입니다 : http://xorl.wordpress.com/2011/01/16/linux-kernel-aslr-implementation/ – Necrolis

+0

@ Basile : 물론 각 실행에 대해 서로 다른 주소를 얻을 수 있지만 하나의 실행에 대해 두 프로세스 (상위 및 하위)의 주소가 다른가? – MetallicPriest

답변

4

당신은 아이의 주소 공간을 다시 무작위 수 없습니다.

포크의 자식은 가상 주소 레이아웃을 포함하여 분기 할 때 부모 주소 공간의 사본을 정확히 가지고 있습니다.

새 주소 공간 레이아웃을 얻으려면 exec* 전화가 필요합니다.

$ 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 

(그리고 /proc/sys/kernel/randomize_va_space도 0이 있는지 확인합니다.)

+0

OP는 주소를 변경하기 위해 포크 이전에 생성 된 매핑을 원하지 않는 것처럼 보입니다. 포크 후에 독립적으로 임의의 주소를 가져 오는 새로운 매핑 용입니다. 이것은 기술적으로 불가능한 것은 아니지만 제 대답에 설명 된 바와 같이 나쁜 생각입니다. –

+0

그래서 미래의 모든 mmap, sbrk, malloc 등이 부모 프로세스와 자식 프로세스에 대해 동일한 주소를 반환한다는 것을 의미합니까? – MetallicPriest

+1

@ MetallicPriest : 똑같은 순서로, 같은 수량으로, 외부 요소 (리소스 제한, 일반 OOM 등)가없는 경우, 평범한 리눅스 커널에서 그렇다. 일부 패치는 동적 할당을 무작위 화하기 위해 존재할 수 있지만 기본 커널에는 존재하지 않을 수 있습니다. 이에 대한 자세한 내용은 R ..의 대답을 참조하십시오. – Mat

5

은 ASLR은 주로 스택에 이르기까지 사용자 공간 주소 공간의 상단에서의 거리를 무작위로하고, stack-의 바닥으로부터의 거리 예약 된 공간을 첫 번째 mmap (아마도 동적 링커의 매핑입니다). 더 이상의 무작위 화는 가상 메모리 공간에 심각한 단편화 효과를 가져올 수 있으므로, 대용량 (예 : 32 비트 시스템에서 1-2GB 매핑)을 필요로하는 프로그램을 중단시킵니다.

mmap에 의해 반환 된 주소에서 훨씬 더 무작위 화를 수행하는 일부 Linux 배포판 패치 커널을 보았습니다. 그 중 일부는 스택에 할당 된 공간과 중복되는 매핑을 제공하기도하고 스택이 커지면 매핑이 깨져서 (엄청나게 큰 보안 구멍이 생기고 무작위가 아닌 임의의 주소 할당이 초래 한 것보다 훨씬 큽니다) . 이러한 해킹을 멀리하십시오.

+0

따라서 fork 된 프로세스에서 mmap이 항상 부모와 동일한 주소를 반환하지는 않는다고 가정 할 수 있습니까? 권리? – MetallicPriest

+0

오늘은 (사실) 사실이지만, 나는 미래의 커널을 위해 그것을 가정하지 않을 것입니다. 아무 것도 지정하지 않고 그냥 현재의 구현입니다. 그리고 커널 사람들은 그것을 향상시키고 자 할 수도 있습니다. –

+0

나는 어떤 방법 으로든 가정을하는 것을 피할 것이다. 예를 들어 매우 큰 매핑 전에 작은 양의 무작위 패딩 (매핑되지 않은 페이지)을 추가하는 것이 안전하거나 합리적 일 수 있습니다 (백분율 별 오버 헤드/조각화가 반드시 매우 작을 것이므로). –