Chinaunix首页 | 论坛 | 博客
  • 博客访问: 328839
  • 博文数量: 41
  • 博客积分: 2540
  • 博客等级: 少校
  • 技术积分: 570
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-18 11:29
文章分类

全部博文(41)

文章存档

2011年(4)

2010年(32)

2009年(3)

2008年(2)

我的朋友

分类: LINUX

2010-10-13 11:15:01

主要是2.6.26内核的module.c中check_version()发生了改变,在检查不到符号版本的时候返回0或者是-ENOEXEC,而之前的版本是返回1,导致的这个问题。

代码如下:
2.6.26:
#ifdef CONFIG_MODVERSIONS
static int check_version(Elf_Shdr *sechdrs,
                         unsigned int versindex,
                         const char *symname,
                         struct module *mod,
                         const unsigned long *crc)
{
        unsigned int i, num_versions;
        struct modversion_info *versions;

        /* Exporting module didn't supply crcs?  OK, we're already tainted. */
        if (!crc)
                return 1;

        /* No versions at all?  modprobe --force does this. */
        if (versindex == 0)
                return try_to_force_load(mod, symname) == 0;

        versions = (void *) sechdrs[versindex].sh_addr;
        num_versions = sechdrs[versindex].sh_size
                / sizeof(struct modversion_info);

        for (i = 0; i < num_versions; i++) {
                if (strcmp(versions[i].name, symname) != 0)
                        continue;

                if (versions[i].crc == *crc)
                        return 1;
                DEBUGP("Found checksum %lX vs module %lX\n",
                       *crc, versions[i].crc);
                goto bad_version;
        }

        printk(KERN_WARNING "%s: no symbol version for %s\n",
               mod->name, symname);
        return 0;

bad_version:
        printk("%s: disagrees about version of symbol %s\n",
               mod->name, symname);
        return 0;
}

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
}

2.6.25:
#ifdef CONFIG_MODVERSIONS                                                     
static int check_version(Elf_Shdr *sechdrs,                                 
                         unsigned int versindex,                            
                         const char *symname,                               
                         struct module *mod,                                
                         const unsigned long *crc)                          
{                                                                           
        unsigned int i, num_versions;                                       
        struct modversion_info *versions;                                   
                                                                            
        /* Exporting module didn't supply crcs?  OK, we're already tainted. */
        if (!crc)                                                           
                return 1;                                                   
                                                                            
        versions = (void *) sechdrs[versindex].sh_addr;                     
        num_versions = sechdrs[versindex].sh_size                           
                / sizeof(struct modversion_info);                           
                                                                            
        for (i = 0; i < num_versions; i++) {                                
                if (strcmp(versions[i].name, symname) != 0)                 
                        continue;                                           
                                                                            
                if (versions[i].crc == *crc)                                
                        return 1;                                           
                printk("%s: disagrees about version of symbol %s\n",        
                       mod->name, symname);                                 
                DEBUGP("Found checksum %lX vs module %lX\n",                
                       *crc, versions[i].crc);                              
                return 0;                                                   
        }                                                                   
        /* Not in module's version table.  OK, but that taints the kernel. */
        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 1;                                                           
}                                                                            


解决方法:
1、重新编译内核,关闭CONFIG_MODVERSIONS选项
2、重新编译内核开启MODULE_FORCE_LOAD选项,强制加载
3、拷贝Module.symversion到内核源码目录,然后在内核源码目录执行make prepare,然后再在编译Module的时候加上KERN_DIR=/usr/src/linux
4、修改Module代码,通过/proc/kallsyms来获得地址,并赋给函数指针来使用
 
参考资料:



阅读(2344) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-10-13 20:11:05

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com