Search code examples
clinuxlinux-kernelkernel-modulelinux-kernel-headers

Broken Linux kernel <linux/...> includes on Ubuntu 20.04


I'm trying to write a kernel module in VS Code on Ubuntu 20.04

The problem is that my includes seem to be completely broken.

Firstly, I have no <linux/uaccess.h> or <asm/uaccess.h> headers. Secondly, I have put many includes on top of my file like:

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

However, no definitions for kernel stuff like printk() are found. Macros like bool or NULL are also not defined in my linux/types.h.

I tried sudo apt-get install linux-headers-generic.

Here's my linux/module.h:

/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LINUX_MODULE_H
#define _LINUX_MODULE_H

/* Flags for sys_finit_module: */
#define MODULE_INIT_IGNORE_MODVERSIONS  1
#define MODULE_INIT_IGNORE_VERMAGIC 2

#endif /* _LINUX_MODULE_H */

My linux/kernel.h:

/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LINUX_KERNEL_H
#define _LINUX_KERNEL_H

#include <linux/sysinfo.h>
#include <linux/const.h>

#endif /* _LINUX_KERNEL_H */


Solution

  • These headers are kernel-space headers, which means they cannot be found within the user-space headers (/usr/include/linux). In my Fedora machine, this is how I diagnose it.

    1. Make sure those headers exist

    I use a simple find /usr -name uaccess.h 2>/dev/null to list all files. The result might look like below:

    /usr/src/kernels/6.6.4-200.fc39.x86_64/arch/x86/include/asm/uaccess.h
    /usr/src/kernels/6.6.4-200.fc39.x86_64/include/asm-generic/uaccess.h
    /usr/src/kernels/6.6.4-200.fc39.x86_64/include/linux/uaccess.h
    /usr/src/kernels/6.6.6-200.fc39.x86_64/arch/x86/include/asm/uaccess.h
    /usr/src/kernels/6.6.6-200.fc39.x86_64/include/asm-generic/uaccess.h
    /usr/src/kernels/6.6.6-200.fc39.x86_64/include/linux/uaccess.h
    /usr/src/kernels/6.6.7-200.fc39.x86_64/arch/x86/include/asm/uaccess.h
    /usr/src/kernels/6.6.7-200.fc39.x86_64/include/asm-generic/uaccess.h
    /usr/src/kernels/6.6.7-200.fc39.x86_64/include/linux/uaccess.h
    

    2. How to use those kernel headers

    An intuitive way to use those headers is to include them all when compiling. However, this is error-prone due to linking issues.

    A (somewhat) standard way is to define it as module.

    Source code:

    // printk-example.c
    
    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/uaccess.h>
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Your Name");
    MODULE_DESCRIPTION("A simple kernel module with printk");
    
    static int __init hello_init(void)
    {
        printk(KERN_INFO "Hello, this is your kernel module!\n");
        return 0;
    }
    
    static void __exit hello_exit(void)
    {
        printk(KERN_INFO "Goodbye, exiting your kernel module!\n");
    }
    
    module_init(hello_init);
    module_exit(hello_exit);
    

    Makefile:

    obj-m += printk-example.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
    

    You might search for the rest on running kernel modules for your machine.

    I hope this will help.