Kernel.html 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. <!doctype html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1, minimal-ui">
  6. <title>Linux-Kurs - Kernel</title>
  7. <link type="text/css" rel="stylesheet" href="assets/css/github-markdown.css">
  8. <link type="text/css" rel="stylesheet" href="assets/css/pilcrow.css">
  9. <link rel="shortcut icon" href="assets/favicon.ico">
  10. </head>
  11. <body>
  12. <article class="markdown-body"><h1 id="linux-kurs---kernel"><a class="header-link" href="#linux-kurs---kernel"></a>Linux-Kurs - Kernel</h1>
  13. <p><a href="https://linuxkurs.ch">https://linuxkurs.ch</a></p>
  14. <p>Wahlweise konntest du dein System auf Slackware -current aktualisieren oder die stabile Version beibehalten. Nun ist es an der Zeit, dass wir uns das Herzstück deines Linux-Systems etwas genauer anschauen, dem Kernel.</p>
  15. <p><strong>Hinweis</strong>: Sofern nicht anders erwähnt, müssen alle folgenden Kommandos mit Root-Rechten ausgeführt werden.</p>
  16. <h2 id="initrd"><a class="header-link" href="#initrd"></a>initrd</h2>
  17. <p>Bisher verwenden wir bei einer klassichen Installation den monolithischen <em>huge</em> Kernel. Dabei handelt es sich um eine grosse Datei, die alle wichtigen Treiber bereits enthält. Eine Alternative ist die Nutzung des sogenannten <em>generic</em> Kernels. Dieser enthält im Kernel-Image nur einen Bruchteil der Treiber. Um das System dennoch erfolgreich starten zu können, benötigst du zusätzlich eine sogenannte <em>initrd</em>, was für <em>initial ramdisk</em> steht.</p>
  18. <p>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. Auf UEFI basierten Systemen kommt bereits standardmässig eine <em>initrd</em> zum Einsatz.</p>
  19. <p>Slackware enthält ein Script mit dem Namen <em>mkinitrd_command_generator.sh</em>, welches dich bei der Erstellung der initrd unterstützt. Es überprüft welche Kernel-Module auf deinem System benötigt werden und gibt dir einen Befehl aus der zur Erstellung der Ramdisk ausgeführt werden kann:</p>
  20. <p><code>/usr/share/mkinitrd/mkinitrd_command_generator.sh</code></p>
  21. <p class="img-container"><img src="./slackware_mkinitrd.png" alt=""></p>
  22. <p>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.</p>
  23. <p>Markiere und kopiere die letzte Zeile und füge Sie in der Shell ein. Mit Enter kannst du den Befehl auslösen. Dadurch wird eine Ramdisk im Verzeichnis /boot mit dem Namen initrd.gz erstellt.</p>
  24. <p>Um den Kernel mit dieser initrd zu starten, müssen entsprechende Einträge in der Bootloader-Konfiguration hinterlegt werden. </p>
  25. <div style="page-break-after: always;"></div>
  26. <p>Auf einem klassichen System ohne UEFI kannst du dazu folgende Zeilen am Ende der <em>/etc/lilo.conf</em> vor dem Hinweis <em># Linux bootable partition config ends</em> hinzufügen:</p>
  27. <pre class="hljs"><code>image = <span class="hljs-regexp">/boot/</span>vmlinuz-generic
  28. initrd = <span class="hljs-regexp">/boot/i</span>nitrd.gz
  29. root = <span class="hljs-regexp">/dev/</span>sda2
  30. label = Linux-Generic
  31. <span class="hljs-keyword">read</span>-only
  32. </code></pre><p>Danach muss <code>lilo</code> ausgeführt werden. Versuche nun die Kernel-Versionen mit der Ramdisk zu starten. Den Kernel musst du beim Starten des Systems auswählen. Der Startvorgang sollte ein wenig schneller gehen als mit dem <em>huge</em> Kernel.</p>
  33. <p>Bei einer UEFI-Installation wird elilo verwendet. Die entsprechende Konfigurationsdatei lautet hier <em>/boot/efi/EFI/Slackware/elilo.conf</em>. Das Kernel-Image und die Ramdisk müssen dazu von <em>/boot/</em> nach <em>/boot/efi/EFI/Slackware/</em> kopiert werden. Bei der Nutzung von elilo muss kein weiterer Befehl ausgeführt werden.</p>
  34. <p>Die initrd muss nach jedem Kernel-Update neu erstellt werden und der Bootloader muss ausgeführt werden damit die Änderungen aktiv werden. Um diesen Prozess zu vereinfachen hat der Slackware-Benutzer <em>zerouno</em> ein Script erstellt, welches nach einem Kernel-Upgrade mittels slackpkg die Möglichkeit bietet die initrd neu zu erstellen und lilo auszuführen. Bei einem UEFI-System werden die benötigten Dateien durch das Script automatisch in die EFI-Partition kopiert. Du kannst es wie folgt herunterladen und aktivieren:</p>
  35. <pre class="hljs"><code>wget https:<span class="hljs-regexp">//</span>linuxkurs.ch<span class="hljs-regexp">/kurs/</span>zlookkernel.sh -O <span class="hljs-regexp">/usr/</span>libexec<span class="hljs-regexp">/slackpkg/</span>functions.d/zlookkernel.sh
  36. chmod +x <span class="hljs-regexp">/usr/</span>libexec<span class="hljs-regexp">/slackpkg/</span>functions.d/zlookkernel.sh</code></pre><p>Beim nächsten Kernel-Update mittels slackpkg wirst du abschliessend gefragt, ob die initrd neu erstellt werden soll und lilo ausgeführt werden soll. Bei einer UEFI-Installation wird angeboten, die benötigten Dateien an die entsprechende Stelle zu kopieren. Sofern du dies mit <strong>Y</strong> beantwortest erfolgt der Prozess automatisch.</p>
  37. <div style="page-break-after: always;"></div>
  38. <h2 id="eigenen-kernel-erstellen"><a class="header-link" href="#eigenen-kernel-erstellen"></a>Eigenen Kernel erstellen</h2>
  39. <p>Wir konnten die Kernel Varianten <em>huge</em> und <em>generic</em> der Distribution kennenlernen. 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. In solchen Fällen kann es sinnvoll sein einen eigenen Kernel zu compilieren.</p>
  40. <p>Wir gehen davon aus das du den <em>generic</em> Kernel gestartet hast. Sollte dies nicht der Fall sein, starte dein System neu und wähle im Bootmenü den Punkt: <em>Linux-Generic</em>.</p>
  41. <p>Um einen eigenen Kernel compilieren zu können, benötigen wir die entsprechenden Quellen. Die offiziellen Kernel-Quellen findest du auf: <a href="https://www.kernel.org">https://www.kernel.org</a></p>
  42. <p>Kopiere dir beispielsweise im Firefox den Link auf die aktuelle stabile Kernelversion indem du mit der rechten Maustaste auf <em>[tarball]</em> klickst und <strong>Link-Adresse kopieren</strong> wählst. Öffne daraufhin ein Terminal und wechsle in das Verzeichnis <em>/usr/src</em> in dem sich üblicherweise die Kernel-Quellen befinden:</p>
  43. <p><code>cd /usr/src</code></p>
  44. <p>Mithilfe des <strong>wget</strong> Befehls kannst du das Kernel-Archiv herunterladen. Gebe dazu <code>wget</code> gefolgt von einem Leerzeichen ein und füge den zuvor kopierten Link mit <code>Ctrl + Shift + V</code> ein.</p>
  45. <p>Zum Beispiel:</p>
  46. <p><code>wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.16.5.tar.xz</code></p>
  47. <p>Entpacken kannst du das Archiv mit folgendem Kommando:</p>
  48. <p><code>tar -xvpf linux-5.16.5.tar.xz</code></p>
  49. <p>Passe dabei den Dateinamen entsprechend an und wechsle daraufhin in den neu erstellten Pfad, in unserem Beispiel mithilfe von:</p>
  50. <p><code>cd linux-5.16.5</code></p>
  51. <p>Als Basis für den neuen Kernel kannst du die Konfiguration des aktiven <em>Generic</em> Kernels verwenden. Mit folgendem Befehl kannst du die bisherige Konfiguration übernehmen:</p>
  52. <p><code>zcat /proc/config.gz &gt; .config</code></p>
  53. <p>Der Befehl <code>zcat</code> verhält sich ähnlich wie der bereits bekannte <code>cat</code> Befehl, ermöglicht aber auch das Anzeigen von gzip-komprimierten Dateien. Das <code>&gt;</code> Zeichen leitet die Ausgabe um, in diesem Falle in die Datei <em>.config</em> im aktuellen Verzeichnis.</p>
  54. <p>Mithilfe von <code>make olddefconfig</code> kann daraufhin die alte Konfiguration adaptiert werden:</p>
  55. <p><code>make olddefconfig</code></p>
  56. <div style="page-break-after: always;"></div>
  57. <p>Nun ist es möglich Anpassungen an der Kernelkonfiguration vorzunehmen. Dabei hilft dir der Befehl <code>make menuconfig</code>. Alternativ gibt es eine grafische Konfigurationsoberfläche, die du mit <code>make xconfig</code> aufrufen kannst.</p>
  58. <p>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.</p>
  59. <p>Starte im Verzeichnis, in dem sich die Kernel-Sourcen befinden den folgenden Befehl:</p>
  60. <p><code>make menuconfig</code></p>
  61. <p>Es begrüsst dich eine TUI-Oberfläche, in der du wie gewohnt navigieren kannst. Wenn du ein Untermenü öffnest, kannst du über den <strong>Exit</strong> Befehl eine Ebene zurückspringen. </p>
  62. <p><strong>Hinweis:</strong> Im Hauptmenü beendet <strong>Exit</strong> die Anwendung.</p>
  63. <p>Navigiere mit den Cursortasten oder durch Aufruf des Kurzbefehls zum Punkt <em>Security Options</em> und öffne das Untermenü durch Eingabe von Enter, sofern der Punkt <strong>Select</strong> aktiviert ist.</p>
  64. <p class="img-container"><img src="./slackware_kernel_security_options.png" alt=""></p>
  65. <p>Scrolle in der sich öffnenden Parameterliste bis zu den Punkt AppArmor Support und aktiviere diesen mit der Space-Taste.</p>
  66. <p class="img-container"><img src="./slackware_kernel_apparmor.png" alt=""></p>
  67. <p>Des Weiteren muss das AppArmor <em>lockdown</em> Modul zur Liste der <em>LSMs</em> (Linux Security Modules) hinzugefügt werden. Wähle dazu weiter unten den Punkt <strong>Ordered list of enabled LMSs</strong> aus:</p>
  68. <p class="img-container"><img src="./slackware_kernel_lockdown.png" alt=""></p>
  69. <p>Es öffnet sich eine Liste der aktivierten Security Module. Füge dort <strong>,apparmor</strong> hinzu:</p>
  70. <p class="img-container"><img src="./slackware_kernel_lockdown_list.png" alt=""></p>
  71. <p>Du kannst bei Bedarf weiter Änderungen vornehmen. Speichere deine Änderungen ab, indem du mit der Tab-Taste den Punkt <strong>Save</strong> anwählst und mit Enter bestätigst.</p>
  72. <p>Du wirst nach einem Dateinamen für die Kernel-Konfigurationsdatei gefragt. Standardmässig lautet dieser <em>.config</em>. Wir gehen davon aus, dass du die Einstellung unverändert beibehältst.</p>
  73. <p>Als Nächstes kannst du die Anwendung mithilfe des <strong>Exit</strong> Befehls beenden. Du musst ihn möglicherweise mehrmals anwählen, falls du dich in einem Untermenü befindest.</p>
  74. <p>Mit folgendem Befehl startest du den Compiliervorgang:</p>
  75. <p><code>make bzImage modules</code></p>
  76. <p>Es werden das Kernel-Image (<em>bzImage</em>) sowie die Kernelmodule (<em>modules</em>) compiliert. Dieser Vorgang kann einige Zeit in Anspruch nehmen. Du kannst den Compiliervorgang beschleunigen, indem du den make-Parameter <code>-j</code> gefolgt von der Anzahl der CPU-Kerne deines Computers angibst.</p>
  77. <p>Bei vier CPU-Kernen wäre dies:</p>
  78. <p><code>make -j 4 bzImage modules</code></p>
  79. <p>Um die Anzahl der CPU-Kerne zu ermitteln, kannst du den Konsolenbefehl <code>nproc</code> nutzen.</p>
  80. <p>Die compilierten Kernelmodule müssen daraufhin in den entsprechenden Pfad kopiert werden. Standardmässig wäre dies <em>/lib/modules/</em> gefolgt von der Kernelversion. Dabei hilft dir das folgende Kommando:</p>
  81. <p><code>make modules_install</code></p>
  82. <p>Der Befehl kopiert nicht nur die Kernelmodule an den richtigen Ort, sondern führt abschliessend auch das <code>depmod</code> Kommando aus. Einige Kernelmodule haben Abhängigkeiten, die mithilfe von <strong>depmod</strong> aufgelöst und in der Datei <em>/lib/modules/KERNELVERSION/modules.dep</em> hinterlegt werden.</p>
  83. <div style="page-break-after: always;"></div>
  84. <p>Das erstellte Kernel-Image muss nun in den <em>/boot</em> Pfad kopiert werden. Bei einem UEFI-System lautet dieser: <em>/boot/efi/EFI/Slackware/</em>. Die folgenden Beispiele beziehen sich auf eine klassische Installation und müssen bei der Verwendung von UEFI entsprechend angepasst werden.</p>
  85. <p><code>cp arch/x86/boot/bzImage /boot/vmlinuz-5.16.5</code></p>
  86. <p>Ersetze die Kernelversion (in diesem Beispiel <em>5.16.5</em>) durch diejenige des Kernels den du compiliert hast.</p>
  87. <p>Es ist sinnvoll auch die <em>System.map</em> sowie die Kernelkonfiguration in den <em>/boot</em> Pfad zu kopieren:</p>
  88. <pre class="hljs"><code><span class="hljs-attribute">cp</span> System.map /boot/System.map-<span class="hljs-number">5</span>.<span class="hljs-number">16</span>.<span class="hljs-number">5</span>
  89. <span class="hljs-attribute">cp</span> .config /boot/config-<span class="hljs-number">5</span>.<span class="hljs-number">16</span>.<span class="hljs-number">5</span></code></pre><p>Auch hier muss der Dateiname entsprechend angepasst werden, sodass er der compilierten Kernelversion entspricht. Die <em>System.map</em> wird im Fehlerfalle zum Debugging genutzt. Ausführliche Informationen dazu findest du auf folgender Webseite: <a href="https://rlworkman.net/system.map/">https://rlworkman.net/system.map/</a></p>
  90. <h3 id="ramdisk"><a class="header-link" href="#ramdisk"></a>Ramdisk</h3>
  91. <p>Da wir den neuen Kernel auf der Basis des <em>generic</em> Kernels erstellt haben, ist eine Ramdisk zwingend notwendig. Zur Erstellung kannst du das <em>mkinitrd_command_generator.sh</em> Script zur Hilfe nehmen.</p>
  92. <p><code>$(/usr/share/mkinitrd/mkinitrd_command_generator.sh -k 5.16.5 -a &quot;-o /boot/initrd-5.16.5.gz&quot; --run)</code></p>
  93. <p>Ersetze hierbei die Kernelversion durch die deines Kernels. Der Parameter <em>--run</em> gibt nur das Kommando zur Erstellung der initrd ohne weitere Bemerkungen aus. Da wir die gesamte Zeichenkette in <em>$()</em> stellen, wird diese von der BASH als Befehl interpretiert, also direkt ausgeführt und die initrd erzeugt. </p>
  94. <p>Jedes Mal, wenn du einen neuen Kernel compilierst und verwenden möchtest, musst du initrd erneut erzeugen.</p>
  95. <h3 id="bootloader"><a class="header-link" href="#bootloader"></a>Bootloader</h3>
  96. <p>Abschliessend wird der Bootloader angepasst, sodass du in der Lage bist deinen neuen Kernel zu starten.</p>
  97. <p>Bei einer klassichen Installation kannst du dazu einen entsprechenden Eintrag vor dem Hinweis <em># Linux bootable partition config ends</em> zu der <em>/etc/lilo.conf</em> Konfigurationsdatei hinzufügen:</p>
  98. <pre class="hljs"><code><span class="hljs-attribute">image</span> = /boot/vmlinuz-<span class="hljs-number">5</span>.<span class="hljs-number">16</span>.<span class="hljs-number">5</span>
  99. <span class="hljs-attribute">initrd</span> = /boot/initrd-<span class="hljs-number">5</span>.<span class="hljs-number">16</span>.<span class="hljs-number">5</span>.gz
  100. <span class="hljs-attribute">root</span> = /dev/sda<span class="hljs-number">2</span>
  101. <span class="hljs-attribute">label</span> = Linux-<span class="hljs-number">5</span>.<span class="hljs-number">16</span>.<span class="hljs-number">5</span>
  102. <span class="hljs-attribute">read</span>-only</code></pre><p>Wobei die Versionsnummer entsprechend angepasst werden muss, sodass sie deinem Kernel entspricht.</p>
  103. <p>Führe <code>lilo</code> aus und versuche deine erste selbstcompilierte Kernelversionen zu starten.</p>
  104. <p>Auf einem UEFI-System muss die Datei <em>/boot/efi/EFI/Slackware/elilo.conf</em> angepasst werden und das Kernel-Image sowie die Ramdisk nach nach <em>/boot/efi/EFI/Slackware/</em> kopiert werden.</p>
  105. <h2 id="apparmor"><a class="header-link" href="#apparmor"></a>AppArmor</h2>
  106. <p>Wir haben den Kernel nun um AppArmor-Unterstützung erweitert. Nun fehlt nur noch die passende Anwendung. Diese lässt sich mithilfe des SlackBuild-Scriptes erstellen:</p>
  107. <p><code>sbopkg -i apparmor</code></p>
  108. <p>Damit AppArmor beim Systemstart automatisch geladen wird, kann ein entsprechender Eintrag zur Datei <em>/etc/rc.d/rc.local</em> hinzugefügt werden:</p>
  109. <p><code>vi /etc/rc.d/rc.local</code></p>
  110. <pre class="hljs"><code><span class="hljs-comment"># Start apparmor</span>
  111. <span class="hljs-keyword">if</span> [ -x <span class="hljs-regexp">/etc/</span>rc.d/rc.apparmor ]; then
  112. <span class="hljs-regexp">/etc/</span>rc.d/rc.apparmor start
  113. fi</code></pre><p>Starte dein System neu und untersuche ob AppArmor aktiv ist:</p>
  114. <p><code>aa-status</code></p>
  115. <p>Damit hast du erfolgreich deinen eigenen Kernel compiliert.</p>
  116. <hr>
  117. <p>© CC-BY-SA - Lioh Moeller</p>
  118. </article>
  119. </body>
  120. </html>