I am looking into cross compiling a kernel module for an ARM linux. I have my toolchain installed.
But there's something I am not quite getting from various how-tos.
The module I want to build is gadgetfs.
The kernel version on my host is 3.5.0-34-generic while
on the target it's 3.6.9-0.1
Now what kernel sources or headers do I actually need to download and install, and where?
I downloaded linux-3.6.9.tar.bz2 from kernel.org and extracted it.
In drivers/usb/gadget/ there's a Makefile and according to this site I need to append these lines to it, then run make:
KDIR := /lib/modules/`uname -r`/build
PWD := `pwd`
obj-m := dummy_hcd.o gadgetfs.o
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
But what do i have to replace uname -r with? Cause this would give me my host's kernel version. But my target version is different. Where is the /lib/modules/3.6.9 folder?
CROSS_COMPILE and ARCH is both set.
You need to cross compile (or download pre-compiled) matching version of Linux for your target on your host machine with right configuration since Linux doesn't have a stable binary API. Host's kernel version is not relevant.
After having target build available on your host you can build a module via
make -C kernel_build_dir M=`pwd` ARCH=arm CROSS_COMPILE=<...> modules
under that module's directory.
Related
I need to perform MITM attack on a router, which is embedded linux system and its architecture is ARM. The linux kernel is 2.4.24. By MITM attack I mean intercept the packet, reedit it and send it forward. I want to use netfilter. But when I try to cross compile the LKM, I encountered plenty of problems.
As usual, a LKM Makefile is as below:
obj-m+=hello.o
KDIR = /lib/modules/$(shell uname -r)/build
all:
make -C $(KDIR) M=$(shell pwd) modules
clean:
make -C $(KDIR) M=$(shell pwd) clean
I downloaded linux kernel 2.4.24. But when it comes to the cross compile environment, the problems arise.
How to set KDIR path? The Path where linux_kernel_2.4.24.tar.gz is extracted? Do I need to cross-compile the kernel first? How?
Firstly, I set KDIR to the path of linux_kernel_2.4.24, then make, the error is "The present kernel configuration has modules disabled". By now I have not successfully make menuconfig this verion of kernel.
Secondly, I try to cross-compile on CentOS 5.4 32bit, whose kernel is 2.6.18. When I add CC=arm-linux-gcc to Makefile and set KDIR as /lib/modules/$(shell uname -r)/build, the result says "there is no arm...".
Can anyone specify how to compile LKM of the old version kernel on the latest linux? And how to cross-compile ARM version of LKM?
How to set KDIR path? The Path where linux_kernel_2.4.24.tar.gz is extracted?
Yes, just as you normally would for any other kind of module, KDIR needs to point to the built kernel source root.
Do I need to cross-compile the kernel first? How?
Yes you do. You do this by:
Downloading/compiling/installing the correct cross-compilation toolchain. For example, on Debian to get an ARM cross-compilation toolchain I can do sudo apt install binutils-arm-linux-gnueabi, which will install all the binaries you normally have in binutils with the prefix arm-linux-gnueabi- (e.g. arm-linux-gnueabi-gcc, arm-linux-gnueabi-objdump, etc...). You need all of the binutils, not only gcc.
Setting ARCH= to your desired target architecture, for example ARCH=arm.
Setting CROSS_COMPILE= to your cross-compilation toolchain prefix, for example CROSS_COMPILE=arm-linux-. This also works if you want to use a downloaded toolchain as you can specify CROSS_COMPILE=/path/to/toolchain/ assuming this directory contains all the needed executables.
Getting a valid config for the target system. If you have a .config on the system you can use that one (simply copy it from the target system into KDIR/.config) and then update it with make menuconfig.
Building with make all or whatever other target you need.
I have a Makefile made by following this example:
cross compile kernel module
I built a 4.14 Linux kernel from an older Xilinx source, and then built a out-of-kernel module with that script, pointing it to the said 4.14 kernel sources, and filling in the blanks for my particular platform architecture.
That worked.
(It's based on this code, if that matters: dma-proxy.c)
Now I need a newer version, and got Xilinx sources with a kernel named 5.6.0-rc1.
(--branch "zynqmp-soc-for-v5.7" from here)
Building that kernel also worked fine.
If I now use a scrubbed clean directory (incl. hidden files) with my module source code and that Makefile again, pointing to the newer kernel sources, it does neither produce a .ko file nor an error message.
All I get is:
make ARCH=arm64 CROSS_COMPILE="aarch64-linux-gnu-" -C /home/sk/src/XILINX/linux-xlnx SUBDIRS=/home/sk/src/XILINX/dma-proxy/driver modules
make[1]: Entering directory '/home/sk/src/XILINX/linux-xlnx'
CALL scripts/checksyscalls.sh
CALL scripts/atomic/check-atomics.sh
MODPOST 28 modules
make[1]: Leaving directory '/home/sk/src/XILINX/linux-xlnx'
No .ko file in my folder as it was before when building with 4.14, and it doesn't list actually compiling anything.
I find it curious that it says "MODPOST 28 modules", whereas with pointing it to kernel 4.14, it expectedly says "1 modules"
Has anything changed between 4.14 and 5.x that would cause this?
Mkay, here is the suggested makefile template by the tutorial I referenced in the question:
PWD := $(shell pwd)
obj-m += hello.o
all:
make ARCH=arm CROSS_COMPILE=$(CROSS) -C $(KERNEL) SUBDIRS=$(PWD) modules
clean:
make -C $(KERNEL) SUBDIRS=$(PWD) clean
Turns out that if I replace SUBDIRS=$(PWD) with M=$(PWD), it works. Now if I google explicitly for that M variable in conjunction with building kernel modules, I do find text that show it that way. But the net is also littered with examples using SUBDIRS, and it worked for me with a fairly recent kernel (4.14).
Then I did find references hinting at this being an old way of doing it, like from here:
make -C $KDIR SUBDIRS=$PWD
Same as M=. The SUBDIRS= syntax is kept for backwards compatibility.
In fact, this seems to be really old, like, kernel 2.6.7 old. Unfortunately, fairly recent tutorials show the old way.
I am trying to compile a hello world module given over here
I have followed the following step.
Downloaded Linux kernel 2.6.35-rc5
extracted to directory /general/source/linux
Complied the entire kernel.
created a dir test in the linux folder.
Created and complied a hello world module as mentioned there.
when I run the insmod command, I get this error
insmod: error inserting 'hello.ko': -1 Invalid module format
How do I sort out this error?
Regards,
Ok the mistake that you are making is the kernel version.
First try
uname -r
You would get the kernel version. The downloaded version mostly likely won't be the kernel version of your system.
So change the make file to
ifeq ($(KERNELRELEASE),)
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
.PHONY: build clean
build:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c
else
$(info Building with KERNELRELEASE = ${KERNELRELEASE})
obj-m := hello.o
endif
Make sure the tabs are in the order as mentioned in the above script.
Your kernel module must match the running kernel. If you want to install this specific module, for example, you'd need to also install the kernel that you've built.
Normally, you'd not build the kernel on your own and use a pre-built version that matches your distribution's kernel. Look for a kernel-headers package in your distribution's repository.
I am trying to run 'make' on a module in User Mode Linux to install a simple makefile. Here is my make file:
obj-m := hello.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
When I run this in User Mode Linux I get the following error:
make[1]: Entering directory `/lib/modules/2.6.28/build'
make[1]: *** No rule to make target `modules'. Stop.
make[1]: Leaving directory `/lib/modules/2.6.28/build'
make: *** [default] Error 2
The problem is that no files are present under /lib/modules/. There's no directory for 2.6.28 or build. From what I've read, these should be symlinks to /usr/src, but under /usr/src, I don't see any files under that either.
Sources and headers of your UML kernel must be used to compile module for it.
You can compile it either inside UML or just in main system, but you must to use UML's kernel's headers and build scripts
You need to build and install the version of the kernel you are compiling for. Get the source from kernel.org, configure (I think make menuconfig picks the config up from the running kernel), build, and install it. You can do the build in your home directory under regular user, then of course you would need root to install it.
Edit:
Just in case you missed this - here's User Mode Linux HOWTO. It contains specific items for building and installing kernel and modules. Hope this helps.
I made certain modifications in hid module.
I can make it and load (insmod) it on kernel v 2.6.27.14 sucessfully
Now I am willing to load the same kernel module on kernel v 2.6.27.11
As there is no differance in the kerbel source files for both the kernel versions
I can make it sucessfully, but I cannot add / insmod in this .11 kernel version
**
ERROR: Module myhid does not exist in /proc/modules
insmod: error inserting 'myhid.ko': -1 Invalid module format
**
Regards,
You can't load a module compiled for another kernel version. That the source code of the module did not change does not mean that the binary will be the same for another kernel version. Any interface change of kernel internal APIs (even when not directly visible) will break the module...
Therefore, the kernel stays on the safe side by disallowing loading of modules that were built for another kernel version. Alternatively, you can set the MODVERSIONS configuration option when building your kernel. This will embed version information into all symbols used by your module and with luck you can load it on another kernel version.
If any interface used by your module changed, the result will be the same though.
see what "modinfo" tells you about your module:
Check that it's compiled properly, linked to the right kernel.
$ modinfo hid
filename: /lib/modules/2.6.27.7/kernel/drivers/hid/hid.ko
license: GPL
depends:
vermagic: 2.6.27.7 mod_unload 486
parm: pb_fnmode:Mode of fn key on Apple keyboards (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst) (int)
When you compile/install modules, don't forget that you have to run "depmod" (as root) to rebuild the modules dependancies before running insmod/modprobe.
Thanks ! Here is the make file . I dowload all the dependent source files for HID.O and rename them
MAKEFILE
obj-m := myhid.o
myhid-objs := my-hiddraw.o my-hid-core.o my-hid-input.o my-hid-input-quirk.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) M=$(PWD) modules