Kernel Module writing with examples
introduction :
Hello all , as we all know linux is a BIG do it your self program
it allow you to do EVERY THING on your system
all what you have to do is to learn how to use it's capabilities
WE are going to deal with kernel by modules right now , but what is module ?
it's like a small kernel application (not user application) that can be loaded into kernel at run time whenever you need it by insmod , modeprobe
that is a good advantage actually , you don't need to compile kernel statically every time you need a module and that will cause you to reboot your system , imagine how could this be a west of time
but why that ([color="#0000FF"]kernel application[/color]) what is the difference between it and user application
[color="#FF0000"]user application:[/color][/i]
as we all know user application (ordinary programs) start execution from [color="#0000FF"]main()[/color] function
continue execution of this function until it satisfy it's job then exit
you can use standard libraries and user libraries
[color="#0000FF"]kernel applications[/color] : modules
piece of code that will be compiled against kernel objects producing a kernel module
that can be linked dynamically and removed dynamically at run time without a need to reboot
kernel modules doesn't start execution like ordinary programs from main()
However , it starts execution from function we call (initialization function) which you will code
module end when you request it to be removed but before kernel unload it . it will call a function we call (cleaning up function) and clean up all it's job.
calling this functions will depend on you because you will specify which function is the init and which function is the cleanup (later);
when a module is loaded kernel get the address of the init function and run it , then it hangs on the kernel until some application requires a symbol that this module exported ;
NOTE : if kernel is suspicious about module job (still hanging around with a file descriptor or what ever) it will not unload it until it finishes it's job .
unless you specified `MODULE_FORCE_UNLOAD` in your kernel configuration
modules doesn't hang in memory like ordinary applications might does . kernel handles it memory and kernel frees it's memory;
any fault at modules can cause a BIG something if you are not careful.....
SIGSEGV in ordinary app will cause a core dumb and exit
but in kernel it might be a disaster...
you can't use library function in modules (NO linking to libc or any other library)
modules are objects files . they only able to deal with internal kernel functions ("/proc/kallsyms")
which we can call SYSTEM CALLS .
system calls are defined in kernel which load the modules and resolve it's referencing
at insmod"ing time ;
in a kernel space you can do anything you want
you are dealing with kernel;
you MUST have a kernel source tree to be able to compile your module
you will NOT be able to do anything without a kernel source
a kernel module runs on kernel 2.6 will definitely not able to run on 2.4
a compiled module runs on 2.6.X might not run in 2.6.D
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++
[color="#0000FF"]your First kernel module :[/color]
get a shell and pick and editor and start typing :
after saving It
let's start explaining what is this
essential headers to make module able to load
+++++++++++++++++++++++
initialization :
+++++++++++++++++++++++
static int __init module_start(void);
this function will be passed to module_init why ? because module_init specify that this is the function should be called when module is loaded
which will point in module(object file) that this is the function should be called whenever this module is loaded
++++++++++++++++++++++
exiting: cleaning up
++++++++++++++++++++++
static void module_end(void);
will be passed to module_exit(); same as module_init() but it does the opposite it points to cleanup = exit function;
passing parameters :
this function allow you to pass parameters to the module at loading time by
insmod module.kp name="Bleh"
specify variablename=value
you can't pass a float point variable;
types:
also you can pass arrays
like
each value separated by (,)
but you will have to change it like
++++++++++++++
[color="#0000FF"]printk: your first kernel hacking[/color]
++++++++++++++
what the hell is printk ? where is f ? did the grinch stole it :@ what a bastard :@
no he didn't , I told you before that you can't use library function
printk is the kernel version of printf function which is a system call allow you to print format messages .it prints by priority by the way , and that is [color="#0000FF"]KERN_INFO[/color] is it's a priority every string is printed by this
information about module as you can see
no what is that make command ?
as I told you before modules compiled against several objects files in the kernel source tree
as an example : magicversion.o this object file contain information about the module
date , version , which kernel it was compiled on , etc
make -C |link source tree| enter that folder and uses it's object files
M=`pwd` this argument says that files in here should be compiled to objects
then against Linux objects the modul
moudles : tell the make command that output will be a module not an ordinary object file
how to load it then ?
or better :
modprobe module.ko
it's better because it solves the references by this module and catches any undefined symbol in kernel . if any it checks for it's standard moudles directory and load any depends required by insmod them
how to unload it then ?
how list running modules ?
files ?
cd /sys/module -> directory contain directories about the running modules
Examples :
Use it in a kernel application if you want , using seq_file
introduction :
Hello all , as we all know linux is a BIG do it your self program
it allow you to do EVERY THING on your system
all what you have to do is to learn how to use it's capabilities
WE are going to deal with kernel by modules right now , but what is module ?
it's like a small kernel application (not user application) that can be loaded into kernel at run time whenever you need it by insmod , modeprobe
that is a good advantage actually , you don't need to compile kernel statically every time you need a module and that will cause you to reboot your system , imagine how could this be a west of time
but why that ([color="#0000FF"]kernel application[/color]) what is the difference between it and user application
[color="#FF0000"]user application:[/color][/i]
as we all know user application (ordinary programs) start execution from [color="#0000FF"]main()[/color] function
continue execution of this function until it satisfy it's job then exit
you can use standard libraries and user libraries
[color="#0000FF"]kernel applications[/color] : modules
piece of code that will be compiled against kernel objects producing a kernel module
that can be linked dynamically and removed dynamically at run time without a need to reboot
kernel modules doesn't start execution like ordinary programs from main()
However , it starts execution from function we call (initialization function) which you will code
module end when you request it to be removed but before kernel unload it . it will call a function we call (cleaning up function) and clean up all it's job.
calling this functions will depend on you because you will specify which function is the init and which function is the cleanup (later);
when a module is loaded kernel get the address of the init function and run it , then it hangs on the kernel until some application requires a symbol that this module exported ;
NOTE : if kernel is suspicious about module job (still hanging around with a file descriptor or what ever) it will not unload it until it finishes it's job .
unless you specified `MODULE_FORCE_UNLOAD` in your kernel configuration
modules doesn't hang in memory like ordinary applications might does . kernel handles it memory and kernel frees it's memory;
any fault at modules can cause a BIG something if you are not careful.....
SIGSEGV in ordinary app will cause a core dumb and exit

but in kernel it might be a disaster...
you can't use library function in modules (NO linking to libc or any other library)
modules are objects files . they only able to deal with internal kernel functions ("/proc/kallsyms")
which we can call SYSTEM CALLS .
system calls are defined in kernel which load the modules and resolve it's referencing
at insmod"ing time ;
in a kernel space you can do anything you want

you MUST have a kernel source tree to be able to compile your module
you will NOT be able to do anything without a kernel source
a kernel module runs on kernel 2.6 will definitely not able to run on 2.4
a compiled module runs on 2.6.X might not run in 2.6.D
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++
[color="#0000FF"]your First kernel module :[/color]
get a shell and pick and editor and start typing :
Code: [Select]
#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/stat.h>
static char *name = "Kernel Hacking first module\n";
module_param(name , charp , S_IRUGO | S_IWUSR);
static int __init module_start(void)
{
printk(KERN_INFO"Hello This IS a kernel module testing\n");
printk(KERN_INFO"Information : %s\n", name);
printk(KERN_INFO"Information Delevered\n");
return 0;
}
static void __exit module_end(void)
{
printk(KERN_INFO"\nEnd And\n\n");
printk(KERN_INFO"Every Thing Has a beginning has an end");
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("St0rM");
MODULE_DESCRIPTION("Something Nice we do in here");
module_init(module_start);
module_exit(module_end);
after saving It
Quote
make -C /lib/modules/`uname -r`/build M=`pwd`
let's start explaining what is this
Code: [Select]
#include <linux/init.h>
#include <linux/module.h>
essential headers to make module able to load
Quote
#include <linux/moduleparam.h> --> allow module to receive parameters while loadingparameters
#include <linux/stat.h> --> contain definition of permission flags like S_IRDWR by it you can specify which user can read/write/read&write on
+++++++++++++++++++++++
initialization :
+++++++++++++++++++++++
static int __init module_start(void);
this function will be passed to module_init why ? because module_init specify that this is the function should be called when module is loaded
which will point in module(object file) that this is the function should be called whenever this module is loaded
++++++++++++++++++++++
exiting: cleaning up
++++++++++++++++++++++
static void module_end(void);
will be passed to module_exit(); same as module_init() but it does the opposite it points to cleanup = exit function;
passing parameters :
Code: [Select]
module_param(name , charp , S_IRUGO | S_IWUSR);
this function allow you to pass parameters to the module at loading time by
insmod module.kp name="Bleh"
specify variablename=value
Quote
module_param(variable name . variable type , permissions);
charp = character pointer ;
you can't pass a float point variable;
types:
Quote
char
charp = character pointer
int
long
short
ushort = unsigned shor
ulong = unsigned long
also you can pass arrays
like
Quote
insmode module.ko array=x,v,d,g
each value separated by (,)
but you will have to change it like
Code: [Select]
int x[5];
module_param_array(x , int , 5 , permissions)
++++++++++++++
[color="#0000FF"]printk: your first kernel hacking[/color]
++++++++++++++
what the hell is printk ? where is f ? did the grinch stole it :@ what a bastard :@
no he didn't , I told you before that you can't use library function
printk is the kernel version of printf function which is a system call allow you to print format messages .it prints by priority by the way , and that is [color="#0000FF"]KERN_INFO[/color] is it's a priority every string is printed by this
Code: [Select]
MODULE_LICENSE("GPL");
MODULE_AUTHOR("St0rM");
MODULE_DESCRIPTION("Something Nice we do in here");
information about module as you can see

no what is that make command ?
as I told you before modules compiled against several objects files in the kernel source tree
as an example : magicversion.o this object file contain information about the module
date , version , which kernel it was compiled on , etc
make -C |link source tree| enter that folder and uses it's object files
M=`pwd` this argument says that files in here should be compiled to objects
then against Linux objects the modul
moudles : tell the make command that output will be a module not an ordinary object file
how to load it then ?
Quote
insmod module.ko |arguments if any|
or better :
modprobe module.ko
it's better because it solves the references by this module and catches any undefined symbol in kernel . if any it checks for it's standard moudles directory and load any depends required by insmod them
how to unload it then ?
Quote
rmmod module.ko
how list running modules ?
Quote
lsmod
files ?
Quote
/proc/modules
cd /sys/module -> directory contain directories about the running modules
Examples :
Code: [Select]
root@St0rM-Man:~/Desktop/linux.programming/kernel/pipe# insmod pipe_char.ko major=100 minor=0
root@St0rM-Man:~/Desktop/linux.programming/kernel/pipe# mknode /dev/pipe_char c 100 0
-bash: mknode: command not found
root@St0rM-Man:~/Desktop/linux.programming/kernel/pipe# mknod /dev/pipe_char c 100 0
root@St0rM-Man:~/Desktop/linux.programming/kernel/pipe# echo "It's only after we have lost every thing that we are free to do anything" > /dev/pipe_char
root@St0rM-Man:~/Desktop/linux.programming/kernel/pipe# cat /dev/pipe_char
It's only after we have lost every thing that we are free to do anything
Code: [Select]
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/moduleparam.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/stat.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <linux/completion.h>
static int major;
static int minor;
static dev_t device_node;
static char buffer[265];
module_param(major , int , S_IWUSR | S_IRUSR);
module_param(minor , int , S_IWUSR | S_IRUSR);
struct cdev device;
struct completion complete_task;
static int pipe_open(struct inode *node , struct file *filp)
{
/* No defice specification Will be Done */
return 0;
}
static int pipe_read(struct file *filp , char __user *buf , size_t size , loff_t *pos)
{
wait_for_completion(&complete_task);
if(copy_to_user(buf , buffer , strlen(buffer)) > 0)
return -1;
else
return strlen(buffer);
}
static int pipe_write(struct file *filp ,
const char __user *buf ,
size_t size ,
loff_t *pos)
{
int count = size;
if(count > 264)
count = 264;
if(copy_from_user(buffer , buf , count) > 0)
return -1;
complete(&complete_task);
return count;
}
static int pipe_release(struct inode *node , struct file *filp)
{
return 0;
}
struct file_operations fops =
{
.open = pipe_open ,
.read = pipe_read ,
.write = pipe_write ,
.release = pipe_release,
};
static int __init pipe_init(void)
{
int result;
if(major)
{
device_node = MKDEV(major , minor);
result = register_chrdev_region(device_node , 1 , "pipe");
}else
{
result = alloc_chrdev_region(&device_node , 1 , 1 , "pipe");
}
if(result == -1)
{
printk(KERN_INFO"Failed To Register Device Number\n\n");
return result;
}
printk(KERN_INFO
"Registred with major:minor %d:%d\n",
MAJOR(device_node) , MINOR(device_node));
cdev_init(&device , &fops);
device.owner = THIS_MODULE;
result = cdev_add(&device , device_node , 1);
if(result == -1)
{
printk(KERN_INFO"Failed To register Char device\n\n");
return result;
}
printk(KERN_INFO"Device Is live\n\n");
/* initialize Complete Structure */
init_completion(&complete_task);
return 0;
}
static void __exit pipe_exit(void)
{
unregister_chrdev_region(device_node , 1);
cdev_del(&device);
printk(KERN_INFO"Device Is Removed\n\n");
}
module_init(pipe_init);
module_exit(pipe_exit);
Use it in a kernel application if you want , using seq_file
Code: [Select]
#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <linux/errno.h>
/* itmes will be sequenced and sended to user interface using the lovely seq_file
* interface; items will be initialized ar initializing modules time
* any fauilr will result in whole module failur and unload immediatly
*/
/* items hold data */
static struct items
{
struct items *next;
char *buffer;
}*head , *cur;
/* open seqeunce proto type function */
static int open_seq(struct inode *inode , struct file *filp);
/*iterator prototypes */
static void *start_seq(struct seq_file *s , loff_t *pos);
static void *next_seq(struct seq_file *s , void *data , loff_t *pos);
static void stop_seq(struct seq_file *s , void *data );
static int show_seq(struct seq_file *s , void *data);
/* Mark eof */
static int eof = 0;
/* erasing list function */
static void erase(struct items *head);
/* Seq operations */
static struct seq_operations seq_ops = {
.start = start_seq,
.next = next_seq,
.stop = stop_seq,
.show = show_seq
};
/* File operations */
struct file_operations fops =
{
.owner = THIS_MODULE,
.open = open_seq ,
.read = seq_read,
.release = seq_release,
.llseek = seq_lseek
};
/* Module initializiation function definition */
static int __init proc_seq_init(void)
{
/* We need to allocate 5 items for items structure and fill buffers in them */
int i;
struct proc_dir_entry *proc_entry;
head = NULL;
cur = NULL;
for(i=0; i <= 5; i++)
{
if(head == NULL) /*first */
{
head = kmalloc(sizeof(struct items) , GFP_KERNEL);
head->buffer = kmalloc(50 *sizeof(char), GFP_KERNEL);
if( !head ||!head->buffer)
{
if(head)
{
erase(head);
printk(KERN_INFO"allocating memory error\n");
}
return -ENOMEM;
}
cur = head;
cur->next = NULL;
}else if(!cur->next) /* other */
{
cur->next = kmalloc(sizeof(struct items) , GFP_KERNEL);
cur = cur->next;
if(cur)
{
cur->buffer = kmalloc(50 *sizeof(char), GFP_KERNEL);
if(!cur->buffer)
{
erase(head); /* the only reason i did this cause
memory is not enough in this case
and i don't want somebody's system
to hang
*/
printk(KERN_INFO"allocating memory error\n");
return -ENOMEM;
}
cur->next = NULL;
}else
{
erase(head);
return -ENOMEM;
}
}
/* fill the buffer with information */
sprintf(cur->buffer , "Ok this is the %d time\n",i);
}
/* initializing items is done at this case we should now register our proc_file */
/*using low level creat_proc_enrty cause we don't want to have a read only proc
* we are not implementing ordinary proc file we are using seq_file proc technique */
proc_entry = create_proc_entry("linked_info" , S_IRUSR | S_IROTH , NULL /* parent */);
if(proc_entry)
proc_entry->proc_fops = &fops;
else
return -1;
printk(KERN_INFO"All seems to be fine\n\n");
return 0;
}
static void __exit proc_seq_clean(void)
{
/* erase list */
erase(head);
/* remove file */
remove_proc_entry("linked_info" , NULL);
}
module_init(proc_seq_init);
module_exit(proc_seq_clean);
/* open_seq definition */
static int open_seq(struct inode *inode , struct file *filp)
{
/* all we want to do is register sequnece operation with file */
eof = 0;
return seq_open(filp , &seq_ops);
}
/* iterator functions definitions */
static void *start_seq(struct seq_file *s , loff_t *pos)
{
/* actually it will do nothing accept updating position */
*pos += sizeof(struct items) +( 50 *sizeof(char));
if(head->next)
return head->next;
else
return NULL;
};
static void *next_seq(struct seq_file *s , void *data , loff_t *pos)
{
struct items *item;
/* update postion and move on sequence list */
item = (struct items*) data;
if(item->next)
{
return item->next;
}
else
return NULL;
}
static void stop_seq(struct seq_file *s , void *data )
{
;
}
static int show_seq(struct seq_file *s , void *data)
{
struct items *item;
int result;
item = (struct items *) data;
if(eof == 1)
{
return 0;
}
result = seq_printf( s , item->buffer );
if(item->next == NULL)
eof = 1;
return result;
}
/* erasing function definition */
static void erase(struct items *item)
{
struct items *temp;
if(!item)
return;
while(item)
{
temp=item->next;
kfree(item);
item = temp;
}
}
MODULE_LICENSE("Gpl");
MODULE_AUTHOR("Ahmed Mosatfa");
MODULE_DESCRIPTION("/proc file system module");
MODULE_VERSION("0.0.1");
No comments:
Post a Comment