Wednesday 18 September 2013

Linux Kernel Module : Internals of insmod and rmmod

The post intends to explain the internals of a kernel module and the way insmod and rmmod utilities work.

Internals of a kernel module 
         The kernel module is a dynamically loadable section of the kernel. It means it is a piece of kernel code which can be added to the running kernel when loaded and can be removed from kernel when the functionality is not required.
         To do so, the kernel configuration of the object is to be made as m, ie., CONFIG_<object> = m in the .config of the kernel build directory. To be more precise, the object has to be given as obj-m in the Makefile.
         This configuration and building will provide a .ko which is nothing but the kernel module. Many device drivers can be written this way, so that they can be loaded only when necessary and can be removed otherwise. This reduces the actual size of the kernel image.
         The loading of a kernel module can be performed by insmod or modprobe utilities, whereas unloading can be done by rmmod utility. These utilities are supported as part of busybox package and module-init-tools package. The busybox commands will not have all the features and options supported. Hence module-init-tools can be installed. If there is a constraint on size, the busybox package itself can be used for basic functionality.
          The kernel module after compilation is nothing but an elf file. It will have .text section for the instructions, .data for the data, .bss section for uninitialized data, .init.text for module_init function of a module, .exit.text section for the module_exit function of the module and .modinfo section which has all the macros.

How insmod works
1) Insmod is a small program, which calls init_module() to intimate the kernel that a module is attempted to be loaded and transfers the control to the kernel.
2) In kernel, sys_init_module() is run. It does a sequence of operations as follows
    a) Verifies if the user who attempts to load the module has the permission to do so or not.
    b) After verification, load_module function is called.
        b.1) The load_module function assigns temporary memory and copies the elf module from user space to kernel memory using copy_from_user.
        b.2) It then checks the sanity of the ELF file (Verification if it is a proper ELF file etc)
        b.3) Then based on the ELF file interpretation, it generates offset in the temporary memory space allocated. This is called the convenience variables.
        b.4) User arguments to the module are also copied to the kernel memory
        b.5) The state of the module is updated to MODULE_STATE_COMING
        b.6) The actual location in the kernel memory is allocated using SHF_ALLOC
        b.7) Symbol resolution is done.
        b.8) The load_module function returns a reference to the kernel module.
    c) The reference to the module returned by load_module is added to a doubly linked list that has a list of all the modules loaded in the system.
    d) Then the module_init function in the module code is called.
    e) Module state is updated to MODULE_STATE_LIVE

How rmmod works
1) rmmod calls delete_module which hints the kernel that an rmmod request has come in and the control is transferred to kernel.
2) The sys_delete_module() is called in the kernel. This does following operations.
     a) Checks if the user who attempts to remove the module has the permission to do so or not.
     b) Checks if any other module that is loaded is dependent on the module attempted to be unloaded. This information can be obtained from the modules_which_uses_me list.
     c) Checks if the module is actually loaded or not in the kernel. This is done by verifying if the current state of the module is MODULE_STATE_LIVE.
     d) It executes the module_exit function written in the module code.
     e) Then free_module function is called, which does the following.
          e.1) Removes any sysfs references of the module
          e.2)Removes all the kernel module object references.
          e.3) Performs architecture specific clean up if any.
          e.4) Unloads the module from kernel
          e.5) Updates the state of module to MODULE_STATE_GOING
          e.6) Frees the memory used by user space arguments for the module.


I sincerely hope that this blog gives a detailed understanding of insmod/rmmod utilities. Please feel free to correct me if any of the above information is incorrect or if it can be elaborated.

Thanks,
Gomathi

4 comments:

  1. Thnaks for this valuable information..

    ReplyDelete
  2. Hi, thanks for this. How does it work with kmod's insmod ? I am trying to find where sys_init_module is called within do_insmod in insmod.c (from kmod v9), but can't find it anywhere ?

    ReplyDelete
  3. Just to add, its is important to add here that allocation of memory for a module uses a VMALLOC. Please also refer my blog - http://rackbrains-esoft.blogspot.com/

    ReplyDelete