Рандомизация расположения адресного пространства (ALSR) и mmap - PullRequest
5 голосов
/ 28 февраля 2012

Я ожидаю, что из-за рандомизации структуры адресного пространства (ALSR) у процесса, разветвленного другим процессом, будут возвращаться другие адреса при вызове mmap. Но, как я выяснил, это был не тот случай. Я сделал следующую тестовую программу для этой цели. Все адреса, возвращаемые malloc, одинаковы для родительского и дочернего элементов. Обратите внимание, что malloc для cl1 , cl2 , pl1 , pl2 внутренне использует 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;
}

Ответы [ 2 ]

5 голосов
/ 28 февраля 2012

ASLR в основном рандомизирует расстояние от вершины адресного пространства пользовательского пространства до стека и расстояние от низа зарезервированного пространства стека до первого mmap (что, вероятно, является отображением динамического компоновщика),Любая дальнейшая рандомизация будет иметь серьезные фрагментирующие эффекты в пространстве виртуальной памяти и, таким образом, приведет к поломке программ, которые должны иметь большие mmap с (например, отображение 1-2 ГБ на 32-битной машине).Я видел несколько дистрибутивов Linux с исправленными ядрами, которые выполняют гораздо большую рандомизацию по адресам, возвращаемым mmap.Некоторые из них даже дают вам отображения, перекрывающиеся с пространством, зарезервированным для стека, в который он расширяется, а затем, когда стек увеличивается, это заглушает ваше отображение (в результате возникает огромная дыра в безопасности, намного большая, чем могло бы вызвать любое случайное назначение адресов),Держись подальше от этих хаков.

4 голосов
/ 28 февраля 2012

Вы не можете повторно рандомизировать адресное пространство ребенка - все указатели должны быть исправлены, и это технически невозможно (среда выполнения даже не знает, какая часть ваших данных является указателями).

Таким образом, ожидаемый результат является ожидаемым, у дочернего элемента разветвленной копии есть точная копия его родительского адресного пространства во время разветвления, включая макет виртуального адреса.

Вам понадобится вызов 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 тоже не ноль.)

...