無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

カーネルモジュールのマジック番号(その2)


カーネルモジュールのロードは、load_module()で行われ、モジュールがロード可能かどうかは、そこからcheck_modstruct_version()およびsame_magic()で行われています。
static noinline struct module *load_module(void __user *umod,
                                 unsigned long len,
                                 const char __user *uargs)
{
   :
   :
       versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
       infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
   :
      if (!check_modstruct_version(sechdrs, versindex, mod)) {
               err = -ENOEXEC;
               goto free_hdr;
       }

       modmagic = get_modinfo(sechdrs, infoindex, "vermagic");
       if (!modmagic) {
               err = try_to_force_load(mod, "magic");
               if (err)
                       goto free_hdr;
       } else if (!same_magic(modmagic, vermagic, versindex)) {
               printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",
                      mod->name, modmagic, vermagic);
               err = -ENOEXEC;
               goto free_hdr;
       }

   :
   :
}
check_modstruct_version()は、CONFIG_MODVERSIONSを設定しないでカーネルを構築した場合、常に1を返すようにコンパイルされます。本チェックは行わない事になります。以下はCONFIG_MODVERSIONSを設定した場合の処理になります。

最初のfind_symbol()は、すでに動作している任意のカーネルモジュールから、struct_moduleと言うシンボル名を探し出し、そのCRCを取得します(たぶん)。そしてcheck_version()で、そのCRCと、ロードしようとしているモジュールのstruct_moduleシンボルのCRCが、同じかどうかチェックします。
static inline int check_modstruct_version(Elf_Shdr *sechdrs,
                                         unsigned int versindex,
                                         struct module *mod)
{
       const unsigned long *crc;

       if (IS_ERR_VALUE(find_symbol("struct_module", NULL, &crc, true, false)))
               BUG();
       return check_version(sechdrs, versindex, "struct_module", mod, crc);
}
same_magic()でマジック番号のチェックを行います。CONFIG_MODVERSIONSが設定されてのカーネルの場合、マジック番号の最初の項目だけのチェックとなります。そうでない場合マジック番号すべてのチェックとなります。引数のhas_crcsは、モジュールに__versionsがあるかどうかのフラグで、モジュールがCONFIG_MODVERSIONSを設定しないで作成された場合、この値は0となります。この場合マジック番号全文字列とのチェックとなります。CONFIG_MODVERSIONSでのカーネルでCONFIG_MODVERSIONSでないモジュールをロードする場合を想定しての事でしょうか?でもこの場合check_modstruct_version()で弾かれるのでは思うのですが・・・。よく解りません。
#ifdef CONFIG_MODVERSIONS
static inline int same_magic(const char *amagic, const char *bmagic,
                            bool has_crcs)
{
       if (has_crcs) {
               amagic += strcspn(amagic, " ");
               bmagic += strcspn(bmagic, " ");
       }
       return strcmp(amagic, bmagic) == 0;
}
#else
static inline int same_magic(const char *amagic, const char *bmagic,
                            bool has_crcs)
{
       return strcmp(amagic, bmagic) == 0;
}
#endif 
try_to_force_load()はvermagicを設定してないモジュールの処理で、カーネルがCONFIG_MODULE_FORCE_LOADでコンパイルされている時に限り、ロード可能となります。
static int try_to_force_load(struct module *mod, const char *symname)
{
#ifdef CONFIG_MODULE_FORCE_LOAD
       if (!(tainted & TAINT_FORCED_MODULE))
               printk("%s: no version for \"%s\" found: kernel tainted.\n",
                      mod->name, symname);
       add_taint_module(mod, TAINT_FORCED_MODULE);
       return 0;
#else
       return -ENOEXEC;
#endif
}

補足

カーネルのバージョンマジック番号は、動的に取得するのでなく、ソース内にstaticの変数として埋め込まれています。
static const char vermagic[] = VERMAGIC_STRING;



最終更新 2012/01/17 16:34:10 - north
(2012/01/17 16:29:55 作成)