アップデート一覧に戻る
New releaseJul 27, 2026

Z-Jail v1.1.0

軽量かつ多層的なLinuxサンドボックスで、namespaces、pivot_root、seccomp-bpf、capability dropping、そしてエビデンスベースの判定エンジン(Truthimatics Public Version)を組み合わせ、安全で監査可能なコード実行を実現します。

共有
Z-Jail

Z-Jail

Linux上でのネイティブコード実行のためのマルチレイヤーサンドボックス。
7つの独立した防御層 — 外部依存関係なし、約73 KiBのPIEバイナリ。


┌──────────────────────────────────────────────────────┐
│                    Z-Jail                            │
├──────────────────────────────────────────────────────┤
│  Truthimatics PV  (エビデンスベースの判定エンジン)     │
│  Namespaces       (mount, pid, net, ipc, uts)        │
│  pivot_root       (chrootの強化版)                    │
│  Capabilities     (すべて削除、securebitsをロック)       │
│  NO_NEW_PRIVS     (権限昇格を禁止)                    │
│  seccomp-BPF     (ホワイトリスト: 15システムコールのみ) │
│  Audit            (JSONログ + BLAKE2bハッシュ)        │
└──────────────────────────────────────────────────────┘

目次


クイックスタート

git clone https://github.com/Division-36/Z-Jail.git
cd Z-Jail
make
sudo ./z_jail --root=/path/to/rootfs --seccomp-enforce -- /bin/ls

--rootディレクトリには、ターゲットバイナリとその依存関係を含む最小限のファイルシステムが必要です(静的バイナリの場合はバイナリのみで十分です)。


なぜZ-Jailか

既存のサンドボックス化ソリューションにはトレードオフがあります:

Z-JailFirecrackergVisorbwrapnsjail
外部依存関係ゼロlibc, seccompGoランタイムlibclibc, protobuf
バイナリサイズ約73 KiB20+ MiB40+ MiB~70 KiB~1 MiB
VM分離なしあり (microVM)なし (サンドボックス)なしなし
seccompホワイトリストありなしありオプションあり
コンテンツハッシュありなしなしなしなし
Audit JSONありなしありなし一部
ビルドの複雑さ1つのmake複雑複雑簡単中程度

Z-Jailはbwrap(最小限、デフォルトでseccompなし)とnsjail(高機能、重い依存関係)の間のニッチを埋めます。CIパイプライン、CTFジャイルチャレンジ、軽量コード評価のために設計されており、コンテナランタイムを導入せずに多層防御を実現します。


アーキテクチャ

データフロー

flowchart LR
    CLI[CLI引数] --> P[parse_args]
    P --> C{名前空間をクローン}
    C -->|子プロセス| CR[child_run]
    C -->|親プロセス| W[waitpid]
    CR --> RL[setrlimit]
    RL --> FD[fd >= 3 を閉じる]
    FD --> DUMP[PR_SET_DUMPABLE=0]
    DUMP --> PV[pivot_root]
    PV --> NNP[PR_SET_NO_NEW_PRIVS]
    NNP --> CAP[ケーパビリティを削除]
    CAP --> SC[seccomp-BPF]
    SC --> SIG[シグナルを親に送信]
    SIG --> EX[execve ターゲット]
    W --> A[監査JSON]
    A --> EXIT[終了]

レイヤーの順序

各レイヤーは、後のレイヤーが前のレイヤーによって元に戻されないように順序付けられています:

  1. setrlimit — CPU、アドレス空間、ファイル数、プロセス数を最初に制限
  2. fdスクラブ — レポートパイプを除くすべての継承されたfdを閉じる
  3. PR_SET_DUMPABLE=0 — コアダンプを無効化、/proc/self/memをロックダウン
  4. pivot_root — ホストファイルシステムから切り離し; 古いルートは遅延アンマウント
  5. PR_SET_NO_NEW_PRIVS — この時点以降、setuidやcapsetによる昇格を禁止
  6. drop_caps — すべてのケーパビリティをゼロにし、securebitsをロック
  7. seccomp-BPF — システムコールをホワイトリストのみに制限
  8. 親にシグナルを送信 — サンドボックスの準備完了を親に通知
  9. execve — プロセスをターゲットバイナリに置き換え
sequenceDiagram
    participant P as 親プロセス
    participant C as 子プロセス
    P->>C: clone (NEWNS|NEWPID|NEWNET|NEWIPC|NEWUTS)
    Note over C: setrlimit(CPU, AS, NOFILE, NPROC)
    Note over C: close(3以上のすべてのfd)
    Note over C: PR_SET_DUMPABLE=0
    Note over C: pivot_root → chdir("/") → umount -l
    Note over C: PR_SET_NO_NEW_PRIVS
    Note over C: capset(すべてゼロ) + securebits
    Note over C: seccomp(SECCOMP_MODE_FILTER, ホワイトリスト)
    C->>P: write(pipe, ready=1)
    Note over C: execve(ターゲット)
    P->>P: waitpid
    P->>P: 監査JSONを書き込み

レイヤー

1. Truthimatics Public Version

エビデンスベースの判定エンジン。実行されたバイナリに関する重み付き観測を収集し、最終的な判定(DETERMINISTICREJECT、またはUNCERTAIN)を決定します。各観測には重みがあり、任意の単一観測の重みが合計の50%を超えると判定が決まります。

2. 名前空間

clone()を介して5つの名前空間が作成されます:

名前空間フラグ目的
マウントCLONE_NEWNS分離されたファイルシステムツリー
PIDCLONE_NEWPIDプロセスID空間 (子プロセスはpid 1)
ネットCLONE_NEWNETネットワークインターフェースなし
IPCCLONE_NEWIPC共有メモリ / セマフォなし
UTSCLONE_NEWUTS独立したホスト名

初期名前空間でCAP_SYS_ADMINが必要です。

3. pivot_root

マウント名前空間のルートを--rootディレクトリに置き換えます:

  1. ルートディレクトリをそれ自身にバインドマウント (MS_BIND|MS_REC)
  2. pivot_root(new_root, put_old) — マウントツリーを交換
  3. chdir("/") — 新しいルートに移動
  4. umount2("/.pivot_old", MNT_DETACH) — 古いルートを切り離し
  5. rmdir("/.pivot_old") — クリーンアップ

これはchroot(2)よりも厳密に強力です — サンドボックス化されたプロセスがホストルートに戻る方法はありません。サンドボックス内部からのCLONE_NEWNS(すでにseccompでブロックされています)を使用しても不可能です。

4. ケーパビリティ

すべてのケーパビリティは以下によって削除されます:

capset(hdr, data)  // data = {0, 0, 0}
prctl(SECBIT_KEEP_CAPS_LOCKED | SECBIT_NO_SETUID_FIXUP | ...)

プロセスはcapset前にsetuid/setgidを削除し、CAP_SETUIDがまだ保持されている間にuid変更を有効にします。capset後、すべてのケーパビリティはなくなり、securebitsはロックされます — 再有効化は不可能です。

5. NO_NEW_PRIVS

prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);

プロセスまたはその子プロセスが、setuidバイナリ、ファイルケーパビリティ、またはLSM遷移を介して新しい特権を取得するのを防ぎます。不可逆的。

6. seccomp-BPF (whitelist-v1)

15のシステムコールの許可リスト — リストにないものはSECCOMP_RET_KILL:

システムコール番号備考
read0標準入力
write1標準出力/標準エラー + レポートパイプ
openat257ファイルアクセス (openではない)
close3
lseek8
brk12ヒープ管理
mmap9引数制限: flags & 4 == 0 (MAP_SHAREDなし), flags == 0x22 (MAP_PRIVATE|MAP_ANONYMOUS)
munmap11
execve59起動時の単一exec
exit_group231クリーンなプロセス終了
rt_sigaction13シグナルハンドラ
rt_sigprocmask14シグナルマスキング
getrandom318乱数ソース
clock_gettime228タイミング
fstat5ファイルメタデータ

BPFフィルタは動的に生成されます: 各ホワイトリストエントリに対して、システムコールが一致すれば許可、そうでなければKILLにフォールスルーするジャンプチェーンが出力されます。アーキテクチャが最初にチェックされます (AUDIT_ARCH_X86_64)。

フィルタはスタンドアロンテスト (tests/seccomp_filter_test.c、8/8合格) によって独立して検証され、root権限を必要とせずに実際のprctl(PR_SET_SECCOMP)に対してテストケースをfork+execveします。

7. 監査

実行ごとにJSON監査レコードが生成されます:

{
  "schema": "z-jail.audit/v1",
  "build_id": "Z-Jail/v1+dev",
  "timestamp": 1749000000,
  "duration_ns": 8500000,
  "executable": "/bin/ls",
  "verdict": "DETERMINISTIC",
  "exit_code": 0,
  "sandbox": {
    "seccomp_filter": "whitelist-v1",
    "seccomp_whitelist_size": 15,
    "seccomp_arg_rules_size": 2,
    "namespaces": ["mount","pid","net","ipc","uts"],
    "pivot_root": "/var/run/z-jail/roots/default",
    "no_new_privs": true,
    "capabilities_dropped": true
  },
  "content_fingerprint": "0e5751c026e543b2e8ab2eb06099daa1..."
}

build/audits/<binary-name>.audit.json に書き込まれます。content_fingerprintは、子プロセスが終了した後に親によって計算されたターゲットバイナリのBLAKE2b-256ハッシュです。


使い方

z_jail --root=<dir> [--seccomp-enforce] [--self-hash=<hex>]
       [--quiet] [--verbose] -- <program> [args...]
フラグ説明
--root=<dir>サンドボックスルートディレクトリ (必須)
--seccomp-enforceseccomp-BPFシステムコールホワイトリストを有効化
--self-hash=<hex>バイナリが期待されるBLAKE2b-256ハッシュと一致するか確認
--quiet監査出力を抑制
--verboseデバッグログを有効化
--versionビルドIDを表示 (Z-Jail/v1+dev)
--help使い方を表示して終了

# すべての保護機能を有効にして静的バイナリを実行
sudo z_jail --root=./roots --seccomp-enforce -- bin/hello_static

# バイナリ整合性検証付きで実行
sudo z_jail --root=./roots --seccomp-enforce \
  --self-hash=$(sha256sum z_jail | cut -c1-64) -- bin/program

# クワイエットモード (監査JSONなし)
sudo z_jail --root=./roots --quiet -- bin/program

終了コード

コード意味
0子プロセスが正常終了 (判定: DETERMINISTIC)
1子プロセスがシグナルで強制終了 (判定: REJECT)
2自己ハッシュ: 不正な16進文字列、またはファイルが読み取れない
3自己ハッシュ: 不一致 (バイナリが改ざんされている)
101子プロセスのセットアップエラー (rlimitなど)
102子プロセスのseccompフィルタインストール失敗
103子プロセスのexecve失敗 (バイナリが見つからない、実行権限なし)
104子プロセスのpivot_root失敗
105子プロセスのケーパビリティ削除失敗
125名前空間の作成失敗 (rootで実行? カーネルサポート?)

ビルド & インストール

要件

  • Linux カーネル ≥ 5.4 (名前空間、seccomp-BPF、pivot_root)
  • GCC ≥ 11 (11.4、13.2、15.2でテスト済み)
  • 外部ライブラリなし — 標準のCツールチェーンだけでOK

コマンド

make              # z_jailをビルド (~130 KiB PIEバイナリ)
make install      # /usr/local/bin + manページにインストール
make clean        # ビルド成果物を削除
make dist         # リリースtarballを作成
make check        # スモークテスト (--version + --help)

バイナリは位置独立実行可能ファイルとしてビルドされ、-fstack-protector-strong-D_FORTIFY_SOURCE=2、完全なRELRO、-z nowが有効です。

コンパイル時オプション

make CC=clang CFLAGS="-O3 -march=native"   # カスタムコンパイラ/フラグ

テスト

クイックテスト (root不要)

# seccompフィルタロジック (8テスト)
tests/build/seccomp_filter_test

# BLAKE2b既知解テスト
tests/build/blake2b_known

これらはrootを必要とせず、100ミリ秒未満で実行されます。

フルテストスイート

make -C tests setup          # ペイロード + テストルートをビルド
sudo bash tests/run_tests.sh # 17シナリオ

名前空間作成のためにrootが必要です。テストスイートの対象:

#シナリオタイプテスト内容
0blake2b_regress既知解BLAKE2b実装の正確性
1seccomp_filterスタンドアロンBPFBPFフィルタロジックの8サブテスト
2hello_staticok基本的な静的バイナリ実行
3hello_dynamicokld-linux + libcを使用した動的バイナリ
4execve_replacementokサンドボックス内のexecve (seccompでブロック)
5fd_inherited_readok標準入力/標準出力が正しく継承される
6mmap_bad_flagskilledMAP_SHARED付きmmapをブロック
7mmap_good_allowedokMAP_PRIVATE|ANONYMOUS付きmmapを許可
8mmap_prot_execkilledPROT_EXEC付きmmapをブロック
9mmap_self_modifykilled自己変更コードをブロック
10ptracekilledptraceをブロック
11socketkilledソケット作成をブロック
12chroot_escapekilledchrootシステムコールをブロック
13double_chrootkilled二重chrootをブロック
14mount_replaykilledマウントシステムコールをブロック
15cpu_exhaustkilledRLIMIT_NPROCがフォーク爆弾をブロック
16signal_parentkilled親へのシグナルをブロック
17self_hashokバイナリ整合性検証

パフォーマンス

WSL2 (カーネル 6.18.x-microsoft-standard-WSL2、Kali Linux) で測定。 ツールあたり50サンプル、統一ワークロード (本体がexit_group(0)であるフリースタンディング静的バイナリ)、getrusageハーネスで計時。方法論については docs/BENCHMARKS.md を参照。

メトリクス
バイナリサイズ約73 KiB (ストリップ前) / 約28 KiB (ストリップ後)
平均サンドボックスレイテンシ5.85 ± 1.45 ms (95% CI [5.45, 6.25])
ピークRSS1.62 MiB
コード行数 (コア)~900

直接比較 (同一ホスト、同一方法論)

ツールレイテンシ平均 ± 標準偏差ピークRSSデフォルトseccomp
Z-Jail5.85 ± 1.45 ms1.62 MiBあり
bwrap3.56 ± 0.40 ms2.19 MiBなし
nsjail8.98 ± 1.68 ms7.91 MiBあり

テスト条件下では、Z-Jailは3つのプロセスレベルサンドボックスの中で最も小さいRSSを持ち、レイテンシはbwrapとnsjailの中間です。Bubblewrapは最速ですが、デフォルトではseccompフィルタリングを行わないため、セットアップ作業が少なくて済みます。Z-Jailは実行ごとにseccompホワイトリストのインストール、ケーパビリティの削除、pivot_rootを実行します。gVisor (runsc)はこのWSL2カーネルでセグメンテーションフォールトが発生し、測定できませんでした。FirecrackerはマイクロVMによる分離 (VMコールドブート、異なるメトリクス) を行うため、fork-to-execテーブルから除外されています。これらは単一ホストの数値です — 相対的なものとして扱ってください。

注意: 以前文書化された値 (~8 ms、~4 MiB、~130 KiB) は現在のmakeビルド (~73 KiB、~5.9 ms) と一致せず、不正確だったようです。上記の数値はこのコードベースで再測定されました。Truthimaticsは依然としてコードの一部であり、削除されていません (古いaxiom_jailレポートは単に異なるバイナリ名とハーネスを使用していました)。ベンチマーク中に見つかったマウント伝搬バグはsrc/sandbox.cで修正されました (MS_REC|MS_PRIVATE をバインドマウントの前に追加); 再帰的な再マウントが測定されたレイテンシの一部に寄与しています。


脅威モデル

対象範囲

  • 信頼されていないペイロードによる任意のネイティブコード実行
  • chrootmountptracesocketprocess_vm_writevを介した脱出
  • フォーク爆弾、CPU枯渇 (RLIMIT_CPU)、メモリ枯渇 (RLIMIT_AS)
  • execveをまたぐファイル記述子リーク
  • setuid / 動的リンカ / LD_PRELOADによる昇格
  • seccompフィルタの削除またはケーパビリティの再有効化

対象外

  • 許可されたシステムコールサーフェス外のカーネルゼロデイ
  • ハードウェアサイドチャネル (Spectre、Meltdown)
  • 共有/proc/sysマウントを介した同一ホストVM脱出
  • CLONE_NEWNET + ブロックされたsocketが提供する以上のネットワークエグレス
  • 兄弟サンドボックスのリソース枯渇 (cgroupサポートが必要)

前提条件

  • ホストカーネルは未改変のLinux ≥ 5.4
  • clone(CLONE_NEWNS|CLONE_NEWPID|...)が成功する (CAP_SYS_ADMINが必要)
  • ターゲットバイナリは静的にリンクされている (または動的ライブラリが--root内で利用可能)
  • 本番環境では--self-hash=<hex>が設定されている

ドキュメント

ファイル説明
README.mdこのファイル
docs/ARCHITECTURE.mdアーキテクチャ概要
docs/SANDBOX.mdレイヤーごとのサンドボックス内部
docs/SECCOMP.mdseccomp-BPFホワイトリスト設計
docs/AUDIT_SCHEMA.md監査JSONスキーマリファレンス
docs/THREAT_MODEL.mdセキュリティ前提条件と範囲
docs/BLAKE2B.mdBLAKE2b実装詳細
docs/BENCHMARKS.mdパフォーマンスベンチマーク
docs/BUILD.mdビルド手順
docs/adr/アーキテクチャ決定記録 (4文書)
man/z_jail.1マニュアルページ
SECURITY.mdセキュリティポリシーと報告
CONTRIBUTING.md貢献方法
CHANGELOG.mdリリース履歴
ROADMAP.md将来計画
TODO.md既知のギャップと計画中の作業

ロードマップ

v1 (現在)

  • 7層の多層防御サンドボックス
  • BLAKE2b-256コンテンツフィンガープリンティング
  • 監査JSON出力
  • 17のテストシナリオ
  • manページ、補完 (bash、zsh、fish)

v2 (計画中)

  • 外部seccompポリシーファイル (JSONまたはBPFソース)
  • サンドボックスインスタンスごとのカスタム名前空間フラグ
  • CLI経由で設定可能なシステムコールホワイトリスト
  • CI統合用のパフォーマンスプロファイリングフック
  • リリース署名 (minisign/signify)

ステータス

build coverage


ライセンス

MIT — 全文はLICENSEを参照してください。


Z-JailはWSL2 (Kali Linux、GCC 15.2.0) 上でビルドされ、Linux 5.4+をターゲットとしています。 Division-36 によってメンテナンスされています。問題は課題トラッカー に報告してください。

カテゴリ