paludarium とは
paludarium は、Rust で書いた、ユーザーモードの x86-64 Linux エミュレータです。 静的にリンクした x86-64 Linux のプログラム(static-musl のバイナリなど)を、 変更せずに、Linux・macOS・Windows の上と、WebAssembly(Node.js とブラウザ)の上で動かします。
「ユーザーモード」とは、OS(カーネル)全体ではなく、プログラムが OS に頼む機能 (システムコール)だけをまねる方式のことです。カーネルを起動しないので、軽く、 すぐに動き始めます。
何ができるか
- x86-64 の整数命令と SSE 系の命令を、ソフトウェアで実行します。
- Linux のシステムコールのうち、プログラムがよく使うもの(ファイル、メモリ、 スレッドと futex、シグナル、時刻、eventfd と timerfd と epoll、AF_UNIX のソケット、 別のプログラムの起動)を、ゲストの中で実装しています。
- ゲストには、そのたびに作るメモリ上のファイルシステムを見せます。指定したときだけ、 ホストのディレクトリを安全に見せられます。
- WebAssembly 版では、ゲストのスレッドごとに Worker を使い、x86-64 のコードを WebAssembly に変換する JIT も使えます。
使い方は 3 つあります。
| 使い方 | 向いている用途 |
|---|---|
paludarium コマンド | ホストでプログラムを 1 つ動かす |
| Rust のライブラリ | 自分のプログラムに組み込む |
| npm パッケージ | ブラウザや Node.js で動かす |
なぜ作ったか
jart/blink は、C で書かれた x86-64 Linux の ユーザーモードエミュレータです。paludarium は、これと同じことを Rust で一から作り直し、 安全性と保守しやすさを上げることを目指しています。最初の利用者は、ブラウザで コマンドラインのツールを動かす姉妹プロジェクトの formicarium です。
blink の動作と設計は参考にしていますが、コードは写していません。
大事にしていること
- ゲストを外に出さない:ゲストのシステムコールを番号のままホストに渡しません。 実装したものだけを明示した表で扱い、それ以外には
ENOSYSを返します。 ホストのディレクトリを見せるときも、..やシンボリックリンクで外に出られません。 - 何が来ても止まらない:命令のバイト列、メモリ、システムコールの引数、ELF の中身が どんなものでも、エミュレータは panic せず、未定義動作にもなりません。ファジングで 確かめています。
- 本物と同じ結果:正しさは「本物の x86-64 Linux と同じ結果になるか」で決めます。 同じプログラムを本物の Linux と paludarium の両方で動かして比べる差分テストを 中心にしています(テストと検証)。
- 許可しなければネットワークなし:ゲストが届くのは、組み込む側が名前かアドレスで 許可した行き先だけで、TCP のクライアントとしてだけです。名前を引けるのも、許可した 名前だけです。ゲスト自身の TCP と UDP のサーバーには、ループバックの上でゲストのソケット だけが届きます(ネットワーク)。