# システムコールフック ## 定義 システムコールフックは、ユーザープログラムがカーネルへ要求を渡すシステムコール境界へ処理を割り込み、呼び出しを観測、遮断、変更、またはユーザー空間でエミュレートする技術である。 フックの配置はカーネル入口、システムコール命令、標準ライブラリのラッパーなどで異なり、網羅性、オーバーヘッド、カーネル変更の要否、既存プログラムへの透明性が設計上の主要な評価軸になる。(Source: [[@2023__USENIX-ATC__zpoline - a system call hook mechanism based on binary rewriting]]) ## 方式 - **カーネル支援型**: `ptrace` はトレーサーが被トレースプロセスのシステムコールを網羅的に捕捉する。SUD(Syscall User Dispatch)は Linux のシステムコール入口から `SIGSYS` を介してユーザー空間へ処理を渡す。 - **シグナル型**: `int3` を `syscall`/`sysenter` の位置へ置き、`SIGTRAP` ハンドラをフック関数にする。命令は一バイトだがシグナル処理が高コストになる。 - **ライブラリ置換型**: `LD_PRELOAD` で標準ライブラリのシステムコールラッパーを関数置換する。低オーバーヘッドだが、libc 内部の直接命令やラッパーのない呼び出しは網羅できない。 - **バイナリ書き換え型**: 実行可能コード内のシステムコール命令を置換する。[[zpoline]] は `syscall`/`sysenter` と同じ二バイトの `callq *%rax`、システムコール番号に対応する仮想アドレス 0 のトランポリン、フック関数を組み合わせる。 ## zpoline の設計 zpoline はシステムコール番号が `rax` にある x86-64 の呼び出し規約を利用する。 二バイトの `syscall`/`sysenter` を二バイトの `callq *%rax` へ置換すると、`rax` の値がそのままトランポリンの仮想アドレスになる。 トランポリンは `nop` の列の後にフック関数への分岐を置き、`callq` が保存した呼び出し元アドレスによって元のプログラムへ戻る。 この構造により、長い絶対アドレス命令を二バイト領域へ押し込む必要がなく、隣接命令を壊さずにシステムコールを網羅的に置換できる。(Source: [[@2023__USENIX-ATC__zpoline - a system call hook mechanism based on binary rewriting]] §2) ## 性能と適用範囲 `getpid` のフック時間は zpoline が 41 nsで、`ptrace` 31,201 ns、`int3 signaling` 1,342 ns、SUD 1,156 nsより小さい。 一方、`LD_PRELOAD` は 6 nsで zpoline より低いが、システムコールを網羅的にはフックできない。 lwIP/DPDK 上の単純 HTTP サーバーと Redis では、`LD_PRELOAD` 基準に対する zpoline の性能低下は 5.2%だった。(Source: [[@2023__USENIX-ATC__zpoline - a system call hook mechanism based on binary rewriting]] §3.2–§3.3) ## 横断的知見 - **網羅性と低オーバーヘッドは同じ機構の単純な二択ではなく、フック位置の選択で分離される**: `ptrace`・SUD・`int3` は網羅性を得る代わりにカーネルとのコンテキスト切り替えやシグナル処理を負担し、`LD_PRELOAD` は低コストな代わりにシステムコール命令を取りこぼす。zpoline は命令長とレジスタ規約を利用して、従来は同時に満たしにくかった二軸を一つのユーザー空間機構へ寄せる。(Source: [[@2023__USENIX-ATC__zpoline - a system call hook mechanism based on binary rewriting]], [[@2023__OReillyJapan__詳解 システム・パフォーマンス 第2版 - Chapter 5 アプリケーション]]) - **動的計装の「観測」とシステムコールフックの「挙動変更」は重なる実装技術を持つが、許容する安全性の範囲が異なる**: DTrace は本番観測のために無効時のゼロ・プローブ効果と安全性を設計目標にするのに対し、zpoline はシステムコールをユーザー空間実装へ振り向け、OS サブシステムをエミュレートする。zpoline 自体はセキュリティ強化を提供しないため、観測用の動的計装と挙動変更用のフックは別の脅威モデルで評価する必要がある。(Source: [[@2004__USENIX-ATC__Dynamic Instrumentation of Production Systems]], [[@2023__USENIX-ATC__zpoline - a system call hook mechanism based on binary rewriting]]) - **ユーザー空間 OS サブシステムの導入障壁は、スタック性能だけでなく既存アプリケーションとの接続方法にある**: mTCP や iip は TCP/IP 処理をユーザー空間へ配置し、API・実行ループ・NIC 依存処理の統合を要求する。一方 zpoline はシステムコール境界を介して lwIP/DPDK を既存の HTTP サーバーと Redis へ透明に接続する。ユーザー空間化の性能利点を既存ソフトウェアへ届けるには、データ経路の高速化と呼び出し境界の透明性を別々に設計する必要がある。(Source: [[@2014__NSDI__mTCP - a Highly Scalable User-level TCP Stack for Multicore Systems]], [[@2024__SIGCOMM CCR__iip - An Integratable TCP IP Stack]], [[@2023__USENIX-ATC__zpoline - a system call hook mechanism based on binary rewriting]]) - **フックの数値比較は、フック単体と適用先ワークロードを分けて行う必要がある**: zpoline の `getpid` では 41 nsという小さな値でも、ネットワーク処理の多い lwIP/DPDK では `ptrace`・シグナル方式・SUDとの性能差がアプリケーションスループットへ増幅される。プローブ効果の評価と同様に、呼び出し頻度・カーネル越境・アプリケーション処理を含む測定境界を明示しなければならない。(Source: [[@2023__USENIX-ATC__zpoline - a system call hook mechanism based on binary rewriting]], [[@2004__USENIX-ATC__Dynamic Instrumentation of Production Systems]]) ## 未解決の問い - zpoline の仮想アドレス 0 依存と x86-64 固有の命令規約を、ARM などの異なる命令長・分岐規約を持つ CPU へ一般化できるか。 - セットアップ後にロードされるコード、JIT コンパイルコード、vDSO の呼び出しを、網羅性と安全性を保ったままオンラインで書き換えられるか。 - システムコールの挙動変更を許す zpoline と、eBPF verifier や seccomp のような安全制約付きフックをどの境界で組み合わせるべきか。 - `nop` の線形オーバーヘッド、NULL 実行検査、`dlmopen` の名前空間分離を、異なるカーネル・libc・ワークロードでどう評価すべきか。 - システムコール単位の挙動変更と、ライブラリ関数単位の `LD_PRELOAD`、カーネル関数単位の eBPF/uprobe を一つの互換性・性能モデルで比較できるか。 ## 関連 - [[zpoline]] — x86-64 の二バイト置換によるシステムコールフック機構。 - [[システムコール]] — ユーザー空間とカーネルの API 境界。 - [[バイナリ書き換え]] — 命令列を書き換えて実行経路を変える技術。 - [[動的計装]] — 実行時または実行直前にコードへ計装を挿入する上位概念。 - [[ゼロコード計装]] — ソースコード変更なしに計装する設計軸。 - [[プローブ効果]] — フック・計装による対象システムへの性能影響。 - [[ユーザーレベルTCPスタック]] — zpoline が透明に適用した OS サブシステムの系譜。 ## 出典 - [[@2023__USENIX-ATC__zpoline - a system call hook mechanism based on binary rewriting]] - [[@2004__USENIX-ATC__Dynamic Instrumentation of Production Systems]] - [[@2014__NSDI__mTCP - a Highly Scalable User-level TCP Stack for Multicore Systems]] - [[@2024__SIGCOMM CCR__iip - An Integratable TCP IP Stack]]