# 機能設計書 4-システムコールインタフェース

## 概要

本ドキュメントは、FreeBSDカーネルにおけるシステムコールインタフェース機能の設計を記述する。ユーザ空間からカーネル機能を呼び出すためのシステムコールディスパッチ機構を対象とする。

### 本機能の処理概要

**業務上の目的・背景**：システムコールインタフェースはユーザ空間のプログラムがカーネルの機能（ファイル操作、プロセス管理、ネットワーク等）を利用するための唯一の正規手段である。安全かつ効率的なユーザ・カーネル間の境界を提供することがOSの根幹機能として不可欠である。

**機能の利用シーン**：すべてのユーザプログラムからのカーネル機能呼び出し（ファイルopen/read/write、プロセスfork/exec、ソケット操作等）、libcの内部実装、互換レイヤ（Linux互換、32bit互換等）で利用される。

**主要な処理内容**：
1. **システムコールテーブル管理**: init_sysent.cで定義されるsysent[]テーブルによるシステムコール番号からハンドラ関数へのマッピング。自動生成されるファイルであり、syscalls.masterから生成される。
2. **システムコールディスパッチ**: トラップハンドラからのシステムコール番号に基づくハンドラ関数の呼び出し。引数のユーザ空間からカーネル空間へのコピー。
3. **ファイルディスクリプタ管理**: kern_descrip.cによるファイルディスクリプタテーブルの管理。open/close/dup/fcntl等のFD操作。
4. **互換性レイヤ**: FreeBSD旧バージョン互換（COMPAT_FREEBSD11等）、Linux互換（Linuxulator）のサポート。

**関連システム・外部連携**：libc（ユーザ空間のシステムコールラッパー）、各カーネルサブシステム（VFS、ネットワーク、プロセス管理等）、ktrace（システムコールトレース）、DTrace systrace providerとの連携。

**権限による制御**：各システムコールは個別のアクセス制御を実装する。priv_check()によるケイパビリティチェック、Capsicumケイパビリティモードによるサンドボックス制限が適用される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 該当なし | - | システムコールインタフェースはカーネル内部機構であり、直接的なUI画面は存在しない |

## 機能種別

カーネル基盤機能（システムコールディスパッチ・ファイルディスクリプタ管理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| syscall番号 | int | Yes | 呼び出すシステムコールの番号 | sysent[]テーブル範囲内 |
| 引数1-6 | register_t | No | アーキテクチャ依存のレジスタ経由引数 | 各システムコール固有 |

### 入力データソース

CPUトラップ（syscall命令 / int 0x80 / svc等）経由のユーザ空間からの呼び出し。引数はレジスタまたはスタック経由で渡される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | register_t | システムコールの実行結果 |
| errno | int | エラー時のエラー番号 |

### 出力先

ユーザ空間への戻り値（レジスタ経由）。

## 処理フロー

### 処理シーケンス

```
1. トラップエントリ
   ├─ CPUがsyscall命令を検出
   │    ├─ ユーザモードからカーネルモードへ切替
   │    ├─ レジスタ保存（trapframe）
   │    └─ syscall()ハンドラへジャンプ
   │
2. システムコールディスパッチ
   ├─ syscall番号からsysent[]テーブル参照
   │    ├─ 引数のcopyin（ユーザ空間→カーネル空間）
   │    ├─ sy_call()関数ポインタ経由でハンドラ呼び出し
   │    └─ 戻り値・errnoの設定
   │
3. トラップリターン
   ├─ ast()処理（シグナル配送、スケジューリング等）
   │    ├─ レジスタ復元
   │    └─ カーネルモードからユーザモードへ切替
```

### フローチャート

```mermaid
flowchart TD
    A[ユーザプログラム: syscall命令] --> B[CPUトラップ]
    B --> C[カーネルエントリ: レジスタ保存]
    C --> D[syscall番号取得]
    D --> E{番号有効?}
    E -->|No| F[ENOSYS返却]
    E -->|Yes| G[sysent テーブル参照]
    G --> H[引数copyin]
    H --> I[sy_call ハンドラ実行]
    I --> J[戻り値設定]
    J --> K[ast処理]
    K --> L[レジスタ復元]
    L --> M[ユーザモード復帰]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 番号範囲チェック | 無効なシステムコール番号にはENOSYSを返す | 全syscall呼び出し時 |
| BR-02 | Capsicum制限 | ケイパビリティモードでは許可されたsyscallのみ実行可能 | cap_enter()後 |
| BR-03 | 互換性マッピング | 旧バージョンのsyscall番号を現行ハンドラにマッピング | COMPAT_FREEBSDx有効時 |
| BR-04 | ktrace記録 | ktraceが有効な場合、syscallの入出力を記録 | KTRACE有効かつプロセスがトレース対象時 |
| BR-05 | audit記録 | セキュリティ監査有効時にsyscall呼び出しを記録 | audit_syscall_enter/exit |

### 計算ロジック

sysent[]テーブルは配列インデックスでアクセスされるためO(1)のディスパッチが可能。

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

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

| 操作 | 対象データ構造 | 操作種別 | 概要 |
|-----|-------------|---------|------|
| open | filedesc | INSERT | ファイルディスクリプタの割り当て |
| close | filedesc | DELETE | ファイルディスクリプタの解放 |
| dup/dup2 | filedesc | INSERT/UPDATE | FDの複製 |
| fcntl | filedesc | UPDATE | FDフラグの変更 |

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

#### struct sysent（システムコールテーブルエントリ）

| 操作 | 項目（フィールド名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| 参照 | sy_narg | 引数の数 | ディスパッチ時に使用 |
| 参照 | sy_call | ハンドラ関数ポインタ | 実行するシステムコール関数 |
| 参照 | sy_auevent | 監査イベント番号 | audit用 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ENOSYS | 未実装 | 無効なシステムコール番号 | 有効なsyscall番号を使用 |
| EFAULT | 不正アドレス | 引数copyin/copyout失敗 | 正しいポインタを渡す |
| EBADF | 不正FD | 無効なファイルディスクリプタ | 有効なFDを指定 |
| ECAPMODE | 制限違反 | Capsicumモードで禁止されたsyscall | 許可されたsyscallのみ使用 |
| EINTR | 割り込み | シグナルによるsyscall中断 | 必要に応じて再試行 |

### リトライ仕様

EINTRで中断されたシステムコールはSA_RESTARTフラグに応じて自動的に再実行される。

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

システムコールディスパッチ自体にトランザクション制御はないが、個々のシステムコールハンドラが適切なロックを取得する。ファイルディスクリプタテーブルはfiledesc lockで保護される。

## パフォーマンス要件

- システムコールエントリ・リターン: サブマイクロ秒オーダー（高速syscall命令使用時）
- sysent[]テーブル参照: O(1)の配列アクセス
- 引数copyin: ページフォルトが発生しない限り高速

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

- ユーザ空間からの引数は必ずcopyin()でカーネル空間にコピーし、TOCTOU攻撃を防止
- Capsicumケイパビリティモードによるシステムコール制限
- ktraceとauditによるシステムコール監査
- syscall引数のバリデーション（各ハンドラ内）

## 備考

- init_sysent.cはsyscalls.masterから自動生成されるファイルであり、手動編集は行わない
- FreeBSD 4/6/7/10/11/12/13との互換レイヤ（compatマクロ）がinit_sysent.cの先頭で定義されている
- 32bitバイナリの64bitカーネル上での実行はfreebsd32_sysent.cで対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sysent.h | `sys/sys/sysent.h` | struct sysentの定義。sy_narg、sy_call、sy_auevent等のフィールド |
| 1-2 | sysproto.h | `sys/sys/sysproto.h` | 各システムコールの引数構造体定義（自動生成） |
| 1-3 | filedesc.h | `sys/sys/filedesc.h` | struct filedescの定義。FDテーブル構造 |

**読解のコツ**: init_sysent.cは自動生成ファイルであり、各エントリが`{ .sy_narg = AS(xxx_args), .sy_call = (sy_call_t *)sys_xxx }`の形式になっている。ASマクロ（11行目）は引数構造体のサイズをsyscallarg_t単位で計算する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | init_sysent.c | `sys/kern/init_sysent.c` | sysent[]テーブル本体。syscall番号→ハンドラマッピング |
| 2-2 | trap.c | `sys/amd64/amd64/trap.c` | （amd64の場合）トラップハンドラ。syscall()関数 |

**主要処理フロー**:
1. **1-11行目（init_sysent.c）**: ファイルヘッダ。自動生成の注記とASマクロ定義
2. **13-59行目**: 互換レイヤのマクロ定義（compat, compat4, compat6, ... compat13）

#### Step 3: ファイルディスクリプタ管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kern_descrip.c | `sys/kern/kern_descrip.c` | FD管理の主要実装。sys_dup2(), sys_fcntl(), fdalloc() |

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

```
ユーザ空間: syscall命令
    |
    +-- CPU トラップ
            |
            +-- amd64_syscall() / arm64_syscall() [アーキテクチャ依存]
                    |
                    +-- sysent[code].sy_call() [ディスパッチ]
                    |       |
                    |       +-- sys_open() / sys_read() / sys_write() / ...
                    |
                    +-- ktrace (KTRACE有効時)
                    +-- audit_syscall_enter/exit (AUDIT有効時)
                    +-- systrace (DTrace有効時)
```

### データフロー図

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

レジスタ(syscall番号) -> sysent[]テーブル参照 ────────> ハンドラ関数選択
レジスタ/スタック(引数) -> copyin() ─────────────────> カーネル空間引数
                          |
                          +-> sy_call()ハンドラ実行 ──> 戻り値(レジスタ)
                                                        errno設定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| init_sysent.c | `sys/kern/init_sysent.c` | ソース（自動生成） | システムコールテーブル本体 |
| kern_descrip.c | `sys/kern/kern_descrip.c` | ソース | ファイルディスクリプタ管理 |
| syscalls.master | `sys/kern/syscalls.master` | 定義ファイル | syscallテーブルのソース定義 |
| sysproto.h | `sys/sys/sysproto.h` | ヘッダ（自動生成） | syscall引数構造体定義 |
| sysent.h | `sys/sys/sysent.h` | ヘッダ | struct sysent定義 |
| filedesc.h | `sys/sys/filedesc.h` | ヘッダ | struct filedesc定義 |
| syscall.h | `sys/sys/syscall.h` | ヘッダ（自動生成） | syscall番号定数定義 |
| trap.c | `sys/amd64/amd64/trap.c` | ソース | amd64トラップハンドラ |
