Linux kernel development

Building a Linux kernel module on Red Hat-derived distributions requires the kernel-devel package. Place the following in hello.c:

#include <linux/module.h>
#include <linux/kernel.h>

int init_module(void)
{
        /* NOTE: See kern_levels.h for level constants. */
        printk(KERN_INFO "Hello, world!\n");

        return 0;
}

void cleanup_module(void)
{
        printk(KERN_INFO "Goodbye, world!\n");
}

MODULE_LICENSE("GPL");

Place the following in Makefile:

obj-m += hello.o

all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Build the module using make. Load the module using insmod hello.ko, and remove it using rmmod hello; upon completing either, you should see a message recorded by the computer’s logging system.

Receiving parameters at module load time

The module_param and MODULE_PARM_DESC macros aid in declaring and documenting kernel-module parameters, respectively. The module_param macro takes as arguments a parameter name, parameter type, and a series of permission bits which, if non-zero, apply to a sysfs entry that the module might later create. Each use of module_param should correspond with a global variable which shares the name of the parameter.

static char *option = "default value";

module_param(option, charp, 0000);
MODULE_PARM_DESC(option, "An example character string option");

The sample option above could be set using the command insmod hello.ko option=foo.

Reproducing the kernel source used to build the kernel for a Red Hat-derived distribution

These steps require the dnf-utils and rpm-build packages, along with the compiler and other tools needed to build the Linux kernel.

  1. yumdownloader --source kernel
  2. rpm -Uvh kernel...
  3. rpmbuild -bp ~/rpmbuild/SPECS/kernel.spec

This will result in a copy of the kernel source tree at ~/rpmbuild/BUILD/kernel.... One way to build the kernel is to modify this source tree, produce a patch, place the patch in ~/rpmbuild/SOURCES, modify ~/rpmbuild/SPECS/kernel.spec to make use of the patch, and rebuild the kernel using rpmbuild -ba ~/rpmbuild/SPECS/kernel.spec:

  1. Make a vanilla copy of the kernel source: cp -a ~/rpmbuild/BUILD/kernel.../linux.../ ~/rpmbuild/BUILD/kernel.../linux...-vanilla/.
  2. Add pr_notice("Hello, world!\n"); to ~/rpmbuild/BUILD/kernel.../linux.../init/main.c immediately after the kernel prints "Kernel command line: ...".
  3. Create a patch by running diff -u --recursive ~/rpmbuild/BUILD/kernel.../linux...-vanilla/ ~/rpmbuild/BUILD/kernel.../linux.../ >~/rpmbuild/SOURCES/kernel-hello.patch.
  4. Add the patch to the kernel’s RPM specification by adding Patch2: kernel-hello.patch to ~/rpmbuild/SPECS/kernel.spec after the definition of Patch1.
  5. Set the specification to apply your patch by adding ApplyOptionalPatch kernel-hello.patch after the application of patch-%{patchversion}-redhat.patch.
  6. Run rpmbuild -ba ~/rpmbuild/SPECS/kernel.spec to build the result. This will take a long time, and it will use a lot of disk space.

Finally run rpm -ivh ~/rpmbuild/RPMS/x86_64/kernel-* to install your new kernel, and reboot the computer. After booting, you should find that dmesg includes Hello, world! in its output.

Assistant Professor

My research interests include free and open source software, system security, and network security.