GNU/Linux >> Linux の 問題 >  >> Linux

決定論的 malloc の実装方法

私はあなたが何を達成しようとしているのか疑問に思っています。プロセスが決定論的である場合、割り当て/解放のパターンは同じでなければなりません。

唯一の違いは、malloc によって返されるアドレスです。 .しかし、おそらくそれらに依存するべきではありません (最も簡単な方法は、ポインタをキー マップやその他のデータ構造として使用しないことです)。それでも、割り当てが sbrk まで行われていない場合にのみ違いがあるはずです (glibc は匿名の mmap を使用します 大規模な割り当ての場合)、または mmap を使用している場合 (デフォルトでは、アドレスはカーネルによって選択されます)。

本当にまったく同じアドレスが必要な場合は、1 つのオプションとして、大きな静的バッファーを用意し、このバッファーからメモリを使用するカスタム アロケーターを作成します。これには、必要なメモリの最大量を事前に知っておく必要があるという欠点があります。非 PIE 実行可能ファイル (gcc -fno-pie -no-pie )、静的バッファーは毎回同じアドレスを持ちます。 PIE 実行可能ファイルの場合、プログラムをロードするためのカーネルのアドレス空間レイアウトのランダム化を無効にすることができます。共有ライブラリでは、ASLR を無効にして同じプログラムを 2 回実行すると、ダイナミック リンカーがライブラリをマップする場所を同じように選択する必要があります。

使用するメモリの最大サイズが事前にわからない場合、またはこのサイズが増加するたびに再コンパイルしたくない場合は、 mmap を使用することもできます 固定アドレスに大きな匿名バッファをマップします。バッファのサイズとアドレスをパラメータとしてプロセスに渡し、返されたメモリを使用して独自の malloc を実装するだけです。

static void* malloc_buffer = NULL;
static size_t malloc_buffer_len = 0;

void* malloc(size_t size) {
    // Use malloc_buffer & malloc_buffer_len to implement your
    // own allocator. If you don't read uninitialized memory,
    // it can be deterministic.
    return memory;
}

int main(int argc, char** argv) {
    size_t buf_size = 0;
    uintptr_t buf_addr = 0;
    for (int i = 0; i < argv; ++i) {
        if (strcmp(argv[i], "--malloc-size") == 0) {
            buf_size = atoi(argv[++i]);
        }
        if (strcmp(argv[i], "--malloc-addr") == 0) {
            buf_addr = atoi(argv[++i]);
        }
    }

    malloc_buffer = mmap((void*)buf_addr, buf_size, PROT_WRITE|PROT_READ,
                         MAP_FIXED|MAP_PRIVATE, 0, 0);
    // editor's note: omit MAP_FIXED since you're checking the result anyway
    if (malloc_buffer == MAP_FAILED || malloc_buffer != (void*)but_addr) {
        // Could not get requested memory block, fail.
        exit(1);
    }

    malloc_size = buf_size;
}

MAP_FIXED を使用して 、buf_addr でこの新しいマッピングと重複する既存のマッピングを置き換えるようにカーネルに指示しています .

(編集者注:MAP_FIXED おそらくあなたが望むものではありません . buf_addr を指定する NULL の代わりにヒントとして 可能であれば、すでにそのアドレスを要求しています。 MAP_FIXED で 、 mmap エラーを返すか、指定したアドレスを返します。 malloc_buffer != (void*)but_addr check は FIXED 以外の場合に意味があります これは、コードや共有ライブラリなどの既存のマッピングを置き換えません。 Linux 4.17 で MAP_FIXED_NOREPLACE が導入されました これを使用して、使用したくない間違ったアドレスのメモリではなく、mmap がエラーを返すようにすることができます。ただし、コードが古いカーネルで動作するように、チェックインはそのままにしておいてください。)

このブロックを使用して独自の malloc を実装し、コードで他の非決定論的操作を使用しない場合、ポインター値を完全に制御できます。

これは、malloc / free のパターン使用法が決定論的であると想定しています。また、非決定論的なライブラリを使用しないこと。

ただし、より簡単な解決策は、アルゴリズムを決定論的に保ち、アドレスに依存しないことだと思います。これは可能です。私は大規模なプロジェクトに取り組んできましたが、複数のコンピューターが決定論的に状態を更新する必要がありました (入力のみを送信しながら、各プログラムが同じ状態になるように)。オブジェクトを参照する以外の目的でポインターを使用しない場合 (最も重要なことは、ハッシュとしてではなく、マップ内のキーとしてではなく、ポインター値を何にも使用しないことです...)、状態は決定論的のままです.

あなたがしたいことが、プロセスメモリ全体のスナップショットを作成し、バイナリ差分を実行して分岐を見つけられるようにすることでない限り。両方の計算が同じポイントに到達したことをどうやって知るのでしょうか?出力を比較するか、プロセスが状態のハッシュを計算できるようにし、それを使用して同期がとられていることを確認できるようにする方がはるかに簡単です。それ以外の場合、測定は非決定論的です)。


決定論的でないのは malloc だけではない ただし、アドレス空間レイアウトのランダム化のため、mmap (より多くのメモリ空間を取得するための基本的なシステム コール。これは関数ではなく、システム コールであるため、アプリケーションの観点からは基本的または原子的です。したがって、アプリケーション内で書き換えることはできません)。

で無効にできます

 echo 0 > /proc/sys/kernel/randomize_va_space

root として、または sysctl を介して。

アドレス空間のレイアウトのランダム化を無効にしないと、スタックします。

そして、あなたは以前に同様の質問をしましたが、そこで私はあなたの malloc を説明しました -s は必ずしも決定論的ではありません。

いくつかの実用的なアプリケーションでは、malloc だと思います。 決定論的であることはできません。たとえば、pid をキーとするハッシュ テーブルを持つプログラムを想像してみてください。 -s 起動している子プロセス。そのテーブルでの衝突は、すべてのプロセスで同じではありません。

malloc を作るのは無理だと思います 何を試しても、あなたの意味では決定論的です (ただし、チェックポイントするアプリケーションを非常に狭いクラスに制限し、ソフトウェアがあまり役に立たないほど狭い場合は除きます)。


簡単に言えば、他の人が述べているように、プログラムの命令の実行が決定論的である場合、 malloc() によって返されるメモリ 決定論的になります。これは、システムの実装に random() への呼び出しがないことを前提としています またはその趣旨の何か。よくわからない場合は、システムの malloc のコードまたはドキュメントを読んでください。 .

他の人も述べているように、これはASLRの例外の可能性があります。 root 権限を持っていない場合は、personality(2) を介してプロセスごとに無効にすることができます syscall および ADDR_NO_RANDOMIZE パラメータ。パーソナリティの詳細については、こちらをご覧ください。

編集:ご存じない方のためにも言っておきます:あなたがしていることは バイシミュレーション と呼ばれます よく研究された技術です。用語を知らなかった場合は、そのキーワードで検索すると役立つ場合があります。


Linux
  1. IPアドレスを逆方向に読み取る方法は?

  2. cPanelにログインする方法

  3. SmarterMailでIPアドレスをホワイトリストに登録する方法

  1. cPanelでIPアドレスを拒否する方法

  2. 専用IPの購入方法

  3. Ubuntu で自分の IP アドレスを見つける方法

  1. LinuxでIPアドレスを見つける方法

  2. AlmaLinuxでIPアドレスを変更する方法

  3. SmarterMailでIPアドレスをブラックリストに登録する方法