カーネルモジュールのマジック番号(その1)
Rev.1を表示中。最新版はこちら。
カーネルモジュールのmakeは、ソースファイルをtest.cとすると、testmod.mod.cというファイルが作成され、tset.c/testmod.mod.cのオブジェクトファイルをバインドし、testmod.koとして、ローダブルカーネルモジュールが作成されるようです。なおtestmod.mod.cにバージョンマジックが埋め込まれ、insmod時モジュールをインサートしてもいいかどうのかのチェックが行われます。testmod.mod.c #include <linux/module.h> #include <linux/vermagic.h> #include <linux/compiler.h> MODULE_INFO(vermagic, VERMAGIC_STRING); struct module __this_module __attribute__((section(".gnu.linkonce.this_module"))) = { .name = KBUILD_MODNAME, .init = init_module, #ifdef CONFIG_MODULE_UNLOAD .exit = cleanup_module, #endif .arch = MODULE_ARCH_INIT, }; static const char __module_depends[] __used __attribute__((section(".modinfo"))) = "depends="; MODULE_INFO(srcversion, "DC76D599D92E61B57FEADEC");VERMAGIC_STRINGがマジック番号となります。これは以下のvermagic.hで定義されていて、CONFIG_SMP/CONFIG_PREEMPT/CONFIG_MODULE_UNLOAD/CONFIG_MODVERSIONSのコンパイルオプションに依存して作成されます。
vermagic.h #include <linux/utsrelease.h> #include <linux/module.h> /* Simply sanity version stamp for modules. */ #ifdef CONFIG_SMP #define MODULE_VERMAGIC_SMP "SMP " #else #define MODULE_VERMAGIC_SMP "" #endif #ifdef CONFIG_PREEMPT #define MODULE_VERMAGIC_PREEMPT "preempt " #else #define MODULE_VERMAGIC_PREEMPT "" #endif #ifdef CONFIG_MODULE_UNLOAD #define MODULE_VERMAGIC_MODULE_UNLOAD "mod_unload " #else #define MODULE_VERMAGIC_MODULE_UNLOAD "" #endif #ifdef CONFIG_MODVERSIONS #define MODULE_VERMAGIC_MODVERSIONS "modversions " #else #define MODULE_VERMAGIC_MODVERSIONS "" #endif #ifndef MODULE_ARCH_VERMAGIC #define MODULE_ARCH_VERMAGIC "" #endif #define VERMAGIC_STRING \ UTS_RELEASE " " \ MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT \ MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS \ MODULE_ARCH_VERMAGICなお、UTS_RELEASEがカーネルソース下のMakefieで設定する、バージョン番号です。
Makefile VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 27 EXTRAVERSION = .41-170.2.117.fc10.i686 NAME = Trembling Tortoiseutsrelease.hは以下の1行だけのファイルです。推測ですが、これはカーネルmake時に作成されるのではと思います。ためしに、Makefileのこれらの設定を変更して、モジュールを作成しても、作成モジュールのマジック番号に反映されませんでした。マジック番号はUTS_RELEASEのその番号のままでした。
utsrelease.h #define UTS_RELEASE "2.6.27.41-170.2.117.fc10.i686"動作しているカーネルと異なるソース下でモジュールを作成する場合、modinfoでシステムで動作しているモジュールのマジック番号を調べ、本ヘッダファイルを修正すれば、そのシステム下で動作するモジュールを作成できるのではと思います。
補足
CONFIG_MODVERSIONSが設定されているシステムでは、マジック番号はVERMAGIC_STRING全体でチェックされ、そうでなければUTS_RELEASEだけのチェックとなっています。CONFIG_MODVERSIONSはシンボルにCRCを埋め込み、その正当性のチェックも行うもので、ロード時のチェックロジックは異なってます。定かでないですが、以前はMakefieのEXTRAVERSIONを修正するだけで、よかったように記憶していますが・・・。記憶違いかもしれません。