How to cross-compile external kernel modules whe the kernel build is out-of-tree? - kernel-module

On an x86_64 host I have cross-compiled a Linux kernel for an ARM target out-of tree. So I have two directories:
~/kernel_git_repo/ - contains kernel source only
~/kernel_buld_dir/ - contains the .config file and built kernel objects
In a third directory
~/external_module - sources for an external kernel module
I have the source code for an external module, with a Makefile.
The "usual" command for an in-tree built kernel would be:
make -C <path-to-compiled-src-code> M=$(PWD) modules
For my out-of-tree built kernel, neither ~/kernel_git_repo/ nor ~/kernel_buld_dir/ work as <path-to-compiled-src-code>. It appears that the make command needs both the kernel source repo with the Kbuild infrastructure and the build directory with the .config file and the objects.
In this situation, what is the make command to use in the ~/external_module/Makefile for building the module?

You're right, it's essentially the same,
$(MAKE) -C $(KDIR) SUBDIRS=$(shell pwd) modules
except
KDIR=/path/to/kernel/source

Related

How to solve :module verification failed: signature and/or required key missing - tainting kernel [duplicate]

I'm using Ubuntu 14.04 LTS and kernel version 3.13.11.4. I'm trying to load patched KVM modules kvm and kvm-intel and I'm getting the following errors
kvm: module verification failed: signature and/or required key missing - tainting kernel
and kvm: module has bad taint, not creating trace events.
The source used is the same source that created the image that I am currently running. I've check the symbols and made sure to the error isn't cause by not including EXPORT_SYMBOL_GPL() in the patched files where I exported functions.
I've also seen some stuff about different kernel versions causing this error but I built the kernel that I'm booted in with the same source that I used to create the patched kvm modules. Everything compile without an warning. Any help is appreciated!
Instead of re-configuring the kernel, this error (module verification failed) could be resolved by just adding one line CONFIG_MODULE_SIG=n to the top of the Makefile for the module itself:
CONFIG_MODULE_SIG=n
# If KERNELRELEASE is defined, we've been invoked from the
# kernel build system and can use its language.
ifneq ($(KERNELRELEASE),)
obj-m := hello.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
Go to the kernel source directory and do (for e.g):
./scripts/sign-file sha512 ./signing_key.priv ./signing_key.x509 /lib/modules/3.10.1/kernel/drivers/char/my_module.ko
for kernel 4.4.*, keys location should be as follows:
./scripts/sign-file sha512 ./certs/signing_key.pem ./certs/signing_key.x509 path/to/your/kernel/module.ko
Check what is the digest algorithm your kernel is using by opening .config and reading it in CONFIG_MODULE_SIG config values.
CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_ALL=y CONFIG_MODULE_SIG_SHA512=y CONFIG_MODULE_SIG_HASH="sha512"
It seems like the vendor of your system has enabled kernel module signature verification on your kernel which means it won't load any module that the vendor hasn't signed. In other words, your patched module isn't signed (properly) and the kernel will refuse to load it.
The point of this is supposed to prevent malware and rootkits from loading malicious kernel modules.
I suggest you contact your vendor. There may be an option somewhere on your platform to disable signature checking. Otherwise, your vendor may be able to sign the module for you. You might even have the key and the details of the signature verification algorithm and can sign it yourself.
Without knowing what platform you're running on, it's hard to give more specific suggestions.
In general, if you are building a custom kernel and using make oldconfig. This copies the exiting config-* file from /boot. Now a days most of the kernel modules required to be signed by the linux vendor. So edit the .config and disable CONFIG_MODULE_SIG_ALL and CONFIG_MODULE_SIG, before compiling the kernel.
CONFIG_MODULE_SIG=n
CONFIG_MODULE_SIG_ALL=n
# CONFIG_MODULE_SIG_FORCE is not set
# CONFIG_MODULE_SIG_SHA1 is not set
# CONFIG_MODULE_SIG_SHA224 is not set
# CONFIG_MODULE_SIG_SHA256 is not set
# CONFIG_MODULE_SIG_SHA384 is not set

Build a .ko file using a .o file

I know that we can make a .ko file using a source .c file with a subsequent makefile given below. Now, I want to create a same kind of .ko file without exposing the source. So I planned to do it using the .o object file. But I'm not hitting the right path, How do I modify the Makefile according to this requirement?
obj-m += somesource.o
all:
make -C $(KERNEL_SRC) M=$(PWD) modules
clean:
make -C $(KERNEL_SRC) M=$(PWD) clean
As far as I know, one cannot build kernel module from object files created on other machine. The only exception is shipped files, which may contain code, but cannot provide any symbol (variables or functions).
I guess this is a protection against using functions and/or types, defined in one kernel, in different kernel with incompatible function signature or type layout.
If you don't want to expose the source, build complete kernel module on your machine and distribute it.

How to build an out-of-tree linux module with an additional include path (includes external header files, librairies like yaml, boost...)

I am trying to build an out-of-tree linux kernel that should take into account external headers files comming from pre- compiled and installed custom libraries. My linux module will use functions from a shared library via a C-interface.
How is it possible to prevent kernel Makefile of the existence of such files?
obj-m+= hello_module.o
$(MAKE) -C $(KDIR) M=$(OUTDIR) modules
#additional include path
INCLUDES :=\
-I $(PROJECT_ROOT)/deps1
-I $(PROJECT_ROOT)/deps2
-I $(PROJECT_ROOT)/deps3
So how can I include this in $(MAKE) line above?
Thanks in advance,
Rgds
sahbi
You cannot link user space libraries into modules.
But you can link multiple files with the following Makefile:
obj-m := combinedmodule.o
combinedmodule-objs := part1.o part2.o
all:
make -C $(KERNEL_SRC) M=$(PWD) modules

What is the role of kernel's top level Makefile while compiling a new module?

For creating a new kernel module we need to use kernel's top level Makefile as:
make -C /lib/modules/$(shell uname -r)/build M=`pwd`
-C specifies the path of the top level Makefile.
My question is what is the need of this Makefile while creating a new module? When my makefile should be sufficient for this...
While kernel module is compiled using the same compiler (gcc) as user-space programs, it is required to pass many special parameters to the compiler for create a module. Moreover, some of these parameters depends on the kernel, against which you build the module.
Yes, you may create the Makefile, which passes proper parameters to the compiler and creates a module.
However, it is much simpler to use existing kernel's Makefile which cares about these parameters. In that case, your makefile needs to provide only source files you wish to compile into the module.
Also, building the kernel module is not just a compiling it. Asides from invoking the compiler, some additional actions should be taken for prepare the module.
E.g., one need to prepropcess Modules.symvers file for extract information of kernel core functions which are used in the module. Without that step the module created cannot be inserted into the kernel.

Disagrees about version of symbol symbol_name after insmod

I am new in kernel programming.
For implementing my project work, I have downloaded the latest stable kernel (v4.3) from kernel.org.
Just for checking I have copied a few files from the kernel directories into my project directory. Made changes to it and inserted a few more code to it.
Then I compiled on SLES11 Linux kernel using
make -C /lib/modules/$(uname -r)/build M=$PWD modules
I have used the below makefile
obj-m := my_module.o
my_module-objs := module_main.0 other_module1.o other_module2.o other_module3.o
It compiled successfully.
But when I tried to insert into the kernel using
insmod my_sample.ko
It showed the following
disagrees about version of symbol symbol_name
You need to build your kernel module against the same version kernel you are going to run. Thus if you have kernel 4.3 sources that you have downloaded you need to compile that version of the kernel and boot with that running before trying to load your kernel.
You have two solutions then:
Download the kernel sources for the kernel you are currently running (you can install those with zypper install kernel-source on SLES or an equivalent command on other distributions.)
Compile and install the 4.3 kernel in to your operating system. If you need help with this then ask a separate question (and it probably belongs on superuser not here). Note that if kernel and glibc are tightly coupled, and it is possible that you can't run a new kernel if you have a very old C library.
The problem here is that your Kernel module is using the exported symbols of other kernel modules which in this case appears to be the linux InfiniBand RDMA stack's exported methods or symbols.
To solve the symbol version problems, copy the Module.symvers file from the
/usr/src/ofa-kernel
directory and paste it to your current working directory. Then you make your modules again. Now the insmod should work perfectly fine.
NOTE: The Module.symvers file contains information of all the kernel
module exported symbol. So by copying it to your working directory,
you are helping kbuild to know more about the used exported symbols.
And if you don't find Module.symvers or it is empty, then create one using create_Module.symvers.sh
make -C /lib/modules/$(uname -r)/build M=$PWD modules,
"$(uname -r)" shows that you are compiling against the kernel version you are running now so you should be able to insmod the module in the current kernel if you haven't changed the headers.
From your text,
"Just for checking I have copied a few files from the kernel directories into my project directory. Made changes to it and inserted a few more code to it."
If you have made modifications to the kernel source then you may need to recompile the new kernel and boot with the new updated kernel. Then you should be able to compile your kernel module with the modified headers.
Looks like you built agAinst right kernel.something to do with how your kernel is compiled. (See Config_conversions). Try --force

Resources