OpenWrt: Adding Patches to a Kernel Module
This document explains how to apply patches to a Linux kernel module inside
the OpenWrt build system, compile it using Kbuild, package it as a
kmod-kernel-hello-world module, install it on an OpenWrt image (e.g., QEMU),
and test the patched behavior.
In this section, you are going to learn:
How to organize and structure a patched OpenWrt kernel module?
How to patch kernel module source files using OpenWrt’s Build/Patch system?
How to compile a kernel module using Kbuild inside OpenWrt?
How to package and install a patched kernel module in OpenWrt?
How to test kernel module load/unload behavior after patching?
Topics in this section:
package/my/kernel-hello-world/
├── Makefile
├── patches/
│ └── 0001-change-printk.patch
└── src/
├── hello_world.c
└── Makefile
patches/stores patch files applied during Build/Prepare.src/contains kernel module source and Kbuild Makefile.Top-level
Makefiledefines OpenWrt kernel package.Patch application occurs inside
$(PKG_BUILD_DIR).
src/hello_world.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int __init hello_world_init(void)
{
pr_info("hello_world: loaded (base message)\n");
return 0;
}
static void __exit hello_world_exit(void)
{
pr_info("hello_world: unloaded (goodbye)\n");
}
module_init(hello_world_init);
module_exit(hello_world_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("you");
MODULE_DESCRIPTION("Minimal Hello-style kernel module (hello_world)");
hello_world_initruns at module load.hello_world_exitruns at unload.pr_infologs to kernel buffer viadmesg.Minimal code suitable for patch demo.
src/Makefile
obj-m += hello_world.o
Kbuild builds
hello_world.ko.Kernel build invocation:
$(KERNEL_MAKE) M="$(PKG_BUILD_DIR)" modules
patches/0001-change-printk.patch
--- a/hello_world.c
+++ b/hello_world.c
@@ -6,7 +6,7 @@ static int __init hello_world_init(void)
{
- pr_info("hello_world: loaded (base message)\n");
+ pr_info("hello_world: loaded — patched message from OpenWrt package\n");
return 0;
}
Patch modifies printed message.
Applied automatically via
Build/Patch.Same flow as userland patching.
package/kernel-hello-world/Makefile
include $(TOPDIR)/rules.mk
PKG_NAME:=kernel-hello-world
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/kernel.mk
include $(INCLUDE_DIR)/package.mk
define KernelPackage/kernel-hello-world
SUBMENU:=Other modules
TITLE:=Minimal hello-style kernel module (hello_world)
FILES:=$(PKG_BUILD_DIR)/hello_world.ko
AUTOLOAD:=$(call AutoLoad,50,hello_world)
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
$(call Build/Patch,$(PKG_BUILD_DIR))
endef
define Build/Compile
$(KERNEL_MAKE) M="$(PKG_BUILD_DIR)" modules
endef
define KernelPackage/kernel-hello-world/install
$(INSTALL_DIR) $(1)/lib/modules
$(INSTALL_BIN) $(PKG_BUILD_DIR)/hello_world.ko $(1)/lib/modules/
endef
$(eval $(call KernelPackage,kernel-hello-world))
kernel.mkprovides kernel build logic.AUTOLOADcreates autoload entry.Build/Preparecopies + patches.Build/Compileinvokes Kbuild.
Build:
make package/my/kernel-hello-world/compile V=s
Output:
bin/targets/x86/64/packages/kmod-kernel-hello-world*.apk
V=sgives verbose logs.Output name includes kernel ABI.
scp -P <QEMU_PORT> bin/targets/x86/64/packages/kmod-kernel-hello-world*.apk \
root@127.0.0.1:/tmp/
/tmpis writable.<QEMU_PORT>depends on hostfwd configuration.
apk add --allow-untrusted /tmp/kmod-kernel-hello-world*.apk
Installs module under
/lib/modules/<kernel-version>/.AUTOLOADadds autoload entry.--allow-untrustedneeded for local builds.
Load module:
modprobe hello_world
View kernel log:
dmesg | tail -20
Expected:
hello_world: loaded — patched message from OpenWrt package
modproberesolves module path automatically.Patched log confirms patch + build correctness.