building "out of the source tree" kernel module - linux

I'm building a sample kernel module under linux . The module sources are "out of the kernel tree". I've got kernel source tree from git. But it takes time to configure the kernel. So at this moment i'm just trying to build the module against kernel headers provided by my Distribution.
My Makefile :
KVERSION=$(shell uname -r)
PWD := $(shell pwd)
all:
make -C /lib/modules/$(KVERSION)/build/ M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
$(info Building with KERNELRELEASE = ${KERNELRELEASE})
obj-m := hello.o
But make stops with reporting that i could not find etc, that means it could not find the headers.
but the files are there :
$ls /lib/modules/$(uname -r)/build
$arch block crypto drivers firmware fs include init ipc kernel lib Makefile Makefile.common mm Module.symvers net samples scripts security sound System.map tools usr virt
I guess its a trivial problem. But still i could not find the solution.
Thanks in advance.
EDIT: Errors :
Building with KERNELRELEASE =
make -C /lib/modules/2.6.32-220.el6.x86_64/build/ M=/usr/local/src/kernel_mods
make[1]: Entering directory `/usr/src/kernels/2.6.32-220.el6.x86_64'
Building with KERNELRELEASE = 2.6.32-220.el6.x86_64
LD /usr/local/src/kernel_mods/built-in.o
CC [M] /usr/local/src/kernel_mods/hello.o
/usr/local/src/kernel_mods/hello.c:2:27: error: linux/modules.h: No such file or directory
/usr/local/src/kernel_mods/hello.c:21: error: expected declaration specifiers or â...â before string constant
/usr/local/src/kernel_mods/hello.c:21: warning: data definition has no type or storage class
/usr/local/src/kernel_mods/hello.c:21: warning: type defaults to âintâ in declaration of âMODULE_LICENSEâ
/usr/local/src/kernel_mods/hello.c:21: warning: function declaration isnât a prototype
/usr/local/src/kernel_mods/hello.c:22: error: expected declaration specifiers or â...â before string constant
/usr/local/src/kernel_mods/hello.c:22: warning: data definition has no type or storage class
/usr/local/src/kernel_mods/hello.c:22: warning: type defaults to âintâ in declaration of âMODULE_AUTHORâ
/usr/local/src/kernel_mods/hello.c:22: warning: function declaration isnât a prototype
/usr/local/src/kernel_mods/hello.c:23: error: expected declaration specifiers or â...â before string constant
/usr/local/src/kernel_mods/hello.c:23: warning: data definition has no type or storage class
/usr/local/src/kernel_mods/hello.c:23: warning: type defaults to âintâ in declaration of âMODULE_DESCRIPTIONâ
/usr/local/src/kernel_mods/hello.c:23: warning: function declaration isnât a prototype
make[2]: *** [/usr/local/src/kernel_mods/hello.o] Error 1
make[1]: *** [_module_/usr/local/src/kernel_mods] Error 2
make[1]: Leaving directory `/usr/src/kernels/2.6.32-220.el6.x86_64'
make: *** [all] Error 2

I think you meant to do
#include <linux/module.h>
rather than
#include <linux/modules.h>

Related

Trying to compile hello world linux kernel module: missing MODULE_LICENSE()

I'm trying to compile the simplest kernel module possible, from the The Linux Kernel Module Programming Guide. hello.c:
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.\n");
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}
Makefile:
obj-m = hello.o
KVERSION = $(shell uname -r)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
Output of make:
make -C /lib/modules/5.14.0/build M=/home/parallels/dev/demo modules
make[1]: Entering directory '/home/parallels/linux-5.14'
CC [M] /home/parallels/dev/demo/hello.o
MODPOST /home/parallels/dev/demo/Module.symvers
ERROR: modpost: missing MODULE_LICENSE() in /home/parallels/dev/demo/hello.o
make[2]: *** [scripts/Makefile.modpost:150: /home/parallels/dev/demo/Module.symvers] Error 1
make[2]: *** Deleting file '/home/parallels/dev/demo/Module.symvers'
make[1]: *** [Makefile:1766: modules] Error 2
make[1]: Leaving directory '/home/parallels/linux-5.14'
make: *** [Makefile:4: all] Error 2
This is all after I have compiled the linux kernel from source and run make modules_install. I don't really understand that second line of output: make[1]: Entering directory '/home/parallels/linux-5.14', that is the directory in which I downloaded and compiled the linux kernel, I don't see what it has to do with this module I'm trying to compile.
I have seen others ask about this missing MODULE_LICENSE() error, but they are usually asking about much more complicated modules and the answers don't seem relevant to this very simple module. A few of the answers had to do with changing the name of either the source code file or the .o file, but trying either way simply produced errors about no rule to make target with the changed name.
Also, this is all on a vm of Kali linux running linux kernel 5.14.0 which I compiled from source.
You need to add call to MODULE_LICENSE to your source file (hello.c in your case). This is what the error message is talking about. E.g.
MODULE_LICENSE("GPL");
Most modules also call MODULE_AUTHOR:
MODULE_AUTHOR("your-name");

Cross-compiling linux module missing include file

I am having some issues cross-compiling a module for the Raspberry Pi 4.
The compiler used is: aarch64-linux-gnu-.
The kernel used is: linux-5.10.42
And the error during compilation is as follows:
make -C /opt/linux-5.10.42 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- M=/home/x/build/linux-driver-gpio-customled modules
make[1]: Entering directory '/opt/linux-5.10.42'
CC [M] /home/x/build/linux-driver-gpio-customled/customled.o
In file included from ./include/linux/types.h:6,
from ./include/linux/list.h:5,
from ./include/linux/module.h:12,
from /home/x/build/linux-driver-gpio-customled/customled.c:1:
./include/uapi/linux/types.h:5:10: fatal error: asm/types.h: No such file or directory
5 | #include <asm/types.h>
| ^~~~~~~~~~~~~
compilation terminated.
make[2]: *** [scripts/Makefile.build:279: /home/x/build/linux-driver-gpio-customled/customled.o] Error 1
make[1]: *** [Makefile:1821: /home/x/build/linux-driver-gpio-customled] Error 2
make[1]: Leaving directory '/opt/linux-5.10.42'
make: *** [Makefile:5: default] Error 2
So my question is as follows: Where should this file asm/types.h come from? To my knowledge it should be included in the kernel arch/arm64/include/asm/ subdirectory. But it's not. Other architectures, namely x86 have it.
Is there another way to build a module without including linux/module.h that i'm not aware of?
Any help is greatly appreciated.
Got it!
The files are autogenerated, there is a handy make command used to prepare the build environment for out-of-tree kernel modules. What I did was run
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- modules_prepare
inside the kernel source.
Hope this helps someone with not spending time on such a simple mistake.

How do I link a static library when building a kernel module?

I want to build a Linux kernel module foo.ko from an existing file foo.c and a static library support.a. The library support.a is compiled from Rust so there is no support.c.
I've used the following Makefile
KERNEL_DIR := /lib/modules/$(shell uname -r)/build
obj-m += foo.o
foo-obs += support.a
all:
$(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules V=1
It seems that support.a is not linked; there are warnings that the functions called from foo.c (and implemented in support.a) are undefined.
Update 0: the Makefile works on Ubuntu LTS (I've tested on 18.04 and 14.04) but not on Fedora (both 29/30). The output in case of Fedora is:
...
make -C /lib/modules/5.1.11-200.fc29.x86_64/build SUBDIRS=/public/Github/rustyvisor modules
make[1] : on entre dans le répertoire « /usr/src/kernels/5.1.11-200.fc29.x86_64 »
Makefile:205: ================= WARNING ================
Makefile:206: 'SUBDIRS' will be removed after Linux 5.3
Makefile:207: Please use 'M=' or 'KBUILD_EXTMOD' instead
Makefile:208: ==========================================
LD [M] /public/Github/rustyvisor/rustyvisor.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: /public/Github/rustyvisor/rustyvisor.o(.init.text+0xbb): Section mismatch in reference from the function init_module() to the function .exit.text:rustyvisor_exit()
The function __init init_module() references
a function __exit rustyvisor_exit().
This is often seen when error handling in the init function
uses functionality in the exit path.
The fix is often to remove the __exit annotation of
rustyvisor_exit() so it may be used outside an exit section.
WARNING: "rustyvisor_core_unload" [/public/Github/rustyvisor/rustyvisor.ko] undefined!
WARNING: "rustyvisor_load" [/public/Github/rustyvisor/rustyvisor.ko] undefined!
WARNING: "rustyvisor_core_load" [/public/Github/rustyvisor/rustyvisor.ko] undefined!
WARNING: "rustyvisor_unload" [/public/Github/rustyvisor/rustyvisor.ko] undefined!
LD [M] /public/Github/rustyvisor/rustyvisor.ko
make[1] : on quitte le répertoire « /usr/src/kernels/5.1.11-200.fc29.x86_64 »
Update 1: There is very similar question but this question is to ask why the Makefile doesn't work on Fedora but I discovered that it works on Ubuntu.
Finally, I found a workaround for the problem (but I still don't understand why). On Fedora, the library name support.a should be changed to support.o, then the linker works!!!

make refuses to build kernel module

I have to write a simple linux kernel module for a study research project, but I am having trouble with make. This is what my Makefile looks like right now:
obj-m := main.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
The source file I want to compile is named main.c, and when I type make in the source code directory I get this output:
root#debian:~/test-module# make
make -C /lib/modules/4.9.0-4-amd64/build M=/root/test-module modules
make[1]: Entering directory '/lib/modules/4.9.0-4-amd64/build'
make[1]: *** No rule to make target 'modules'. Stop.
make[1]: Leaving directory '/lib/modules/4.9.0-4-amd64/build'
Makefile:6: recipe for target 'all' failed
make: *** [all] Error 2
As the output already suggests, I am running Debian 9 with kernel 4.9.0-4-amd64. Since I am pretty new to Makefiles, I can't find any errors in the file. Could somebody please explain to me where my error is?
UPDATE: After some research I found out that /lib/modules/4.9.0-4-amd64/build must contain the kernel source tree. So i did
ln -s /usr/src/linux-source-4.9 /lib/modules/4.9.0-4-amd64/build
where the link's target directory contains the complete linux kernel source tree. When I run make now, I get this output:
root#debian:~/test-module# make
make -C /lib/modules/4.9.0-4-amd64/build modules
make[1]: Entering directory '/usr/src/linux-source-4.9'
scripts/kconfig/conf --silentoldconfig Kconfig
***
*** Configuration file ".config" not found!
***
*** Please run some configurator (e.g. "make oldconfig" or
*** "make menuconfig" or "make xconfig").
***
scripts/kconfig/Makefile:37: recipe for target 'silentoldconfig' failed
make[3]: *** [silentoldconfig] Error 1
Makefile:548: recipe for target 'silentoldconfig' failed
make[2]: *** [silentoldconfig] Error 2
The present kernel configuration has modules disabled.
Type 'make config' and enable loadable module support.
Then build a kernel with module support enabled.
Makefile:1271: recipe for target 'modules' failed
make[1]: *** [modules] Error 1
make[1]: Leaving directory '/usr/src/linux-source-4.9'
Makefile:4: recipe for target 'all' failed
make: *** [all] Error 2
Looks better than last time, but still doesn't work. I guess I just have to run a make config or so in some directory of the kernel source tree, but I don't know where. What should I do?
I finally found out the error: I forgot to specify the M variable in my makefile. It works properly now. This is what my makefile looks like right now, if future users want to know:
obj-m := testmodule.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
Thank you all for your help anyways!

How to compile a kernel module against a new Source

I am trying to compile a Hello World module. I am having a fresh Ubuntu in my system which doesn't have any compiled kernel.
My kernel is:
2.6.32-34-generic
I gave the following Makefile and got the error:
obj-m += hello-1.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
# make
make -C /lib/modules/2.6.32-34-generic/build M=/home/james/Desktop/hello modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.32-34-generic'
make[2]: *** No rule to make target `/home/james/Desktop/hello/hello-1.c', needed by `/home/james/Desktop/hello/hello-1.o'. Stop.
make[1]: *** [_module_/home/james/Desktop/hello] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-34-generic'
make: *** [all] Error 2
The contents of my /lib/modules/2.6.32-34-generic are
total 3864
lrwxrwxrwx 1 root root 40 2011-11-05 15:55 build -> /usr/src/linux-headers-2.6.32-34-generic
drwxr-xr-x 2 root root 4096 2011-11-05 15:49 initrd
drwxr-xr-x 10 root root 4096 2011-11-05 15:49 kernel
.......................................................
.......................................................
The folder /usr/src/linux-headers-2.6.32-34-generic exists.
Since it didnt work, I downloaded the linux-headers-2.6.32-34-generic source from Ubuntu and compiled and changed my Makefile to:
obj-m += hello-1.o
all:
make -C /usr/src/linux-2.6.32/ M=$(PWD) modules
clean:
make -C /usr/src/linux-2.6.32/ M=$(PWD) clean
#make
make -C /usr/src/linux-2.6.32/ M=/home/james/Desktop/hello modules
make[1]: Entering directory `/usr/src/linux-2.6.32'
ERROR: Kernel configuration is invalid.
include/linux/autoconf.h or include/config/auto.conf are missing.
Run 'make oldconfig && make prepare' on kernel src to fix it.
WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers
is missing; modules will have no dependencies and modversions.
make[2]: *** No rule to make target `/home/james/Desktop/hello/hello-1.c', needed by `/home/james/Desktop/hello/hello-1.o'. Stop.
make[1]: *** [_module_/home/james/Desktop/hello] Error 2
make[1]: Leaving directory `/usr/src/linux-2.6.32'
make: *** [all] Error 2
Could someone help me solving this.http://packages.ubuntu.com/lucid-updates/devel/linux-headers-2.6.32-34-generic
I have some general questions to ask.
After a fresh install what is the best way of compiling a kernel. After I compiled the kernel and built a module it worked flawlessly earlier. But I couldnt know what to do this in this situation
The error:
ERROR: Kernel configuration is invalid.
include/linux/autoconf.h or include/config/auto.conf are missing.
Run 'make oldconfig && make prepare' on kernel src to fix it.
WARNING: Symbol version dump /usr/src/linux-2.6.32/Module.symvers
is missing; modules will have no dependencies and modversions.
simply is because your kernel source is newly downloaded and uncompiled before.
This is how u should compile any kernel module.
After download the kernel source, you must prepare it for adding any modules to it.
Copy the older-kernel's "config-xxxx" file from the /boot/ directory into the new kernel source directory, and rename it as ".config".
Then execute "make oldconfig", which will take a backup of the .config into .config.old, and regenerate a new .config based on the new kernel source. Just enter "ENTER" for all the default settings (lots of them).
Next is to do a "make" (and wait for some time) - it will generate a new kernel file "vmlinux", together with many other files which is read by the modules compilation process.
Now you can go to your directory where the kernel module source code is located, and based on the following Makefile:
obj-m += hello-1.o
default: modules
modules:
make -C /kernel_source/ M=$(PWD) modules
clean:
make -C /kernel_source/ M=$(PWD) clean
Together with Makefile are your header and source file, which is hello-1.c located together.
Just "make" and your kernel modules should be generated successfully.
You need to install some package like 'kernel-devel' on Fedora (sorry I am not a Ubuntu user), it provides the headers and .config to compile your kernel module.
make[2]: * No rule to make target
/home/james/Desktop/hello/hello-1.c', needed by/home/james/Desktop/hello/hello-1.o'. Stop
Your are facing this error in the first compilation because hello-1.c file is missing in /home/james/Desktop/hello/ directory.
Check if hello-1.c exists in /home/james/Desktop/hello/ directory.
You need to have modules_enabled in your kernel. You need to compile a fresh kernel to do this.
Following post explains how to build kernel nicely. Enable modules in configuration of kernel build.
http://kernelnewbies.org/FAQ/KernelCompilation

Resources