この記事は後半です。前半は Qiita にあります: PwnEscapeが突き刺したのはハイパーバイザーではなくLinuxカーネルだった
画像: github.com より
この研究の肝は、チェックサムが「今すぐの計算結果」ではなく、「あとで書き込む場所を指す指示書」でもある点にある。CHECKSUM_PARTIAL の状態では、skb->csum_start が計算開始位置、skb->csum_offset が csum_start から結果の書き込み先までのオフセットを示す。つまりメタデータ自体が、後続の書き込みを成立させる権限になる。
普通の経路なら、その権限は安全だ。ところが pwn.ai の説明では、ゲスト由来のパケット処理の途中で、この情報がホスト側で再解釈される。その結果、すでに検証を終えたはずのパケット内容に対して、あとから別の位置へ書き込みが起きうる。ここで壊れるのは「値が正しいか」ではなく、「その値が指してよい範囲はどこか」という前提だ。
Vercel の公表では、研究者は microVM 内から送った特定のパケットで、ホストメモリの漏えい、ホストのクラッシュ、ホストでのコード実行を示した。pwn.ai 側でも、最初は限定されたホストメモリの露出として見えたものが、やがてホストカーネル書き込みへ発展したと述べている。
ここで面白いのは、単なる情報漏えいで終わらなかったことだ。読めるだけなら、被害は断片の観測で止まることがある。だが書けるようになると話が変わる。カーネルのどこか 1 か所を動かせれば、次の参照先が変わり、さらに別の制御点が開く。pwn.ai が owned 環境で示したのは、この「読む」から「書く」への転換だった。
もう少し細かく見ると、問題は境界判定の座標系が揃っていなかったことにある。pwn.ai は、__virtio_net_hdr_to_skb() の入力側チェックが skb->data 視点では見えても、ネットワークヘッダ基準では足りなかったと説明している。フレーム相対で安全でも、IPv4 正規化後に見ると話が違う。
この手のずれは現場で起きやすい。リンク層の情報を剥がす前に見た位置と、上位層で意味を持つ位置は同じではないからだ。入力時に「十分後ろ」と判断しても、後でヘッダが剥がれれば、その判定は別の意味を持つ。今回の欠陥は、まさにその遅延した再解釈を突かれた。
続編では、漏れたホスト物理メモリを足がかりに、Firecracker の実行中プロセスを探し当てる流れが描かれる。Firecracker は単一の VMM プロセスで microVM を管理し、vCPU スレッドは KVM_RUN を呼び出している。その戻り際に、ホスト側の保存レジスタフレーム pt_regs が残る。
pwn.ai は、まずゲストの既知ページをホスト物理メモリ上で見つけ、そこからホストのページテーブル根を逆引きし、Firecracker の実行ファイルとそのロード位置を特定し、最後に vCPU の保存フレームを探し当てる。狙いはコード本体の改変ではなく、KVM からユーザ空間へ戻る瞬間の再開先だ。戻り先を握れれば、同じプロセスの文脈で任意の処理を走らせられる。
この話を実務に引き寄せるなら、教訓は「microVM だから終わり」ではないことだ。Replit も Firecracker も、microVM の外側にあるホスト Linux の健全性を前提にしている。Vercel の件が示したのは、その前提が 1 つ崩れるだけで、隔離の価値が一気に薄れるという事実だった。
一方で、この研究をそのまま一般化するのも危険だ。pwn.ai が強調しているのは、あくまで owned 環境での再現であり、特定の本番環境で root を取ったと断言しているわけではない。したがって、読む側は「どの環境でも同じ」と短絡せず、ホスト共有カーネル、仮想 NIC、offload、VMM の組み合わせを点検する材料として受け取るべきだ。
自分なら、まずホストとゲストの境界で「あとで書く」タイプのメタデータを洗う。チェックサムだけでなく、遅延評価される属性や、後段で再解釈される値は危ない。次に、ゲスト入力がホストのどの層で信頼に変わるのかを追う。そこが曖昧なら、隔離は強そうに見えても、実際には細い橋でつながっているだけだ。