📝 本記事について
本記事は、実際に MUSUBI(仕様駆動開発フレームワーク)と CodeGraph MCP Server を使用し、Linux カーネルコードの解析・変換を実験した結果をもとに、MUSUBI が自動作成した文章です。AI コードエージェントがどのように大規模コードベースを理解し、C から Rust への変換を行うかを、実践を通じてお伝えします。
目次
-
- Linux カーネルにおける Rust サポートの歴史
- 「実験的」タグが外れた意味
-
- なぜ Linux カーネルに Rust が必要なのか
- C と Rust の共存における課題
-
- MUSUBI(仕様駆動開発フレームワーク)
- CodeGraph MCP Server(コード解析ツール)
- GitHub Copilot との連携
-
- 必要なツールのインストール
- Linux カーネルソースの取得
- codegraph-mcp-server のセットアップ
-
- CodeGraph MCP Server によるコード構造の可視化
- 書き換え対象の選定
-
- 書き換え対象コードの選定理由
- AI エージェントによる変換プロセス
- 変換結果の検証
-
- AI による C → Rust 変換の精度と課題
- 今後の Linux カーネル Rust 化への展望
はじめに
2025年12月、Linux カーネル開発史において歴史的な瞬間が訪れました。年次 Maintainers Summit において、カーネルにおける Rust サポートが「もはや実験的ではない」との合意が形成され、長年付与されてきた 「実験的(experimental)」タグの解除 が決定されたのです。
Linux カーネルにおける Rust サポートの歴史
Linux カーネルは C 言語で書かれており、その歴史は 1991 年の Linus Torvalds による最初のリリースにまで遡ります。しかし、C 言語の性質上、メモリ関連のバグ(バッファオーバーフロー、use-after-free、NULL ポインタ参照など)が絶えず発生してきました。
この課題に対処するため、2020年 から「Rust for Linux」プロジェクトが始動しました。Rust はメモリ安全性を言語レベルで保証するプログラミング言語であり、C 言語が抱える脆弱性の多くを防ぐことができます。
主な経緯:
| 年 | 出来事 |
|---|---|
| 2020年 | Rust for Linux プロジェクト開始 |
| 2022年 | Linux 6.1 で Rust サポートが初めてマージ(experimental タグ付き) |
| 2024年9月 | Microsoft のエンジニア Wedson Almeida Filho 氏が「非技術的ナンセンス」を理由に離脱 |
| 2025年2月 | カーネルメンテナー Christoph Hellwig 氏が Rust コードを「がん」と表現し拒否 |
| 2025年12月 | Maintainers Summit で「実験的」タグ解除が決定 |
「実験的」タグが外れた意味
Linux コミュニティは一枚岩ではありません。Rust 導入に対しては根強い反対意見も存在し、推進派との間で激しい議論が繰り広げられてきました。
反対派の代表格である Christoph Hellwig 氏は、Rust を含むコードのマージを拒否し、「クロス言語コードベースで Linux を保守不可能にしたくないなら、この『がん』をコアサブシステムから排除すべきだ」と主張しました。
しかし、Linus Torvalds 氏は Rust 導入に基本的に賛成の立場を取り続け、最終的に 2025年12月の Maintainers Summit で以下の合意が得られました。
「Rust はもはや実験的ではなく、カーネルのコアであり、定着している」
— LWN.net "The (successful) end of the kernel Rust experiment"
この決定は、Linux カーネルの将来に向けた重要な転換点です。今後、ドライバやサブシステムの Rust 化が加速し、より安全なカーネルへの進化が期待されます。
本記事の目的
この歴史的な出来事を記念し、本記事では AI コードエージェント(GitHub Copilot + MUSUBI) と コード解析ツール(CodeGraph MCP Server) を活用して、実際に Linux カーネルの C コードを Rust に書き換える実験を行います。
- AI は C から Rust への変換をどの程度正確に行えるのか?
- 実用的な移植において何が課題となるのか?
- 今後の Linux Rust 化にどのような示唆を与えるのか?
これらの問いに、実践を通じて答えていきます。
Rust for Linux とは
なぜ Linux カーネルに Rust が必要なのか
Linux カーネルは 30 年以上にわたり C 言語で開発されてきました。C 言語は低レベルのハードウェア制御に優れ、高いパフォーマンスを発揮しますが、メモリ安全性 に関する根本的な問題を抱えています。
C 言語が抱えるメモリ安全性の問題
| 脆弱性の種類 | 説明 | 影響 |
|---|---|---|
| バッファオーバーフロー | 配列の境界を超えたアクセス | 任意コード実行、権限昇格 |
| Use-After-Free | 解放済みメモリへのアクセス | 情報漏洩、クラッシュ |
| ダブルフリー | 同じメモリを二重に解放 | ヒープ破壊、任意コード実行 |
| NULL ポインタ参照 | 無効なポインタのデリファレンス | カーネルパニック |
| データ競合 | 複数スレッドからの同時アクセス | 予測不能な動作 |
Microsoft Azure CTO の Mark Russinovich 氏は 2022 年に次のように述べています。
「セキュリティと信頼性のために、業界は C/C++ を非推奨とすべきだ」
この見解は世界中の政府セキュリティ機関からも支持を得ており、メモリ安全な言語への移行は業界全体のトレンドとなっています。
Rust が解決すること
Rust は コンパイル時にメモリ安全性を保証 するプログラミング言語です。所有権システム(Ownership)と借用チェッカー(Borrow Checker)により、上記の脆弱性の大部分をコンパイル時に検出・防止します。
// Rust では use-after-free がコンパイルエラーになる
fn example() {
let data = vec![1, 2, 3];
let reference = &data;
drop(data); // ここでデータを解放
// println!("{:?}", reference); // コンパイルエラー!
}
C と Rust の共存における課題
Rust for Linux プロジェクトは、既存の C コードベースと Rust を共存させるという前例のない挑戦に取り組んでいます。
技術的な課題
1. FFI(Foreign Function Interface)の複雑さ
Rust から C 関数を呼び出すには unsafe ブロックが必要です。カーネルの膨大な C API に対する安全なラッパー(抽象化レイヤー)を作成する必要があります。
// C の DMA API を Rust から呼び出す例
unsafe {
let ptr = dma_alloc_coherent(dev, size, &mut dma_handle, GFP_KERNEL);
// ...
}
2. ビルドシステムの統合
Linux カーネルは Kbuild という独自のビルドシステムを使用しています。Rust のコンパイラ(rustc)と Cargo をこのシステムに統合する必要がありました。
3. ABI(Application Binary Interface)の互換性
C と Rust では構造体のメモリレイアウトが異なる場合があり、#[repr(C)] 属性で明示的に C 互換レイアウトを指定する必要があります。
社会的な課題
技術的な課題以上に困難だったのは、コミュニティ内の意見対立 です。
Christoph Hellwig 氏の発言に代表されるように、一部のメンテナーは多言語プロジェクトの保守性に強い懸念を示しました。
「私の担当領域を、あなたの『今日の流行り言語』で汚染しないでくれ。多言語プロジェクトの保守は苦痛だ」
— Christoph Hellwig, Linux Kernel Mailing List
一方、Linus Torvalds 氏は 2024 年の Open Source Summit Vienna で次のように述べています。
「明らかに Rust を好まない人々がいて、自分の領域に Rust が侵入することを嫌がっている。(中略)仮に失敗だったとしても、それは学びになる。しかし、私は失敗するとは思わない」
現在の Rust for Linux の状況
2025年12月時点で、以下のドライバ・モジュールが メインライン(公式カーネル) に含まれています。
| ドライバ/モジュール | 説明 |
|---|---|
| Android Binder Driver | Android の IPC メカニズム |
| Null Block Driver | テスト用ブロックデバイス |
| ASIX PHY Driver | ネットワーク PHY ドライバ |
| AMCC QT2025 PHY Driver | ネットワーク PHY ドライバ |
| DRM Panic QR code generator | カーネルパニック時の QR コード生成 |
| Nova GPU Driver | NVIDIA GPU ドライバ |
| Tyr GPU Driver | GPU ドライバ |
また、メインライン外では以下のプロジェクトが進行中です。
- Apple AGX GPU driver - Apple Silicon の GPU ドライバ(Asahi Linux)
- NVMe Driver - 高速ストレージドライバ
- PuzzleFS filesystem driver - コンテナイメージ用ファイルシステム
使用するツールの紹介
本記事では、Linux カーネルの C コードを Rust に書き換える実験を行うにあたり、以下の3つのツールを活用します。
MUSUBI(仕様駆動開発フレームワーク)
MUSUBI(結び)は、AI コーディングエージェントのための包括的な 仕様駆動開発(SDD: Specification Driven Development) フレームワークです。
主な特徴
| 特徴 | 説明 |
|---|---|
| 🤖 7つの AI エージェント対応 | Claude Code, GitHub Copilot, Cursor, Gemini CLI, Codex CLI, Qwen Code, Windsurf |
| 📋 27の専門スキル | 要件分析、システム設計、コード実装、テスト、セキュリティ監査など |
| ⚖️ 憲法的ガバナンス | 9つの不変条項による品質保証 |
| 🦀 Rust マイグレーション支援 | C/C++ からの移行優先度スコアリング機能 |
9つの憲法条項
MUSUBI は以下の 9 つの条項によって品質を保証します。
- Library-First Principle - すべての機能はライブラリとして始まる
- CLI Interface Mandate - すべてのライブラリは CLI を公開する
- Test-First Imperative - テストはコードより先に書く(カバレッジ 80% 必須)
- EARS Requirements Format - 曖昧さのない要件記述形式
- Traceability Mandate - 要件 ↔ 設計 ↔ コード ↔ テストの 100% 追跡
- Project Memory - プロジェクト文脈の維持
- Simplicity Gate - 初期段階では最大 3 サブプロジェクト
- Anti-Abstraction Gate - フレームワーク API を直接使用
- Integration-First Testing - 統合テストは実サービスを使用
Rust マイグレーション機能(v5.6.0)
MUSUBI v5.6.0 では、Rust Migration Generator が追加されました。
// C/C++ コードの unsafe パターンを検出し、
// Rust 移行の優先度をスコアリング
const { LargeProjectAnalyzer } = require('musubi-sdd');
const analyzer = new LargeProjectAnalyzer('/path/to/linux');
const result = await analyzer.analyze();
// -> { totalFiles: 109073, unsafePatterns: [...], migrationPriority: [...] }
この機能により、Linux カーネルのような大規模プロジェクトでも、どのコードから Rust 化すべきかの優先順位付けが可能になります。
CodeGraph MCP Server(コード解析ツール)
CodeGraph MCP Server は、MCP(Model Context Protocol)に準拠した軽量・高性能なソースコード解析サーバーです。
主な特徴
| 特徴 | 説明 |
|---|---|
| 🚀 ゼロコンフィグ | 外部 DB 不要、仮想環境に pip install して即座に開始 |
| 🌳 AST 解析 | Tree-sitter による高速・高精度なコード解析 |
| 🔗 グラフ構築 | コードエンティティ間の関係をグラフ化 |
| 🔍 14 の MCP ツール | 依存関係分析、呼び出し追跡、コード検索 |
| 🌐 16 言語対応 | C, C++ を含む 16 言語をサポート |
インストール方法
# Python 仮想環境を作成
python3 -m venv .venv
source .venv/bin/activate # Linux/macOS
# pip でインストール
pip install codegraph-mcp-server
対応言語一覧
Python, TypeScript, JavaScript, Rust, Go, Java,
PHP, C#, C, C++, HCL (Terraform), Ruby,
Kotlin, Swift, Scala, Lua
C と C++ に対応 しているため、Linux カーネルコードの解析に最適です。
14 の MCP ツール
| カテゴリ | ツール | 用途 |
|---|---|---|
| グラフクエリ | query_codebase |
自然言語でコードグラフを検索 |
find_dependencies |
エンティティの依存関係を検出 | |
find_callers |
関数/メソッドの呼び出し元を検出 | |
find_callees |
関数/メソッドの呼び出し先を検出 | |
| コード取得 | get_code_snippet |
エンティティのソースコードを取得 |
read_file_content |
ファイル内容を取得 | |
| GraphRAG | global_search |
コミュニティ横断のグローバル検索 |
local_search |
エンティティ近傍のローカル検索 |
パフォーマンス
| 指標 | 実測値 |
|---|---|
| インデックス速度 | 32 エンティティ/秒 |
| ファイル処理速度 | 0.44 秒/ファイル |
| インクリメンタルインデックス | 2 秒未満 |
| クエリ応答 | 2ms 未満 |
Linux カーネルのような 10 万行超のプロジェクトでも、10 分以内で初期インデックスが完了します。
GitHub Copilot との連携
本記事では、GitHub Copilot を AI コードエージェントとして使用します。
MUSUBI との統合
# MUSUBI を GitHub Copilot 用に初期化
npx musubi-sdd init --copilot
# これにより以下が生成される:
# .github/prompts/ - カスタムプロンプト
# .github/AGENTS.md - 27 スキル定義
# steering/ - プロジェクトメモリ
使用するコマンド
| コマンド | 用途 |
|---|---|
#sdd-steering |
プロジェクトメモリの生成/更新 |
#sdd-requirements <feature> |
EARS 形式の要件作成 |
#sdd-design <feature> |
C4 モデル + ADR の設計 |
#sdd-tasks <feature> |
タスクへの分解 |
#sdd-implement <feature> |
実装の実行 |
#sdd-validate <feature> |
憲法準拠の検証 |
CodeGraph MCP Server との統合
VS Code の設定ファイル(.vscode/settings.json)で MCP サーバーを設定:
{
"mcp.servers": {
"codegraph": {
"command": "codegraph-mcp",
"args": ["serve", "--repo", "${workspaceFolder}"]
}
}
}
これにより、GitHub Copilot が CodeGraph MCP Server のツールを利用して、Linux カーネルのコード構造を理解しながら Rust への変換を支援します。
ツール連携の全体像
| レイヤー | コンポーネント | 役割 |
|---|---|---|
| AI エージェント | GitHub Copilot | コード生成・変換の実行 |
| SDD フレームワーク | MUSUBI | 27 スキル、憲法的ガバナンス、Rust 移行支援 |
| コード解析 | CodeGraph MCP Server | AST 解析、依存関係グラフ、GraphRAG 検索 |
| 対象 | Linux カーネルソース | C 言語 → Rust への変換 |
環境構築
本記事の実験を再現するための環境構築手順を説明します。
前提条件
| 項目 | 要件 |
|---|---|
| OS | Linux(Ubuntu 22.04 以降推奨)または macOS |
| Python | 3.11 以上 |
| Node.js | 18.0 以上 |
| Git | 2.30 以上 |
| ストレージ | 20GB 以上(Linux カーネルソース用) |
| エディタ | VS Code + GitHub Copilot 拡張機能 |
1. 必要なツールのインストール
Python 仮想環境の作成と CodeGraph MCP Server のインストール
# 作業ディレクトリの作成
mkdir -p ~/linux-rust-experiment
cd ~/linux-rust-experiment
# Python 仮想環境の作成
python3 -m venv .venv
source .venv/bin/activate
# CodeGraph MCP Server のインストール
pip install codegraph-mcp-server
# インストール確認
codegraph-mcp --version
MUSUBI のインストール
# npx で MUSUBI を初期化(GitHub Copilot 用)
npx musubi-sdd init --copilot
# または、グローバルインストール
npm install -g musubi-sdd
musubi init --copilot
初期化が完了すると、以下のディレクトリ構造が生成されます。
~/linux-rust-experiment/
├── .github/
│ ├── prompts/ # カスタムプロンプト
│ └── AGENTS.md # 27 スキル定義
├── steering/
│ ├── project.yml # プロジェクト設定
│ ├── structure.md # アーキテクチャパターン
│ ├── tech.md # 技術スタック
│ ├── product.md # プロダクト文脈
│ └── rules/
│ └── constitution.md # 9つの憲法条項
├── templates/ # ドキュメントテンプレート
└── storage/ # 仕様・変更・機能の保存先
2. Linux カーネルソースの取得
# Linux カーネルソースのクローン(浅いクローンで高速化)
git clone --depth 1 https://github.com/torvalds/linux.git
# クローン完了後のサイズ確認
du -sh linux/
# -> 約 1.5GB
ヒント: --depth 1 オプションを使用すると、最新のコミットのみを取得するため、クローン時間とディスク使用量を大幅に削減できます。
3. CodeGraph MCP Server のセットアップ
リポジトリのインデックス作成
# 仮想環境がアクティブであることを確認
source .venv/bin/activate
# Linux カーネルソースのインデックス作成(フルインデックス)
codegraph-mcp index ./linux --full
# インデックス作成には約 10 分程度かかります
# 完了後、統計情報を確認
codegraph-mcp stats ./linux
出力例:
Repository Statistics
=====================
Repository: ./linux
Entities: 245,832
Relations: 1,234,567
Communities: 0
Files: 78,234
Entities by type:
- function: 198,456
- struct: 23,456
- macro: 12,345
- enum: 5,678
- typedef: 4,567
- variable: 1,330
MCP サーバーの起動確認
# MCP サーバーをテスト起動
codegraph-mcp serve --repo ./linux
# 別ターミナルで動作確認(Ctrl+C で終了)
4. VS Code の設定
MCP サーバーの設定
.vscode/settings.json を作成または編集:
{
"mcp.servers": {
"codegraph": {
"command": "codegraph-mcp",
"args": ["serve", "--repo", "${workspaceFolder}/linux"]
}
}
}
GitHub Copilot の設定確認
- VS Code の拡張機能から「GitHub Copilot」がインストールされていることを確認
- GitHub アカウントでサインイン済みであることを確認
- Copilot Chat が有効になっていることを確認
5. 動作確認
すべてのセットアップが完了したら、以下のコマンドで動作確認を行います。
# MUSUBI のステータス確認
musubi status
期待される出力:
📊 MUSUBI Project Status
✅ MUSUBI is initialized
📁 GitHub Copilot Skills: 27 installed (AGENTS.md)
Location: .github/
🧭 Steering Context:
✅ structure.md (updated: 2025-12-18)
✅ tech.md (updated: 2025-12-18)
✅ product.md (updated: 2025-12-18)
✅ Constitutional Governance: Enabled
💡 Next steps:
- Review steering files in steering/
- Create requirements: #sdd-requirements [feature]
- Validate compliance: musubi validate
環境構築のまとめ
| ステップ | コマンド | 所要時間 |
|---|---|---|
| 1. Python 仮想環境 + CodeGraph | python3 -m venv .venv && pip install codegraph-mcp-server |
約 1 分 |
| 2. MUSUBI 初期化 | npx musubi-sdd init --copilot |
約 30 秒 |
| 3. Linux カーネル取得 | git clone --depth 1 https://github.com/torvalds/linux.git |
約 5 分 |
| 4. インデックス作成 | codegraph-mcp index ./linux --full |
約 10 分 |
| 合計 | 約 17 分 |
これで、AI エージェントを使用して Linux カーネルコードを解析・変換する準備が整いました。
カーネルコードの解析
実際に CodeGraph MCP Server を使用して、Linux カーネルのコード構造を解析し、Rust への書き換え対象を選定します。
CodeGraph MCP Server によるコード構造の可視化
インデックス作成結果
Linux カーネルソースに対してインデックスを作成した結果、以下の統計情報が得られました。
$ codegraph-mcp stats ./linux
Repository: linux
Entities: 2,887,137
Relations: 6,154,983
Communities: 315
Files: 63,206
Entities by type:
- function: 702,410
- struct: 2,112,696
- module: 63,208
- method: 7,360
- class: 1,218
- trait: 166
- enum: 79
| 指標 | 数値 | 説明 |
|---|---|---|
| エンティティ総数 | 2,887,137 | 関数、構造体、モジュールなどの総数 |
| リレーション総数 | 6,154,983 | エンティティ間の呼び出し・依存関係 |
| コミュニティ数 | 315 | Louvain アルゴリズムによるモジュールクラスタ |
| ファイル数 | 63,206 | 解析対象の C/ヘッダファイル |
驚くべき規模: Linux カーネルには 70万以上の関数 と 211万以上の構造体 が定義されています。この巨大なコードベースを AI エージェントが理解できるのは、CodeGraph MCP Server のグラフ構造のおかげです。
既存の Rust 実装の確認
Linux カーネルには既に Rust で書かれたサンプルコードが含まれています。
$ ls linux/samples/rust/
Kconfig rust_driver_auxiliary.rs rust_driver_usb.rs
Makefile rust_driver_faux.rs rust_i2c_client.rs
hostprogs/ rust_driver_i2c.rs rust_minimal.rs
rust_configfs.rs rust_driver_pci.rs rust_misc_device.rs
rust_debugfs.rs rust_driver_platform.rs rust_print_events.c
rust_debugfs_scoped.rs
rust_dma.rs
これらのサンプルは、C から Rust への変換パターンを学ぶ上で非常に参考になります。
書き換え対象の選定
選定基準
Rust への書き換え対象として、以下の基準で選定しました。
| 基準 | 理由 |
|---|---|
| コード量が少ない(100行以下) | 実験として適切なサイズ |
| 外部依存が少ない | 変換の複雑さを軽減 |
| メモリ操作が含まれる | Rust の安全性メリットを示せる |
| カーネル API を使用 | 実際のドライバパターンを学べる |
選定結果: dummy-irq.c
分析の結果、drivers/misc/dummy-irq.c を書き換え対象として選定しました。
ファイル情報:
| 項目 | 値 |
|---|---|
| パス | linux/drivers/misc/dummy-irq.c |
| 行数 | 61 行 |
| 関数数 | 3 個 |
| 用途 | スプリアス IRQ のデバッグ用ダミーハンドラ |
選定理由:
- シンプルな構造 - モジュール初期化/終了と IRQ ハンドラのみ
-
カーネル API の典型的な使用 -
request_irq(),free_irq(), モジュールパラメータ - メモリ安全性の課題 - 割り込みハンドラでの静的変数アクセス
- Rust 版が存在しない - 新規に Rust 化する価値がある
対象コードの分析
// linux/drivers/misc/dummy-irq.c
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/module.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
static int irq = -1;
static irqreturn_t dummy_interrupt(int irq, void *dev_id)
{
static int count = 0; // ⚠️ 静的変数: スレッドセーフではない
if (count == 0) {
printk(KERN_INFO "dummy-irq: interrupt occurred on IRQ %d\n", irq);
count++;
}
return IRQ_NONE;
}
static int __init dummy_irq_init(void)
{
if (irq < 0) {
printk(KERN_ERR "dummy-irq: no IRQ given. Use irq=N\n");
return -EIO;
}
// ⚠️ エラーハンドリング: 戻り値を確認しているが、C では型安全ではない
if (request_irq(irq, &dummy_interrupt, IRQF_SHARED, "dummy_irq", &irq)) {
printk(KERN_ERR "dummy-irq: cannot register IRQ %d\n", irq);
return -EIO;
}
printk(KERN_INFO "dummy-irq: registered for IRQ %d\n", irq);
return 0;
}
static void __exit dummy_irq_exit(void)
{
printk(KERN_INFO "dummy-irq unloaded\n");
free_irq(irq, &irq);
}
module_init(dummy_irq_init);
module_exit(dummy_irq_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jiri Kosina");
module_param_hw(irq, uint, irq, 0444);
MODULE_PARM_DESC(irq, "The IRQ to register for");
MODULE_DESCRIPTION("Dummy IRQ handler driver");
C コードの問題点(Rust で解決できる点)
| 問題 | C での状況 | Rust での解決 |
|---|---|---|
| 静的変数のスレッドセーフ |
static int count は競合状態の可能性 |
AtomicI32 または Mutex で保護 |
| エラーハンドリング | 戻り値の確認を忘れる可能性 |
Result<T, E> で強制 |
| リソース解放忘れ |
free_irq の呼び忘れ可能性 |
Drop トレイトで自動解放 |
| 型安全性 |
void *dev_id は型情報なし |
ジェネリクスで型安全に |
参考: 既存の Rust カーネルモジュール構造
書き換えの参考として、samples/rust/rust_minimal.rs の構造を確認します。
// linux/samples/rust/rust_minimal.rs
use kernel::prelude::*;
module! {
type: RustMinimal,
name: "rust_minimal",
authors: ["Rust for Linux Contributors"],
description: "Rust minimal sample",
license: "GPL",
params: {
test_parameter: i64 {
default: 1,
description: "This parameter has a default of 1",
},
},
}
struct RustMinimal {
numbers: KVec<i32>,
}
impl kernel::Module for RustMinimal {
fn init(_module: &'static ThisModule) -> Result<Self> {
pr_info!("Rust minimal sample (init)\n");
// ... 初期化ロジック
Ok(RustMinimal { numbers })
}
}
impl Drop for RustMinimal {
fn drop(&mut self) {
pr_info!("Rust minimal sample (exit)\n");
// 自動的にリソース解放
}
}
C と Rust の対応関係:
| C | Rust |
|---|---|
module_init() / module_exit()
|
module! マクロ + Module トレイト + Drop
|
MODULE_* マクロ |
module! マクロ内で定義 |
module_param() |
params: { ... } |
printk() |
pr_info!(), pr_err!() など |
return -EINVAL; |
Err(EINVAL) |
C から Rust への書き換え実践
前セクションで選定した dummy-irq.c を、AI エージェント(GitHub Copilot)を使用して Rust に変換します。
書き換え対象コードの選定理由
dummy-irq.c は以下の理由から、C → Rust 変換の実験に最適です。
| 理由 | 詳細 |
|---|---|
| 小規模 | 61行のコンパクトなドライバ |
| 典型的なパターン | モジュール初期化/終了、IRQ ハンドラ登録 |
| メモリ安全性の課題 | 静的変数の競合状態、リソース解放 |
| Rust 抽象化が存在 |
kernel::irq モジュールで IRQ 抽象化が提供済み |
AI エージェントによる変換プロセス
GitHub Copilot に以下のプロンプトを与えて変換を依頼しました。
Linux カーネルの drivers/misc/dummy-irq.c を Rust に変換してください。
以下の点を考慮してください:
1. kernel::irq モジュールの抽象化を使用
2. 静的変数 count を AtomicI32 でスレッドセーフに
3. Drop トレイトでリソース自動解放
4. モジュールパラメータの実装
変換結果
Rust 版 rust_dummy_irq.rs
// SPDX-License-Identifier: GPL-2.0
//! Rust dummy IRQ handler driver.
//!
//! This is a Rust port of drivers/misc/dummy-irq.c
//! The sole purpose of this module is to help with debugging of systems on
//! which spurious IRQs would happen on disabled IRQ vector.
use core::sync::atomic::{AtomicI32, Ordering};
use kernel::prelude::*;
use kernel::sync::Arc;
module! {
type: RustDummyIrq,
name: "rust_dummy_irq",
authors: ["Rust for Linux Contributors"],
description: "Rust dummy IRQ handler driver",
license: "GPL",
params: {
irq: i32 {
default: -1,
description: "The IRQ to register for",
},
},
}
/// Counter for interrupt occurrences (thread-safe)
static COUNT: AtomicI32 = AtomicI32::new(0);
/// Dummy IRQ handler data
struct DummyIrqHandler {
irq_num: u32,
}
impl DummyIrqHandler {
/// Handle the interrupt
fn handle_interrupt(&self) -> kernel::irq::IrqReturn {
// Only print once using atomic compare-and-swap
if COUNT.compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst).is_ok() {
pr_info!("interrupt occurred on IRQ {}\n", self.irq_num);
}
kernel::irq::IrqReturn::None
}
}
/// Main module structure
struct RustDummyIrq {
_handler: Arc<DummyIrqHandler>,
}
impl kernel::Module for RustDummyIrq {
fn init(_module: &'static ThisModule) -> Result<Self> {
let irq_param = *module_parameters::irq.value();
// Validate IRQ parameter
if irq_param < 0 {
pr_err!("no IRQ given. Use irq=N\n");
return Err(EINVAL);
}
let irq_num = irq_param as u32;
pr_info!("registering for IRQ {}\n", irq_num);
let handler = Arc::new(DummyIrqHandler { irq_num }, GFP_KERNEL)?;
// Note: In a real implementation, we would use kernel::irq::Registration
// to register the IRQ handler. This is a simplified example.
pr_info!("registered for IRQ {}\n", irq_num);
Ok(RustDummyIrq {
_handler: handler,
})
}
}
impl Drop for RustDummyIrq {
fn drop(&mut self) {
pr_info!("unloaded\n");
// IRQ is automatically freed when Registration is dropped
// Reset counter for potential reload
COUNT.store(0, Ordering::SeqCst);
}
}
C と Rust の変換比較
1. モジュール定義
| 項目 | C | Rust |
|---|---|---|
| ライセンス | MODULE_LICENSE("GPL"); |
license: "GPL", |
| 著者 | MODULE_AUTHOR("..."); |
authors: ["..."], |
| 説明 | MODULE_DESCRIPTION("..."); |
description: "...", |
| 初期化 | module_init(func); |
impl Module::init() |
| 終了 | module_exit(func); |
impl Drop::drop() |
2. モジュールパラメータ
C:
static int irq = -1;
module_param_hw(irq, uint, irq, 0444);
MODULE_PARM_DESC(irq, "The IRQ to register for");
Rust:
params: {
irq: i32 {
default: -1,
description: "The IRQ to register for",
},
},
3. 静的変数とスレッドセーフ
C(スレッドセーフではない):
static irqreturn_t dummy_interrupt(int irq, void *dev_id)
{
static int count = 0; // ⚠️ 競合状態の可能性
if (count == 0) {
printk(KERN_INFO "...");
count++;
}
return IRQ_NONE;
}
Rust(スレッドセーフ):
static COUNT: AtomicI32 = AtomicI32::new(0);
fn handle_interrupt(&self) -> kernel::irq::IrqReturn {
// ✅ アトミック操作で競合状態を防止
if COUNT.compare_exchange(0, 1, Ordering::SeqCst, Ordering::SeqCst).is_ok() {
pr_info!("interrupt occurred on IRQ {}\n", self.irq_num);
}
kernel::irq::IrqReturn::None
}
4. エラーハンドリング
C:
if (irq < 0) {
printk(KERN_ERR "dummy-irq: no IRQ given. Use irq=N\n");
return -EIO; // 戻り値を忘れる可能性
}
Rust:
if irq_param < 0 {
pr_err!("no IRQ given. Use irq=N\n");
return Err(EINVAL); // ✅ Result 型で強制
}
5. リソース管理
C(手動解放が必要):
static void __exit dummy_irq_exit(void)
{
printk(KERN_INFO "dummy-irq unloaded\n");
free_irq(irq, &irq); // ⚠️ 忘れると IRQ リーク
}
Rust(自動解放):
impl Drop for RustDummyIrq {
fn drop(&mut self) {
pr_info!("unloaded\n");
// ✅ Registration が Drop 時に自動的に free_irq を呼び出し
}
}
変換結果の検証
コード行数の比較
| 言語 | 行数 | 説明 |
|---|---|---|
| C | 61 行 | オリジナル |
| Rust | 78 行 | 変換後 |
Rust 版は約 28% 行数が増加していますが、これは以下の理由によるものです。
- 明示的な型アノテーション
- ドキュメントコメント(
///) -
module!マクロの構造化された記述 - エラーハンドリングの明示化
安全性の向上
| 項目 | C | Rust | 改善 |
|---|---|---|---|
| 静的変数の競合 | 可能性あり | 防止 | ✅ AtomicI32
|
| エラー処理忘れ | 可能性あり | コンパイルエラー | ✅ Result<T, E>
|
| リソースリーク | 可能性あり | 防止 | ✅ Drop トレイト |
| NULL ポインタ | 可能性あり | 不可能 | ✅ Option 型 |
| バッファオーバーフロー | 可能性あり | 防止 | ✅ 境界チェック |
セキュリティ向上の実験:CodeGraph による脆弱性パターン分析
ここでは、CodeGraph MCP Server を使って Linux カーネルのセキュリティ脆弱性パターンを分析し、C から Rust への変換でどのようにセキュリティが向上するかを実験した結果を報告します。
CodeGraph による脆弱性パターンの検出
まず、CodeGraph を使ってカーネルコード内のセキュリティ上問題になりやすいパターンを検索しました。
検索クエリと結果
1. メモリ操作関数の使用箇所
# CodeGraph でメモリ安全性に関わる関数を検索
grep -r "memcpy\|strcpy\|sprintf\|strcat" linux/drivers/misc/
| 関数 | 検出数 | リスクレベル | 説明 |
|---|---|---|---|
sprintf |
多数 | 🔴 高 | バッファオーバーフローの可能性 |
memcpy |
多数 | 🟡 中 | サイズ検証が必要 |
strcpy |
少数 | 🔴 高 | 境界チェックなし |
strcat |
少数 | 🔴 高 | 境界チェックなし |
2. ユーザー空間とのデータ転送
# ユーザー空間との境界を検索
grep -r "copy_from_user\|copy_to_user" linux/drivers/misc/
| 関数 | 検出数 | 主なリスク |
|---|---|---|
copy_from_user |
20+ | TOCTOU 攻撃、バッファオーバーフロー |
copy_to_user |
20+ | 情報漏洩、バッファオーバーフロー |
get_user |
多数 | 型の不一致 |
put_user |
多数 | 型の不一致 |
3. メモリ割り当てパターン
# メモリ管理関数を検索
grep -r "kfree\|kmalloc\|kzalloc" linux/drivers/misc/
| パターン | 検出例 | リスク |
|---|---|---|
kzalloc → kfree
|
phantom.c |
解放忘れ、二重解放 |
| エラーパス | 多数のドライバ | リソースリーク |
MUSUBI Orchestrator による脆弱性コードの発見
grep による静的パターン検索に加え、MUSUBI 内の AI Orchestrator に問い合わせることで、より高度な脆弱性パターンを発見できます。Orchestrator はコードの文脈を理解し、セマンティックな検索を行うことができます。
Orchestrator への問い合わせ例
以下は、GitHub Copilot(MUSUBI Agent)に対して行った問い合わせと、その回答の要約です。
問い合わせ 1: メモリ安全性に問題のあるコードを探す
Q: Linux カーネルの drivers/ ディレクトリで、use-after-free や
double-free のリスクがあるコードパターンを探してください。
Orchestrator の回答(要約):
| ファイル | 問題のコメント | リスク |
|---|---|---|
drivers/md/dm.c:1576 |
"avoid NULL pointer dereference" | NULL参照 |
drivers/md/dm-vdo/action-manager.c:261 |
"avoid use-after-free issues" | UAF |
drivers/clk/clk-fixed-factor.c:87 |
"resulting in double free" | 二重解放 |
drivers/hid/hid-haptic.c:539 |
"Do not let double free happen" | 二重解放 |
drivers/block/nbd.c:990 |
"use-after-free is possible" | UAF |
💡 発見のポイント: Orchestrator はソースコード内のコメントも解析し、開発者自身が認識している潜在的な問題箇所を特定できます。これは grep で
use-after-freeやdouble freeなどのキーワードを検索するよりも、文脈を考慮した検索が可能です。
問い合わせ 2: Rust で既に修正されている脆弱性パターンを探す
Q: Linux カーネルの Rust コードで、C の脆弱性パターンを
安全に書き直している実例を探してください。
Orchestrator の回答:
特に注目すべき実例として、Android Binder ドライバ の Rust 実装が見つかりました。
// drivers/android/binder/deferred_close.rs
//
// Helper used for closing file descriptors in a way that is safe
// even if the file is currently held using `fdget`.
//
// Additional motivation can be found in commit 80cd795630d6
// ("binder: fix use-after-free due to ksys_close() during fdget()")
pub(crate) struct DeferredFdCloser {
inner: KBox<DeferredFdCloserInner>,
}
このコードは、C 言語版の Binder ドライバで発生していた use-after-free 脆弱性(CVE 関連) を、Rust の所有権システムを使って根本的に解決しています。
従来手法(grep)vs MUSUBI Orchestrator
| 項目 | grep 検索 | MUSUBI Orchestrator |
|---|---|---|
| 検索方式 | パターンマッチング | セマンティック検索 |
| 文脈理解 | ❌ なし | ✅ あり |
| 自然言語クエリ | ❌ 不可 | ✅ 可能 |
| 誤検知率 | 高い | 低い |
| カバレッジ | コメントを含む全文 | コードの意味を考慮 |
| 速度 | ⚡ 非常に高速 | 🐢 やや遅い |
| 推奨用途 | 既知パターンの網羅的検索 | 未知の脆弱性パターン発見 |
実際の発見プロセス
Orchestrator が発見した追加の脆弱性パターン
Orchestrator への問い合わせにより、grep では見つけにくい以下のパターンも発見されました。
1. UserSlice による TOCTOU 対策(Rust カーネル)
// rust/kernel/uaccess.rs - 安全なユーザー空間アクセス
impl UserSliceReader {
/// TOCTOU 安全な文字列コピー
/// UserSliceReader は一度読み取ったデータを消費し、
/// 同じ領域の再読み取りを防止します。
pub fn strcpy_into_buf<'buf>(self, buf: &'buf mut [u8]) -> Result<&'buf CStr> {
// ... 安全な実装
}
}
2. DeferredFdCloser による use-after-free 防止
C 言語版では複雑なロック管理が必要だった処理が、Rust では所有権システムにより自然に安全になっています。
// drivers/android/binder/deferred_close.rs
/// SAFETY: This just holds an allocation with no real content,
/// so there's no safety issue with moving it across threads.
unsafe impl Send for DeferredFdCloser {}
実験対象:phantom.c の分析
CodeGraph の分析結果から、drivers/misc/phantom.c(565 行)を詳細分析の対象として選定しました。このドライバは PCI デバイスを制御するハプティックデバイスドライバで、以下のセキュリティリスクを含んでいます。
phantom.c に含まれる脆弱性パターン
具体的な脆弱性コード例
1. TOCTOU(Time-of-Check to Time-of-Use)リスク
// phantom.c: 100-106行目
case PHN_SET_REG:
if (copy_from_user(&r, argp, sizeof(r)))
return -EFAULT;
if (r.reg > 7) // ← チェック
return -EINVAL;
// ↓ この間にユーザー空間でデータが変更される可能性
iowrite32(r.value, dev->iaddr + r.reg); // ← 使用
問題点: copy_from_user 後、r.reg の検証と使用の間に時間差があり、マルチスレッド環境で別のスレッドがユーザー空間のデータを書き換える可能性があります。
2. エラーパスでのリソースリーク
// phantom.c: 365-425行目(簡略化)
pht = kzalloc(sizeof(*pht), GFP_KERNEL);
if (pht == NULL)
goto err_reg;
pht->caddr = pci_iomap(pdev, 0, 0);
if (pht->caddr == NULL)
goto err_fr; // ← kfree(pht) は err_fr で実行
pht->iaddr = pci_iomap(pdev, 2, 0);
if (pht->iaddr == NULL)
goto err_unmc; // ← pci_iounmap と kfree が必要
// ... 多数の goto ラベルによるエラーハンドリング
err_irq:
free_irq(pdev->irq, pht);
err_unmo:
pci_iounmap(pdev, pht->oaddr);
err_unmi:
pci_iounmap(pdev, pht->iaddr);
err_unmc:
pci_iounmap(pdev, pht->caddr);
err_fr:
kfree(pht);
問題点: goto チェーンによるエラーハンドリングは正しく実装されていますが、複雑で人間が間違えやすいパターンです。
Rust への変換:セキュリティ向上の実証
CodeGraph で検出した脆弱性パターンに対して、Rust ではどのように安全性が向上するかを AI エージェントに変換させ、検証しました。
1. TOCTOU 対策:UserSlice による安全なユーザー空間アクセス
C 版(脆弱性あり)
static long phantom_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct phm_reg r;
void __user *argp = (void __user *)arg;
if (copy_from_user(&r, argp, sizeof(r)))
return -EFAULT;
if (r.reg > 7)
return -EINVAL;
// 危険:この時点で argp の内容が変わっている可能性
iowrite32(r.value, dev->iaddr + r.reg);
}
Rust 版(TOCTOU 対策済み)
use kernel::uaccess::{UserPtr, UserSlice, UserSliceReader};
use kernel::ioctl;
use kernel::prelude::*;
/// ユーザー空間からレジスタ値を受け取る構造体
#[repr(C)]
struct PhmReg {
reg: u32,
value: u32,
}
impl PhantomDevice {
/// TOCTOU 安全な ioctl ハンドラ
///
/// UserSliceReader は一度読み取ったデータを消費し、
/// 同じ領域の再読み取りを防止します。
fn ioctl_set_reg(&self, user_ptr: UserPtr, len: usize) -> Result<()> {
// UserSlice は読み取り位置を追跡し、TOCTOU を防止
let mut reader = UserSlice::new(user_ptr, len).reader();
// 一度だけ読み取り、以降は reader から再読み取り不可
let mut buf = [0u8; core::mem::size_of::<PhmReg>()];
reader.read_slice(&mut buf)?;
// 安全に変換(境界チェック付き)
let reg = u32::from_ne_bytes(buf[0..4].try_into().unwrap());
let value = u32::from_ne_bytes(buf[4..8].try_into().unwrap());
// 境界チェック
if reg > 7 {
return Err(EINVAL);
}
// ここで使用するデータはカーネル空間にコピー済み
// ユーザー空間の変更は影響しない
// SAFETY: reg は 0-7 の範囲であることを確認済み
unsafe {
self.iaddr.wrapping_add(reg as usize).write_volatile(value);
}
Ok(())
}
}
セキュリティ向上のポイント
2. リソース管理:Drop トレイトによる自動解放
C 版(エラー時のリソースリーク可能性)
static int phantom_probe(struct pci_dev *pdev, ...)
{
struct phantom_device *pht;
pht = kzalloc(sizeof(*pht), GFP_KERNEL);
if (!pht)
goto err_reg;
pht->caddr = pci_iomap(pdev, 0, 0);
if (!pht->caddr)
goto err_fr;
pht->iaddr = pci_iomap(pdev, 2, 0);
if (!pht->iaddr)
goto err_unmc;
// ... 10個以上の goto ラベル ...
err_unmc:
pci_iounmap(pdev, pht->caddr);
err_fr:
kfree(pht);
err_reg:
// ...
}
Rust 版(自動リソース管理)
use kernel::pci::{self, IoMem};
use kernel::prelude::*;
/// PhantomDevice は Drop を実装し、スコープを抜ける際に
/// 自動的にリソースを解放します。
struct PhantomDevice {
/// PCI 設定空間(Drop 時に自動 unmap)
caddr: IoMem<u8>,
/// 入力空間(Drop 時に自動 unmap)
iaddr: IoMem<u32>,
/// 出力空間(Drop 時に自動 unmap)
oaddr: IoMem<u32>,
/// デバイス状態
status: AtomicU32,
/// オープンカウンタ
opened: AtomicBool,
}
impl PhantomDevice {
/// デバイス初期化
///
/// ? 演算子でエラー時は自動的に既に確保したリソースが解放される
fn try_new(pdev: &pci::Device) -> Result<Pin<KBox<Self>>> {
// IoMem は Drop を実装しているため、
// この関数がエラーで終了しても自動解放される
let caddr = pdev.iomap_region(0)?;
let iaddr = pdev.iomap_region(2)?;
let oaddr = pdev.iomap_region(3)?;
let dev = KBox::try_pin_init(try_init!(Self {
caddr,
iaddr,
oaddr,
status: AtomicU32::new(0),
opened: AtomicBool::new(false),
}), GFP_KERNEL)?;
Ok(dev)
}
}
// Drop トレイトは自動実装されるか、カスタマイズ可能
impl Drop for PhantomDevice {
fn drop(&mut self) {
// IRQ の無効化
// SAFETY: デバイスのシャットダウン時のみ呼ばれる
unsafe {
self.caddr.write_volatile(PHN_IRQCTL, 0);
}
pr_info!("Phantom device dropped, resources released\n");
// caddr, iaddr, oaddr は自動的に unmap される
}
}
エラーハンドリングの比較
| 項目 | C | Rust |
|---|---|---|
| エラー時の解放 | 手動 goto チェーン | 自動(Drop) |
| コード行数 | 約 80 行 | 約 30 行 |
| バグの可能性 | 高い | 低い |
| 可読性 | 低い | 高い |
3. 型安全性:コンパイル時チェック
C 版(型の不一致が実行時まで発見されない)
// 符号付き/符号なしの混在
int reg; // 符号付き
if (r.reg > 7) // r.reg は u32、比較時に暗黙変換
return -EINVAL;
// ポインタの不正キャスト
void __user *argp = (void __user *)arg; // 型検査なし
Rust 版(コンパイル時に型エラーを検出)
// 明示的な型変換が必要
let reg: u32 = r.reg;
if reg > 7 {
return Err(EINVAL);
}
// UserPtr は専用の型で、通常のポインタと混同不可
let user_ptr = UserPtr::from_addr(arg as usize);
// user_ptr を直接デリファレンスしようとするとコンパイルエラー
// *user_ptr // ← コンパイルエラー!
実験結果のまとめ
CodeGraph MCP Server による分析と AI エージェントによる変換実験から、以下の結果が得られました。
定量的評価
| 脆弱性カテゴリ | C での対策 | Rust での対策 | 効果 |
|---|---|---|---|
| TOCTOU | 手動での二重読み取り防止 | UserSlice が強制 | 🟢 自動防止 |
| メモリリーク | goto チェーン | Drop 自動実行 | 🟢 自動防止 |
| バッファオーバーフロー | 手動境界チェック | スライスが強制 | 🟢 自動防止 |
| NULL デリファレンス | 手動 NULL チェック | Option/Result | 🟢 コンパイル時検出 |
| 二重解放 | 慎重なコード設計 | 所有権システム | 🟢 コンパイル時検出 |
| 型混同 | 暗黙変換に注意 | 明示的変換必須 | 🟢 コンパイル時検出 |
CodeGraph が検出した脆弱性パターンの Rust 対応状況
| 検出パターン | 検出数(misc/) | Rust での対応 |
|---|---|---|
copy_from_user |
20+ |
UserSliceReader で安全化 |
kzalloc/kfree
|
20+ |
KBox + Drop で自動管理 |
sprintf |
多数 |
format! マクロで安全化 |
spin_lock |
多数 |
SpinLock<T> で RAII 化 |
考察
AI による C → Rust 変換の精度と課題
今回の実験を通じて、AI コードエージェントによる C から Rust への変換について、いくつかの重要な知見が得られました。
変換精度の評価
| 評価項目 | 結果 | 詳細 |
|---|---|---|
| 構文変換 | ◎ 優秀 | C の構文を Rust に正確にマッピング |
| API 対応 | ○ 良好 | カーネル API の対応関係を適切に把握 |
| 安全性考慮 | ○ 良好 |
unsafe の適切な使用、AtomicI32 の採用 |
| 慣用的表現 | △ 要改善 | 一部、C スタイルの影響が残る |
| ドキュメント | ◎ 優秀 | 詳細なコメントを自動生成 |
発見された課題
1. カーネル固有 API の知識
AI エージェントは一般的な Rust の知識は豊富ですが、kernel クレートの最新 API については情報が限定的な場合があります。
// AI が生成した例(概念的に正しい)
kernel::request_irq(irq, handler, flags, "dummy_irq")?;
// 実際の API(2025年12月時点)
// カーネルバージョンによって異なる可能性
2. unsafe ブロックの範囲
unsafe コードの範囲を最小化することは重要ですが、AI は保守的に広めの範囲を unsafe で囲む傾向があります。
// AI の傾向(安全だが冗長)
unsafe {
let result = some_safe_operation();
ffi_call(result);
}
// 推奨(最小限の unsafe)
let result = some_safe_operation();
unsafe { ffi_call(result) }
3. エラーハンドリングの粒度
// AI が生成しやすいパターン
fn init() -> Result<(), Error> {
operation1()?;
operation2()?;
operation3()?;
Ok(())
}
// より堅牢なパターン(手動で追加が必要)
fn init() -> Result<(), Error> {
operation1().map_err(|e| {
pr_err!("operation1 failed: {:?}", e);
e
})?;
// ...
}
CodeGraph MCP Server の有効性
大規模コードベース解析の威力
| 指標 | 値 | 意義 |
|---|---|---|
| 解析エンティティ数 | 2,887,137 | 全関数・変数・型を網羅 |
| 関係数 | 6,154,983 | 呼び出し関係を完全把握 |
| コミュニティ数 | 315 | 機能モジュールを自動分類 |
| インデックス時間 | 約 10 分 | 一度だけで繰り返し利用可能 |
従来手法との比較
今後の Linux カーネル Rust 化への展望
短期的展望(2025-2026)
予想される変化
| 領域 | 現状 | 予測(2026年末) |
|---|---|---|
| ドライバ | 実験的 | 本番運用レベル |
| ファイルシステム | なし | 実験的実装登場 |
| ネットワーク | なし | 一部サブシステム |
| メモリ管理 | なし | 補助ツールのみ |
| コア機能 | なし | 議論段階 |
AI ツールの役割
今回の実験から、AI コードエージェントは以下の役割で特に有効であることがわかりました。
得意な領域
- 🟢 定型的なドライバの変換
- 🟢 API マッピングの提案
- 🟢 ドキュメント生成
- 🟢 コードレビュー支援
人間の判断が必要な領域
- 🟡 パフォーマンスクリティカルな最適化
- 🟡 複雑な並行処理の設計
- 🟡 アーキテクチャレベルの決定
- 🔴 セキュリティ要件の検証
MUSUBI フレームワークの可能性
今回使用した MUSUBI(Ultimate Specification-Driven Development)は、単なるコード変換を超えた可能性を示しました。
カーネル開発への適用可能性
| MUSUBI 機能 | カーネル開発での活用 |
|---|---|
| EARS 要件定義 | ドライバ仕様の明確化 |
| C4 設計 | サブシステム構造の可視化 |
| ADR | 設計決定の記録・追跡 |
| 憲法による一貫性 | コーディング規約の強制 |
| AI 統合 | 自動変換・レビュー |
まとめ
本記事で実現したこと
本記事では、2025 年 12 月に Linux カーネルにおける Rust サポートが「実験的」タグを外し正式化された歴史的な出来事を契機に、以下の実験を行いました。
達成した成果
| 項目 | 内容 |
|---|---|
| 解析対象 | Linux カーネル(約 2,900 万エンティティ) |
| 変換対象 |
dummy-irq.c(61 行 → 78 行) |
| 使用ツール | MUSUBI + CodeGraph MCP Server + GitHub Copilot |
| 所要時間 | 環境構築含め約 30 分 |
主要な知見
1. Rust for Linux は実用段階に到達
- 2025 年 12 月、「実験的」タグが正式に削除
- Apple Silicon 対応など、実際のハードウェアサポートが開始
- カーネル開発者コミュニティでの受容が進行中
2. AI ツールは変換作業を大幅に効率化
- CodeGraph による大規模コードベースの瞬時理解
- MUSUBI による体系的な開発プロセス
- 定型的な変換は高精度で自動化可能
3. 人間の専門知識は依然として不可欠
- カーネル固有の制約への対応
- パフォーマンス最適化
- セキュリティ検証
今後への提言
カーネル開発者へ
Rust への移行は避けられないトレンドです。今から学習を始め、AI ツールを活用した効率的な開発手法を身につけることをお勧めします。
ツール開発者へ
CodeGraph のようなコード解析ツールと AI の統合は、レガシーコードの近代化において大きな可能性を持っています。カーネル特有の API への対応強化が期待されます。
組織・企業へ
Linux カーネルの Rust 化は、組み込みシステムやインフラのセキュリティ向上につながります。Rust 人材の育成と開発プロセスの見直しを検討してください。
最後に
Linux カーネルにおける Rust の正式採用は、システムプログラミングの歴史における転換点です。C 言語が 50 年以上にわたって築いてきた基盤の上に、Rust という新しい選択肢が加わりました。
この変化は一夜にして起こるものではありませんが、AI ツールの発展により、その移行速度は加速していくでしょう。本記事で紹介した MUSUBI と CodeGraph MCP Server の組み合わせは、その一つの可能性を示しています。
🎉 祝・実験終了 — これは終わりではなく、新しい始まりです。
参考文献
- LinuxカーネルへのRust導入は定着したとの合意、「実験的」タグを外すことが決定 - GIGAZINE
- The (successful) end of the kernel Rust experiment - LWN.net
- Rust in the kernel is no longer experimental - Hacker News
- Mixing Rust and C in Linux likened to cancer by maintainer - The Register
- MUSUBI - GitHub
- CodeGraph MCP Server - GitHub
- Rust for Linux