2012-02-28 5 views
5

アドレス空間レイアウトのランダム化(ALSR)により、別のプロセスから分岐されたプロセスは、mmapを呼び出すときに返されるアドレスが異なります。しかし、わかったように、そうではありませんでした。私はその目的のために次のテストプログラムを作った。 mallocによって返されたすべてのアドレスは、親と子の場合とまったく同じです。彼らは大きなブロックであるためmallocPL2CL1CL2PL1のために内部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'が別のアドレスを返すことを要求しているとは確信していません。それは単にそれが異なるものを返すかもしれないことを意味します。そしておそらく(ちょうど推測ですが) 'execve'によって' fork'よりもトリガされます。確かに、あなたのプログラムを2回連続して起動すると、私は別のアドレスを取得しています。これは将来のカーネルやSELinux対応のもので変更されるかもしれません... –

+2

これは便利かもしれません:http://xorl.wordpress.com/2011/01/16/linux-kernel-aslr-implementation/ – Necrolis

+0

@ Basile:もちろん、実行ごとに異なるアドレスが得られますが、1回の実行で2つのプロセス(親と子)のアドレスが異なるのですか? – 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

OPは、フォークの前に作成されたマッピングがアドレスを変更するのを望んでいないようです。これは技術的に不可能ではありませんが、私の答えに記載されているように、それは悪い考えです。 –

+0

したがって、将来のすべてのmmap、sbrk、mallocなどが親プロセスと子プロセスの同じアドレスを返すことを意味しますか? – MetallicPriest

+1

@ MetallicPriest:同じ量で同じ順序で実行し、外部要因(リソース制限、単純なOOMなど)がない場合は、普通のLinuxカーネルではおそらくyesです。いくつかのパッチは、動的割り当てをランダム化するために存在しますが、ベースカーネルはランダム化しません。これについては、R ..の答えを参照してください。 – Mat

5

はASLRは主にスタックまでのユーザ空間のアドレス空間の上部からの距離をランダム化し、stack-の下端からの距離予約されたスペースを最初のmmap(おそらく動的リンカーのマッピング)に置き換えます。それ以上のランダム化は、仮想メモリ空​​間に深刻な断片化の影響を及ぼし、したがって、大きなビット数を必要とするプログラム(例えば、32ビットマシン上で1〜2GBのマッピング)を破ることになる。

私は、mmapが返すアドレスでより多くのランダム化を実行するいくつかのLinuxディストリビューションパッチカーネルを見ました。それらの中には、スタックのために予約されているスペースと重なるマッピングを与えることさえできます。スタックが成長すると、マッピングが壊れてしまいます(巨大なセキュリティホールが発生する可能性があります) 。これらのハッキングから離れてください。

+0

したがって、フォークされたプロセスのmmapは、親と同じアドレスを返すとは限りません。右? – MetallicPriest

+0

今日は(通常)真実ですが、将来のカーネルについては想定しません。何も指定するものではなく、現在の実装に過ぎません。そして、カーネルの人々はそれを改善したいかもしれません。 –

+0

私はどちらか一方の仮定をすることを避けるでしょう。例えば、非常に大きなマッピングの前に、少量のランダムなパディング(マッピングされていないページ)を追加することは、おそらく安全/合理的です(パーセンテージによるオーバーヘッド/フラグメンテーションが必然的に非常に小さいため)。 –

関連する問題