ローダ
実行ファイルをメモリに載せ、実行を開始させる。 OS の一部。
手順#
execveシステムコールが呼ばれる- ヘッダを読み、形式とアーキテクチャを確認する
- セグメントを**仮想アドレス空間に対応づける**
.bssをゼロで埋める- スタックを用意し、引数と環境変数を積む
- 動的リンカを起動して共有ライブラリを解決する
- エントリポイントにジャンプする
実際には読み込まない#
「メモリに載せる」と言うが、 実際にはファイルをマップするだけで内容は読まない。
mmap でページテーブルに対応関係を登録し、
そのページに初めて触ったときの
ページフォルトで読み込む(デマンドページング)。
- 起動が速い(使う部分だけ読む)
- 同じ実行ファイルの複数プロセスが
.textの物理ページを共有できる
ASLR#
セグメントの配置アドレスを実行のたびに乱数で変える。
攻撃者が「この関数はこのアドレスにある」と 決め打ちできなくなるので、 バッファオーバーフローからの攻撃が難しくなる。
これに対応するため、実行ファイルは どこに置かれても動く形(PIE、位置独立実行形式)で 作られるようになっている。
参考文献#
- Randal E. Bryant, David R. O’Hallaron. Computer Systems: A Programmer’s Perspective, 3rd ed. Pearson, 2016. https://csapp.cs.cmu.edu/
- John R. Levine. Linkers and Loaders. Morgan Kaufmann, 1999.
- Abhishek Bhattacharjee, Daniel Lustig. Architectural and Operating System Support for Virtual Memory. Morgan & Claypool, 2017. https://doi.org/10.1007/978-3-031-01757-5