Kernel.md_full 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. # Linux-Kurs - Kernel
  2. Du konntest dein System erfolgreich auf Slackware -current aktualisieren. Nun ist es an der Zeit, dass wir uns den Kernel etwas genauer anschauen. Doch dazu ist einiges an Vorarbeit notwendig, denn wenn dein Kernel nicht mehr startet, kannst Du nur noch über Umwege auf dein System zugreifen.
  3. **Hinweis**: Sofern nicht anders erwähnt, müssen alle folgenden Kommandos mit Root-Rechten ausgeführt werden.
  4. ## -current Synchronisation.
  5. Zunächst möchten wir die Slackware-Paketaktualisierungen nicht mehr wie bisher über einen Internet-Mirror beziehen, sondern über einen lokalen Spiegelserver. Das heisst wir erstellen eine lokale Kopie des vollständigen Slackware -current Paketrepositories für die x86_64 Architektur. Wir werden diesen lokalen Mirror nutzen um Schwierigkeiten beim Upgrade zu vermeiden und weil wir den Kernel von der Aktualisierung mittels slackpkg ausschliessen möchten, um diesen später unabhängig von slackpkg updaten zu können.
  6. Der Slackware Entwickler alienBOB stellt ein Script zur Synchronisation des -current Repositories zur Verfügung. Du kannst es mit Hilfe des **wget** Befehls herunterladen und mittels **chmod** als ausführbar markieren:
  7. ```
  8. su -
  9. wget http://slackware.uk/people/alien/tools/mirror-slackware-current.sh -O /usr/local/sbin/mirror-slackware-current.sh
  10. chmod +x /usr/local/sbin/mirror-slackware-current.sh
  11. ```
  12. Das Script ermöglicht die Synchronisation des -current Repositories mit Hilfe des **rsync** Kommandos und die Erstellung von ISO-Images. Standardmässig würde die 32bit Version synchronisiert. Um stattdessen die 64bit Variante der Distribution zu synchronisieren, bearbeite das heruntergeladene Script:
  13. `vi /usr/local/sbin/mirror-slackware-current.sh`
  14. Ändere den Inhalt der Variable *ARCH* von *x86* auf *x86_64*:
  15. `ARCH=${ARCH:-"x86_64"}`
  16. ![](./slackware_mirror_current_arch.png)
  17. Da wir keine ISO-Images erstellen möchten, kannst Du den Inhalt der Variable *ISO* auf *NONE* setzen:
  18. `ISO=${ISO:-"NONE"}`
  19. ![](./slackware_mirror_current_iso.png)
  20. Speichere deine Änderungen ab und verlasse den Editor.
  21. Das Script verwendet als Standard-Speicherort den Pfad */home/ftp/pub/Linux/Slackware/slackware64-current* zur Synchronisation der 64bit-Variante. Da dieser noch nicht existiert musst Du es mit dem **mkdir** Kommando anlegen:
  22. `mkdir -p /home/ftp/pub/Linux/Slackware/slackware64-current/`
  23. Starte die Synchronisation indem Du das Script ausführst. Diese kann initial einige Zeit in Anspruch nehmen, da alle Pakete synchronisiert werden müssen. Wenn Du zu einem späteren Zeitpunkt das Script erneut aufrufst, werden nur noch die Änderungen synchronisiert:
  24. `mirror-slackware-current.sh`
  25. **Hinweis**: sollte die Synchronisation einmal abbrechen, kannst Du das Script erneut unter Angabe des Parameters **-f** aufrufen. Dieser erzwingt eine Synchronisation, auch wenn sich der Changelog nicht geändert hat. Über den zusätzlichen Parameter **-v** erhältst Du eine ausführlichere Ausgabe.
  26. <div style="page-break-after: always;"></div>
  27. ### slackpkg Anpassungen
  28. Zur Verwaltung der offiziellen Slackware-Pakete nutzen wir weiterhin den Paketmanager **slackpkg**. In der Datei */etc/slackpkg/mirrors* haben wir bisher einen Internet-Spiegelserver hinterlegt.
  29. Diesen kannst Du auskommentieren und in der gleichen Datei den lokalen Mirror aktivieren.
  30. ```
  31. vi /etc/slackpkg/mirrors
  32. ```
  33. Suche die Zeile mit dem aktiven Slackware64 *-current* Mirror und füge am Zeilenanfang ein *#*-Zeichen ein.
  34. Zu Beginn der Datei findest Du eine Beispielkonfiguration für einen lokalen Mirror. Diese beginnt mit *file://*. Entferne das *#*-Zeichen vor dem Eintrag und passe den Pfad an, so dass er auf das lokale Verzeichnis zeigt:
  35. `file://home/ftp/pub/Linux/Slackware/slackware64-current/`
  36. Beachte bitte den abschliessenden */* in der Pfadangabe. Zusammengefasst sollte die Konfiguration wie folgt aussehen:
  37. ![](./slackware_slackpkg_mirror_current.png)
  38. Du kannst natürlich die weiteren auskommentierten Mirrors in der Datei beibehalten. Es darf allerdings nur ein Mirror aktiv konfiguriert sein.
  39. <div style="page-break-after: always;"></div>
  40. Zusätzlich möchten wir gerne den Kernel von der Aktualisierung mittels slackpkg ausnehmen, da andernfalls die bisherige Kernelversion durch ein Update überschrieben würde. Sollte es mit der neueren Kernelversion zu Schwierigkeiten kommen, könntest Du nur noch über ein Rettungsmedium auf dein Linux-System zugreifen.
  41. Füge dazu folgende Einträge zur Datei */etc/slackpkg/blacklist* hinzu:
  42. ```
  43. kernel-generic
  44. kernel-generic-smp
  45. kernel-headers
  46. kernel-huge
  47. kernel-huge-smp
  48. kernel-modules
  49. kernel-modules-smp
  50. kernel-source
  51. ```
  52. ![](./slackware_slackpkg_blacklist_ponce_wsr_kernel.png)
  53. ### System aktualisieren
  54. Die Aktualisierung deines Systems erfolgt wie gewohnt, mit dem Zusatz, dass Du nun zuvor das *mirror-slackware-current.sh* ausführen musst.
  55. ```
  56. mirror-slackware-current.sh
  57. slackpkg update
  58. slackpkg install-new
  59. slackpkg upgrade-all
  60. slackpkg clean-system
  61. ```
  62. Optional erfolgt die Aktualisierung der 3rd-Party-Repositories, falls Du diese konfiguriert hast:
  63. `slackpkg install ktown`
  64. und/oder:
  65. `slackpkg install multilib`
  66. ## Kernel aktualisieren
  67. Da wir nun den Kernel in der slackpkg Blacklist-Konfiguration von der Aktualisierung ausgenommen haben, wird dieser bei einem *slackpkg upgrade-all* nicht mehr geupdated. Ein Scriptes des Slackware Benutzers *luvr* ermöglicht die Aktualisierung des Kernels unter Beibehalten der bisherigen lauffähigen Version. So hast Du im Bedarfsfall immer die Möglichkeit dein System mit der vorherigen Kernel-Version zu starten.
  68. Lade das Script herunter und markiere es mit Hilfe des **chmod** Befehls als ausführbar:
  69. ```
  70. wget 'https://www.linuxquestions.org/questions/attachment.php?attachmentid=31763&d=1572878978' -O /usr/local/sbin/upgrade-kernel.sh
  71. chmod +x /usr/local/sbin/upgrade-kernel.sh
  72. ```
  73. **Hinweis**: die Anführungszeichen um die Download-URL sind in diesem Falle notwendig, da der Link ein `&`-Zeichen enthält, welches andernfalls von der BASH interpretiert würden. Alternativ könntest Du statt der einfachen Anführungszeichen um den Link auch das Sonderzeichen mit Hilfe von `\` *escapen* um es von der Interpretation durch die BASH auszuschliessen: `../questions/attachment.php?attachmentid=30786\&..`
  74. Führe das Script zur Aktualisierung des Kernels aus:
  75. `/usr/local/sbin/upgrade-kernel.sh`
  76. <div style="page-break-after: always;"></div>
  77. Es begrüsst dich mit einer TUI-Oberfläche und bietet dir an die neue Kernelversion herunterzuladen und zu installieren, sowie vorhandene Kernelversionen zu entfernen. Eine mögliche Ausgabe sieht wie folgt aus:
  78. ![](./slackware_upgrade_kernel.png)
  79. Die Installation erfolgt dabei parallel zur vorhandenen Kernel-Version. Es werden entsprechende Symlinks im Verzeichnis */boot* generiert auf welche Du in lilo referenzieren kannst.
  80. Sollte keine Kernel-Aktualisierung vorliegen, kannst Du die TUI verlassen. Dann ist es an der Zeit abzuwarten bis das nächste Kernel-Update im -current Zweig erfolgt, bevor Du weiter fortfährst. Zur Kontrolle hilft ein regelmässiger Blick in den Changelog:
  81. ftp://ftp.osuosl.org/pub/slackware/slackware64-current/ChangeLog.txt
  82. Wenn sich dort Veränderungen ergeben haben, kannst Du deinen lokalen Mirror mit Hilfe des *mirror-slackware-current.sh* Scriptes aktualisieren und die zuvor erwähnten Schritte ausführen. Falls die Änderungen eine aktuellere Kernel-Version beinhalten, kannst Du nun das *upgrade-kernel.sh* Script ausführen.
  83. ### Bootloader anpassen
  84. Sobald das erste Kernel-Update mit Hilfe des *upgrade-kernel-sh* Scriptes installiert worden ist, werden symbolische Links auf die jeweils neue und die vorherige Kernelversion erstellt. Diese werden bei fortlaufenden Kernel-Aktualisierungen entsprechend angepasst.
  85. Um die vom *upgrade-kernel.sh* Script erstellten symbolischen Links beim Systemstart auswählen zu können, muss die Datei */etc/lilo.conf* angepasst werden:
  86. `vi /etc/lilo.conf`
  87. Ersetze den bisherigen Abschnitt am Ende der Datei durch:
  88. ```
  89. image = /boot/vmlinuz-huge
  90. root = /dev/sda2
  91. label = Huge
  92. read-only
  93. image = /boot/vmlinuz-huge-prev
  94. root = /dev/sda2
  95. label = Huge-prev
  96. read-only
  97. ```
  98. Nach der Anpassung muss der Bootloader neu geschrieben werden:
  99. `lilo`
  100. Dies Aktualisierung des Bootloaders muss zwingend nach jeder Kernel-Aktualisierung ausgeführt werden.
  101. ### Funktion überprüfen
  102. Sobald die erste Kernelaktualisierung erfolgt ist, was unter Slackware -current sehr häufig der Fall sein kann, prüfe bitte ob Du den neuen Kernel mit der Bezeichnung *Linux* sowie den vorherigen Kernel mit der Bezeichnung *Linux-prev* erfolgreich starten kannst. Die aktive Kernelversion kannst Du dir mit Hilfe des `uname` Befehls ausgeben lassen:
  103. `uname -a`
  104. ## initrd
  105. Sollte alles soweit funktioniert haben, können wir die erste Änderung an der Kernelkonfiguration vornehmen. Bisher verwenden wir den monolithischen *huge* Kernel. Dabei handelt es sich um eine grosse Datei, die alle wichtigen Kernelmodule bereits enthält. Eine Alternative ist die Nutzung des sogenannten *generic* Kernels. Dieser enthält im Kernel-Image nur einen Bruchteil der Module. Um das System dennoch erfolgreich starten zu können, benötigst Du zusätzlich eine sogenannte *initrd*, was für *initial ramdisk* steht.
  106. Diese initrd ist dynamisch und wird auf dein System angepasst. Beim Startvorgang lädt der Kernel die initrd nach und fährt dann mit dem init Prozess fort.
  107. Slackware enthält ein Script mit dem Namen *mkinitrd_command_generator.sh* welches dich bei der Erstellung der initrd unterstützt. Es überprüft welche Module auf deinem System benötigt werden und gibt dir einen Befehl aus der zur Erstellung der Ramdisk ausgeführt werden kann:
  108. `/usr/share/mkinitrd/mkinitrd_command_generator.sh`
  109. ![](./slackware_mkinitrd.png)
  110. Ohne weitere Parameter bezieht sich das Script auf den aktuell laufenden Kernel. Es wird standardmässig keine Ramdisk erstellt sondern nur der Befehl ausgegeben, mit dem diese generiert werden kann.
  111. Das *upgrade-kernel.sh* Script ruft den *mkinitrd_command_generator.sh* automatisch bei einer Kernel-Aktualisierung auf. Es ist daher nicht notwendig die Ramdisk manuell zu erstellen. Schaue dir das *upgrade-kernel.sh* Script einmal mit dem `view` Befehl an:
  112. `view /usr/local/sbin/upgrade-kernel.sh`
  113. Suche dort im Befehlsmodus mit Hilfe von `/mkinitrd` nach dem Aufruf des *mkinitrd_command_generator.sh* Scriptes:
  114. ![](./slackware_upgrade_kernel_mkinitrd.png)
  115. `$(/usr/share/mkinitrd/mkinitrd_command_generator.sh -a '-o '"${INITRD}" --run "${KERNEL}")`
  116. Hier wird das Script zur Erstellung der Ramdisk unter Angabe des gewünschten Namens und der Kernelversion aufgerufen.
  117. Um den Kernel mit der initrd zu starten, müssen entsprechende Einträge in der Bootloader-Konfiguration hinterlegt werden. Füge dazu folgende Zeilen am Ende der */etc/lilo.conf* vor dem Hinweis *# Linux bootable partition config ends* hinzu:
  118. ```
  119. image = /boot/vmlinuz-generic
  120. initrd = /boot/initrd-generic
  121. root = /dev/sda2
  122. label = Generic
  123. read-only
  124. image = /boot/vmlinuz-generic-prev
  125. initrd = /boot/initrd-generic-prev
  126. root = /dev/sda2
  127. label = Generic-Prev
  128. read-only
  129. ```
  130. Auch hier werden die passenden symbolischen Links für den neuen sowie den vorherigen Kernel vom *upgrade-kernel.sh* Script erzeugt.
  131. Führe `lilo` aus und versuche die Kernel-Versionen mit der Ramdisk zu starten. Der Startvorgang sollte ein wenig schneller gehen als mit dem *huge* Kernel.
  132. ## Eigenen Kernel erstellen
  133. Bisher haben wir die Kernel Varianten *huge* und *generic* der Distribution genutzt. Es kann allerdings vorkommen, dass eine neuere Kernelversion benötigt wird. Grund dafür kann zum Beispiel fehlende Hardwareunterstützung in der Distributions-Version sein.
  134. Wir gehen davon aus das Du den *generic* Kernel gestartet hast. Sollte dies nicht der Fall sein, starte dein System neu und wähle im lilo Bootmenü den Punkt: *Generic*.
  135. Um einen eigenen Kernel compilieren zu können, benötigen wir die entsprechenden Quellen. Die offiziellen Kernel-Quellen findest du auf: https://www.kernel.org
  136. Kopiere dir beispielsweise im Firefox den Link auf die aktuelle stabile Kernelversion indem du mit der rechten Maustaste auf *[tarball]* klickst und **Link-Adresse kopieren** wählst. Öffne daraufhin ein Terminal und wechsle in das Verzeichnis */usr/src* in dem sich üblicherweise die Kernel-Quellen befinden:
  137. `cd /usr/src`
  138. Mit Hilfe des **wget** Befehls kannst Du das Kernel-Archiv herunterladen. Gebe dazu `wget` gefolgt von einem Leerzeichen ein und füge den zuvor kopierten Link mit `Ctrl + Shift + V` ein.
  139. Zum Beispiel:
  140. `wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.3.7.tar.xz`
  141. Entpacken kannst Du das Archiv mit folgendem Kommando:
  142. `tar -xvpf linux-*.tar.xz`
  143. Wechsle daraufhin in den neu erstellten Pfad, in unserem Beispiel mit Hilfe von:
  144. `cd linux-5.3.7`
  145. Als Basis für den neuen Kernel kannst Du die Konfiguration deines bisherigen Kernels verwenden. Mit folgendem Befehl kannst Du die bisherige Konfiguration übernehmen:
  146. `zcat /proc/config.gz > .config`
  147. Der Befehl `zcat` verhält sich ähnlich wie der bereits bekannte `cat` Befehl, ermöglicht aber auch das Anzeigen von gzip-komprimierten Dateien. Das `>` Zeichen leitet die Ausgabe um, in diesem Falle in die Datei *.config* im aktuellen Verzeichnis.
  148. Mit Hilfe von `make olddefconfig` kann daraufhin die alte Konfiguration adaptiert werden:
  149. `make olddefconfig`
  150. Nun ist es möglich Anpassungen an der Kernelkonfiguration vorzunehmen. Dabei hilft dir der Befehl `make menuconfig`. Alternativ gibt es eine grafische Konfigurationsoberfläche die Du mit `make xconfig` aufrufen kannst.
  151. Anpassungen am Kernel sind optional. Als Beispiel möchten wir die Unterstützung für das Sicherheitsframework AppArmor aktivieren. Dieses bietet zusätzlichen Schutz auch vor noch nicht öffentlich bekannten Sicherheitslücken, sogenannten Zero-Day-Exploits.
  152. Starte im Verzeichnis in dem sich die Kernel-Sourcen befinden den folgenden Befehl:
  153. `make menuconfig`
  154. Es begrüsst dich eine TUI-Oberfläche in der Du wie gewohnt navigieren kannst. Wenn Du ein Untermenü öffnest, kannst Du über den **Exit** Befehl eine Ebene zurückspringen.
  155. **Hinweis:** Im Hauptmenü beendet **Exit** die Anwendung.
  156. Navigiere mit den Cursortasten oder durch Aufruf des Kurzbefehls zum Punkt *Security Options* und öffne das Untermenü durch Eingabe von Enter, sofern der Punkt **Select** aktiviert ist.
  157. ![](./slackware_kernel_security_options.png)
  158. Scrolle in der sich öffnenden Parameterliste bis zu den Punkt AppArmor Support und aktiviere diesen mit der Space-Taste.
  159. ![](./slackware_kernel_apparmor.png)
  160. Du kannst bei Bedarf weiter Änderungen vornehmen. Speichere deine Änderungen ab, indem Du mit der Tab-Taste den Punkt **Save** anwählst und mit Enter bestätigst.
  161. Du wirst nach einem Dateinamen für die Kernel-Konfigurationsdatei gefragt. Standardmässig lautet dieser *.config*. Wir gehen davon aus, dass Du die Einstellung unverändert beibehältst.
  162. Als nächstes kannst Du die Anwendung mit Hilfe des **Exit** Befehls beenden. Du musst ihn möglicherweise mehrmals anwählen, falls Du dich in einem Untermenü befindest.
  163. Mit folgendem Befehl startest Du den Compiliervorgang:
  164. `make bzImage modules`
  165. Es werden das Kernel-Image (*bzImage*) sowie die Kernelmodule (*modules*) compiliert. Dieser Vorgang kann einige Zeit in Anspruch nehmen.
  166. Die compilierten Kernelmodule müssen daraufhin in den entsprechenden Pfad kopiert werden. Standardmässig wäre dies */lib/modules/* gefolgt von der Kernelversion. Dabei hilft dir das folgende Kommando:
  167. `make modules_install`
  168. Der Befehl kopiert nicht nur die Kernelmodule an den richtigen Ort sondern führt abschliessend auch das `depmod` Kommando aus. Einige Kernelmodule haben Abhängigkeiten, die mit Hilfe von **depmod** aufgelöst und in der Datei */lib/modules/KERNELVERSION/modules.dep* hinterlegt werden.
  169. Das eigentliche Kernel-Image muss nun in den */boot* Pfad kopiert werden:
  170. `cp arch/x86/boot/bzImage /boot/vmlinuz-5.3.7`
  171. Ersetze die Kernel-Version (in diesem Beispiel *5.3.7*) durch diejenige des Kernels den Du compiliert hast.
  172. Es ist sinnvoll auch die *System.map* sowie die Kernel-Konfiguration in den */boot* Pfad zu kopieren:
  173. ```
  174. cp System.map /boot/System.map-5.3.7
  175. cp .config /boot/config-5.3.7
  176. ```
  177. Auch hier muss der Dateiname entsprechend angepasst werden, so dass er der compilierten Kernelversion entspricht. Die *System.map* wird im Fehlerfalle zum Debugging genutzt. Ausführliche Informationen dazu findest du auf folgender Webseite: https://rlworkman.net/system.map/
  178. ### Ramdisk
  179. Da wir den neuen Kernel auf der Basis des *generic* Kernels erstellt haben, ist eine Ramdisk zwingend notwendig. Zur Erstellung kannst Du das *mkinitrd_command_generator.sh* Script zur Hilfe nehmen.
  180. `$(/usr/share/mkinitrd/mkinitrd_command_generator.sh -k 5.3.7 -a "-o /boot/initrd-5.3.7.gz" --run)`
  181. Ersetze hierbei die Kernelversion durch die deines Kernels. Der Parameter *--run* gibt nur das Kommando zur Erstellung der initrd ohne weitere Bemerkungen aus. Da wir die gesamte Zeichenkette in *$()* stellen, wird diese von der BASH als Befehl interpretiert, also direkt ausgeführt und die initrd erzeugt.
  182. Das *upgrade-kernel.sh* Script kümmert sich nicht um die Erstellung der Ramdisk für deinen persönlichen Kernel. Jedes Mal wenn Du einen neuen Kernel compilierst und verwenden möchtest musst Du initrd erneut erzeugen.
  183. ### Bootloader
  184. Abschliessend wird der Bootloader angepasst, so dass Du in der Lage bist deinen neuen Kernel zu starten.
  185. Füge dazu einen entsprechenden Eintrag vor dem Hinweis *# Linux bootable partition config ends* zu der */etc/lilo.conf* Konfigurationsdatei hinzu:
  186. ```
  187. image = /boot/vmlinuz-5.3.7
  188. initrd = /boot/initrd-5.3.7.gz
  189. root = /dev/sda2
  190. label = Linux-5.3.7
  191. read-only
  192. ```
  193. Wobei die Versionsnummer entsprechend angepasst werden muss, so dass sie deinem Kernel entspricht.
  194. Führe `lilo` aus und versuche deine erste selbstcompilierte Kernel-Versionen zu starten.
  195. ...
  196. Würdest Du neben den Standardmodulen die automatisch vom *mkinitrd_command_generator.sh* Script integriert werden weitere Module oder Parameter angeben wollen, könntest Du diese Zeile entsprechend anpassen.
  197. Ein Beispiel zur Verwendung des Schweizerdeutschen Tastaturlayouts zum Entsperren von verschlüsselten Partitionen könnte wie folgt aussehen:
  198. `$(/usr/share/mkinitrd/mkinitrd_command_generator.sh -a -l sg-latin1 -h /dev/cryptvg/swap '-o '"${INITRD}" --run "${KERNEL}")`
  199. Hier wird ausserdem der Parameter `-h /dev/cryptvg/swap` verwendet, welcher besagt, dass bei einem Hibernate-Vorgang die verschlüsselte Swap Partition zur Sicherung des Systemstands verwendet werden soll.
  200. Da Du bisher auf deinem Linux-System keine Festplattenverschlüsselung