Merge pull request #1765 from rneugeba/kmod

Add support for building custom kernel modules
This commit is contained in:
Rolf Neugebauer 2017-05-03 17:06:49 +01:00 committed by GitHub
commit ba6c210029
8 changed files with 127 additions and 3 deletions

View File

@ -36,6 +36,35 @@ In summary, LinuxKit offers a choice of the following kernels:
- [linuxkit/kernel-fedora](https://hub.docker.com/r/linuxkit/kernel-fedora/): Selected Fedora kernels.
## Compiling kernel modules
The LinuxKit kernel packages include `kernel-dev.tar` which contains
the headers and other files required to compile kernel modules against
the specific version of the kernel. Currently, the headers are not
included in the initial RAM disk, but it is possible to compile custom
modules offline and include then include the modules in the initial
RAM disk.
There is a [example](../tests/kmod), but basically one can use a
multi-stage build to compile the kernel modules:
```
FROM linuxkit/kernel:4.9.x AS ksrc
# Extract headers and compile module
FROM linuxkit/kernel-compile:1b396c221af673757703258159ddc8539843b02b@sha256:6b32d205bfc6407568324337b707d195d027328dbfec554428ea93e7b0a8299b AS build
COPY --from=ksrc /kernel-dev.tar /
RUN tar xf kernel-dev.tar
# copy module source code and compile
```
To use the kernel module, we recommend adding a final stage to the
Dockerfile above, which copies the kernel module from the `build`
stage and performs a `insmod` as the entry point. You can add this
package to the `onboot` section in your YAML
file. [kmod.yml](../tests/kmod/kmod.yml) contains an example for the
configuration.
## Working with Linux kernel patches for LinuxKit
We may apply patches to the Linux kernel used in LinuxKit, primarily to

View File

@ -53,9 +53,13 @@ RUN DVER=$(basename $(find /tmp/kernel-modules/lib/modules/ -mindepth 1 -maxdept
dir=/tmp/usr/src/linux-headers-$DVER && \
mkdir -p $dir && \
cp /linux/.config $dir && \
cd /linux && \
cp -a include "$dir" && \
mkdir -p "$dir"/arch/x86 && cp -a arch/x86/include "$dir"/arch/x86/ && \
cp /linux/Module.symvers $dir && \
find . -path './include/*' -prune -o \
-path './arch/*/include' -prune -o \
-path './scripts/*' -prune -o \
-type f \( -name 'Makefile*' -o -name 'Kconfig*' -o -name 'Kbuild*' -o \
-name '*.lds' -o -name '*.pl' -o -name '*.sh' \) | \
tar cf - -T - | (cd $dir; tar xf -) && \
( cd /tmp && tar cf /out/kernel-dev.tar usr/src )
RUN printf "KERNEL_SOURCE=${KERNEL_SOURCE}\n" > /out/kernel-source-info

21
test/kmod/Dockerfile Normal file
View File

@ -0,0 +1,21 @@
# This Dockerfile extracts the kernel headers from the kernel image
# and then compiles a simple hello world kernel module against them.
# In the last stage, it creates a package, which can be used for
# testing.
FROM linuxkit/kernel:4.9.x AS ksrc
# Extract headers and compile module
FROM linuxkit/kernel-compile:1b396c221af673757703258159ddc8539843b02b@sha256:6b32d205bfc6407568324337b707d195d027328dbfec554428ea93e7b0a8299b AS build
COPY --from=ksrc /kernel-dev.tar /
RUN tar xf kernel-dev.tar
WORKDIR /kmod
COPY ./src/* ./
RUN make all
# Package
FROM alpine:3.5
COPY --from=build /kmod/hello_world.ko /
COPY check.sh /check.sh
ENTRYPOINT ["/bin/sh", "/check.sh"]

15
test/kmod/check.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/sh
function failed {
printf "Kernel module test suite FAILED\n"
/sbin/poweroff -f
}
uname -a
modinfo hello_world.ko || failed
insmod hello_world.ko || failed
[ -n "$(dmesg | grep -o 'Hello LinuxKit')" ] || failed
rmmod hello_world || failed
printf "Kernel module test suite PASSED\n"
/sbin/poweroff -f

17
test/kmod/kmod.yml Normal file
View File

@ -0,0 +1,17 @@
kernel:
image: "linuxkit/kernel:4.9.x"
cmdline: "console=ttyS0"
init:
- linuxkit/init:63eed9ca7a09d2ce4c0c5e7238ac005fa44f564b
- linuxkit/runc:b0fb122e10dbb7e4e45115177a61a3f8d68c19a9
- linuxkit/containerd:18eaf72f3f4f9a9f29ca1951f66df701f873060b
onboot:
- name: check
image: "kmod-test"
binds:
- /dev:/dev
- /lib/modules:/lib/modules
capabilities:
- all
outputs:
- format: kernel+initrd

10
test/kmod/run_test.sh Executable file
View File

@ -0,0 +1,10 @@
#! /bin/sh
# Make sure we have the latest kernel image
docker pull linuxkit/kernel:4.9.x
# Build a package
docker build -t kmod-test .
# Build a LinuxKit image with kernel module (and test script)
moby build kmod
# Run it
linuxkit run kmod

6
test/kmod/src/Makefile Normal file
View File

@ -0,0 +1,6 @@
obj-m += hello_world.o
KVER=$(shell basename /usr/src/linux-headers-*)
all:
make -C /usr/src/$(KVER) M=$(PWD) modules
clean:
make -C /usr/src/$(KVER) M=$(PWD) clean

View File

@ -0,0 +1,22 @@
/*
* A simple Hello World kernel module
*/
#include <linux/module.h>
#include <linux/kernel.h>
int init_hello(void)
{
printk(KERN_INFO "Hello LinuxKit\n");
return 0;
}
void exit_hello(void)
{
printk(KERN_INFO "Goodbye LinuxKit.\n");
}
module_init(init_hello);
module_exit(exit_hello);
MODULE_AUTHOR("Rolf Neugebauer <rolf.neugebauer@docker.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A simple Hello World kernel module for testing");