Linuxkernel selber bauen
Überblick, Komponenten
ZIEL: Erweiterte Funktionalitäten im Kernel bereitstellen oder z.B. für Sicherheitsanforderungen Funktionen entfernen
Linux ist ein monolithischer Kernel, d.h. Hardware-Treiber sind zu einem gewissen Teil fest integriert. Es besteht aber auch die Möglichkeit, Treiber auf modulare Art nachzuladen. Damit sie zur Laufzeit nachgeladen werden können, müssen allerdings Anschlusstellen vorgesehen werden. Hier drängt sich das Bild vom Schweizer Käse auf:
Käse = monolithisches Fertigprodukt
Löcher = Anschlusstellen für nachladbare Module
Wichtige Pfade für den Buildvorgang und für den späteren, neu übersetzten Kernel sind:
Kernelquellen: /usr/src/linux (ist i.d.R. ein Symlink auf das eigentliche Quellen-Verzeichnis)
Kernel und Initrd: /boot
Kernelmodule: /lib/modules
Kernel kompilieren
Ein gutes Grundlagendokument ist unter https://wiki.archlinux.org/index.php/Kernel/Traditional_compilation zu finden.
Zu den Release-Bezeichnungen:
Historisch gesehen, trug der letzte Entwicklerkernel die Nummer 2.5 (= letzte ungerade Minor-Nummer), ab Version 2.6 wurde anders verfahren.
Es gibt jetzt offiziell nur noch:
Prepatch (Prepatch or „RC“ kernels are mainline kernel pre-releases)
Mainline (Mainline tree is maintained by Linus Torvalds. It’s the tree where all new features…)
Stable (After each mainline kernel is released, it is considered „stable.“)
Longterm (There are usually several „longterm maintenance“ kernel releases provided for the purposes of backporting bugfixes for older kernel trees)
Siehe https://www.kernel.org/releases.html
Kernelbau mit Distributionspaket
Im einfachsten Fall benutzt man die vorgepatchten Kernelquellen der Distribution (Paket linux-source) und nicht die von https://kernel.org, womit eine bessere Kompatibilität zum vorliegenden System gegeben ist. Unter Debian 10 mit den älteren 4-er Kerneln benötigen wir dazu insgesamt die folgenden Pakete:
apt-get install linux-source build-essential libncurses-dev libelf-dev libssl-dev
Soll ein ganz neuer Kernel von https://kernel.org heruntergeladen und gebaut wenden (= Vanilla-Kernel, z.B. 5.10.11), sieht die Zeile etwas anderes aus:
apt-get install build-essential libncurses-dev libelf-dev libssl-dev flex bison
Nach dem Wechseln ins Quellverzeichnis entpacken wir den Tarball mit den Kernelquellen, erstellen einen Symlink namens „linux“ und wechseln weiterhin dort hinein:
$ cd /usr/src
$ tar xf linux-source-4.19.tar.xz
$ ln -s linux-source-4.19 linux
$ cd linux
$ make mrproper ### Nur anfänglich auszuführen!
In diesem Verzeichnispfad finden nun künftig alle Arbeiten statt. Bevor es ans Auswählen der künftigen Kernelfeatures geht, sollte man sich überlegen, wie schlank und angepasst der Kernel werden soll:
a) Minimal angepasst: Die Konfiguration der Distribution ist Ausgangspunkt, mit make menuconfig
braucht im Prinzip nur der CPU-Typ angepasst werden (Vorteil: weniger Konfigurationsaufwand; Nachteile: größerer Kernel, mehr Module, mehr Zeitaufwand beim Kompilieren)
b) Stark optimiert: Die .config-Datei wird mittels make localmodconfig
generiert (Vorteile: schlanker Kernel mit wenigen Modulen, schnelleres Kompilieren; Nachteil: größerer Konfigurationsaufwand wegen nicht ausgewählten Systemfunktionen und Treibern)
Je nachdem, für welche Variante man sich entscheidet, sollte man folgendes beachten:
Zu a)
Mit
cp /boot/config-`uname -r` .config
kopiert man sich die Default-Config unter DebianMit
zcat /proc/config.gz > .config
tun wir dasselbe unter Arch-, Artix- und SuSE-LinuxMittels
make menuconfig
stellen wir unter ‚Processor type and features‘ die ‚Processor family‘ ein. ACHTUNG: Unter Debian bitte unbedingt unter ‚Kernel hacking‘ -> ‚Compile-time checks and compiler options‘ die Option ‚Compile the kernel with debug info‘ deaktivieren! Ansonsten dauert der Übersetzungsprozess sehr lange; außerdem wird viel Festplattenplatz beansprucht!! Nach dem abschließenden <Save> wird von diesem Konfigrationsprogramm die Datei.config
modifiziert. Achtung: Die Datei darf später nicht manuell editiert werden, weil dabei natürlich keine Abhängigkeitsprüfung möglich ist!
Zu b)
Hier kann gleich mit
make localmodconfig
begonnen werden, wobei nur die vorgefundenen und erkannten Geräte (USB-Devices vorher anstecken!) in die Konfigration aufgenommen werdenMittels
make menuconfig
muss wiederum weiterkonfiguriert werden, wobei es jetzt deutlich mehr zu tun gibt, so muss neben der oben genannten ‚Processor family‘ z.B. auch folgendes aktiviert werden:Dateisysteme (ISO, vfat, ntfs, …)
Blockgeräte (Loopback-Treiber, Multiple Disks, …)
Verschlüsselung (z.B. für cryptsetup/LUKS)
Netzwerksicherheit (iptables, nftables, VPN, …)
Device Driver…
Außerdem bitte wieder bei ‚Kernel hacking‘, … die Option ‚Compile the kernel with debug info‘ deaktivieren! Siehe auch weiter unten bei Wichtige config-Parameter.
Danach geht es endlich mit dem Übersetzungsprozess los, der bei einem ganz frischen Quelltextverzeichnis drei Schritte umfasst: das Bauen des Kernels, der Module und das Installieren der Module nach „/lib/modules/<KERNELVERSION>“:
$ make bzImage
$ make modules
$ make modules_install
Siehe dazu die folgende Abbildung, in der ein erfolgreicher Abschlusss der drei Kompilerschritte jeweils dargestellt ist:
Falls der Kernel ein zweites Mal im selben Quelltextverzeichnis gebaut werden soll, ist vorher ein Cleaning erforderlich; wir haben dadurch einen Schritt mehr:
$ make clean
$ make bzImage
$ make modules
$ make modules_install
Anstelle von clean
können auch die make-Targets mrproper
und distclean
eingesetzt werden. Aber ACHTUNG: die beiden letzteren löschen jeweils immer gründlicher - auch die .config
-Datei wird mit entfernt!
Bis zur Kernelversion 2.4 gab es übrigens vor make clean
noch einen weiteren Schritt: make dep
Er ist mit Version 2.6 entfallen.
Warnung
Möchte man mit dem selben Quelltextverzeichnis weiterarbeiten und wiederholt Kernel mit unterschiedlichen Features bauen, ist es ratsam, die Datei Makefile
zu editieren und bei EXTRAVERSION =
einen eigenen Bezeichner wie etwa „-myKernel-Nr2“ mitzugeben. Das stellt sicher, dass nicht ein und derselbe Treiber doppelt eingebunden wird: als fest integriertes Builtin und zugleich auch als nachladbares Modul (was sich evl. immer noch im Verzeichnis /lib/modules/<KERNELVERSION>
befindet).
Aus einer LPI-Braindump Fragensammlung:
„After unpacking the source code for a Linux kernel, what is the first make command that should be run which will delete any current configuration and all generated files? This command will ensure that no inappropriate files were left in the kernel archive by the maintainer.“
A) make clean # sanft bereinigen (temp), '.config' bleibt erhalten
B) make mrproper # hart bereinigen, '.config' wird gelöscht!
C) make distclean # noch härter bereinigen, '.config' wird ebenfalls gelöscht!
D) make depend # nur bis Kernel 2.4, außerdem 'make dep' und NICHT 'depend'!
E) make config # Textbasierter Assistent mit tausend Fragen...
Correct Answer: C
Kernelbau mit Vanilla-Kernel
Distribution: Debian 8 (Jessie)
Vorbereitungen
Downloaden der ungepatchen Originalquellen von https://kernel.org (= Vanilla-Kernel):
$ mkdir /home/src
$ cd /home/src
$ wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.14.51.tar.xz
Installieren von Hilfsprogrammen:
$ apt-get install gcc make automake build-essential gcc-4.9-plugin-dev libncurses5-dev
Kernel im Verzeichnis /home/src entpacken:
$ tar xvJf linux-3.14.51.tar.xz
Symlink erzeugen:
$ cd /home/src
$ ln -s linux-3.14.51 /usr/src/linux
Kernel patchen
Patch von https://raw.githubusercontent.com/kdave/grsecurity-patches/master/grsecurity_patches/grsecurity-3.1-3.14.51-201508181951.patch herunterladen und unter ‚/home/src‘ speichern:
$ cd /home/src
$ wget https://raw.githubusercontent.com/kdave/grsecurity-patches/master/grsecurity_patches/grsecurity-3.1-3.14.51-201508181951.patch
Dann geht es so weiter:
root@deb8:/usr/src# rm linux
root@deb8:/usr/src#
root@deb8:/usr/src# ln -s /home/src/linux-3.14.51 linux
root@deb8:/usr/src#
root@deb8:/usr/src# ls -l
insgesamt 12
lrwxrwxrwx 1 root root 23 Jan 13 09:26 linux -> /home/src/linux-3.14.51
drwxr-xr-x 4 root root 4096 Jan 13 09:25 linux-headers-3.16.0-4-amd64
drwxr-xr-x 4 root root 4096 Okt 20 10:49 linux-headers-3.16.0-4-common
lrwxrwxrwx 1 root root 24 Dez 14 2015 linux-kbuild-3.16 -> ../lib/linux-kbuild-3.16
lrwxrwxrwx 1 root root 17 Okt 4 11:19 linux-OLDVERSION.1475658617 -> linux-source-3.16
drwxr-xr-x 23 root root 4096 Okt 4 13:05 linux-source-3.16
lrwxrwxrwx 1 root root 49 Okt 5 11:11 vboxguest-5.1.6 -> /opt/VBoxGuestAdditions-5.1.6/src/vboxguest-5.1.6
root@deb8:/usr/src#
root@deb8:/usr/src# cd linux
root@deb8:/usr/src/linux#
root@deb8:/usr/src/linux# ls -F
arch/ CREDITS drivers/ include/ Kbuild lib/ mm/ REPORTING-BUGS security/ usr/
block/ crypto/ firmware/ init/ Kconfig MAINTAINERS net/ samples/ sound/ virt/
COPYING Documentation/ fs/ ipc/ kernel/ Makefile README scripts/ tools/
root@deb8:/usr/src/linux#
Wir stehen im richtigen Verzeichnis und können den Patch nun anwenden:
$ patch -p1 < /home/src/grsecurity-3.1-3.14.51-201508181951.patch
Alternativ:
$ cat /home/src/grsecurity-3.1-3.14.51-201508181951.patch | patch -p1
ACHTUNG:
Dem Kommando ‚patch‘ kann man den Dateinamen nicht direkt übergeben!
Dateien, die beim patchen rejectetd werden, erhalten das Suffix ‚.rej‘
Mit der Option ‚-R‘ können Patches rückgangig gemacht werden
Siehe auch http://www.thegeekstuff.com/2014/12/patch-command-examples
Kernel-Konfiguration
ZIEL: Einstellungen vornehmen, Konfigurationsdatei ‚.config‘ erzeugen
Zuerst müssen wir den Prozessortyp ermitteln, diesen dann im Konfig-Programm unter ‚Processor type and features‘, Untermenü ‚Processor family‘ auswählen, danach unter ‚Preemption Model‘ den Eintrag ‚No Forced Preemption (Server)‘ aktivieren und das Programm vorerst beenden, wobei die Einstellungen gespeichert werden müssen:
$ cat /proc/cpuinfo
$ make menuconfig
Konfiguration fortführen
Nachdem wir nun eine ‚.config‘ haben, geht es weiter im Verzeichnis der entpackten Kernelquelldateien. Mit dem neuen make-Ziel localmodconfig ist es viel schneller erledigt, die passenden Module für das aktuell laufende System auszuwählen. Die wichtigsten Module werden dabei automatisch erkannt, später ist nur wenig manuelle Nacharbeit erforderlich. Es werden allerdings nur bereits geladene Module (siehe ‚lsmod‘) berücksichtigt, was bedeutet, dass im Vorfeld alle benötigten USB-Geräte an den Rechner angeschlossen sein müssen!
Danach können manuell weitere gewünschte Einstellungen vorgenommen werden. Für grsecurity macht die „automatische Konfiguration“ auf alle Fälle erst einmal Sinn.
$ make localmodconfig
Taucht hierbei „NEW“ auf, übernehemn wir alles einfach mit ENTER. Das könnte z.B. so aussehen:
root@deb8:/usr/src/linux# make localmodconfig
using config: '.config'
vboxsf config not found!!
vboxguest config not found!!
*
* Restart config...
*
*
* GPIO Support
*
GPIO Support (GPIOLIB) [Y/n/?] y
Debug GPIO calls (DEBUG_GPIO) [N/y/?] n
/sys/class/gpio/... (sysfs interface) (GPIO_SYSFS) [N/y/?] n
*
* Memory mapped GPIO drivers:
*
Generic memory-mapped GPIO controller support (MMIO platform device) (GPIO_GENERIC_PLATFORM) [N/m/y/?] n
IT8761E GPIO support (GPIO_IT8761E) [N/m/y/?] n
F71882FG and F71889F GPIO support (GPIO_F7188X) [N/m/y/?] n
SMSC SCH311x SuperI/O GPIO (GPIO_SCH311X) [N/m/y/?] n
TS-5500 DIO blocks and compatibles (GPIO_TS5500) [N/m/y/?] n
Intel SCH/TunnelCreek/Centerton GPIO (GPIO_SCH) [N/m/y/?] n
Intel ICH GPIO (GPIO_ICH) [N/m/y/?] n
VIA VX855/VX875 GPIO (GPIO_VX855) [N/m/y/?] n
Intel Lynxpoint GPIO support (GPIO_LYNXPOINT) [N/m/y/?] n
*
* I2C GPIO expanders:
*
Maxim MAX7300 GPIO expander (GPIO_MAX7300) [N/m/?] n
MAX7319, MAX7320-7327 I2C Port Expanders (GPIO_MAX732X) [N/m/?] n
PCA953x, PCA955x, PCA957x, TCA64xx, and MAX7310 I/O ports (GPIO_PCA953X) [N/m/?] n
PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders (GPIO_PCF857X) [N/m/?] n
ADP5588 I2C GPIO expander (GPIO_ADP5588) [N/m/?] n
*
* PCI GPIO expanders:
*
BT8XX GPIO abuser (GPIO_BT8XX) [N/m/y/?] (NEW)
AMD 8111 GPIO driver (GPIO_AMD8111) [N/m/y/?] n
Intel Mid GPIO support (GPIO_INTEL_MID) [N/y/?] n
Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO (GPIO_PCH) [N/m/y/?] n
OKI SEMICONDUCTOR ML7213 IOH GPIO support (GPIO_ML_IOH) [N/m/y/?] n
RDC R-321x GPIO support (GPIO_RDC321X) [N/m/y/?] n
*
* SPI GPIO expanders:
*
Maxim MAX7301 GPIO expander (GPIO_MAX7301) [N/m/y/?] n
Freescale MC33880 high-side/low-side switch (GPIO_MC33880) [N/m/y/?] n
*
* AC97 GPIO expanders:
*
*
* LPC GPIO expanders:
*
*
* MODULbus GPIO expanders:
*
*
* USB GPIO expanders:
*
#
# configuration written to .config
#
Jetzt können gern weitere Schalter de- und aktiviert werden:
$ make menuconfig
Alle für uns wichtigen Einstellungen finden sich im Untermenü ‚Security options‘. Da wir nur grsecurity-Patches wollen, können die anderen, auf die umstrittene LSM-Schnittstelle aufsetzenden Sicherheitserweiterungen in der angegebenen Reihenfolge deaktiviert werden, wobei der Eintrag ‚Socket and Networking Security Hooks‘ dann die LSM-Schnittstelle insgesamt deaktiviert.
Zu deaktivieren ist hierbei:
AppArmor support
TOMOYO Linux Support
NSA SELinux Support
Socket and Networking Security Hooks
Nun geht es in das Untermenü „Grsecurity ->“ hinein, wir schalten unser Feature mit der Leertaste ein (‚[*] Grsecurity‘) und wählen als ‚Configuration Method‘ „Automatic“ aus. Danach sollten weitere Anpassungen in den jeweiligen Untermenüs erfolgen.
Wichtige config-Parameter
Stand 03.06.2020, Debian-Sources 4.19.118
Die folgenden Angaben beziehen sich auf die Konfiguration der Kernelquellen per make menuconfig.
Allgemeine Optimierung
Anpassen der CPU-Familie (siehe cat /proc/cpuinfo), Verbesserung der Performance:
> Processor type and features --->
Processor family (Generic-x86-64) --->
dort auf jeweilige CPU anpassen...
> General setup --->
Preemption Model --->
auswählen von entweder:
"Preemptible Kernel (Low-Latency Desktop)"
oder falls der RT-Patch installiert ist:
"Fully Preemptible Kernel (RT)"
Debian-spezifisches
Kernel ohne Debug-Infos bauen (=> https://www.olimex.com/forum/index.php?topic=5946.0):
> Kernel hacking
Compile-time checks and compiler options --->
unbedingt "Compile the kernel with debug info" deaktivieren, ansonsten dauert der
Übersetzungsvorgang sehr lang und benöigt viel Plattenplatz!
(Symbol: DEBUG_INFO [=y])
Beim Fehler „System keyring enabled but keys „debian/certs/debian-uefi-certs.pem“ not found“:
> Cryptographic API --->
Certificates for signature checking --->
den Dateipfad in
"Additional X.509 keys for default system keyring" entfernen...
Bei Verwendung von ‚make localmodconfig‘
Für’s mounten von ISO-Dateien, LUKS/cryptsetup und andere Dinge:
> Device Drivers --->
Block devices --->
"Loopback device support"
"Cryptoloop Support"
Multiple devices driver support (RAID and LVM) --->
auswählen von:
"Device mapper support"
"Crypt target support"
Multimedia support --->
Media USB Adapters --->
für TechnoTrend S2400 auswählen:
"Support for various USB DVB devices"
"Pinnacle 400e DVB-S USB2.0 support"
Verschiedenste Dateisysteme aktivieren:
> File systems --->
auswählen von:
"Inotify support for userspace"
"FUSE (Filesystem in Userspace) support"
"Overlay filesystem support"
CD-ROM/DVD Filesystems --->
auswählen aller gewünschten/möglichen Optionen...
DOS/FAT/NT Filesystems --->
auswählen aller gewünschten/möglichen Optionen...
Network File Systems --->
auswählen aller gewünschten/möglichen Optionen...
Für LUKS/cryptsetup (=> https://wiki.gentoo.org/wiki/Dm-crypt/de):
> Cryptographic API --->
auswählen von:
"XTS support"
"SHA224 and SHA256 digest algorithm"
"AES cipher algorithms"
"AES cipher algorithms (x86_64)"
"User-space interface for hash algorithms"
"User-space interface for symmetric key cipher algorithms"
Für iptables-Firewall:
> Networking support --->
Networking options --->
Network packet filtering framework (Netfilter) --->
Core Netfilter Configuration --->
(Hier nun alle gewünschten/erforderlichen Optionen auswählen.)
Sicherheit
Die wichtigen Einstellungen befinden sich im Untermenü „Security options“.
Wer nicht explizit AppArmor, SELinux, SMAC, oder TOMOYO benötigt, kann die umstrittene Schnittstelle für die Linux Security Modules (LSM) namens „Socket and Networking Security Hooks“ insgesamt deaktivieren. Von der Reihenfolge her müssen aber zuerst die darauf aufsetzenden Mandatory Access Control (MAC) modules abgeschaltet werden, zum Schluss erst LSM. Beim Kernel 5.7.0 gestaltet sich dies so:
NSA SELinux Support
Simplified Mandatory Access Control Kernel Support
TOMOYO Linux Support
AppArmor support
Socket and Networking Security Hooks
Zu den Linux Security Modules siehe:
Kernel und Module bauen
$ make bzImage && make modules
Module installieren und Verzeichnisgröße kontrollieren
$ make modules_install
$ du -sh /lib/modules/*
105M /lib/modules/3.14.51-grsec
101M /lib/modules/3.2.0-4-amd64
Kernel kopieren und umbenennen, Initrd erzeugen
Wichtig ist dabei, sich den Namen des eben kontrollierten, 105 MByte großen Verzeichnisses, nämlich „3.14.51-grsec“ zu notieren, denn diesen Namen benötigen wir gleich als Suffix zur richtigen Bennenung von Kernel und Initrd, so dass das Kommando ‚update-grub‘ im Anschluss gültige Booteinträge in der ‚/boot/grub/grub.cfg‘ erstellen kann.
Der Name der Kerneldatei muss mit „vmlinuz-“ beginnen, insgesamt dann also „/boot/vmlinuz-3.14.51-grsec“ heißen, die initiale RAM-Disk entsprechend „/boot/initrd.img-3.14.51-grsec“. Die beiden Dateien bekommen wir auf folgende Art an Ort und Stelle:
$ cp arch/x86/boot/bzImage /boot/vmlinuz-3.14.51-grsec
$ update-initramfs -c -k 3.14.51-grsec
Alternativ kann bei vielen Distributionen dieses Kommando verwendet werden: mkinitramfs -k 3.14.51-grsec -o /boot/initrd.img-3.14.51-grsec
Bei Arch/Artix-Linux sieht das etwas anders aus, z.B. so: mkinitcpio -k 5.6.15 -g /boot/initramfs-5.6.15.img
Bootloader automatisch um neuen Kernel erweitern:
Das folgende Debian-Kommando stellt einen Wrapper für grub-mkconfig -o /boot/grub/grub.cfg
dar:
$ update-grub
Nun können wir den neuen Kernel testen und das System neu starten, wobei neuere Distributionen automatisch den neuesten Kernel auswählen
HyperLinks, Fragen zur Vertiefung
Installation und Konfiguration
Anpassungen für Webbrowser
Fragen zur Vertiefung
Welche make-Targets gibt es, die speziell für die Konfiguration der Kernel-Features eingesetzt werden können?
config, oldconfig, menuconfig, xconfig, gconfig
Welche make-Targets verwendet man gewöhnlich, um den Kernel und die Module zu bauen sowie die Module an Ort und Stelle zu kopieren?
make dep # Nur bis Kernel 2.4
make clean
make bzImage
make modules
make modules_install
Welche make-Targets gibt es zum Bereinigen von /usr/src/linux?
clean (Temporäre Dateien von vorherigen make bzImage löschen)
mrproper (gründlisches Löschen: Temporäre Dateien UND die .config-Datei)
distclean (Ganz tiefgreifend aufräumen: mrproper + remove editor backup and patch files)
Was hat es mit der Variable „EXTRAVERSION“ in der Datei „Makefile“ auf sich?
Anhang an Kernelnamen? Genau! Sinn ist, bei Durchführen eines neuen Kompilervorganges, ein neues Verzeichnis unter /lib/modules zu erhalten.
Was bewirkt das Kommando ‚make‘ oder ‚make all‘ im Verzeichnis ‚/usr/src/linux‘?
Es werden die hierbei die folgenden drei Aufgaben mit einem Mal erledigt:
Kernel ‚vmlinuz‘ bauen
Komprimiertes Kernel-Image ‚bzImage‘ bauen
Module bauen
Siehe dazu auch: