Linux内核模块LKM的动态加载技术分析

时间:2022-04-30 20:09:36

Linux内核模块LKM的动态加载技术分析

 

原文: http://blog.csdn.net/sailor_8318/archive/2008/09/20/2954380.aspx

 

【摘要】本文详解了Linux内核模块的动态加载技术。首先介绍了Linux内核采用LKM的好处,接着介绍了内核模块的基本结构。在分析了动态加载链接技术/ELF格式内核模块组成/内核符号表的基础之上,详细介绍了模块加载卸载的实现细节,包括模块拷贝/符号解析/模块重定位/依赖性检查/资源释放等。

 

【关键字】内核模块,单内核,微内核,动态扩充,动态加载链接,ELF,内核符号表,insmod,rmmod

 

 

1       为什么需要LKM

Linux 就是通常所说的单内核(monolithic kernel),即操作系统的大部分功能都被称为内核,整个系统内核都运行于一个单独的保护域中,并在特权模式下运行。它与微型内核不同,后者只把基本的功能(进程间通信[IPC]、调度、基本的输入/输出 [I/O]和内存管理)当作内核运行,而把其他功能(驱动程序、网络堆栈和文件系统)排除在特权空间之外。因此,您可能认为 Linux是一个完全静态的内核,但事实恰恰相反。通过Linux 内核模块(Loadable Kernel Modules,LKM)可以在运行时动态地更改 Linux。

 

可动态更改是指允许内核在运行时动态地向其中插入或从中删除代码。这些代码包括相关的子例程、数据、函数入口和函数出口被一并组合在一个单独的二进制镜像中,即所谓的可装载内核模块中,或被简称为模块。这是一种区别于一般应用程序的系统级程序,它主要用于扩展linux的内核功能。LKM的优点是基本内核镜像可以尽可能的小,可以最小化内核的内存占用,只加载需要的元素(这是嵌入式系统的重要特性),可选的功能和驱动程序可以利用模块形式再提供。模块允许我们方便的删除和重新载入内核代码,也方便了调试工作,无须重新编译内核。而且当热插拔新设备时,可通过命令载入新的驱动程序。

 

Linux 可加载内核模块是 Linux 内核的最重要创新之一。它们提供了可伸缩的、动态的内核。探索隐藏在可加载模块后面的原理将会异常有趣。

 

2       模块的基本结构

LKM 与直接编译到内核或典型程序的元素有根本区别。典型的程序有一个 main 函数,其中 LKM 包含 entry 和exit 函数。当向内核插入模块时,调用 entry 函数,从内核删除模块时则调用 exit函数。因为 entry 和 exit 函数是用户定义的,所以存在 module_init 和 module_exit宏,用于定义这些函数属于哪种函数。LKM 还包含一组必要的宏和一组可选的宏,用于定义模块的许可证、模块的作者、模块的描述等等。图 1提供了一个非常简单的 LKM 的视图。

图 1 简单 LKM 的源代码视图

 

因为entry函数通常不会被外部函数直接调用,所以不必导出该函数,故它可被标记为static类型。init函数会返回一个int型数值,如果初始化顺利完成,那么它的返回值为零,否则失败的话,则返回一个非零值。

 

exit()函数是模块的出口函数,它由module_exit()例程注册到系统。在模块从内存卸载时,内核便会调用exit()。退出函数可能会在返回前负责清理资源,以保证硬件处于一致状态。在退出函数返回后,模块就被卸载了。其返回值对模块无任何意义,故exit函数无返回值。与init函数的原因一样,你也可以标记exit函数为static。如果上述文件被静态地编译到内核映像中,那么退出函数将不被包含,而且永远都不会被调用。

 

3       LKM动态加载链接的技术基础

3.1   模块动态加载链接技术

传统嵌入式开发过程中需要将应用与操作系统编译链接成一个整体,然后下载到目标机上运行。如果在调试过程中发现问题,需要重新编链接然后重复下载运行的过程。这样的开发流程周期长而且繁琐,已经越来越不适应快速市场化的需要。新一代的嵌入式操作系统已经开始使用动态扩展技术:将基本系统(包括操作系统以及其他共享功能调用库)和应用程序开发分开处理,支持模块更新和动态加载技术。

 

为了成为可动态扩展系统平台,大部分嵌入式操作系统需要使用动态加载技术。总的来说,动态加载是指应用或者系统在运行过程中需要使用某模块的服务,于是通过一系列预定的动作将指定模块加载到系统中,让调用者继续顺利工作。它实现的关键就是加载与动态链接技术。因为加载和动态链接互相依赖,关系紧密,所以将两者放在一起进行讨论。

 

加载主要负责将模块程序从二级存储设备(比如硬盘或者Flash)搬移到指定内存空间,并且将模块交由系统加载器统一管理。

 

程序链接分为静态链接、加载时链接和运行时链接。

静态链接就是将程序和它运行所需的全部库链接成一个执行文件。它的优点是可以独立运行、速度快,但是它链接生成的代码尺寸比较大。

加载时链接是指程序在编译链接时不会把它用到的库链接到执行程序中,而是在它被加载器加载时才解析执行文件,依次把用到的库装载到系统中让其运行。它的优点是程序本身代码量减小,但运行时程序占的内存并没有减小,同时增加了加载器的工作量。

动态链接是加载时链接的进一步发展,它是指将库的加载过程延迟到程序运行时执行。这种方式不会给程序引入额外的代码,也不会增加加载器的开销,只有当应用真正使用某库时才会加载该库,减少了不必要的空间占用。它的缺点是可能会有一些运行开销。

 

3.2   内核模块ELF格式

LKM 只不过是一个特殊的可执行可链接格式(Executable and Linkable Format,ELF)对象文件,是用于linux操作系统上的可执行文件格式。当链接两个ELF object 文件的时候,链接程序需要知道每个object文件里相关符号的一些情况。通常,必须链接对象文件才能在可执行文件中解析它们的符号和结果。由于必须将 LKM 加载到内核后 LKM才能解析符号,所以 LKM 仍然是一个 ELF 对象。您可以在 LKM 上使用标准对象工具(在 2.6 版本中,内核对象带有后缀.ko,)。例如,如果在 LKM 上使用 objdump实用工具,您将发现一些熟悉的区段(section),比如.text(代码段)、.data(已初始化数据)和.bss(块开始符号或未初始化数据)。

 

您还可以在模块中找到其他支持动态特性的区段.init.text 区段包含 module_init 代码,.exit.text区段包含 module_exit 代码(参见图 2)。.modinfo 区段包含各种表示模块许可证、作者和描述等的宏文本。

图 2 具有各种 ELF 区段的 LKM 的示例

 

lkm的object文件包含了两个重要部分.symtab 和 .strtab这两个section 是用来存储每个符号的信息结构的。

 

.symtab section这部分是一个结构列表。当链接程序使用那些ELF object文件里的符号时,就需要这些数据。在/usr/include/elf.h里可以找到这个结构的定义:

/* Symbol table entry. */(符号列表入口)

typedef struct

{

  Elf32_Word    st_name;    /* Symbol name (string tbl index) */(符号名(字符串列表索引))

  Elf32_Addr    st_value;    /* Symbol value */(符号的值)

  Elf32_Word    st_size;    /* Symbol size */(符号数据占用空间的大小)

  unsigned char    st_info;    /* Symbol type and binding */(符号类型和绑定)

  unsigned char    st_other;    /* Symbol visibility */(符号的可见性)

  Elf32_Section    st_shndx;    /* Section index */(各section 的索引)

} Elf32_Sym;

 

这里我们只对st_name感兴趣。实际上它是 .strtab section 的索引,而那些符号的名称就是存储在 .strtab 里面的。

 

.strtab section 是一个非空字符串的列表。Elf32_Sym里面的st_name是 .strtab section 的索引。如果我们寻找的符号在某个字符串里,我们可以很方便的得到这个字符串的偏移地址。下面是我们的计算公式:

offset_sym_name = offset_strtab + st_name

offset_strtab 是 .strtab section 相对于文件起始处的偏移地址,可以通过section 名称解析机制获得。

 

3.3   内核符号表

Linux的内核是个单内核monolithic,任一函数都可以访问公共数据结构和函数调用。在设计程序时,需要命名一些函数名、变量名等;同样内核中就含有很多的全局符号。内核要使用变量和函数-地址(指针)-来访问对应的变量和函数。内核符号表就是为程序员通过符号来访问程序体的对应地址(指针),建立了一个动态的,可变更的映射表格

一个符号表例子:

c03441a0 b dmi_broken

c03441a4 b is_sony_vaio_laptop

可以看出变量dmi_broken位于内核地址c03441a0处。 这和gdb的按图索骥的功能很相似,不同的是内核采用文件为载体的形式。

 

/proc/ksyms内核公共符号的动态映像文件,在内核引导时创建,其实就是内核数据,没有实际大小的。ksyms中的每一个表项代表着一个全局内核符号。这些符号可被LKM引用的,即可以看出LKM可以调用哪些函数和访问哪些全局变量。模块加载的过程中若有输出全局变量或者函数,则也会添加到这个文件中。

 

System.map列出了内核所有的静态符号,编译链接内核时生成。位于/或者/boot、/usr/src/linux/下,在每次重新编译内核时,各符号名及其对应的地址指针可能有所变化。所以系统需要自行更新此文件。System.map文件作为特定内核的静态内核符号表,其链接了系统所使用的System.map。 一般的创建步骤:当编译后生成内核vmlinux-2.X.Y后,存于/usr/src/linux/下,这时编译脚本将运行“nm /usr/src/linux/vmlinux-2.X.Y > System.map”,并将其拷入/boot下。 nm vmlinux的作用是过滤掉其中不需要的符号。值得注意的是内核本身并不真正使用System.map,但其它程序比如klogd, lsof和ps等软件需要一个正确的System.map。某些与内核头连接而非glibc库的驱动也需要System.map来解析符号。klogd 内核日志守护进程为了执行名称-地址解析,klogd需要使用System.map。 man klogd可知,klogd将从一下路径查找System.map: /boot/System.map /System.map /usr/src/linux/System.map

 

3.4   导出符号表

模块被载入后,就会动态连接到了内核。注意,它与用户空间中的动态连接库类似,只有当被显式导出后的外部函数,才可以被动态库调用。在内核中,导出内核函数需要使用特殊的指令:

EXPORT_SYMBOL()

这样在编译模块时,就会生成一个.symtab段,所有需要到出的符号都放在此,加载该模块时会将这些符号加载到内核的全局符号表中,以便以后供其他模块使用。

 

导出的内核函数可以被模块调用,而未导出的函数模块则无法被调用。模块代码的链接和调用规则相比核心内核镜像中的代码而言,要更加严格。核心代码在内核中可以调用任意非静态接口,因为所有的核心源代码文件被链接成了同一个镜像。当然,被导出的符号表所含的函数必然也是非静态的。

 

导出的内核符号表被看作是导出的内核接口,甚至称为内核API。导出符号相当简单,在声明函数后,紧跟上EXPORT_SYMBOL(XXX)指令就搞定了

 

如果你的代码被配置为模块,那么就必须确保当它被编译为模块时所用的全部接口都已被导出否则就会产生连接错误。

 

3.5   模块依赖性

有时候Linux模块之间存在依赖性,加载某模块时需要先加载依赖模块。当模块较多时可能依赖关系比较复杂,这时可以利用modprobe destmod,其将自动根据依赖关系加载相关模块,但这里需要的依赖信息必须事先生成。若想产生内核依赖关系的信息,root用户可运行命令:

depmod

为了执行更快的更新操作,可以只为新模块生成依赖信息,而不是生成所有的依赖关系,这时root用户可运行命令:

depmod -A

模块依赖关系信息存放在/lib/modules/version/modules.dep文件中。

 

4       动态加载链接的实现细节

了解 LKM 动态加载链接的基础知识之后,现在我们进一步探索模块是如何进入内核的,以及在内核内部是如何管理模块的。构建 LKM时,可以使用典型的用户工具管理模块:标准 insmod(安装 LKM),rmmod(删除LKM),modprobe(insmod 和 rmmod 的包装器),depmod(用于创建模块依赖项),以及modinfo(用于为模块宏查找值)。

 

4.1   LKM 的生命周期

在用户空间中,insmod(插入模块)启动模块加载过程。insmod命令定义需要加载的模块,并调用 init_module用户空间系统调用,开始加载过程。2.6 版本内核的 insmod 命令经过修改后变得非常简单,可以在内核中执行更多工作。insmod 并不进行所有必要的符号解析,它只是通过 init_module函数将模块二进制文件复制到内核,然后由内核完成剩余的任务。

 

init_module 函数通过系统调用层,进入内核到达内核函数 sys_init_module(参见图3)。这是加载模块的主要函数,它利用许多其他函数完成困难的工作。类似地,rmmod 命令会使 delete_module 执行 system call 调用,而 delete_module 最终会进入内核,并调用 sys_delete_module 将模块从内核删除。

图 3 加载和卸载模块时用到的主要命令和函数

 

在模块的加载和卸载期间,模块子系统维护了一组简单的状态变量,用于表示模块的操作。加载模块时,状态为MODULE_STATE_COMING。如果模块已经加载并且可用,状态为 MODULE_STATE_LIVE。此外,卸载模块时,状态为MODULE_STATE_GOING。

 

4.2   模块加载细节

内核模块的加载是通过insmod这个用户空间工具实现的。insmod包含在modutils包里[6]。我们感兴趣的东西是insmod.c文件里的init_module()函数。

 

static int init_module(const char *m_name, struct obj_file *f,

        unsigned long m_size, const char *blob_name,

        unsigned int noload, unsigned int flag_load_map)

{

(1)     struct module *module;

        struct obj_section *sec;

        void *image;

        int ret = 0;

        tgt_long m_addr;

 

        ....

 

(2)     module->init = obj_symbol_final_value(f, obj_find_symbol(f, "module_init"));

(3)     module->cleanup = obj_symbol_final_value(f, obj_find_symbol(f, " module_exit"));

 

        ....

 

        if (ret == 0 && !noload) {

                fflush(stdout);         /* Flush any debugging output */

(4)             ret = sys_init_module(m_name, (struct module *) image);

                if (ret) {

                        error("init_module: %m");

                        lprintf(

      "Hint: insmod errors can be caused by incorrect module parameters, "

      "including invalid IO or IRQ parameters./n"

      "You may find more information in syslog or the output from dmesg");

                }

        }

 

在 (1) 里,函数向一个结构体模块(struct module)填充了加载模块必须的数据。需要关注的部分是 init和 cleanup。这是两个函数指针,分别指向被加载模块的module_init() 和module_exit函数。

 

(2)里面的 obj_find_symbol()函数遍历符号列表查找名字为module_init的符号,然后提取这个结构体符号(struct symbol)并把它传递给 obj_symbol_final_value()。后者从这个结构体符号提取出module_init函数的地址。同理,在 (3) 里这个工作对于module_exit ()又重复了一遍。

 

当结构体模块填充完毕后,(4) 使用了 sys_init_module() 这个系统调用(syscall)通知内核加载相应模块。模块加载过程中程序调用了 sys_init_module(),其中有我们感兴趣的部分。

 

现在,我们看看加载模块时的内部函数(参见图 4)。当调用内核函数 sys_init_module时,会开始一个许可检查,查明调用者是否有权执行这个操作(通过 capable 函数完成)。然后,调用 load_module函数,这个函数负责将模块加载到内核并执行必要的调试。load_module函数返回一个指向内核中最新加载分配的模块引用。然后将这个模块加载到系统内所有模块的双向链表上,并且通过 notifier列表通知正在等待模块状态改变的线程。最后,调用模块的 init()函数,更新模块状态,表明模块已经加载并且可用。

图 4  内部(简化的)模块加载过程

 

加载模块的内部细节是 ELF 模块解析和操作。load_module函数(位于./linux/kernel/module.c)首先分配一块用于容纳整个 ELF 模块的临时内存。然后,通过 copy_from_user 函数将 ELF模块从用户空间读入到临时内存。作为一个 ELF 对象,这个文件的结构非常独特,易于解析和验证。

 

下一步是对加载的 ELF 映像执行一组健康检查(它是有效的 ELF文件吗?它适合当前的架构吗?等等)。完成健康检查后,就会解析ELF 映像,然后会为每个区段头创建一组方便变量,简化随后的访问。因为 ELF对象的偏移量是基于 0的(除非重新分配),所以这些方便变量将相对偏移量包含到临时内存块中。在创建方便变量的过程中还会验证 ELF 区段头,确保加载的是有效模块。

 

任何可选的模块参数都从用户空间加载到另一个已分配的内核内存块(第 4 步),并且更新模块状态,表明模块已加载(MODULE_STATE_COMING)。如果需要 per-CPU 数据(这在检查区段头时确定),那么就分配 per-CPU 块。

 

在前面的步骤,模块区段被加载到内核(临时)内存,并且知道哪个区段应该保持,哪个可以删除。步骤 7为内存中的模块分配最终的位置,并移动必要的区段(ELF 头中的SHF_ALLOC,或在执行期间占用内存的区段)。然后执行另一个分配,大小是模块必要区段所需的大小。迭代临时 ELF块中的每个区段,并将需要执行的区段复制到新的块中。接下来要进行一些额外的维护。同时还进行符号解析,可以解析位于内核中的符号(被编译成内核映象),或临时的符号(从其他模块导出)。

 

然后为每个剩余的区段迭代新的模块并执行重新定位。这个步骤与架构有关,因此依赖于为架构(./linux/arch/<arch>/kernel/module.c)定义的 helper函数。最后,刷新指令缓存(因为使用了临时 .text 区段),执行一些额外的维护(释放临时模块内存,设置系统文件),并将模块最终返回到 load_module。

 

4.3   模块卸载细节

卸载模块的过程和加载模块基本一样,除了必须进行几个健康检查外(确保安全删除模块)。卸载模块过程首先在用户空间调用 rmmod(删除模块)命令。在 rmmod 命令内部,对 delete_module执行系统调用,它最终会导致在内核内部调用 sys_delete_module(查看图 3)。图 5 演示了删除模块的基本操作过程。

图 5 内部(简化的)模块卸载过程

 

当调用内核函数sys_delete_module(将要删除的模块的名称作为参数传入)之后,第一步便是确保调用方具有权限。接下来会检查一个列表,查看是否存在依赖于这个模块的其他模块。这里有一个名为 modules_which_use_me的列表,它包含每个依赖模块的一个元素。如果这个列表为空,就不存在任何模块依赖项,因此这个模块就是要删除的模块(否则会返回一个错误)。接下来还要测试模块是否加载。用户可以在当前安装的模块上调用 rmmod,因此这个检查确保模块已经加载。在几个维护检查之后,倒数第二个步骤是调用模块的exit 函数(模块内部自带)。最后,调用 free_module 函数。

 

调用 free_module 函数之后,您将发现模块将被安全删除。该模块不存在依赖项,因此可以开始模块的内核清理过程。首先,从安装期间添加的各种列表中(系统文件、模块列表等)删除模块。其次,调用一个与架构相关的清理例程(可以在 ./linux/arch/<arch>/kernel/module.c中找到)。然后迭代具有依赖性的模块,并将这个模块从这些列表中删除。最后,从内核的角度而言,清理已经完成,为模块分配的各种内存已被释放,包括参数内存、per-CPU 内存和模块的 ELF 内存(core 和 init)。

 

4.4   为模块管理优化内核

在许多应用程序中,动态加载模块非常重要,但加载之后,就没有必要卸载模块。这允许内核在启动时是动态的(根据找到的设备加载模块),但并不是在整个操作过程中都是动态的。如果不需要在加载之后卸载模块,那么可以进行一些优化,减少模块管理所需的代码。您可以 “取消” 内核配置选项CONFIG_MODULE_UNLOAD,删除大量与卸载模块相关的内核功能。

 

要获得模块管理的细节,源代码本身就是最佳的文档。关于在模块管理中调用的主要函数,请查看./linux/kernel/module.c(以及./linux/include/linux/module.h 中的头文件)。您还可以在./linux/arch/<arch>/kernel/module.c中找到几个与架构相关的函数。最后,可以在./linux/kernel/kmod.c 中找到内核自动加载函数(可以根据需要从内核自动加载模块)。这个功能可以通过 CONFIG_KMOD配置选项启用。

 

 

 

5       参考书目

LKM 注射:http://www.cnpaf.net/Class/hack/05121820345113486242.htm

Linux 可加载内核模块剖析:http://bbs.cnw.com.cn/viewthread.php?tid=95476

在内核中寻找内核符号表

内核符号表详解 - [Linux内核技术],笑雨bladerunner

内核符号表

内核符号表和系统调用

Linux内核设计与实现

嵌入式系统中的模块动态加载技术

http://www.linuxforum.net/forum/showflat.php?Cat=&Board=linuxK&Number=93082&page=169&view=collapsed&sb=5&o=all

 

6       附加代码

1901/* This is where the real work happens */

1902asmlinkage long

1903sys_init_module(void__user *umod,

1904                unsigned longlen,

1905                const char__user *uargs)

1906{

1907        structmodule *mod;

1908        intret = 0;

1909

1910        /* Must have permission */

1911        if (!capable(CAP_SYS_MODULE))

1912                return -EPERM;

1913

1914        /* Only one module load at a time, please */

1915        if (mutex_lock_interruptible(&module_mutex) != 0)

1916                return -EINTR;

1917

1918        /* Do all the hard work */

1919       mod =load_module(umod,len,uargs);

1920        if (IS_ERR(mod)) {

1921               mutex_unlock(&module_mutex);

1922                returnPTR_ERR(mod);

1923        }

1924

1927       stop_machine_run(__link_module,mod,NR_CPUS);

1928

1929        /* Drop lock so they can recurse */

1930       mutex_unlock(&module_mutex);

1931

1932       blocking_notifier_call_chain(&module_notify_list,

1933                       MODULE_STATE_COMING,mod);

1934

1935        /* Start the module */

1936        if (mod->init != NULL)

1937               ret =mod->init();

1938        if (ret < 0) {

1939                /* Init routine failed: abort.  Try to protect us from

1940                   buggy refcounters. */

1941               mod->state = MODULE_STATE_GOING;

1942               synchronize_sched();

1943                if (mod->unsafe)

1944                       printk(KERN_ERR "%s: module is now stuck!/n",

1945                              mod->name);

1946                else {

1947                       module_put(mod);

1948                       mutex_lock(&module_mutex);

1949                       free_module(mod);

1950                       mutex_unlock(&module_mutex);

1951                }

1952                returnret;

1953        }

1954

1955        /* Now it's a first class citizen! */

1956       mutex_lock(&module_mutex);

1957       mod->state = MODULE_STATE_LIVE;

1958        /* Drop initial reference. */

1959       module_put(mod);

1960       unwind_remove_table(mod->unwind_info, 1);

1961       module_free(mod,mod->module_init);

1962       mod->module_init = NULL;

1963       mod->init_size = 0;

1964       mod->init_text_size = 0;

1965       mutex_unlock(&module_mutex);

1966

1967        return 0;

1968}

 

 

1480/* Allocate and load the module: note that size of section 0 is always

1481   zero, and we rely on this for optional sections. */

1482static structmodule *load_module(void__user *umod,

1483                                  unsigned longlen,

1484                                  const char__user *uargs)

1485{

1486       Elf_Ehdr *hdr;

1487       Elf_Shdr *sechdrs;

1488        char *secstrings, *args, *modmagic, *strtab =NULL;

1489        unsigned inti;

1490        unsigned intsymindex = 0;

1491        unsigned intstrindex = 0;

1492        unsigned intsetupindex;

1493        unsigned intexindex;

1494        unsigned intexportindex;

1495        unsigned intmodindex;

1496        unsigned intobsparmindex;

1497        unsigned intinfoindex;

1498        unsigned intgplindex;

1499        unsigned intcrcindex;

1500        unsigned intgplcrcindex;

1501        unsigned intversindex;

1502        unsigned intpcpuindex;

1503        unsigned intgplfutureindex;

1504        unsigned intgplfuturecrcindex;

1505        unsigned intunwindex = 0;

1506        unsigned intunusedindex;

1507        unsigned intunusedcrcindex;

1508        unsigned intunusedgplindex;

1509        unsigned intunusedgplcrcindex;

1510        structmodule *mod;

1511        longerr = 0;

1512        void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */

1513        structexception_table_entry *extable;

1514       mm_segment_told_fs;

1515

1516       DEBUGP("load_module: umod=%p, len=%lu, uargs=%p/n",

1517              umod,len,uargs);

1518        if (len < sizeof(*hdr))

1519                returnERR_PTR(-ENOEXEC);

1520

1521        /* Suck in entire file: we'll want most of it. */

1522        /* vmalloc barfs on "unusual" numbers.  Check here */

1523       if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) ==NULL)

1524                returnERR_PTR(-ENOMEM);

1525        if (copy_from_user(hdr,umod,len) != 0) {

1526               err = -EFAULT;

1527                gotofree_hdr;

1528        }

1529

1530        /* Sanity checks against insmoding binaries or wrong arch,

1531           weird elf version */

1532        if (memcmp(hdr->e_ident,ELFMAG, 4) != 0

1533            ||hdr->e_type != ET_REL

1534            || !elf_check_arch(hdr)

1535            ||hdr->e_shentsize != sizeof(*sechdrs)) {

1536               err = -ENOEXEC;

1537                gotofree_hdr;

1538        }

1539

1540        if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr))

1541                gototruncated;

1542

1543        /* Convenience variables */

1544       sechdrs = (void *)hdr + hdr->e_shoff;

1545       secstrings = (void *)hdr +sechdrs[hdr->e_shstrndx].sh_offset;

1546       sechdrs[0].sh_addr = 0;

1547

1548        for (i = 1; i <hdr->e_shnum;i++) {

1549                if (sechdrs[i].sh_type != SHT_NOBITS

1550                    &&len <sechdrs[i].sh_offset + sechdrs[i].sh_size)

1551                        gototruncated;

1552

1553                /* Mark all sections sh_addr with their address in the

1554                   temporary image. */

1555                sechdrs[i].sh_addr = (size_t)hdr + sechdrs[i].sh_offset;

1556

1557                /* Internal symbols and strings. */

1558               if (sechdrs[i].sh_type ==SHT_SYMTAB) {

1559                       symindex =i;

1560                       strindex =sechdrs[i].sh_link;

1561                       strtab = (char *)hdr + sechdrs[strindex].sh_offset;

1562                }

1568        }

1569

1570       modindex =find_sec(hdr,sechdrs,secstrings,

1571                            ".gnu.linkonce.this_module");

1572        if (!modindex) {

1573               printk(KERN_WARNING "No module found in object/n");

1574               err = -ENOEXEC;

1575                gotofree_hdr;

1576        }

1577       mod = (void *)sechdrs[modindex].sh_addr;

1578

1579        if (symindex == 0) {

1580               printk(KERN_WARNING "%s: module has no symbols (stripped?)/n",

1581                       mod->name);

1582               err = -ENOEXEC;

1583                gotofree_hdr;

1584        }

1585

1586        /* Optional sections */

1587       exportindex =find_sec(hdr,sechdrs,secstrings, "__ksymtab");

1588       gplindex =find_sec(hdr,sechdrs,secstrings, "__ksymtab_gpl");

1589       gplfutureindex =find_sec(hdr,sechdrs,secstrings, "__ksymtab_gpl_future");

1590       unusedindex =find_sec(hdr,sechdrs,secstrings, "__ksymtab_unused");

1591       unusedgplindex =find_sec(hdr,sechdrs,secstrings, "__ksymtab_unused_gpl");

1592       crcindex =find_sec(hdr,sechdrs,secstrings, "__kcrctab");

1593       gplcrcindex =find_sec(hdr,sechdrs,secstrings, "__kcrctab_gpl");

1594       gplfuturecrcindex =find_sec(hdr,sechdrs,secstrings, "__kcrctab_gpl_future");

1595       unusedcrcindex =find_sec(hdr,sechdrs,secstrings, "__kcrctab_unused");

1596       unusedgplcrcindex =find_sec(hdr,sechdrs,secstrings, "__kcrctab_unused_gpl");

1597       setupindex =find_sec(hdr,sechdrs,secstrings, "__param");

1598       exindex =find_sec(hdr,sechdrs,secstrings, "__ex_table");

1599       obsparmindex =find_sec(hdr,sechdrs,secstrings, "__obsparm");

1600       versindex =find_sec(hdr,sechdrs,secstrings, "__versions");

1601       infoindex =find_sec(hdr,sechdrs,secstrings, ".modinfo");

1602       pcpuindex =find_pcpusec(hdr,sechdrs,secstrings);

 

1606

1607        /* Don't keep modinfo section */

1608       sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;

1609#ifdefCONFIG_KALLSYMS

1610        /* Keep symbol and string tables for decoding later. */

1611       sechdrs[symindex].sh_flags |= SHF_ALLOC;

1612       sechdrs[strindex].sh_flags |= SHF_ALLOC;

1613#endif

1614        if (unwindex)

1615               sechdrs[unwindex].sh_flags |= SHF_ALLOC;

1616

1622

1623       modmagic =get_modinfo(sechdrs,infoindex, "vermagic");

1624        /* This is allowed: modprobe --force will invalidate it. */

1625        if (!modmagic) {

1626               add_taint_module(mod,TAINT_FORCED_MODULE);

1627               printk(KERN_WARNING "%s: no version magic, tainting kernel./n",

1628                      mod->name);

1629        } else if (!same_magic(modmagic,vermagic)) {

1630               printk(KERN_ERR "%s: version magic '%s' should be '%s'/n",

1631                      mod->name,modmagic,vermagic);

1632               err = -ENOEXEC;

1633                gotofree_hdr;

1634        }

1635

1636        /* Now copy in args */

1637       args =strndup_user(uargs, ~0UL >> 1);

1638        if (IS_ERR(args)) {

1639               err =PTR_ERR(args);

1640                gotofree_hdr;

1641        }

1642

1643        if (find_module(mod->name)) {

1644               err = -EEXIST;

1645                gotofree_mod;

1646        }

1647

1648       mod->state = MODULE_STATE_COMING;

1649

1650        /* Allow arches to frob section contents and sizes.  */

1651       err =module_frob_arch_sections(hdr,sechdrs,secstrings,mod);

1652        if (err < 0)

1653                gotofree_mod;

1654

1667

1668        /* Determine total sizes, and put offsets in sh_entsize.  For now

1669           this is done generically; there doesn't appear to be any

1670           special cases for the architectures. */

1671       layout_sections(mod,hdr,sechdrs,secstrings);

1672

1673        /* Do the allocs. */

1674       ptr =module_alloc(mod->core_size);

1675        if (!ptr) {

1676               err = -ENOMEM;

1677                gotofree_percpu;

1678        }

1679       memset(ptr, 0, mod->core_size);

1680       mod->module_core = ptr;

1681

1682       ptr =module_alloc(mod->init_size);

1683        if (!ptr && mod->init_size) {

1684               err = -ENOMEM;

1685                gotofree_core;

1686        }

1687       memset(ptr, 0, mod->init_size);

1688       mod->module_init = ptr;

1689

1690        /* Transfer each section which specifies SHF_ALLOC */

1691       DEBUGP("final section addresses:/n");

1692        for (i = 0; i <hdr->e_shnum;i++) {

1693                void *dest;

1694

1695                if (!(sechdrs[i].sh_flags & SHF_ALLOC))

1696                        continue;

1697

1698                if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK)

1699                       dest =mod->module_init

1700                                + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);

1701                else

1702                       dest =mod->module_core + sechdrs[i].sh_entsize;

1703

1704                if (sechdrs[i].sh_type != SHT_NOBITS)

1705                       memcpy(dest, (void *)sechdrs[i].sh_addr,

1706                              sechdrs[i].sh_size);

1707                /* Update sh_addr to point to copy in image. */

1708               sechdrs[i].sh_addr = (unsigned long)dest;

1709               DEBUGP("/t0x%lx %s/n",sechdrs[i].sh_addr,secstrings +sechdrs[i].sh_name);

1710        }

1711        /* Module has been moved. */

1712       mod = (void *)sechdrs[modindex].sh_addr;

1713

1714        /* Now we've moved module, initialize linked lists, etc. */

1715       module_unload_init(mod);

1716

1717        /* Set up license info based on the info section */

1718       set_license(mod,get_modinfo(sechdrs,infoindex, "license"));

1719

1720        if (strcmp(mod->name, "ndiswrapper") == 0)

1721                add_taint(TAINT_PROPRIETARY_MODULE);

1722        if (strcmp(mod->name, "driverloader") == 0)

1723               add_taint_module(mod,TAINT_PROPRIETARY_MODULE);

1724

1725        /* Set up MODINFO_ATTR fields */

1726       setup_modinfo(mod,sechdrs,infoindex);

1727

1728        /* Fix up syms, so that st_value is a pointer to location. */

1729       err =simplify_symbols(sechdrs,symindex,strtab,versindex,pcpuindex,

1730                              mod);

1731        if (err < 0)

1732                gotocleanup;

1733

1734        /* Set up EXPORTed & EXPORT_GPLed symbols (section 0 is 0 length) */

1735       mod->num_syms =sechdrs[exportindex].sh_size / sizeof(*mod->syms);

1736       mod->syms = (void *)sechdrs[exportindex].sh_addr;

1737        if (crcindex)

1738               mod->crcs = (void *)sechdrs[crcindex].sh_addr;

1739       mod->num_gpl_syms = sechdrs[gplindex].sh_size / sizeof(*mod->gpl_syms);

1740       mod->gpl_syms = (void *)sechdrs[gplindex].sh_addr;

1741        if (gplcrcindex)

1742               mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;

1743       mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size /

1744                                        sizeof(*mod->gpl_future_syms);

1745       mod->num_unused_syms = sechdrs[unusedindex].sh_size /

1746                                        sizeof(*mod->unused_syms);

1747       mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /

1748                                        sizeof(*mod->unused_gpl_syms);

1749       mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr;

1750        if (gplfuturecrcindex)

1751               mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr;

1752

1753       mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr;

1754        if (unusedcrcindex)

1755               mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr;

1756       mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr;

1757        if (unusedgplcrcindex)

1758               mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr;

1759

1760#ifdefCONFIG_MODVERSIONS

1761        if ((mod->num_syms && !crcindex) ||

1762            (mod->num_gpl_syms && !gplcrcindex) ||

1763            (mod->num_gpl_future_syms && !gplfuturecrcindex) ||

1764            (mod->num_unused_syms && !unusedcrcindex) ||

1765            (mod->num_unused_gpl_syms && !unusedgplcrcindex)) {

1766                printk(KERN_WARNING "%s: No versions for exported symbols."

1767                       " Tainting kernel./n",mod->name);

1768               add_taint_module(mod,TAINT_FORCED_MODULE);

1769        }

1770#endif

1771

1772        /* Now do relocations. */

1773        for (i = 1; i <hdr->e_shnum;i++) {

1774                const char *strtab = (char *)sechdrs[strindex].sh_addr;

1775                unsigned intinfo =sechdrs[i].sh_info;

1776

1777                /* Not a valid relocation section? */

1778                if (info >= hdr->e_shnum)

1779                        continue;

1780

1781                /* Don't bother with non-allocated sections */

1782                if (!(sechdrs[info].sh_flags & SHF_ALLOC))

1783                        continue;

1784

1785                if (sechdrs[i].sh_type == SHT_REL)

1786                        err = apply_relocate(sechdrs,strtab,symindex,i,mod);

1787                else if (sechdrs[i].sh_type == SHT_RELA)

1788                       err =apply_relocate_add(sechdrs,strtab,symindex,i,

1789                                                 mod);

1790                if (err < 0)

1791                        gotocleanup;

1792        }

1793

1794        /* Find duplicate symbols */

1795       err =verify_export_symbols(mod);

1796

1797        if (err < 0)

1798                gotocleanup;

1799

1808

1809       add_kallsyms(mod,sechdrs,symindex,strindex,secstrings);

1810

1811       err =module_finalize(hdr,sechdrs,mod);

1812        if (err < 0)

1813                gotocleanup;

1814

1819        /*

1820         * Flush the instruction cache, since we've played with text.

1821         * Do it before processing of module parameters, so the module

1822         * can provide parameter accessor functions of its own.

1823         */

1824        if (mod->module_init)

1825                flush_icache_range((unsigned long)mod->module_init,

1826                                   (unsigned long)mod->module_init

1827                                   +mod->init_size);

1828       flush_icache_range((unsigned long)mod->module_core,

1829                           (unsigned long)mod->module_core + mod->core_size);

1830

1831       set_fs(old_fs);

1832

1833       mod->args = args;

1834        if (obsparmindex)

1835               printk(KERN_WARNING "%s: Ignoring obsolete parameters/n",

1836                      mod->name);

1837

1838        /* Size of section 0 is 0, so this works well if no params */

1839       err =parse_args(mod->name,mod->args,

1840                         (structkernel_param *)

1841                        sechdrs[setupindex].sh_addr,

1842                        sechdrs[setupindex].sh_size

1843                         / sizeof(structkernel_param),

1844                        NULL);

1845        if (err < 0)

1846                gotoarch_cleanup;

1847

1848       err =mod_sysfs_setup(mod,

1849                              (structkernel_param *)

1850                             sechdrs[setupindex].sh_addr,

1851                             sechdrs[setupindex].sh_size

1852                              / sizeof(structkernel_param));

1853        if (err < 0)

1854                gotoarch_cleanup;

1855       add_sect_attrs(mod,hdr->e_shnum,secstrings,sechdrs);

1856

1857        /* Size of section 0 is 0, so this works well if no unwind info. */

1858       mod->unwind_info = unwind_add_table(mod,

1859                                            (void *)sechdrs[unwindex].sh_addr,

1860                                            sechdrs[unwindex].sh_size);

1861

1862        /* Get rid of temporary copy */

1863       vfree(hdr);

1864

1865        /* Done! */

1866        returnmod;

1867

1868arch_cleanup:

1869       module_arch_cleanup(mod);

1870cleanup:

1871       module_unload_free(mod);

1872       module_free(mod,mod->module_init);

1873free_core:

1874       module_free(mod,mod->module_core);

1875free_percpu:

1876        if (percpu)

1877               percpu_modfree(percpu);

1878free_mod:

1879       kfree(args);

1880free_hdr:

1881       vfree(hdr);

1882        returnERR_PTR(err);

1883

1884truncated:

1885       printk(KERN_ERR "Module len %lu truncated/n",len);

1886       err = -ENOEXEC;

1887        gotofree_hdr;

1888}