# Extending Applications Safely and Efficiently > [!abstract] 概要 > 本論文は、Extension Interface Model(EIM)とbpftimeを提案する。これらは、現行の最先端手法よりも安全かつ効率的なユーザ空間アプリケーションの拡張を可能にする。EIMは、拡張機能に必要な各要素をリソースとして扱う新しいモデルである。具体的なハードウェアリソース(例: メモリ)から、抽象的なリソース(例: 拡張対象アプリケーションの関数呼び出し能力)までを含む。拡張マネージャ、すなわちデプロイメントを管理する者は、EIMを用いて拡張がそのタスクを実行するために必要なリソースのみを指定する。bpftimeは、EIM仕様を強制する新しい拡張フレームワークである。先行システムと比較して、bpftimeはeBPFスタイルの検証、ハードウェア支援の隔離機能(例: Intel MPK)、動的バイナリ書き換えを用いるため効率的である。さらに、bpftimeは現在のeBPFエコシステムと互換性があるため、既存のワークフローへの導入が容易である。本論文は、セキュリティ強化、性能の監視と向上、設定トレードオフの探索という6つのユースケースを通じて、EIMとbpftimeの有用性を実証する。 ## 論文情報 - **タイトル**: Extending Applications Safely and Efficiently - **著者・所属**: Yusheng Zheng (UC Santa Cruz), Tong Yu (eunomia-bpf Community), Yiwei Yang (UC Santa Cruz), Yanpeng Hu (ShanghaiTech University), Xiaozheng Lai (South China University of Technology), Dan Williams (Virginia Tech), Andi Quinn (UC Santa Cruz) - **媒体**: 19th USENIX Symposium on Operating Systems Design and Implementation (OSDI 25) - **発表日・場所**: 2025年7月7–9日、Boston, MA, USA - **ISBN**: 978-1-939133-47-2 - **ページ**: Proceedings pp. 557–574(論文PDFは19ページ) - **URL**: https://www.usenix.org/conference/osdi25/presentation/zheng-yusheng - **PDF**: https://www.usenix.org/system/files/osdi25-zheng-yusheng.pdf - **コード**: https://github.com/eunomia-bpf/bpftime ## 概要 ソフトウェア拡張(extension)は、アプリケーションのソースコードを変更することなく、性能向上、セキュリティ強化、カスタム機能追加、オブザーバビリティ獲得を実現する手法である。しかし、既存の拡張フレームワークは「相互接続性(interconnectedness)」と「安全性(safety)」のトレードオフをうまく扱えていない。相互接続性とは拡張がホストアプリケーションの状態を読み書きし、ホスト定義関数を呼び出す能力であり、安全性とは拡張のバグがホストや下位システムを損なわないことを意味する。 本論文は、このトレードオフを細粒度に指定する**Extension Interface Model(EIM)**と、それを効率的に強制する**bpftime**を提案する。EIMは拡張に必要なあらゆる機能を「リソース」としてモデル化し、ケイパビリティ(capability)で保護する。bpftimeは、eBPFスタイルの静的検証で安全性を、Intel MPKなどのハードウェア支援プロセス内隔離で拡張の保護を、動的バイナリ書き換えで未使用時の拡張入口コストをゼロにする。さらにbpftimeは既存eBPFツールチェーンと互換性があり、6つの実ユースケースでその有効性と高性能を示す。 **Figure 1: 拡張適用モデルとステークホルダー** ![[_attachments/osdi25-zheng-yusheng/fig01-system-model.png]] (Figure 1. ユーザはホストアプリケーションを利用し、アプリケーション開発者と拡張開発者がそれぞれホストと拡張プログラムを書く。拡張マネージャはどの拡張をどの拡張入口(extension entry)で許可するかを決定する。Source: Adapted from the paper.) ## 問題設定 ### 対象と用語 - **ホストアプリケーション(host application)**: 拡張の対象となる元のアプリケーション(例: Nginx, Redis)。 - **拡張入口(extension entry)**: ホスト内で拡張を呼び出す特定の位置。多くの場合関数の先頭や末尾に対応する。 - **拡張マネージャ(extension manager)**: デプロイメントでどの拡張を許可し、どのリソースを許可するかを決定する信頼できる運用者。 - **拡張開発者(extension developer)**: 拡張プログラムを書く信頼できる開発者(フォール可能だが悪意はない)。 ### 3つの要求 拡張フレームワークには以下の3つが求められる。 1. **細粒度の安全性/相互接続性トレードオフ**: 同じ拡張入口でもユースケースごとに読み取りのみや書き込み許可などを分けたい。 2. **隔離(isolation)**: ホスト側の脆弱性を突かれて拡張の状態が改竄されることを防ぎたい(特にセキュリティ監視拡張)。 3. **効率性(efficiency)**: 拡張は本番のホットパスで動作しうるため、ネイティブ実行に近い速度が望ましい。 ### 既存手法の限界 | カテゴリ | 例 | 限界 | |---|---|---| | ネイティブ実行 | LD_PRELOAD, 動的計装 | 高速だが安全性・隔離がない | | SFI | WebAssembly, Lua, NaCl, RLBox | 安全性/隔離の指定が粗いか欠如、実行時オーバーヘッド大 | | サブプロセス隔離 | Wedge, lwC, Shreds, Orbit | コンテキストスイッチ的コスト大、拡張のための設計ではない | | eBPF uprobe | Linux eBPF | カーネルトラップによるオーバーヘッド大、細粒度トレードオフ不可 | Table 1に示すように、拡張の安全性違反は本番でライブロック、クラッシュ、任意コード実行を引き起こしている。 | バグ | ソフトウェア | 概要 | |---|---|---| | Bilibili [73] | Nginx | 拡張の無限ループにより本番停止 | | CVE-2021-44790 [47] | Apache | httpd Luaモジュールのバッファオーバーフローでクラッシュ | | CVE-2024-31449 [42] | Redis | LuaスクリプトのスタックオーバーフローでRCE | (Table 1. 拡張の安全性違反による事例。Source: Table 1 in the paper.) ### 脅威モデル 拡張マネージャが各拡張入口のトレードオフを正しく指定し、アプリケーションの制御フローが改竄されない(制御フロー完全性)ことを前提とする。対象となる脅威は、(1) 拡張のバグによる許可されたインターフェース外のクラッシュ/ハング/メモリ破壊、(2) 侵害されたホストによる拡張状態の改竄の2つである。 ## 提案手法 ### Extension Interface Model (EIM) EIMは、拡張に必要な機能や制限すべき機能を「リソース」として表現する。リソースには具体例としてメモリや命令数などのハードウェアリソースと、ホスト変数の読み書きやホスト関数の呼び出しなどの抽象リソースがある。EIMは「リソースを使う能力」として**ケイパビリティ**を用いる。 EIM仕様は2段階で作成される。 1. **開発時仕様(development-time EIM)**: アプリケーション開発者が、ホストが提供可能な状態ケイパビリティ(state capability)、関数ケイパビリティ(function capability)、拡張入口(extension entry)を定義する。 2. **デプロイ時仕様(deployment-time EIM)**: 拡張マネージャが、各拡張入口で許可するケイパビリティ集合を**拡張クラス(extension class)**として定義する。 **Figure 2: EIM開発時仕様の例(Nginxオブザーバビリティ)** ```text State_Capability( name = "readPid", operation = read(ngx_pid)) Function_Capability( name = "nginxTime", prototype = (void) -> time_t, constraints = {rtn > 0}) Extension_Entry( name = "processBegin", extension_entry = "ngx_http_process_request", prototype = (Request *r) -> int) ``` (Figure 2. Nginxオブザーバビリティの簡易版に対するEIM開発時仕様。状態ケイパビリティ、関数ケイパビリティ、拡張入口を定義する。Source: Figure 2 in the paper.) **制約(constraints)**は、関数の事前条件・事後条件、引数と戻り値の関係、IO/割り当て/読み書き事実などを表現し、拡張が安全にホスト関数を使うために利用される。 ```text Extension_Class( name = "observeProcessBegin", extension_entry = "processBegin", allowed = {instructions <inf, nginxTime, readPid, read(r)}) ``` (Figure 3. 簡易Nginxオブザーバビリティに対するEIMデプロイ時仕様。拡張クラスは拡張入口と許可ケイパビリティ集合を指定する。Source: Figure 3 in the paper.) ### bpftime の設計 bpftimeはEIMを効率的に強制し、拡張の隔離を提供するユーザ空間eBPFランタイムである。13,000行で実装され、現在はIntel x86上でMPKによる隔離をサポートする。 **Figure 4: bpftimeアーキテクチャ** ![[_attachments/osdi25-zheng-yusheng/fig04-bpftime-design.png]] (Figure 4. 白いコンポーネントはeBPF由来、オレンジはbpftime新規。青矢印はコンパイル・ロード時の流れ、緑矢印は実行時の流れ、白黒矢印はeBPFマップとの相互作用。Source: Adapted from Figure 4 in the paper.) 主要コンポーネントは以下の通り。 - **bpftimeローダー**: eBPF関連のシステムコールを傍受し、ユーザ空間で実装する。libbpfやbccなど既存eBPFアプリケーションを変更なしで動作させる。 - **検証器(verifier)**: EIM仕様をeBPFバイトコードに変換して、eBPF検証器を流用し安全性を保証する。DWARFからBTFを生成し、kfunc呼び出しで関数ケイパビリティを表現する。 - **JITコンパイラ**: 検証済みのeBPFバイトコードをネイティブコードにコンパイルする。 - **バイナリ書き換え器(rewriter)**: Fridaとlibcapstoneを使い、ホストプロセスにトランポリンを挿入して拡張入口を有効化する。 - **ランタイム**: ホストと同一プロセス内で拡張を実行し、ERIMスタイルのMPK隔離を提供する。 - **bpftimeマップ**: プロセス内/プロセス間/プロセス-カーネル間で共有可能なeBPF互換マップ。システムコールを介さない高速アクセスを提供する。 ### 隠蔽拡張入口(concealed extension entries) bpftimeは、拡張がロードされていない拡張入口に対しては実行時コストを発生させない。これを実現するため、バイナリ書き換え器はホストの拡張入口呼び出しを削除しておき、拡張がロードされた時点でトランポリンを挿入する。未使用時のコストをゼロにしつつ、使用時はトランポリンによるわずかなコスト(84 ns)で拡張を呼び出す。 ## 新規性 本論文の新規性は以下の3点に集約される。 1. **EIMによる細粒度トレードオフの定式化**: 従来の拡張フレームワークが固定された安全性/相互接続性を提供するのに対し、EIMはアプリケーション開発者と拡張マネージャの2者が協調して、拡張入口ごとに最小権限を指定できる。 2. **安全性と隔離を分離した軽量強制**: bpftimeはeBPFスタイル検証で安全性を(実行時オーバーヘッドゼロ)、MPKなどのハードウェア機能で隔離を(低オーバーヘッド)提供する。これを組み合わせるのは初めてである。 3. **eBPF互換性を保ったユーザ空間拡張**: カーネルeBPFエコシステムを再実装するのではなく、システムコールとマップ共有の狭い「腰」で横断して相互運用することで、既存ツール(BCC/bpftrace/libbpf)やカーネルeBPF拡張と協調できる。 ## 実験設定 評価は2台のサーバで行われた。 - **Server A**: 2ソケットIntel Xeon Gold 5418Y(24コア、2.00 GHz、45 MB LLC)、256 GB DDR5 - **Server B**: 2ソケットIntel Xeon E5-2697 v2(48コア、2.7 GHz、30 MB LLC)、256 GB DDR3 6つのユースケースを評価した。 1. **Nginxプラグイン**: ファイアウォール拡張をNginxリバースプロキシに導入。 2. **sslsniff**: OpenSSLの暗号化/復号関数にuprobeを当ててSSL/TLSトラフィックを監視。 3. **DeepFlow**: eBPFベースの分散トレースをbpftime上で動作させ、マイクロサービスの観測。 4. **FUSEキャッシング**: FUSEファイルシステムのメタデータキャッシュとブラックリストを拡張で実装。 5. **Redis耐久性調整**: 書き込みとfsync/fdatasyncの動作を拡張でカスタマイズ。 6. **Syscount**: bccツールをbpftime上で動作させ、特定プロセスのシステムコールを監視。 比較対象はネイティブ実行、eBPF uprobes、Lua、WebAssembly、ERIM、RLBoxなどである。 ## 実験結果 ### Nginxプラグイン **Figure 5: 各拡張手法のNginxスループット比較** ![[_attachments/osdi25-zheng-yusheng/fig06-nginx-overhead.png]] (Figure 6. wrk(8スレッド、64コネクション、30秒)でのNginxスループット。bpftimeはネイティブの2%オーバーヘッド。LuaとWebAssemblyはそれぞれ11%と12%、ERIMとRLBoxは11%と9%のオーバーヘッド。bpftimeはLua/WebAssemblyに対して5.5×、ERIM/RLBoxに対してそれぞれ5.5×/4.5×低いオーバーヘッド。Source: Figure 6 in the paper.) | 手法 | スループット(RPS) | 備考 | |---|---|---| | Native | 4536 | ベースライン | | Baseline C | 4559 | ネイティブと同等 | | bpftime | 4461 | 2%オーバーヘッド | | RLBox | 4148 | 9%オーバーヘッド | | ERIM | 4024 | 11%オーバーヘッド | | WebAssembly | 4007 | 12%オーバーヘッド | | Lua | 3982 | 11%オーバーヘッド | ### DeepFlow **Figure 6: DeepFlowのスループット低下** ![[_attachments/osdi25-zheng-yusheng/fig07-deepflow.png]] (Figure 7. HTTP/HTTPSそれぞれで、DeepFlowのeBPF版は最大54%スループット低下。bpftime版は最小でも1.5倍のスループット改善。残りのオーバーヘッドはカーネル・ユーザ空間双方に多数のプローブを張っていることに起因。Source: Figure 7 in the paper.) DeepFlowをbpftimeに移植するのに、eBPFコード5,000行中10行のみを変更した。bpftimeはDeepFlowのスループットを少なくとも1.5倍に改善した。 ### sslsniff **Figure 7: sslsniffのNginxスループット影響** ![[_attachments/osdi25-zheng-yusheng/fig09-sslsniff.png]] (Figure 9. データサイズを変えたNginx上のsslsniff評価。カーネルuprobe版は最大28.06%のスループット低下。bpftime版は最大7.41%に抑えた。Source: Figure 9 in the paper.) Nginx上のSSLトラフィック監視で、カーネルuprobe版sslsniffは最大28.06%スループット低下。bpftime版は最大7.41%に抑えた。これはSSLトラフィック監視のオーバーヘッドを3.79倍低減する。 ### Redis耐久性調整 **Figure 8: Redisのスループットと耐久性トレードオフ** ![[_attachments/osdi25-zheng-yusheng/fig08-redis-durability.png]] (Figure 8. Redisのalwayson設定に対し、batch size 48はスループットを4.17倍にしつつクラッシュ時のデータ損失を24件に抑える。delayed-fsync with fast-notifyはeverysecより10%遅いだけで、データ損失を5桁少なくする。Source: Figure 8 in the paper.) - batch size 48: alwayson比4.17倍スループット、クラッシュ時24件損失(everysecは72,000件)。 - delayed-fsync単体: 40k req/s(4.15倍)。 - delayed-fsync + fast-notify: 65k req/s、everysec比10%遅いのみ。 ### FUSEキャッシング Passthrough/LoggedFSワークロードで、bpftimeキャッシュはレイテンシを最大2.4桁(orders of magnitude)改善した。 | Test | Native(s) | bpftime(s) | |---|---|---| | Passthrough, fstat | 3.65 | 0.176 | | LoggedFS, fstat | 7.40 | 0.184 | | LoggedFS, openat | 17.0 | 0.074 | | Passthrough, find | 5.1 | 1.6 | (Table 2. FUSE操作レイテンシ。Source: Table 2 in the paper.) ### Syscount NginxサーバでSyscountを評価。eBPF版は監視対象・非対象プロセス双方でそれぞれ10.3%と9.6%のスループット低下を生じた。bpftime版は監視対象プロセスで3.36%、非対象プロセスには影響しなかった。 ### マイクロベンチマーク **Figure 9: bpftime/ubpf/rbpf/ネイティブのマイクロベンチマーク比較** ![[_attachments/osdi25-zheng-yusheng/fig11-microbenchmarks.png]] (Figure 11. 整数計算・文字列・メモリ・制御フローなど8マイクロベンチマーク。bpftimeはubpf比1.53倍、rbpf比1.72倍の平均レイテンシ改善。Source: Figure 11 in the paper.) | 操作 | eBPF(ns) | bpftime(ns) | |---|---|---| | Uprobe | 2561.57 | 190.02 | | Uretprobe | 3019.45 | 187.10 | | Syscall tracepoint | 151 | 232 | | User memory read | 23.3 | 1.5 | | User memory write | 23.9 | 1.4 | | hash_map_update | 50.8 | 23.8 | | hash_map_delete | 19.5 | 10.1 | | hash_map_lookup | 9.8 | 22.0 | (Table 3. bpftimeとeBPFのマイクロベンチマーク比較。Source: Table 3 in the paper.) uprobe/uretprobeではbpftimeが1桁以上高速だが、syscall tracepoint/hash_map_lookupではeBPFが有利というトレードオフも観測された。 ### ロードレイテンシと内訳 - libcのmallocを監視する拡張のロードレイテンシ: bpftime 48 ms、LD_PRELOAD 30 ms。 - 空拡張関数呼び出し: トランポリンあり190 ns、トランポリンなし実行エンジンあり106 ns、両方なし1.35 ns。 - MPK隔離の有無で測定可能な差は観測されなかった。 ## 考察 bpftimeの性能優位は、主に以下の2つの設計に依存する。 1. **隠蔽拡張入口**: 未使用時の拡張入口はゼロコスト。使用時もトランポリンによるわずかなコストで済む。プロセス内で多数の自動拡張入口(uprobe/uretprobe/syscall tracepoint)を持つケースで特に効果が大きい。 2. **プロセス内隔離**: ERIMスタイルのMPKは、コンテキストスイッチを伴わずに拡張メモリを保護する。SFIのような実行時チェックより低オーバーヘッド。 ただし、本論文も以下の制約を認めている。 - 拡張マネージャが正しいEIM仕様を指定する責任がある。誤った指定は安全を損なう。 - 制御フロー完全性が前提。攻撃者が制御フローを改竄できると、拡張を迂回可能。 - 現在の実装はIntel x86のMPKに依存。ARMのメモリドメインなど他のハードウェアでも同様の手法は可能とされている。 - MPKに対するシステムコールベース攻撃のリスクはあり、Jennyのシステムコールフィルタリング防御を採用できる。 ## 強みと限界 **強み**: - EIMにより、拡張の安全性と相互接続性を拡張入口ごとに細粒度に指定できる。 - eBPFエコシステムとの互換性により、既存ツールや知見を流用しやすい。 - 6つの多様なユースケースで、高い性能と実用性を実証した。 - オープンソース(github.com/eunomia-bpf/bpftime)として公開され、コミュニティが形成されている。 **限界・課題**: - EIM仕様を作成し、拡張が検証を通過するまでの開発コストは、LuaやWebAssemblyより高い。 - ホストアプリケーションに注釈や新規関数を追加する必要がある場合もある(例: Redis)。 - ハードウェア隔離機能への依存が残る。 - 悪意のある拡張ではなくバグのある拡張を対象としており、完全な悪意者モデルではない。 ## 関連 - ソース: [[@2026__eunomia.dev__eBPF × AI-LLMs - The Convergence of System Observability and AI]] / [[@2025__HCDS__eGPU - Extending eBPF Programmability and Observability to GPUs]] / [[@2025__eBPF__eInfer - Unlocking Fine-Grained Tracing for Distributed LLM Inference with eBPF]] / [[@2026__eunomia.dev__CUDA Events - eBPF-based CUDA API Tracing]] - エンティティ: [[Yusheng Zheng]] / [[Tong Yu]] / [[Yiwei Yang]] / [[Yanpeng Hu]] / [[Xiaozheng Lai]] / [[Dan Williams]] / [[Andi Quinn]] / [[bpftime]] / [[eunomia-bpf]] / [[Nginx]] / [[Redis]] / [[DeepFlow]] - 概念: [[eBPF]] / [[uprobe]] / [[BPF]] / [[分散トレーシング]] / [[オブザーバビリティ]] / [[動的計装]]