Linux LKM (loadable kernel module) is a relocateable elf file. This type of file can be created directly by using "format elf" or format elf64" fasm's directive. To build a valid LKM with fasm, we need to create at least 2 sections : one for our code/data and another is a special section named ".gnu.linkonce.this_module", which only content is the "module" structure. Within this structure, only 3 members need to be initialized at assembly time : the "name", "init" and "exit" members.

The "name" member is the internal name of our module (must be unique at runtime).
The "init" member must be set to our module's initialization routine address, and its C prototype is "int init(void)".
The "exit" member should be set to our module's termination routine address, and its C prototype is "void exit(void)"

If we read the definition of "struct module" in kernel source header "module.h", we can see that it will be different across different kernel configuration. The offset of "init" member also differs in different kernel configuration. Also, if we configured our kernel to not support module unloading, the "exit" member should not exist in our module strcuture. In particular, these kernel configuration affect our "module" structure :

Apart than this mandatory section, there are other sections that our module can have, depending on our needs. The '.modinfo" section is the way to provide information about our module (e.g can be retrieve using "modinfo" program). It contains one or more <tag>=<value> strings. For example, to provide license information, you can include the null terminated string "license=whatever your license" in this section. Note that absence of "license" info from our module make the kernel tainted (i.e the kernel assume our module isn't GPL compatible). Although the ".modinfo" section is not mandatory, but when it exist, there is one information in this section that, when inspected by kernel can cause loading failure if the check failed. It is the "vermagic" info. When this info exist, it must be the same as VERMAGIC_STRING, which is defined as

for example, in my kernel 2.6.22-kamikaze5 configured with smp and module unloading support, I can put "vermagic=2.6.22-kamikaze5 SMP mod_unload " in ".modinfo" section of my module. Note that modprobe can force loading of module where its vermagic is different from the running kernel using the option --force or --force-vermagic.

If our module accept parameter, then it must have the "__param" section. This section consists of array of kernel_param structure, which is defined like below (example for 64-bit)

it is easy to understand this structure, where "name" is the address of null terminated string, specifying the name of this parameter. "perm" is the file permission. This is relevant if we allow users to access this parameter in /sys/module/<module_name>/parameters. "set" and "get" is the setter and getter function for the variable, respectively. The kernel already export some predefined setter and getter functions for predefined types, e.g if our variable is of type int, then we should set getter and setter function to the "param_get_int" and "param_set_int" symbols. "arg" is the address of our variable. Whenever we setup a kernel_param structure, we usually also setup a "parmtype=<param_name>:<type>" info in ".modinfo" section, but it's not mandatory.

Others section which is also useful is "__ksymtab" section which allows us to export symbols to be used by other modules. There also "__ksymtab_gpl", "__ksymtab_gpl_future", "__ksymtab_unused" and "__ksymtab_unused_gpl" that has the same sections layout but each has different meanings (for example, exported symbols in __ksymtab_gpl can only be used by others that are licensed under GPL or compatible).

The example code below show an example of a very simple lkm written in fasm. Due to fasm's bug as described here, this code can only be run (loaded) correctly by applying the rela patch here to the fasm's code and assembling it with the new fasm binary.

What this code does is printing the value of its 2 parameters "lkm_param1" (of type int) and "lkm_param2" (of type string) at init and exit routine. Assemble normally with patched fasm, and insmod the object file to load the module, e.g "fasm lkm.asm" then "insmod lkm.o".
You can change the value of the 2 parameter with insmod, e.g "insmod lkm.o lkm_param1=99 lkm_param2="anything"" or at runtime using the /sys interface, e.g "echo 1 > /sys/module/lkm/parameters/lkm_param1". Note that the kernel configuration variable at the beginning of the code must match to your kernel configuration) and this is strictly for 64-bit machine.

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot vote in polls in this forumYou cannot attach files in this forumYou can download files in this forum