[HowTo] Build a (patched) kernel module

Difficulty: ★★★★☆

Sometimes the need arises to apply a patch to a kernel module for testing purposes or to fix a regression.
The below example uses kernel 5.10 as this was the procedure I followed for a non-working Bluetooth adapter on kernel 5.10 prior to 5.10.7-2.

Install needed packages for building and source control
pamac install base-devel git
Install matching kernel headers
pamac install linux510-headers
Clone matching repository for manjaro kernel
mkdir ~/MyKernel
#Where you obviously change '~/MyMernel' to whatever directory you wish the kernel sources to be cloned into  
cd ~/MyKernel
git clone https://gitlab.manjaro.org/packages/core/linux510.git
cd linux510/

Optionally one has to git checkout (or git reset --hard to) a former commit here as the development on the linux510 repository continues and might interfere with our testing (especially if you are on a slower moving branch like testing or stable):

 git reset commitHash --hard
 #Where onbviously 'commitHash' is the exact git commit you want to revert to.

This step is important, especially if you see error messages like this when loading the built kernel module:

modprobe: ERROR: could not insert 'btusb': Exec format error
Create new patch file with needed contents

In the below example we’re using 0900-btusb.patch as patch-extension to make life easier for us later on:

Bradley Jarvis
Avoid returning error code when bluetooth version match is not made from qca_devices_table and version high is set.
--- a/drivers/bluetooth/btusb.c	
+++ a/drivers/bluetooth/btusb.c	
@@ -4070,6 +4070,7 @@ static int btusb_setup_qca(struct hci_dev *hdev)
 	if (!info) {
 		bt_dev_err(hdev, "don't support firmware rome 0x%x", ver_rom);
+		if (ver_rom & ~0xffffU) return 0;
 		return -ENODEV;

Just for reference one might want to take a look at the arch wiki.

  1. add our 0900-btusb.patch to end of source array:

        # Temp Fixes
  2. add (sha256-)checksum or SKIP to the end of sha256sums array:

  3. Normally we would need to apply our patch in the prepare() function; but there already is a loop in place which applies all files named *.patch

    it looks like this:
    local src
    for src in "${source[@]}"; do
        [[ $src = *.patch ]] || continue
        msg2 "Applying patch: $src..."
        patch -Np1 < "../$src"
Download and extract source files
makepkg --nobuild
Prepare source directory for building our module
ln -s /usr/lib/modules/5.10.7-1-MANJARO/build/Module.symvers "$srcDir/"
zcat /proc/config.gz > "$srcDir/.config"
make -C "$srcDir" modules_prepare
Actually build the module

The following command builds all modules in that directory, including our patched btusb:

make --directory="$srcDir" M=drivers/bluetooth/
And there is the newly built module
ls -l "$srcDir/drivers/bluetooth/btusb.ko"

If it actually is to be used/loaded instead of the originally installed one, it needs to be copied to the right location:

mv /usr/lib/modules/5.10.7-1-MANJARO/kernel/drivers/bluetooth/btusb.ko.xz /usr/lib/modules/5.10.7-1-MANJARO/kernel/drivers/bluetooth/btusb.ko.xz.backup
sudo cp "$srcDir/drivers/bluetooth/btusb.ko" /usr/lib/modules/5.10.7-1-MANJARO/kernel/drivers/bluetooth/
sudo depmod -a

If all went well, it will get loaded after a reboot or we can just do it “live” after unloading the old one:

sudo modprobe -r btusb 
sudo modprobe btusb

Nice Guide,

Please change the below line to $(uname -r), as I have to change the command manually everytime I follow this guide.

That would imply/require that the kernel we want to build the module for is the running/booted kernel, which is not always the case.

I am following your guide EXACTLY but an error occours :
A failure occurred in prepare().
What should I do ?

I ran into the same brick as @anon79574093. An error that occurs running “makepkg --nobuild”

patching file MAINTAINERS
Hunk #1 succeeded at 3243 (offset 534 lines).
  -> Applying patch: 0511-bootsplash.patch...
patching file Documentation/ABI/testing/sysfs-platform-bootsplash
patching file Documentation/bootsplash.rst
patching file drivers/video/fbdev/core/bootsplash.c
  -> Applying patch: 0512-bootsplash.patch...
patching file MAINTAINERS
Hunk #1 succeeded at 3249 (offset 534 lines).
patching file tools/bootsplash/.gitignore
patching file tools/bootsplash/Makefile
patching file tools/bootsplash/bootsplash-packer.c
  -> Applying patch: 0900-btusb.patch...
patching file drivers/bluetooth/btusb.c
Hunk #1 FAILED at 433.
1 out of 1 hunk FAILED -- saving rejects to file drivers/bluetooth/btusb.c.rej
==> ERROR: A failure occurred in prepare().

The patch cannot be applied, probably because the checked out linux510 kernel and file to patch changed since the original tutorial.
This is not a tutorial to get some bluetooth adapter working, this is a tutorial on “how to build a patched kernel module” when there is a proper/matching patch.

Please open a new thread for your problem, post the contents of the rejects (drivers/bluetooth/btusb.c.rej).

What is this $srcDir you used in your tutorial ?
I am using your guide to build a patched kernel module for tplink UB500 bluetooth adapter, I run srcDir=src/linux-5.14 because I am running the 5.14 kernel, the command runs fine.
Then I do ln -s /usr/lib/modules/5.14.10-1-MANJARO/build/Module.symvers "$srcDir/" , it runs as well.
Then I do zcat /proc/config.gz > "$srcDir/.config" it shows error permission denied even when using sudo. I ran it under su and then it ran fine.
Now when I run make -C "$srcDir" modules_prepare it shows make: the '-C' option requires a non-empty string argument Usage: make [options] [target] ... . Please tell me what did I do wrong ? I am not knowlegeble enough to figure this out on my own. Also I did a detailed post of what I did and what went wrong while following your tutorial : patching kernel module to support tplink UB500. Please help me out here.

I figured it out, it was my foolishness that I was facing those problems. I now have the module in place but when I do modprobe btusb I get this error modprobe: ‘ERROR: could not insert ‘btusb’: Exec format error’

A post was split to a new topic: I built a kernel module but cannot load it: exec format error

Well after your reply I re-did EVERYTHING from scratch in your tutorial, I double checked to make sure I was building the module against the kernel 5.14 which is my currently running kernel. Here is a complete dump of what happend in the terminal. Please see if you find anything. The error modprobe: ERROR: could not insert 'btusb': Exec format error still shows up.

mkdir kernelbuild
cd kernelbuild
git clone https://gitlab.manjaro.org/packages/core/linux514.git
cd linux514
nano 0900-btusb.patch
sha256sum 0900-btusb.patch
makepkg --nobuild
ln -s /usr/lib/modules/5.14.10-1-MANJARO/build/Module.symvers "$srcDir/"
zcat /proc/config.gz > "$srcDir/.config"
make -C "$srcDir" modules_prepare
make --directory="$srcDir" M=drivers/bluetooth/
ls -l "$srcDir/drivers/bluetooth/btusb.ko"
sudo mv /usr/lib/modules/5.14.10-1-MANJARO/kernel/drivers/bluetooth/btusb.ko.xz /usr/lib/modules/5.14.10-1-MANJARO/kernel/drivers/bluetooth/btusb.ko.xz.backup
sudo cp "$srcDir/drivers/bluetooth/btusb.ko" /usr/lib/modules/5.14.10-1-MANJARO/kernel/drivers/bluetooth/
sudo depmod -a
sudo modprobe -r btusb 
sudo modprobe btusb

When building the modules I saw this, it’s skipping the BTF generation for drivers due to unavailability of vmlinux hope this helps :

  CC [M]  drivers/bluetooth/ath3k.mod.o
  LD [M]  drivers/bluetooth/ath3k.ko
  BTF [M] drivers/bluetooth/ath3k.ko
Skipping BTF generation for drivers/bluetooth/ath3k.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/bcm203x.mod.o
  LD [M]  drivers/bluetooth/bcm203x.ko
  BTF [M] drivers/bluetooth/bcm203x.ko
Skipping BTF generation for drivers/bluetooth/bcm203x.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/bfusb.mod.o
  LD [M]  drivers/bluetooth/bfusb.ko
  BTF [M] drivers/bluetooth/bfusb.ko
Skipping BTF generation for drivers/bluetooth/bfusb.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/bluecard_cs.mod.o
  LD [M]  drivers/bluetooth/bluecard_cs.ko
  BTF [M] drivers/bluetooth/bluecard_cs.ko
Skipping BTF generation for drivers/bluetooth/bluecard_cs.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/bpa10x.mod.o
  LD [M]  drivers/bluetooth/bpa10x.ko
  BTF [M] drivers/bluetooth/bpa10x.ko
Skipping BTF generation for drivers/bluetooth/bpa10x.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/bt3c_cs.mod.o
  LD [M]  drivers/bluetooth/bt3c_cs.ko
  BTF [M] drivers/bluetooth/bt3c_cs.ko
Skipping BTF generation for drivers/bluetooth/bt3c_cs.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btbcm.mod.o
  LD [M]  drivers/bluetooth/btbcm.ko
  BTF [M] drivers/bluetooth/btbcm.ko
Skipping BTF generation for drivers/bluetooth/btbcm.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btintel.mod.o
  LD [M]  drivers/bluetooth/btintel.ko
  BTF [M] drivers/bluetooth/btintel.ko
Skipping BTF generation for drivers/bluetooth/btintel.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btmrvl.mod.o
  LD [M]  drivers/bluetooth/btmrvl.ko
  BTF [M] drivers/bluetooth/btmrvl.ko
Skipping BTF generation for drivers/bluetooth/btmrvl.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btmrvl_sdio.mod.o
  LD [M]  drivers/bluetooth/btmrvl_sdio.ko
  BTF [M] drivers/bluetooth/btmrvl_sdio.ko
Skipping BTF generation for drivers/bluetooth/btmrvl_sdio.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btmtksdio.mod.o
  LD [M]  drivers/bluetooth/btmtksdio.ko
  BTF [M] drivers/bluetooth/btmtksdio.ko
Skipping BTF generation for drivers/bluetooth/btmtksdio.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btmtkuart.mod.o
  LD [M]  drivers/bluetooth/btmtkuart.ko
  BTF [M] drivers/bluetooth/btmtkuart.ko
Skipping BTF generation for drivers/bluetooth/btmtkuart.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btqca.mod.o
  LD [M]  drivers/bluetooth/btqca.ko
  BTF [M] drivers/bluetooth/btqca.ko
Skipping BTF generation for drivers/bluetooth/btqca.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btrsi.mod.o
  LD [M]  drivers/bluetooth/btrsi.ko
  BTF [M] drivers/bluetooth/btrsi.ko
Skipping BTF generation for drivers/bluetooth/btrsi.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btrtl.mod.o
  LD [M]  drivers/bluetooth/btrtl.ko
  BTF [M] drivers/bluetooth/btrtl.ko
Skipping BTF generation for drivers/bluetooth/btrtl.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btsdio.mod.o
  LD [M]  drivers/bluetooth/btsdio.ko
  BTF [M] drivers/bluetooth/btsdio.ko
Skipping BTF generation for drivers/bluetooth/btsdio.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/btusb.mod.o
  LD [M]  drivers/bluetooth/btusb.ko
  BTF [M] drivers/bluetooth/btusb.ko
Skipping BTF generation for drivers/bluetooth/btusb.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/dtl1_cs.mod.o
  LD [M]  drivers/bluetooth/dtl1_cs.ko
  BTF [M] drivers/bluetooth/dtl1_cs.ko
Skipping BTF generation for drivers/bluetooth/dtl1_cs.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/hci_nokia.mod.o
  LD [M]  drivers/bluetooth/hci_nokia.ko
  BTF [M] drivers/bluetooth/hci_nokia.ko
Skipping BTF generation for drivers/bluetooth/hci_nokia.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/hci_uart.mod.o
  LD [M]  drivers/bluetooth/hci_uart.ko
  BTF [M] drivers/bluetooth/hci_uart.ko
Skipping BTF generation for drivers/bluetooth/hci_uart.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/hci_vhci.mod.o
  LD [M]  drivers/bluetooth/hci_vhci.ko
  BTF [M] drivers/bluetooth/hci_vhci.ko
Skipping BTF generation for drivers/bluetooth/hci_vhci.ko due to unavailability of vmlinux
  CC [M]  drivers/bluetooth/virtio_bt.mod.o
  LD [M]  drivers/bluetooth/virtio_bt.ko
  BTF [M] drivers/bluetooth/virtio_bt.ko
Skipping BTF generation for drivers/bluetooth/virtio_bt.ko due to unavailability of vmlinux
make: Leaving directory '/home/sensei/kernelbuild/linux514/src/linux-5.14'

Hope this helps, thanks for your time

If it’s on purpose it is confusing.

Thanks, I corrected that typo.

that too.

Make sure, the linux514.git-checkout is at the same version as your running kernel: 5.14.10:

I’ve amended that section to mention the specific error you were seeing.

Yes, I have reverted to the desired commit and now it works ! Thanks for this tutorial :smile:

1 Like