7
votes

I have a simple kernel object that I built for probing around at kernel memory.

If I build it on my 64-bit Ubuntu (3.2) machine it works fine on that machine. But it won't insmod on my 64-bit Ubuntu (3.9) machine. And vice versa. It gives me a "-1 Invalid module format" error if I try to run it on a Kernel rev other than the one I'd built it on.

I thought insmod linked it dynamically against the exported symbol table and the exported symbol table does not change between kernel revisions. (It gets appended.)

Can someone tell me how I can build a kernel module (.ko) that is compatible with future (or past) Linux kernels without having to be rebuilt on that kernel?

Here's my make file:

ccflags-y = -g

obj-m += access_mem.o

all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

2
Your Ubuntu 3.2 is a 32-bits or 64-bits version ? Same question with your Ubuntu 3.9nouney
Both 64-bit. Thx for reminding me of this important data point.Joe C

2 Answers

7
votes

Joe, Ubuntu (3.2) maybe using kernel version x.y.z but Ubuntu (3.9) maybe using kernel version x.y.z1. If kernel versions differ you must need to build/compile your driver against that particular kernel version. If the kernel versions are same then no need to build your driver. Important point is that every driver module is been compiled or built linking with version.ko module (which actually embeds the information about the kernel version the driver module built against), while loading kernel module it checks for this information and kernel version, if different then throws "-1 Invalid module format" or if matched then kernel module is loaded successfully. To develop kernel module which is future or backward compatible you need to know on which kernel version which API's or functions signature have been changed for ex: ioctl signature changed from kernel version 2.3.36 onwards, so your code should be as below

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
static long minor_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
#else
static int minor_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,  
                                                               unsigned long arg)
#endif 

If developed in such a way then your kernel module is future or backward compatible. Compatibility is only adaptation of API's or function signature etc.. changes for the kernel version by preserving the older API's or function signature etc.. in your kernel module as in the above example, but still you need to build/compile your kernel module against the kernel version on which you are trying to load.

1
votes

I'm not an expert on the subject but I'm pretty sure that you must build your driver against each version of the kernel. As for the symbols staying the same between kernel versions, I'm quite certain that is not true after reading https://www.kernel.org/doc/Documentation/stable_api_nonsense.txt.