要約

  • RFC 894はIPv4を示すEtherTypeを16進数0800とし、Ethernetのデータ部が最小46オクテットに届かないときはゼロで補う一方、その追加分をIPパケットにもTotal Lengthにも含めなかった。
  • 受信実装は、リンクが実際に渡したサイズで外側のメモリを確保し、IPのTotal Lengthで内側の解析を止める必要がある。RFC 6274は、リンク側がIPの主張より短い場合を破棄・記録すべき不正な入力として整理した。
  • IPの外にあるバイトも無害とは限らない。CERT/CCは古いバッファ内容をパディングとして送るドライバを報告した。RFC 894の「minimum 1500」という誤記も、原文と検証済み訂正を別の証拠として残す必要を示す。

二つの長さが一致しない正常系

RFC 791で、IPv4のTotal LengthはIPヘッダとデータを合わせたデータグラム全体のオクテット数と定義された。IHLは32ビット語単位のヘッダ長であり、データが始まる位置を決める。IHLとTotal Lengthは、同じ長さを重複して表すフィールドではない。

最小のIPv4ヘッダは20オクテットである。データを持たないならTotal Lengthも20になり得る。しかしRFC 894のEthernetデータ部は最低46オクテットを必要とする。送信側は差分の26オクテットをゼロで埋める。

ここでIPのTotal Lengthを46へ書き換えてはいけない。アプリケーションもIPも26オクテットのデータを作っていないからだ。かといってEthernetの最小値を無視することもできない。RFC 894は、追加分を物理的に送信しつつ、IPパケットの外に置くことで両方の契約を守った。

したがって正常な受信でも、次の不等式は厳密な小なりになり得る。

IHL × 4 <= IP Total Length <= リンク層ペイロード長

外側が長いという事実だけで、内側のオブジェクトは延長されない。

0800はサイズではなく読み方だった

RFC 894では、EthernetのTypeフィールドに16進数0800を置き、その後ろにIPヘッダとIPデータを連続して格納する。0800は10進数で2048だが、2048オクテットという長さではない。

この違いは、EthernetとIEEE 802.3が同じケーブル上に混在した時代に重要になった。RFC 1122は、同じ位置の2オクテットが1500以下なら802.3のLength、1500を超える有効値ならEtherTypeとして区別できると説明した。2048はIPv4というプロトコルを選ぶ値である。

外側のフィールドが文法を選び、選ばれたIPv4文法の中でTotal Lengthが終端を示す。この順序を逆にして、受信バッファの末尾からIPの長さを推定すると、パディングまで上位データとして取り込んでしまう。

RFC 1122は10 Mb/s Ethernet上のホストにRFC 894形式の送受信を必須とした。RFC 1042のIEEE 802形式は受信を推奨し、送信を任意とした。両方を送れるホストは選択スイッチを持ち、既定値をRFC 894にする必要があった。同じ媒体だから自動的に同じ構文になるわけではない。

八オクテットの外装はIPの中身を変えない

RFC 1042ではIPとARPをIEEE 802.2 LLCおよびSNAPで包む。LLCとSNAPの合計は8オクテットで、SNAPの最後の16ビットにEtherTypeを残した。IPは2048、ARPは2054である。

IEEE 802が最小サイズを必要とする場合も、データ部はゼロで補われ、そのパディングはIP Total Lengthから除外された。RFC 1042が述べる最小28オクテットは、最小IPヘッダ20とLLC/SNAP 8の合計であり、MACヘッダを含まない。RFC 894の46オクテットとは数えている範囲が違う。

RFC 1122はEthernet MTUを1500、802.3 MTUを1492とした。8オクテットの差はLLC/SNAPの収容に使われる。IPヘッダから8を引く規則でも、パディングをTotal Lengthへ足す規則でもない。

同じ1984年4月のRFC 895は、3 Mb/s Experimental Ethernetを扱った。8ビットアドレスと別のType値を用い、IPデータグラムの最大値は1536だった。それでも最小フレームのためのパディングはIP外である。媒体固有の数値が変わっても、データグラムの所有境界は変わらなかった。

一語の誤りは原文から消されなかった

RFC 894の公開テキストには、Ethernetデータ部の「minimum」が1500オクテットだという文がある。同じ文は直後にIPデータグラムのmaximumを1500と結論づけ、前段は本当のminimumを46と述べている。技術的に整合する訂正は一つしかない。

検証済みTechnicalのerratum 570はminimumをmaximumへ直す。2001年に報告された。erratum 5141は2017年に同じ問題を報告し、2024年に検証された。2024年にEthernetの上限が変わったわけではない。

RFC Editorのerrata方針では、公開済みRFCは変更されない。Verified errataは正確とみなされるが、TXT、PDF、XMLへは組み込まれない。原文は「何が公開されたか」、erratumは「どう読むべきか」をそれぞれ保存する。

ローカルコピーだけを無言で修正すると読みやすいが、変更の来歴を失う。誤記をそのまま技術要件とみなせば、来歴は守れても実装を誤る。二つの証拠を結び付けたまま残すことが解決になる。

trailerとpadは後ろにあるという理由だけでは同じにならない

RFC 893のtrailer encapsulationは、可変長の上位ヘッダをデータの後ろへ移し、一部の受信機でメモリ整列とコピーを有利にする別形式だった。受信側がその表現を理解する必要がある。

RFC 894のpaddingはIPヘッダを動かさない。IPデータも順序どおり続き、Total Lengthが示す終端の後にゼロが付く。再構成ではなく、そこでIP解析を止めることが受信側の仕事である。

pad、trailer、IP option、FCSは物理的に末尾付近へ見える場合があっても別の構文要素である。位置の近さは権限の同一性を意味しない。

外側の受信と内側の解析を分ける

RFC 6274は、リンク層がTotal Lengthより大きなペイロードをIPモジュールへ渡し得ると注意した。通常は正当なリンクパディングが理由になり、攻撃者の入力である可能性もある。

受信バッファはリンク層が報告するペイロードサイズに基づいて確保する。小さな内側オブジェクトだけを見て外側の容器を受けると、メモリ安全性を損なうからだ。ただしIPとして解釈する終端はTotal Lengthのままである。

逆方向は許されない。リンク層ペイロードがTotal Lengthより短ければ、パケットを破棄して記録する。IHLの4倍もTotal Length以下でなければならない。届かなかった部分を隣のメモリから読んではならない。

一つの長さに統一することが安全なのではない。リンク実長は収納を支配し、IP長は意味を支配する。異なる質問に異なる測定値を使うことが安全である。

IPが読まない領域からメモリが読めた

2003年1月のCERT/CC VU#412115は、短いEthernetフレームをゼロではなく古いフレームバッファの内容で埋めるネットワークドライバを報告した。実装によっては、カーネルメモリ、ドライバの静的メモリ、NICのハードウェアバッファが遠隔の観測者へ漏れ得た。

漏れた領域は正規のIPペイロードではない。正しいIPパーサはTotal Lengthで止まる。それでも相手のEthernetインターフェースには物理的に到着する。IPの意味から除外することと、通信路から消去することは別である。

CERTのベンダー情報には影響あり、影響なし、不明が混在する。全ドライバに一般化してはならない。歴史的に確認できるのは、ゼロ初期化を省いた複数の報告対象で情報漏えいが成立したことだ。

追加した層は、上位層が読まないことを理由に責任を放棄できない。送信したバイトの機密性は、Total Lengthの外でも現実に存在する。

出典