Bewertung: 3


Die Kandidaten sollten in der Lage sein, ein Linux-System sowohl während des Bootvorgangs, als auch im Recovery-Mode zu manipulieren. Dieses Prüfungsziel beinhaltet sowohl den Umgang mit dem init-Programm, als auch mit dem Kernel-Parameter init=

Schlüsseldateien, Begriffe und Hilfsmittel beinhalten:

  • LILO
  • init
  • /etc/inittab
  • mount
  • fsck

Wie wir im letzten Kapitel ja schon gesehen haben, ist der init-Prozess der Prozess, der sich um die gesamte Initialisierung des Systems kümmert und praktisch die Kontrolle über das System übernimmt, sobald der Kernel und seine notwendigen Module geladen sind und das Wurzeldateisystem das erste Mal (read only) eingehängt ist.

In manchen Fällen kann es beim Systemstart zu der Notwendigkeit eines Benutzereingriffs kommen, etwa wenn bei der Überprüfung der Dateisysteme ein Fehler auftaucht, der nicht automatisch repariert werden kann. In diesem Fall wechselt der init-Prozess in den sogenannten Recovery-Mode, in dem sich nur der Systemverwalter bewegen darf. Aus diesem Grund fragt init nach dem root-Passwort und öffnet dann eine Shell, die eben einen manuellen Eingriff ermöglicht. Dieser Recovery-Mode (oder auch maintanance mode) kann nur durch die Eingabe eines Dateiende-Zeichens (Strg-D) beendet werden, worauf der normale Bootvorgang fortfährt.

Typische Arbeiten im Recovery-Mode

Dateisystemcheck von Hand aufrufen

Im Normallfall wird der Recovery-Mode nur aufgerufen, wenn beim Booten eine schwerwiegende Unstimmigkeit bei der Überprüfung der Dateisysteme gefunden wurde. In diesem Fall ist es notwendig, das System „von Hand“ zu reparieren. In der Regel geschieht das mit dem Programm fsck (FileSystemChecK). Meist ist die Fehlermeldung noch auf dem Bildschirm zu sehen, die zum Wechsel in den Recovery-Mode geführt hat und dort ist dann auch die Partition zu lesen, bei der es zu dem Fehler kam. Diese Partition wird dann manuell überprüft, indem wir einfach den Befehl

  fsck Partition

eingeben, wobei statt Partition natürlich die entsprechende Gerätedatei (z.B. /dev/hdc3 oder /dev/sdb2) angegeben wird. Im weiteren Verlauf der Überprüfung werden dann entsprechende Fragen gestellt, ob bestimmte Reparaturarbeiten ausgeführt werden sollen. In den allermeisten Fällen werden diese Fragen mit ja (y) beantwortet.

Das Wurzelsystem read-write mounten

Wenn andere Arbeiten im Recovery-Modus anstehen, dann sind es in der Regel Aufgaben, die Veränderungen am Dateisystem bedingen. Aber beim Start dieses Modus ist die Wurzelpartition ja read-only gemountet. Das heißt, es ist unmöglich, Arbeiten an Dateien vorzunehmen oder Dateien zu löschen. Damit diese Arbeiten trotzdem möglich werden, muß das Wurzeldateisystem von Hand read-write gemountet werden. Dazu wird der folgende Befehl eingegeben:

  mount -n -o remount,rw /

Dabei haben die Parameter folgende Bedeutung: -n Es wird kein Eintrag in /etc/mtab geschrieben – das ist ja eben auch nicht möglich, weil wir ja noch ein read-only Dateisystem haben. -o remount,rw Mit -o werden Optionen zum Einhängen des Dateisystems angegeben. Hier sind es die Optionen remount (ein schon eingehängtes Dateisystem wird erneut eingehängt) und rw (read-write). Mehrere Optionen werden durch Kommata voneinander getrennt. / Das zu mountende Dateisystem – hier also die Wurzel.

Jetzt können beliebige Arbeiten am Wurzeldateisystem ausgeführt werden (außer dem Filesystemcheck, dazu sollte das Dateisystem readonly gemountet sein).

Mounten anderer Dateisysteme

In manchen Fällen kann es auch notwendig werden, andere Dateisysteme einzuhängen um notwendige Reparaturen vorzunehmen. Wenn ein notwendiges Hilfsmittel z.B. unter /usr/bin oder /usr/sbin liegt und das /usr Dateisystem auf einer anderen Partition liegt, dann müssen wir dieses Dateisystem von Hand einhängen. Dazu haben wir zwei Möglichkeiten. Entweder wir mounten gleich alles mit dem Befehl

  mount -a

oder wir begnügen uns mit dem Notwendigen – in unserem Beispiel also der /usr Partition. Das Wurzelsystem ist ja bereits geladen, wir haben also Zugriff auf die Datei /etc/fstab, die ja die notwendigen Informationen über die zu mountenden Partitionen enthält. Es reicht also ein

  mount /usr

um das /usr Verzeichnis zu mounten.

Runlevel während des laufenden Betriebs wechseln

Wenn auf einem laufenden System die oben beschriebenen Reparaturarbeiten ausgeführt werden sollen, dann haben wir ein Problem. Ein Multiuser-System wie Linux birgt immer die Gefahr, dass andere User oder einfach nur andere Prozesse (z.B. Serverdienste) etwas auf die Partition schreiben wollen, während wir gerade am Reparieren des Dateisystems sind. Das kann zu ernsthaften Fehlern bis hin zur Unbrauchbarkeit eines Dateisystems führen. In diesem Fall müssen wir also „von Hand“ in den Single-User Modus wechseln, damit so etwas garnicht passieren kann.

Wie wir im letzten Kapitel ja gesehen haben, verwaltet der init-Prozess verschiedene Runlevel. Wir haben zwar einen voreingestellten Runlevel (initdefault in /etc/inittab) aber wir können während des Betriebs jederzeit in einen anderen Runlevel wechseln. Dazu dienen die beiden Befehle init und telinit. Beide Befehle bewirken exakt das selbe, in der Regel ist telinit nur ein symbolischer Link auf init. Als Parameter geben wir den gewünschten Runlevel an. Um in den Single-User Mode zu wechseln werden wir also das S eingeben:

  telinit S

Genauso können wir natürlich jederzeit auch in jeden anderen Runlevel wechseln, je nachdem, wie unser System eingerichtet ist.

Kernelparameter

Im letzten Kapitel haben wir bereits gesehen, dass jeder Kernel noch Parameter beim Start mitbekommen kann. Es ist von Version zu Version unterschiedlich, welche Parameter der Kernel versteht, die aktuelle Liste für jeden Kernel finden Sie jeweils im Verzeichnis Documentation auf der Wurzel des Kernelquellbaums. Hier liegt eine Datei kernel-parameters.txt, die alle bekannten Parameter auflistet.

Die Liste der aktuell verwendeten Parameter ist in /proc/cmdline einsehbar. Wenn keine Parameter angegeben wurden steht hier immer der Parameter auto und der Name des geladenen Images.

Kernelparameter beim Booten angeben

Wenn einzelne Parameter dem Kernel nur einmal mitgegeben werden sollen – etwa für eine Notfallreparatur, oder um eine andere Einstellung auszuprobieren, so kann dies direkt am Bootprompt geschehen. Wenn wir z.B. ein Linux-System mit lilo starten, dann haben wir am Bildschirm während des Startens die Angabe:

  LILO boot:

An dieser Stelle erwartet lilo die Angabe eines Kernel-Labels (was wir vorher in /etc/lilo.conf als label=xxx angegeben hatten) und eventuell zusätzlichen Kernelparametern. In unserem Beispiel aus Kapitel 2.201.2 hatten wir die Label linuxneu und linuxorg benutzt. Statt jetzt nur linuxneu anzugeben könnten wir auch schreiben:

  LILO boot: linuxneu root=/dev/hda7

In diesem Fall wäre also die Angabe root=/dev/hda7 ein Kernelparameter, den wir von Hand beim Booten eingegeben haben. Zu beachten ist übrigens, dass während des Bootvorgangs natürlich noch kein Tastaturtreiber geladen ist und somit die englische Tastatur aktiv ist.

Diese Methode ist natürlich nur geeignet, um bestimmte Dinge auszuprobieren oder Parameter einzugeben, die nur einmal benötigt werden – etwa zur Wiederherstellung eines Systems.

Kernelparameter fest in lilo.conf eintragen

Wenn wir dem Kernel regelmäßig bei jedem Booten bestimmte Parameter mitgeben wollen, etwa die I/O Adresse unserer Netzwerkkarte, so wäre es natürlich sehr aufwendig, wenn wir das jedesmal von Hand eingeben müssten. Aus diesem Grund bietet uns die Datei /etc/lilo.conf die Möglichkeit, diese Parameter hier schon anzugeben.

Für jedes angegebene Linux-Image können wir in der Datei /etc/lilo.conf einmal eine Parameterzeile angeben, die jedesmal mit diesem Kernel dann aufgerufen werden soll. Dazu dient die Anweisung

  append = Kernelparameter

Wobei die Kernelparameter, die wir hier angeben in Anführungszeichen („…“) stehen sollten, wenn wir mehrere angeben wollen, weil wir einzelne Kernelparameter mit Leerzeichen voneinander trennen. Wir können also einfach eine Append-Zeile an den jeweiligen Kernelblock in der Datei anhängen:

  image = /boot/bzImage_2
  label = linuxneu
  root = /dev/hdc1
  append = "ne=0x320,5 mem=96M"

Natürlich muß nach dieser Änderung wiederum der Befehl lilo eingegeben werden, damit sie wirksam wird. Auf diese Weise können wir jedem einzelnen Kernel, den wir booten wollen feste Parameter mitgeben, die automatisch übergeben werden.

init= als Kernelparameter

Ein Kernelparameter verdient eine gesonderte Betrachtung. Das ist der Parameter init= mit dem wir festlegen, welches Programm als init-Programm aufgerufen werden soll. Normalerweise – ohne diesen Parameter – wird angenommen, dass init im Verzeichnis /sbin liegt. Der Parameter init= ermöglicht es uns jetzt ein alternatives init-Programm anzugeben oder einen bestimmten Runlevel anzugeben, indem wir z.B. schreiben

  LILO boot: linuxneu init=/sbin/init S

Das würde unser System jetzt alo zwingend im Runlevel S (Single-User) starten.

Das wäre weiter kein Problem, wenn wir hier nicht einfach jedes beliebige Programm angeben könnten, also auch eine Shell. Es ist tatsächlich möglich, beim Booten des Systems den folgenden Parameter einzugeben:

  LILO boot: linuxneu init=/bin/bash

Jetzt wird das init-Programm gar nicht erst gestartet, sondern an seiner Stelle kommt gleich eine Shell (bash) zum Einsatz. Es wird also kein Runlevelwechsel stattfinden, die Dienste werden nicht gestartet aber wir bekommen sofort – ohne Einloggen und Passwort – eine Shell, auf der wir vollen root-Zugriff haben.

Immerhin ist zu diesem Zeitpunkt das Wurzeldateisystem nur ReadOnly gemountet, wir haben ja aber auf dieser Seite etwas weiter oben schon gesehen, wie wir das Wurzeldateisystem read-write mounten können.

Das ganze kann natürlich sehr praktisch sein, wenn wir beispielsweise das root-Passwort vergessen haben sollten, allerdings ist dieser Parameter eine echte Sicherheitslücke, wenn jemand tatsächlich Zugriff auf den Rechner selbst haben sollte. Im Netz spielt es natürlich keine Rolle, aber wenn der Rechner selbst von fremden Händen manipulierbar ist, dann wird die gesamte Sicherheit des Systems durch diese Eigenschaft eingeschränkt.

Schutz vor Mißbrauch

Damit nicht jeder User, der Zugriff auf einen Rechner hat, diesen Rechner mit beliebigen Kernelparametern booten kann, bietet lilo die Möglichkeit an, Kernelparameter mit Passwort zu schützen. Nur wer ein bestimmtes Passwort weiß, hat das Recht, ein System zu booten oder ein System mit Kernelparametern zu booten.

Nachdem es – zumindestens bei einem Server – sehr lästig ist, wenn er nicht alleine booten kann, ohne dass ein Passwort eingegeben wird, wird auf die völlig strenge Methode gerne verzichtet. Aber der Schutz vor Kernelparametern muß sein. Aus diesem Grund bietet Lilo die folgenden Schlüsselwörter zum Schutz vor ungewolltem Zugriff: password= Diese Angabe kann entweder in der globalen Sektion von /etc/lilo.conf stehen (dann gilt es für alle Images) oder es wird für jedes Image extra angegeben, dann gilt es für das Image, in dessen Kontext die Anweisung steht. Hier kann ein Passwort direkt eingegeben werden, was den Nachteil hat, dass es dann unverschlüsselt in der Datei /etc/lilo.conf steht. Modernere Formen von Lilo können auch eine verschlüsselte Speicherung vornehmen, wenn hier einfach steht password=““. Dann fragt lilo beim Einrichten nach dem Passwort und speichert es verschlüsselt in /etc/lilo.conf.crc ab. mandatory Steht dieser Schlüsselbegriff in einer Image-Sektion der Datei /etc/lilo.conf, so muß zum Booten dieses Images ein Passwort eingegeben werden. restricted Ein Passwort wird nur dann gefordert, wenn das Image mit zusätzlichen Kernelparametern aufgerufen werden soll. Normales Booten funktioniert ohne Passwort. Diese Angabe wird am häufigsten verwendet. bypass Kein Passwort wird verlangt. Diese Angabe kann notwendig sein, wenn wir ein globales Passwort setzen, aber ein bestimmtes Image (etwa Windows) ohne Passwort bootbar machen wollen.

Sollte das Passwort direkt in der Datei /etc/lilo.conf stehen, so ist natürlich darauf zu achten, dass die Datei nur für root lesbar ist. Ansonsten könnte ja jeder User einfach nachsehen…

Eine Beispieldatei mit Passwortschutz könnte also folgendermaßen aussehen:

  boot=/dev/hda
  lba32
  prompt
  timeout = 80
  message = /boot/message
  password = wrdlbrnft

  image = /boot/bzImage_2
  label = linuxneu
  root = /dev/hdc1
  restricted

  image = /boot/bzImage
  label = linuxorg
  root = /dev/hdc1
  restricted

  other  = /dev/hda1
  label  = windows
  bypass

Auf diese Weise wird das System also vor unbefugter Angabe von Kernelparametern geschützt, insbesondere der init= Parameter kann also nicht mehr mißbraucht werden.