# 機能設計書 46-Capsicum（ケイパビリティモード）

## 概要

本ドキュメントは、FreeBSDのCapsicumケイパビリティベースセキュリティフレームワークについて記述する。Capsicumはサンドボックス化のためのケイパビリティモードとファイルディスクリプタのケイパビリティ権限制限を提供する。

### 本機能の処理概要

Capsicumはプロセスをケイパビリティモードに遷移させ、グローバルな名前空間（ファイルシステムパス、PIDなど）へのアクセスを制限し、既に開いているファイルディスクリプタに対するケイパビリティ権限の制限を可能にするセキュリティフレームワークである。

**業務上の目的・背景**：従来のUNIXセキュリティモデルではプロセスが持つ権限が広範すぎ、脆弱性を突かれた場合のダメージが大きい。Capsicumは最小権限の原則に基づき、プロセスが必要最小限のリソースのみアクセスできるよう制限することで、脆弱性のエクスプロイトによる被害を最小化する。

**機能の利用シーン**：信頼できない入力を処理するプログラムのサンドボックス化（例：gzip, tar, tcpdump等の標準ツール）、ネットワークデーモンのセキュリティ強化、Casperデーモンを通じたケイパビリティモード下でのシステムサービスアクセスに使用される。

**主要な処理内容**：
1. ケイパビリティモードへの遷移（cap_enter()）
2. ファイルディスクリプタのケイパビリティ権限制限（cap_rights_limit()）
3. ioctlコマンドの制限（cap_ioctls_limit()）
4. fcntlコマンドの制限（cap_fcntls_limit()）
5. Casperデーモンによるサービスプロキシ（dns, grp, pwd, syslog等）
6. capsicum_helpersによるストリーム権限の簡易設定

**関連システム・外部連携**：カーネルのファイルディスクリプタ管理（kern_descrip.c）、VFS層、ソケット層と統合。Casperデーモン（libcasper）はケイパビリティモード下でDNS解決やユーザ情報取得などのサービスをプロキシする。

**権限による制御**：cap_enter()はいかなるプロセスでも呼び出し可能（root権限不要）。一度ケイパビリティモードに入ると元に戻すことはできない（不可逆的遷移）。子プロセスもケイパビリティモードを継承する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （APIベースのためGUI画面なし） | - | cap_enter()/cap_rights_limit()等のシステムコールAPI |

## 機能種別

サンドボックス化 / ケイパビリティ権限管理 / アクセス制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| fd | int | Yes（権限制限時） | 対象ファイルディスクリプタ | 有効なfd |
| rights | cap_rights_t | Yes（権限制限時） | 付与するケイパビリティ権限セット | 有効な権限フラグの組み合わせ |
| cmds | unsigned long[] | No | 許可するioctlコマンドリスト | 有効なioctlコマンド値 |
| fcntlrights | uint32_t | No | 許可するfcntlコマンドビットマスク | 有効なfcntlフラグ |

### 入力データソース

- アプリケーションコードからのシステムコール呼び出し
- capsicum_helpers.hのユーティリティ関数

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| return_value | int | 成功（0）/ エラー（-1, errno設定） |
| capability_mode | bool | プロセスがケイパビリティモードかどうか |
| fd_rights | cap_rights_t | fdに設定されたケイパビリティ権限 |

### 出力先

- システムコールの戻り値
- カーネル内のファイルディスクリプタテーブル（権限情報の更新）

## 処理フロー

### 処理シーケンス

```
1. 初期化フェーズ（ケイパビリティモード遷移前）
   └─ 必要なファイル/ソケットをすべてオープン
2. ケイパビリティ権限の制限
   └─ 各fdに対してcap_rights_limit()で必要最小限の権限を設定
3. ケイパビリティモード遷移
   └─ cap_enter()でグローバル名前空間アクセスを遮断
4. 制限された環境での実行
   └─ 既存fdのみ使用可能、新規open/socket等は制限
5. Casperサービス利用（必要に応じて）
   └─ libcasper経由でDNS解決等のサービスを利用
```

### フローチャート

```mermaid
flowchart TD
    A[プログラム開始] --> B[必要なリソースをオープン]
    B --> C[Casperサービス接続（必要時）]
    C --> D[cap_rights_limit: fd権限制限]
    D --> E[cap_enter: ケイパビリティモード遷移]
    E --> F[制限環境で処理実行]
    F --> G{新規リソースアクセス?}
    G -->|許可されたfd操作| H[操作実行]
    G -->|グローバル名前空間| I[ECAPMODE エラー]
    G -->|権限外のfd操作| J[ENOTCAPABLE エラー]
    H --> F
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-46-01 | 不可逆的遷移 | cap_enter()によるケイパビリティモードへの遷移は不可逆 | cap_enter()呼び出し後 |
| BR-46-02 | 権限の単調減少 | ケイパビリティ権限は制限のみ可能で、拡大はできない | cap_rights_limit()呼び出し時 |
| BR-46-03 | 子プロセス継承 | ケイパビリティモードはfork()した子プロセスに継承される | fork()時 |
| BR-46-04 | グローバル名前空間制限 | ケイパビリティモードではopen(), socket(), shm_open()等のグローバル名前空間操作が制限される | ケイパビリティモード中 |

### 計算ロジック

- ケイパビリティ権限チェック：fdに設定されたcap_rights_tと要求される操作の権限マスクの論理積比較
- capsicum_helpers.hのcaph_stream_rights()：CAP_EVENT, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, CAP_SEEKの基本権限セット

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

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

本機能はデータベースを使用しない。カーネルのファイルディスクリプタテーブル内にケイパビリティ権限情報を格納する。

| 操作 | 対象データ構造 | 操作種別 | 概要 |
|-----|-------------|---------|------|
| cap_rights_limit | filedesc capability | UPDATE | fd権限の制限設定 |
| cap_rights_get | filedesc capability | SELECT | fd権限の取得 |
| cap_enter | process flag | UPDATE | ケイパビリティモードフラグ設定 |

### テーブル別操作詳細

#### filedesc（ファイルディスクリプタテーブル）

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| UPDATE | fd_cap_rights | cap_rights_t権限マスク | 権限の縮小のみ可能 |
| UPDATE | fd_cap_ioctls | ioctl許可リスト | NULL=全許可、空=全拒否 |
| UPDATE | fd_cap_fcntls | fcntl許可マスク | ビットマスク形式 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ECAPMODE | ケイパビリティモード違反 | ケイパビリティモード下でのグローバル名前空間操作 | 事前にリソースをオープンしておく |
| ENOTCAPABLE | 権限不足 | fdに設定された権限外の操作 | cap_rights_limitで適切な権限を設定 |
| EBADF | 不正なfd | 無効なファイルディスクリプタ | fdの有効性を確認 |
| ENOSYS | 未サポート | Capsicumが無効なカーネル | CAPSICUMオプション付きカーネルを使用 |

### リトライ仕様

ケイパビリティ違反はプログラムの設計に起因するため、リトライではなく事前のリソース準備が必要。

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

cap_enter()とcap_rights_limit()は個別の原子的操作。複数fdの権限を同時に設定する仕組みはなく、各fdに対して個別に権限を設定する必要がある。

## パフォーマンス要件

- ケイパビリティチェックはシステムコール実行時の追加チェックのみで低オーバーヘッド
- cap_rights_tはビットマスク比較のためO(1)
- ioctl制限チェックはリストの線形探索

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

- Capsicumはサンドボックスの「最後の防衛線」であり、アプリケーションの脆弱性を突かれた場合のダメージを限定する
- ケイパビリティモード遷移前に適切なリソース準備が重要
- Casperサービスの安全性（通信チャネルの保護）
- 不可逆的遷移によりケイパビリティモードの回避が困難

## 備考

- CapsicumはFreeBSDとLinux（一部）でサポートされるケイパビリティベースセキュリティ
- FreeBSDの多数の標準ツール（gzip, tar, tcpdump, dhclient等）がCapsicum対応済み
- capsicum_helpers.hはCapsicum対応を簡素化するユーティリティ関数を提供
- CAPH_IGNORE_EBADF, CAPH_READ, CAPH_WRITE, CAPH_LOOKUPフラグで権限設定を制御

---

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

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

### 推奨読解順序

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

Capsicumのケイパビリティ権限構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | capsicum.h | `sys/sys/capsicum.h` | cap_rights_t構造体とCAP_*権限定数の定義を理解する |
| 1-2 | capsicum_helpers.h | `lib/libcapsicum/capsicum_helpers.h` | caph_stream_rights()（63-76行目）で標準的な権限セットの構成を理解する。CAPH_*フラグ定義（42-45行目） |

**読解のコツ**: cap_rights_tはバージョン付きの構造体で、将来の拡張に対応している。権限はCAP_READ, CAP_WRITE, CAP_SEEK, CAP_FSTAT等の個別ケイパビリティの組み合わせで表現される。

#### Step 2: カーネル実装を理解する

ケイパビリティモードとケイパビリティ権限チェックのカーネル実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | kern_capsicum.c | `sys/kern/kern_capsicum.c` | cap_enter(), cap_rights_limit(), cap_rights_get()等のシステムコール実装 |
| 2-2 | kern_descrip.c | `sys/kern/kern_descrip.c` | ファイルディスクリプタテーブルにおけるケイパビリティ権限の管理 |

**主要処理フロー**:
- cap_enter(): プロセスのp_flagにP_CAPMODEを設定。以降のシステムコールでケイパビリティモードチェックが有効化
- cap_rights_limit(): fdに関連付けられたcap_rights_tを制限（縮小のみ可能）

#### Step 3: Casperデーモンを理解する

ケイパビリティモード下でのシステムサービスアクセスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | libcasper/ | `lib/libcasper/libcasper/` | Casperデーモンのライブラリ実装。cap_init()でCasper接続を初期化 |
| 3-2 | services/ | `lib/libcasper/services/` | DNS解決（cap_dns）、ユーザ情報（cap_pwd, cap_grp）、syslog等のサービスモジュール |

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

```
アプリケーション
    │
    ├─ リソース準備（open, socket等）
    │
    ├─ capsicum_helpers.h: caph_limit_stream()
    │      └─ cap_rights_limit() → カーネル
    │
    ├─ cap_enter() → カーネル
    │      └─ P_CAPMODEフラグ設定
    │
    ├─ （サンドボックス内実行）
    │      ├─ 許可されたfd操作 → 成功
    │      ├─ 禁止された操作 → ECAPMODE/ENOTCAPABLE
    │      └─ Casperサービス利用
    │             └─ libcasper: cap_service_open()
    │                    └─ Casperデーモン（プロキシ処理）
    │
カーネル:
    ├─ kern_capsicum.c: sys_cap_enter()
    ├─ kern_capsicum.c: sys_cap_rights_limit()
    └─ 各システムコール内: IN_CAPABILITY_MODE() チェック
```

### データフロー図

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

cap_rights_t権限 ──▶ cap_rights_limit() ────▶ fd権限テーブル更新
(アプリケーション)     kern_capsicum.c

cap_enter() ───────▶ sys_cap_enter() ──────▶ P_CAPMODE設定
(アプリケーション)     kern_capsicum.c

システムコール ────▶ IN_CAPABILITY_MODE() ──▶ 許可/ECAPMODE
(サンドボックス内)     各syscall内チェック

Casper要求 ────────▶ libcasper ─────────────▶ サービス結果
(DNS/pwd/grp等)       cap_service_open()       (プロキシ経由)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| capsicum_helpers.h | `lib/libcapsicum/capsicum_helpers.h` | ヘッダ | Capsicumヘルパー関数 |
| capsicum.h | `sys/sys/capsicum.h` | ヘッダ | ケイパビリティ権限定義 |
| kern_capsicum.c | `sys/kern/kern_capsicum.c` | ソース | カーネルCapsicum実装 |
| kern_descrip.c | `sys/kern/kern_descrip.c` | ソース | fdテーブルのケイパビリティ管理 |
| libcasper/ | `lib/libcasper/libcasper/` | ソース | Casperデーモンライブラリ |
| services/ | `lib/libcasper/services/` | ソース | Casperサービスモジュール群 |
| capsicum_helpers.3 | `lib/libcapsicum/capsicum_helpers.3` | マニュアル | ヘルパー関数のmanページ |
