In Debian Linux, there are two ways to compile custom kernels:
We’ll use the traditional method because it applies to all Linux distributions (in fact, the guide we linked is from the ArchWiki).
First and foremost, please take a snapshot of your VM before you get started.
Make sure you have the following kernel configuration/compilation dependencies installed:
build-essential bc python bison flex rsync libelf-dev libssl-dev libncurses-dev dwarves
Reboot and make sure that your system is all good.
uname -r to make sure that you are running the stock kernel that ships
with Debian. At this time of writing, our arm64 system reports
If you are on an x86 system, it should report
In the Spring 2023 semester, you will be working with Linux kernel version 5.10.158.
But instead of fetching the Linux source code from kernel.org,
you will be compiling the kernel source code provided in each kernel
assignment’s skeleton repo. You will find the pristine, mainline
Linux kernel source tree in the
linux/ directory in your assignment repo.
You should verify the version of the kernel. The first 6 lines of Linux’s
Makefile will show you the version:
$ head -n 6 Makefile # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 10 SUBLEVEL = 158 EXTRAVERSION = NAME = Dare mighty things
It is standard practice to run
make mrproper in a freshly cloned repo before
proceeding. This removes any configuration files that might have been
accidentally left over from previous builds.
The Linux kernel build system can be configured using
.config, which must
be located at the root of the Linux source tree. This file is used to specify a
truly astounding number of options with which you can build your kernel.
You can start with the
.config file of your running kernel (e.g. the stock
Debian kernel). The
.config file that was used to build the stock Debian
kernel is located in the
/boot/ directory. The following command copies over
.config file, and updates any missing options with default values:
$ make olddefconfig
Depending on how your stock kernel is configured, this may report some warnings. For example:
/boot/config-5.10.0-20-arm64:7855:warning: symbol value 'm' invalid for ASHMEM /boot/config-5.10.0-20-arm64:8981:warning: symbol value 'm' invalid for ANDROID_BINDER_IPC
You should be able to ignore these without running into any trouble.
There are two recommended methods to edit your
You can run
make menuconfig, which will open up an interactive menu that
organizes configuration options in a more user-friendly manner. If you make
any configuration changes, it will also create a backup of your original
.config file, named
config.old will be created every time you run a
make target related to
config, and every time you save in
make menuconfig. If you choose this
method, we recommend that you save once, only after making all of the
changes listed below – this will allow you to take a clear diff of the
.config vs. the original config file saved in
You can use the
scripts/config command, which allows you to manipulate
options in a
.config file from the command line. Note that this method
does not create a
.config.old file. However, you can find the original
.config file in the
/boot directory if necessary.
Make the following changes, using either of the above methods:
CONFIG_LOCALVERSION: This setting gives your custom kernel a unique
name to distinguish it from other kernels present in your system.
The local version will be appended to your kernel version to
form your kernel name. For example, if we build a 5.10.158 kernel with the
local version set to
-cs4118, it will be named
For your pristine kernel build, set this to
menuconfig, this can be found under
General setup, in the
“Local Version - append to kernel release” option.
scripts/config --set-str LOCALVERSION "-cs4118".
SYSTEM_TRUSTED_KEYS: This is used to bake additional trusted X.509 keys
directly into the kernel image, which can be used to verify kernel modules
before loading them. Debian 11 comes with this
configuration, but we won’t actually need this, so we will remove it.
You may find this option set to
clear out this field and leave it empty.
menuconfig, this can be found by opening the
section, then opening the
Certificates for signature checking section
at the bottom. The specific field is “Additional X.509 keys for default
scripts/config --set-str SYSTEM_TRUSTED_KEYS "".
After setting your local version, take a moment to inspect the contents of the
.config file. Make sure that the options you configured are set to what you
expect them to be, using
scripts/config --state <option> for each of the
Linux also provides the
scripts/diffconfig utility, which can be used to
.config files. For example, if you used
you would see:
$ scripts/diffconfig .config.old .config LOCALVERSION "" -> "-cs4118" SYSTEM_TRUSTED_KEYS "debian/certs/debian-uefi-certs.pem" -> ""
If you used
scripts/config, you can find your stock
.config file in the
/boot directory, as
config-5.10.0-20-arm64 (on an arm64 machine). You can
scripts/diffconfig /boot/config-5.10.0-20-arm64 .config, and should
see the same output.
A large amount of time is spent compiling and installing kernel modules you
never use. You can regenerate
.config so that it contains only the modules
your system is currently using. This will drastically cut down the number of
make localmodconfig will take your current
.config and turn off
any unused modules. Running this will ask you several questions about how to
configure the kernel, so rather than doing this manually, run:
$ yes '' | make localmodconfig
This should generate a much smaller
.config, leading to a shorter compilation
time. You can use the
scripts/config commands listed above to verify that the
configuration options we care about are still set properly.
Compiling a kernel takes a long time – it can take over an hour on a slow
machine. You can speed up this process by running compilation jobs in parallel
-j flag, which takes the number of parallel jobs to spawn
as an argument. If your computer has multiple CPU cores, you should configure
your VM to use them.
make as a non-root user:
$ make -j$(nproc)
This uses command substitution to invoke the
nproc command, which prints the
number of cores available on the machine.
Check that running
0022 (this should be the case by default).
If not, run
umask 0022. This will ensure that the kernel modules are
installed with correct permissions. Note that if your
umask is not
you’ve likely modified your
umask in your
a non-default value. Since this is a single-user system, a umask of
reasonable, and you should undo those changes.
Then, install the kernel modules and the kernel itself:
# make modules_install # make install
Verify that you have the following 3 files in
initrd.img-5.10.158-cs4118 System.map-5.10.158-cs4118 vmlinuz-5.10.158-cs4118
When you are hacking kernel code, you’ll often make simple changes to only a
handful of source files. If you didn’t modify any header or module source
files, the modules will not be rebuilt when you run
make. As such, there is
no reason to reinstall all modules every time you rebuild your kernel.
Reboot by running:
Make sure to pick your custom kernel from the boot loader menu.
Now verify that you’re running your own custom kernel by running:
$ uname -a
5.10.0-20-arm64, you should now see your kernel version string,
Last updated: 2023-01-04