9.2. Recompiling the Linux Kernel
The kernels provided by Kali include the largest possible number of features, as well as the maximum number of drivers, in order to cover the broadest spectrum of existing hardware configurations. This is why some users prefer to recompile the kernel in order to include only what they specifically need. There are two reasons for this choice. First, it is a way to optimize memory consumption since all kernel code, even if it is never used, occupies physical memory. Because the statically compiled portions of the kernel are never moved to swap space, an overall decrease in system performance will result from having drivers and features built in that are never used. Second, reducing the number of drivers and kernel features reduces the risk of security problems since only a fraction of the available kernel code is being run.
Recompilation of the kernel is also necessary if you want to use certain features that are only available as patches (and not included in the standard kernel version).
Unsurprisingly, Debian and Kali manage the kernel in the form of a package, which is not how kernels have traditionally been compiled and installed. Since the kernel remains under the control of the packaging system, it can then be removed cleanly, or deployed on several machines. Furthermore, the scripts associated with these packages automate the interaction with the bootloader and the initrd generator.
The upstream Linux sources contain everything needed to build a Debian package of the kernel but you still need to install the build-essential package to ensure that you have the tools required to build a Debian package. Furthermore, the configuration step for the kernel requires the libncurses5-dev package. Finally, the fakerootpackage will enable creation of the Debian package without needing administrative privileges.
# apt install build-essential libncurses5-dev fakeroot
Since the Linux kernel sources are available as a package, you can retrieve them by installing the linux-source-version package. The
apt-cache search ^linux-source command should list the latest kernel version packaged by Kali. Note that the source code contained in these packages does not correspond precisely with that published by Linus Torvalds and the kernel developers; like all distributions, Debian and Kali apply a number of patches, which might (or might not) find their way into the upstream version of Linux. These modifications include backports of fixes/features/drivers from newer kernel versions, new features not yet (entirely) merged in the upstream Linux tree, and sometimes even Debian or Kali specific changes.
The remainder of this section focuses on the 4.9 version of the Linux kernel, but the examples can, of course, be adapted to the particular version of the kernel that you want.
In this example, we assume that the linux-source-4.9 binary package has been installed. Note that we install a binary package containing the upstream sources but do not retrieve the Kali source package named linux.
# apt install linux-source-4.9
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
libncurses-dev | ncurses-dev libqt4-dev
The following NEW packages will be installed:
bc libreadline7 linux-source-4.9
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 95.4 MB of archives.
After this operation, 95.8 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
# ls /usr/src
linux-config-4.9 linux-patch-4.9-rt.patch.xz linux-source-4.9.tar.xz
The next step consists of configuring the kernel according to your needs. The exact procedure depends on the goals.
The kernel build depends on a kernel configuration file. In most cases, you will most likely keep as close as possible to that proposed by Kali, which, like all Linux distributions, is installed in the
/boot directory. In this case, rather than reconfiguring everything from scratch, it is sufficient to make a copy of the
/boot/config-version file. (The version should be the same as that version of the kernel currently used, which can be found with the
uname -r command.) Place the copy into a
.config file in the directory containing the kernel sources.
$ cp /boot/config-4.9.0-kali1-amd64 ~/kernel/linux-source-4.9/.config
Alternatively, since the kernel provides default configurations in
arch/arch/configs/*_defconfig, you can put your selected configuration in place with a command like
make x86_64_defconfig (in the case of a 64-bit PC) or
make i386_defconfig (in the case of a 32-bit PC).
Unless you need to change the configuration, you can stop here and skip to Section 9.2.4, "Compiling and Building the Package". If you need to make changes or if you decide to reconfigure everything from scratch, you must take the time to configure your kernel. There are various dedicated interfaces in the kernel source directory that can be used by calling the
make target command, where target is one of the values described below.
make menuconfig compiles and launches a text-mode kernel configuration interface (this is where the libncurses5-dev package is required), which allows navigating the many available kernel options in a hierarchical structure. Pressing the Space key changes the value of the selected option, and Enter validates the button selected at the bottom of the screen; returns to the selected sub-menu; closes the current screen and moves back up in the hierarchy; will display more detailed information on the role of the selected option. The arrow keys allow moving within the list of options and buttons. To exit the configuration program, choose from the main menu. The program then offers to save the changes that you have made; accept if you are satisfied with your choices.
Other interfaces have similar features but they work within more modern graphical interfaces, such as
make xconfig, which uses a Qt graphical interface, and
make gconfig, which uses GTK+. The former requires libqt4-dev, while the latter depends on libglade2-dev and libgtk2.0-dev.
Once the kernel configuration is ready, a simple
make deb-pkg will generate up to five Debian packages in standard
.deb format: linux-image-version, which contains the kernel image and the associated modules; linux-headers-version, which contains the header files required to build external modules; linux-firmware-image-version, which contains the firmware files needed by some drivers (this package might be missing when you build from the kernel sources provided by Debian or Kali); linux-image-version-dbg, which contains the debugging symbols for the kernel image and its modules; and linux-libc-dev, which contains headers relevant to some user-space libraries like GNU's C library (glibc).
The version is defined by the concatenation of the upstream version (as defined by the variables
EXTRAVERSION in the
Makefile), of the
LOCALVERSION configuration parameter, and of the
LOCALVERSION environment variable. The package version reuses the same version string with an appended revision that is regularly incremented (and stored in
.version), except if you override it with the
KDEB_PKGVERSION environment variable.
$ make deb-pkg LOCALVERSION=-custom KDEB_PKGVERSION=$(make kernelversion)-1
$ ls ../*.deb
To actually use the built kernel, the only step left is to install the required packages with
dpkg -i file.deb. The "linux-image" package is required; you only have to install the "linux-headers" package if you have some external kernel modules to build, which is the case if you have some "*-dkms" packages installed (check with
dpkg -l "*-dkms" | grep ^ii). The other packages are generally not needed (Unless you know why you need them!).