# 機能設計書 65-jail（コンテナ）

## 概要

本ドキュメントは、FreeBSD標準のOSレベル仮想化機構であるjailの機能設計を記述する。jailはカーネルの名前空間分離機能を活用し、軽量なコンテナ環境を提供する。

### 本機能の処理概要

**業務上の目的・背景**：サーバ上で複数のサービスを安全に分離して運用するために、OSレベルの仮想化が必要とされる。jailはハードウェア仮想化のオーバーヘッドなしに、プロセス空間、ファイルシステム、ネットワークスタックの分離を実現する。2000年のFreeBSD 4.0で導入され、FreeBSDの代表的なセキュリティ・隔離機構として広く利用されている。

**機能の利用シーン**：Webサーバ/DBサーバの分離運用、マルチテナント環境でのサービス提供、開発・テスト環境の隔離、セキュリティサンドボックスとしての利用、CI/CDパイプラインでのビルド環境分離に使用される。

**主要な処理内容**：
1. jail設定ファイル（/etc/jail.conf）のパースとパラメータ解決
2. jail環境の作成（カーネルjail構造体の生成、jail_set()システムコール）
3. ファイルシステムマウント（devfs, fdescfs, procfs等）
4. ネットワーク設定（IPアドレス割り当て、VNETインタフェース設定）
5. jail内コマンド実行（exec.start, exec.stop等のライフサイクルフック）
6. jail間の依存関係管理と並列起動
7. ZFSデータセット/VNETインタフェースのjailへの委譲
8. jailの停止・削除処理

**関連システム・外部連携**：カーネルのjailサブシステム（sys/kern/kern_jail.c）がjailの中核を担う。jail(8)コマンドはjail_set(2)/jail_get(2)システムコールを介してカーネルと通信する。devfs、ZFS、ネットワークスタックと連携する。

**権限による制御**：jailの作成・管理にはroot権限が必要。jail内のrootは制限されたroot（securelevelやallow.*パラメータで制御）。jail内からのホスト操作は原則不可。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能にはGUI画面の関連はない |

## 機能種別

OSレベル仮想化 / コンテナ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -c | flag | No | jailを作成・起動 | 他の操作フラグと排他 |
| -r | flag | No | jailを停止・削除 | 他の操作フラグと排他 |
| -m | flag | No | jailパラメータを変更 | 既存jail対象 |
| -C | flag | No | クリーンアップ（停止後コマンド実行） | 既存jail対象 |
| -f configfile | string | No | 設定ファイル（デフォルト: /etc/jail.conf） | 存在するファイル |
| -p paralimit | int | No | 並列実行数上限 | 正の整数（0で無制限） |
| -v | flag | No | 詳細出力 | なし |
| -q | flag | No | 静粛モード | なし |
| jail_name | string | Yes | jail名 | jail.conf内で定義されていること |

### 入力データソース

- `/etc/jail.conf`: jail設定ファイル
- コマンドライン引数
- カーネルjailパラメータ（sysctl security.jail.*）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| JID | int | 割り当てられたJail ID |
| 実行結果 | int | コマンド終了ステータス |
| jail一覧 | text | -e オプション時のjail名一覧 |

### 出力先

- 標準出力: jail情報、-eオプション時の一覧
- JIDファイル: -Jオプション指定時のJIDファイル
- カーネル: jail_set()によるjailパラメータ設定

## 処理フロー

### 処理シーケンス

```
1. 設定ファイルパース
   └─ /etc/jail.confのパース、パラメータ解決
2. 依存関係解決
   └─ depend指定による起動順序の決定
3. jail作成（-c時）
   a. exec.prepare実行
   b. IPアドレス設定（ip4.addr/ip6.addr）
   c. ファイルシステムマウント（mount, mount.devfs等）
   d. jail_set()システムコール発行
   e. exec.created実行
   f. ZFSデータセット委譲
   g. VNETインタフェース設定
   h. exec.start実行（jail内）
   i. exec.poststart実行
4. jail停止（-r時）
   a. exec.prestop実行
   b. exec.stop実行（jail内）
   c. プロセス強制終了（stop.timeout後）
   d. jail_remove()
   e. ファイルシステムアンマウント
   f. IPアドレス解除
   g. exec.poststop実行
   h. exec.release実行
```

### フローチャート

```mermaid
flowchart TD
    A[jail コマンド起動] --> B[設定ファイルパース]
    B --> C{操作種別}
    C -->|作成 -c| D[依存jailの起動確認]
    C -->|停止 -r| E[exec.prestop]
    C -->|変更 -m| F[パラメータ更新]
    D --> G[exec.prepare]
    G --> H[IPアドレス設定]
    H --> I[ファイルシステムマウント]
    I --> J[jail_set システムコール]
    J --> K[exec.created]
    K --> L[ZFSデータセット/VNET設定]
    L --> M[exec.start jail内実行]
    M --> N[exec.poststart]
    E --> O[exec.stop jail内実行]
    O --> P[プロセス強制終了]
    P --> Q[jail_remove]
    Q --> R[アンマウント・IP解除]
    R --> S[exec.poststop/release]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-65-01 | 起動コマンド順序 | startcommands配列の順序で実行 | jail作成時 |
| BR-65-02 | 停止コマンド順序 | stopcommands配列の逆順で実行 | jail停止時 |
| BR-65-03 | 依存関係 | depend指定されたjailは先に起動、後に停止 | 依存関係設定時 |
| BR-65-04 | 読み取り専用パラメータ | CTLFLAG_RDTUNフラグ付きパラメータはjail作成時のみ設定可 | パラメータ変更時 |
| BR-65-05 | allow権限制御 | allow.set_hostname, allow.raw_sockets等でjail内の操作を制限 | 常時 |
| BR-65-06 | securelevel制御 | jail内のsecurelevelはホスト以上の値のみ設定可 | securelevel変更時 |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベースを使用しない。カーネルのjail構造体でjail状態を管理する。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EEXIST | jail名重複 | 同名のjailが既に存在 | 既存jailの停止後に再作成 |
| EPERM | 権限不足 | root以外のユーザが実行 | root権限で再実行 |
| - | 設定パースエラー | jail.confの文法エラー | エラー箇所を修正 |
| - | マウント失敗 | マウントポイントが存在しない | パス確認 |
| - | exec.startタイムアウト | exec.timeout超過 | タイムアウト値調整 |

### リトライ仕様

コマンド実行のリトライは行わない。失敗時はJF_FAILEDフラグが設定され、依存するjailも起動を停止する（nofail指定がない場合）。

## トランザクション仕様

jail作成は複数ステップからなるが、途中失敗時はクリーンアップコマンド（cleancommands配列）が実行される。

## パフォーマンス要件

- jailはカーネルレベルの名前空間分離であり、仮想マシンと比較して極めて低いオーバーヘッド
- 並列起動（-p オプション）により多数のjailを効率的に起動可能

## セキュリティ考慮事項

- jail内のrootは制限されたrootであり、ホストシステムへの操作は制限される
- allow.*パラメータにより、jail内で許可される操作を細かく制御可能
- securelevelによりカーネルの保護レベルを設定可能
- VNETにより独立したネットワークスタックを提供し、ネットワーク分離を実現
- security.jail.*のsysctlパラメータにより、デフォルトの許可ポリシーを制御

## 備考

- jail.confの文法はkey=value形式とブロック構造をサポート
- 旧式のコマンドライン（パス ホスト名 IP コマンド）も互換性のためサポート
- bectl jail によりZFS Boot Environmentをjailとしてマウント可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | jailp.h | `usr.sbin/jail/jailp.h` | jail管理の内部データ構造。cfjail、cfparam、JF_*フラグ、enum intparamの定義 |
| 1-2 | jail.h | `sys/sys/jail.h` | カーネル側のjail構造体定義（システムヘッダ） |

**読解のコツ**: jailp.hのenum intparamは起動/停止シーケンスの各ステップを表す。startcommands/stopcommands配列と対応させて読むことで、jailのライフサイクルが理解できる。JF_*フラグはjailの操作状態を管理する。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | jail.c | `usr.sbin/jail/jail.c` | main()関数 - コマンドライン解析とjail操作ディスパッチ |

**主要処理フロー**:
1. **50-82行目**: permspec構造体とperm_sysctl配列 - sysctl互換パラメータ
2. **84-107行目**: startcommands配列 - 起動シーケンスの定義
3. **109-129行目**: stopcommands配列 - 停止シーケンスの定義
4. **131-147行目**: cleancommands配列 - クリーンアップシーケンス
5. **163-266行目**: main() - getoptによるオプション解析（-c/-r/-m/-C等）
6. **270-277行目**: -e オプション - jail一覧表示

#### Step 3: jail設定パーサを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | config.c | `usr.sbin/jail/config.c` | jail.confのパース処理 |
| 3-2 | jailparse.y | `usr.sbin/jail/jailparse.y` | yacc文法定義 |
| 3-3 | jaillex.l | `usr.sbin/jail/jaillex.l` | lex字句解析 |

#### Step 4: jail操作コマンドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | command.c | `usr.sbin/jail/command.c` | exec.*コマンドの実行処理 |
| 4-2 | state.c | `usr.sbin/jail/state.c` | jailの状態遷移管理 |

#### Step 5: カーネル側を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | kern_jail.c | `sys/kern/kern_jail.c` | カーネルjailサブシステム実装 |

### プログラム呼び出し階層図

```
main() [jail.c]
    |
    +-- load_config() [config.c]
    |       +-- yyparse() [jailparse.y]
    |
    +-- start_jail() [state.c]
    |       +-- exec.prepare [command.c]
    |       +-- ip4/ip6設定 [jail.c - update_jail]
    |       +-- mount処理
    |       +-- jail_set() [libjail → カーネル]
    |       |       └─ kern_jail.c
    |       +-- exec.created [command.c]
    |       +-- zfs.dataset委譲
    |       +-- vnet.interface設定
    |       +-- exec.start [command.c] (jail内)
    |       +-- exec.poststart [command.c]
    |
    +-- stop_jail() [state.c]
            +-- exec.prestop
            +-- exec.stop (jail内)
            +-- jail_remove()
            +-- アンマウント
            +-- exec.poststop / exec.release
```

### データフロー図

```
[入力]                      [処理]                         [出力]

/etc/jail.conf ──────▶ config.c パーサ ──▶ cfjail構造体
                                              |
コマンドライン ──────▶ jail.c main() ──────▶ state.c
                                              |
                                         jail_set() ──▶ カーネルjail
                                              |
                                         command.c ──▶ exec.*コマンド実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| jail.c | `usr.sbin/jail/jail.c` | ソース | メインエントリポイント |
| jailp.h | `usr.sbin/jail/jailp.h` | ヘッダ | 内部データ構造定義 |
| config.c | `usr.sbin/jail/config.c` | ソース | 設定ファイルパース |
| command.c | `usr.sbin/jail/command.c` | ソース | コマンド実行 |
| state.c | `usr.sbin/jail/state.c` | ソース | 状態遷移管理 |
| jailparse.y | `usr.sbin/jail/jailparse.y` | ソース | yacc文法定義 |
| jaillex.l | `usr.sbin/jail/jaillex.l` | ソース | lex字句解析 |
| kern_jail.c | `sys/kern/kern_jail.c` | ソース | カーネルjailサブシステム |
| jail.8 | `usr.sbin/jail/jail.8` | マニュアル | jailマニュアルページ |
| jail.conf.5 | `usr.sbin/jail/jail.conf.5` | マニュアル | 設定ファイルマニュアル |
