Linuxでは、カーネルのモジュールをロードしようとした際に、カーネルモジュールの整合性の検証が行われます。整合性の検証には、vermagicが使用されていると記憶していたのですが、最近のLinuxではmodversionsによる検証が行われているようです。
このmodversionsによる整合性の検証について調査した内容を備忘録としてまとめておきます。
注意点
本内容にあるカーネルモジュールのロードには予期せぬ挙動を示す可能性がありますので、必ず自己責任の元で作業してください。
環境
- ディストリビューション
Ubuntu 12.04.2 LTS - カーネルバージョン
3.5.0-27-generic、3.5.0-23-generic - 調査対象カーネルモジュール
net/ipv4/tcp_bic.ko
vermagicによる整合性検証
従来のvermagicによる検証では、カーネルコンパイル時に設定されている主な設定値を文字列化したものを使用します。この文字列は、include/linux/vermagic.hで定義されています。
- UTS_RELEASEについては、include/generated/utsrelease.hを参照してください。
- その他の値は、vermagic.hおよびカーネルコンパイル時の設定値を参照してください。
カーネルモジュールに組み込まれているvermagicの値は、modinfoコマンドで確認することができます。
カーネルコンパイル時に、CONFIG_MODVERSIONSという設定値が有効になっていた場合、MODULE_VERMAGIC_MODVERSIONSの値が”modversions “となり、VERMAGIC_STRINGに埋め込まれ、modversionsによる整合性検証が行われます。
modversionsによる整合性検証
modversionsによる整合性検証では、カーネルコンパイル時にカーネル内の各関数のシンボル情報についてCRCが計算されます。カーネルモジュールに保持されている、モジュール内からコールしているカーネル内の関数のCRCと、動作しているカーネル内の関数のCRCが一致していない場合、エラーとなりロードすることができません。
例えば、3.5.0-27-genericのカーネル上で、3.5.0-23-genericのtcp_bic.koをロードしようとすると、以下のようなエラーメッセージが出力されます。
各モジュール内に保持されているCRCについてはmobprobeコマンドの–dump-modversionsオプションで確認することができます。
試しに3.5.0-27-genericと3.5.0-23-genericそれぞれのtcp_bic.koのCRCを確認してみると、一致していない関数があることが分かります。
3.5.0-27-generic
3.5.0-23-generic
ここで、3.5.0-23-genericのtcp_bic.ko内のCRCの値を、3.5.0-27-genericの値と一致させることでモジュールがロードできないか試してみました。
一致していない関数は以下なので、3.5.0-23-genericのtcp_bic.koをバイナリエディタで編集し、3.5.0-27-genericと一致させてみました。
vermagicの値は3.5.0-23ですが、CRCは3.5.0-27と一致しています。
このedit_tcp_bicをロードすると以下のメッセージが表示され、ロードできたことが確認できます。
異なるバージョンのカーネルモジュールをロードしたいという状況は稀だと思いますが、 ちょっと実装を変えてみたので、試してみたいという場合には使えるかもしれません。
但し、予期せぬ挙動を示す可能性がありますので、必ず自己責任の元で作業してください。
※実行中のカーネルのCRCは、以下のファイル内に保持されています。
/lib/modules/`uname -r`/build/Module.symvers
参考URL
- http://d.hatena.ne.jp/enakai00/20110509/1304910773