4 Das Betriebssystem L3

Als Basis der vorliegenden Arbeit dient das an der Gesellschaft für Mathematik und Datenverarbeitung (GMD) entwickelte Betriebssystem L3. Da die vorliegende Arbeit auf den verschiedensten Konzepten des Systems aufbaut, sollen hier die wichtigsten geschildert werden. Dazu gehören insbesondere das Taskkonzept, die Behandlung von Datenräumen und die Interprozeßkommunikation.

4.1 Überblick über die Struktur von L3

L3 ist ein mikrokernbasiertes Betriebssystem. Es besteht aus einem inneren Kern, der elementare Operationen bereitstellt und einer Menge von Servern, die auf dem Kern aufbauend die fehlenden betriebssystemspezifischen Dienste zur Verfügung stellen.

Die Struktur des L3-Systems

In Abbildung [hier] ist die Struktur eines L3-Systems dargestellt. Zu sehen ist der Kern mit einer Menge auf ihn aufsetzender Server. Eine besondere Rolle spielt dabei der Task-Server, der sogenannte Supervisor. Er stellt einen privilegierten, für den Kern vertrauenswürdigen Prozeß dar. Er ist mit der Verwaltung des Tasksystems betraut und wird auch als äußerer Kern bezeichnet.

Auf diesen Servern setzen dann die Anwendungen auf, die dem Nutzer unter anderem eine Oberfläche bieten, mit deren Hilfe er mit dem System arbeiten kann. Diese Anwendungen sind für das Verständnis der weiteren Ausführungen nicht notwendig und werden deshalb nicht näher betrachtet.

4.1.1 Der Kern

Der Kern wurde nach dem Minimalitätsprinzip entworfen. Dabei stellt sich die Frage, was ist minimal? Welche Funktionen gehören in den Kern, welche können außerhalb implementiert werden? In [16] werden folgende Kriterien für den Entwurf definiert:

Sicherheit
Es ist kaum möglich, eine Sicherheitsarchitektur ohne Kernunterstützung zu bauen. Deshalb muß der Kern Konzepte bereitstellen, die die Realisierung einer Sicherheitsarchitektur ermöglichen.
Management von Betriebssystemresourcen
Dieser Aspekt ist eine traditionell von Betriebssystemen gehandhabte Aufgabe. Sie sollte allerdings nur soweit wie nötig in den Kern integriert werden.
Fehlertoleranz
Aufgrund der Verwendung als Timesharing-OS wurde der Schwerpunkt hier nur auf die Realisierung einer error recovery-Methode gelegt, die ein konsistentes Wiederaufsetzen nach einem schweren Systemfehler gestattet und Datenverlust möglichst gering hält.

Resultat war ein Kern, der als abstrakte Maschine den Datentyp Task implementiert [17]. Eine Task besteht aus:

Tasks werden mit Hilfe einer 64 Bit breiten Id identifiziert und stellen die protection domain in L3 dar. Auf welchen Grundlagen dieser Schutz basiert, wird im folgenden Kapitel beschrieben.

Aufbauend auf dem Konzept der Task stellt der Kern Clans zur Verfügung, auf die in Kapitel [hier] eingegangen wird.

Sicherheit in L3

Die im ersten Punkt der Kriterien geforderte Unterstützung einer Sicherheitsarchitektur erfolgt durch folgende Eigenschaften:

Autonomie der Task
Task stellen die protection domain in L3 dar. Eine äußere Beeinflussung einer Task ist gegen ihren Willen nicht möglich. Vom Kern wird garantiert, daß kein Datenraum oder Thread einer Task von außen durch einen Thread einer anderen Task verändert oder beeinflußt werden kann.

Die einzige Möglichkeit, Einfluß auf das Verhalten einer Task zu nehmen, stellt die Interprozeßkommunikation dar. Hier erklärt sich die Task bzw. ein Thread der Task bereit, etwas zu empfangen, entscheidet dabei aber darüber, was er zu empfangen bereit ist und wie er bei Erhalt der Nachricht reagiert.

Eine Kommunikation verletzt also nicht die Autonomie der Task, da ihr auch dadurch nichts aufgezwungen werden kann. Die Task entscheidet immer selbst, was sie tut.

Integrität der Kommunikation
Ein zweiter Punkt, der für eine Sicherheitsarchitektur unabdingbar ist, ist die Integrität der Kommunikation. Eine Task muß sich darauf verlassen können, daß eine Nachricht, die sie erhält, nicht gefälscht ist. Hier garantiert der Kern drei Dinge:
  1. der Inhalt einer Nachricht kann nicht gefälscht werden,
  2. der Identifikator des Absenders ist nicht fälschbar und
  3. nur der spezifizierte Empfänger sieht die Nachricht.

Auf der Grundlage dieser beiden Prinzipien ist man in der Lage, eine Sicherheitsarchitektur zu entwerfen, die den Anforderungen der Anwendung genügt.

Das Resourcenmanagement in L3

Der L3-Kern realisiert eine elementare Resourcenverwaltung. Er verwaltet lediglich:

Alle anderen Resourcen, wie Drucker, Terminals oder andere Ein-/Ausgabegeräte werden von Tasks verwaltet.

Error recovery und Fehlerbehandlungsmechanismen

Error Recovery auf Kernniveau wird in Form des Fixpunktmechanismus angeboten. Ein Fixpunkt ist eine konsistente Kopie aller Task- und Threadkontrollblöcke, sowie aller Datenräume der Tasks zu einem bestimmten Zeitpunkt. Stürzt das System aufgrund eines Hard- oder Softwarefehlers ab, ist es möglich, den Systemzustand zum Zeitpunkt des letzten Fixpunktes wiederherzustellen. Das geschieht automatisch beim ,,Hochfahren'' des Systems.

Programmfehler, wie Zugriffe auf nicht gemappte Bereiche u.a.m., werden der Task über einen Standardmechanismus zugestellt, der in einem späteren Kapitel noch beschrieben wird.

Operationen des Kerns

Die Operationen des L3-Kerns

Für den Datentyp Task und die zugehörigen Objekte werden Operationen bereitgestellt, die sich nach [18] wie in Abbildung [hier] darstellen lassen. In dieser Abbildung wird auch versucht, eine Einteilung in Funktionskomplexe vorzunehmen. Das ist aufgrund der Überschneidungen nicht eindeutig möglich, bietet aber einen Überblick über die bereitgestellte Funktionalität. Für eine Beschreibung der Funktionen und ihrer Anbindung an die Programmiersprache C sei die folgenden Abschnitte und auf [19] verwiesen.

4.1.2 Der Supervisor und die Server

Aufbauend auf den Funktionen des Kerns stellen der Supervisor und die Server die fehlende betriebssystemspezifische Funktionalität bereit. In Form von Tasks werden Funktionen zur Behandlung der Systemkonfiguration, zur Arbeit mit Geräten, der Manipulation von Tasks u.a.m. realisiert. Einige besondere Server seien in den folgenden Ausführungen kurz beschrieben.

Der Supervisor
Der Supervisor nimmt im L3-System eine besondere Stellung ein. Er ist in den Augen des Kerns eine besonders vertrauenswürdige Task und hat dadurch einige Privilegien. Er ist verantwortlich für die Erzeugung von Tasks und Threads und für die Verwaltung ihrer Hierarchie. Er selbst ist dabei die Wurzel der Taskhierarchie, die von ihm selbst implementiert wird.

Der Supervisor ist die erste Usertask. Er wird bei der Installation erzeugt und lebt dann ewig, d.h. bis zu einer Neuinstallation oder einem Austausch gegen einen anderen Supervisor.

Er dient weiterhin als Nameserver im System. Threads und Tasks haben in L3 neben ihrer orts- und zeiteindeutigen Id auch einen Namen. Will ein Thread mit einem anderen kommunizieren, wendet er sich mit dem Namen an den Supervisor, um die Id seines Partners herauszufinden.

SYS
Die Task SYS stellt die Wurzel der Hierarchie privilegierter Tasks dar. Die unter SYS befindlichen Tasks stellen Funktionen zur Verwaltung des Gesamtsystems, Konfiguration der Gerätetreiber und anderes mehr bereit.

Die Anordnung dieser privilegierten Tasks in der Taskhierarchie ist kein vom Kern vorgegebenes Dogma, sondern ein Prinzip des Supervisors, der privilegierte und residente Tasks nur unterhalb von SYS erzeugt. Wird versucht, eine solche Task an einer anderen Stelle zu erzeugen, wird der Dienst vom Supervisor abgelehnt.

SYSIO
,,SYSIO'' übernimmt Aufgaben der Terminalverwaltung, die Zuordnung von Terminal, Keyboard und Maus zur Nutzertask. Diese Zuordnung wird über das Linkprotokoll abgewickelt.

Will eine Task das erstemal eine Ausgabe auf ein Terminal machen, wickelt sie mit SYSIO das Linkprotokoll ab und erhält nach erfolgreichem Abschluß Zugriff auf die Task, die das Terminal behandelt.

Für eine genauere Beschreibung der Taskhierarchie und der durch sie bereitgestellten Funktionalität sei auf [20] verwiesen.

4.2 Interprozeßkommunikation

Tasks nehmen in der Regel zur Erfüllung einer Aufgabe Dienste anderer Tasks in Anspruch. Sie benötigen dazu eine Möglichkeit zur Kommunikation.

IPC in L3 ist synchron, direkt und mit Timeouts behaftet. Aktive Elemente, Threads, kommunizieren direkt mit anderen Threads. Es gibt keine Kanäle oder Ports, nur die globalen, zeit- und ortseindeutigen Thread-Id's.

Da es keine zwischengeschalteten Objekte gibt, werden Nachrichten auch nicht gepuffert. Sendet ein Thread eine Nachricht an einen anderen, wird er solange blockiert, bis der Empfänger bereit ist und die Nachricht in Empfang nimmt.

Nachrichten sind strukturiert. Sie werden durch sogenannte message dopes beschrieben und können aus bis zu vier Komponenten bestehen. Diese Komponenten sind:

Aufbau einer Nachricht in L3

Abbildung [hier] stellt den Aufbau einer Nachricht dar.

Ein großer Teil der Kommunikation zwischen Klient und Server besteht aus kurzen Nachrichten, die nur eine Statusinformation oder einen Ergebniswert enthalten. Deshalb wurde in L3 eine spezielle Optimierung für kurze Nachrichten implementiert. Nachrichten, die bis zu 8 Byte lang sind, werden in Registern übertragen, was zu einem beträchtlichen Geschwindigkeitszuwachs führt. Aber auch komplexere Nachrichten werden in L3 schneller übertragen als in anderen System wie z.B. Mach [7].

L3-IPC stellt folgende Primitive zur Verfügung:

4.3 Datenräume

Datenräume sind Objekte, die in den virtuellen Adreßraum gemappt werden können. Sie sind bis zu einem GByte groß und unterliegen dem Paging.

In einem Datenraum können sich Daten beliebigen Typs befinden. Datenräume werden dynamisch in den Adreßraum gemappt und sind dann linear adressierbar. Es ist daher möglich, Programmkode, der sich in einem Datenraum befindet, direkt auszuführen.

Datenräume sind tasklokale Objekte. Sie werden innerhalb der Task erzeugt oder mittels IPC von einer anderen Task empfangen. Wird ein Datenraum gesendet, geht das Eigentumsrecht an die Empfängertask über.

Die Standarddatenraumverwaltung (der Standardpager) stellt den Mechanismus des copy on write zur Verfügung, d.h., beim Kopieren eines Datenraumes wird nur eine Referenz auf das Original erzeugt. Datenräume werden in L3 über baumartige Strukturen verwaltet, die eine doppelstufige Pagetablehierarchie darstellen. Die erste Stufe realisiert die Eigentumsrelation zwischen Task und Datenraum, die zweite ordnet den Datenräumen Blöcke auf der Platte zu. Das Kopieren von Datenräumen erfolgt durch das Erzeugen eines Eintrages für den Datenraum, der auf den gleichen Eintrag in der zweiten Stufe verweist wie das Original. In einem zweiten Schritt werden alle Seiten des Datenraums als read only und shared gekennzeichnet. Erst wenn eine Veränderung in dem alten oder in dem neuen Datenraum vorgenommen wird, wird eine physische Kopie der veränderten Seiten erzeugt.

Mappen eines Datenraums eines externen Pagers

L3 stellt wie Mach auch das Konzept der externen Pager zur Verfügung [21]. Als externer Pager kann jede L3-Task fungieren, die dann den von ihr zur Verfügung gestellten Datenräumen eine Semantik aufprägt.

Eine Task mappt einen Datenraum unter Angabe verschiedener Parameter. Diese beschreiben:

In Abbildung [hier] ist die Situation nach dem mappen eines Datenraums eines externen Pagers dargestellt.

Greift ein Thread nun auf diesen Bereich zu, entstehen wie bei einem normalen Datenraum Seitenfehler. Diese werden vom Kern analysiert (1) und mittels des Externen Pager Protokolls an den implementierenden Pager weitergeleitet. Dieser stellt die entsprechenden Informationen auf Seiten seines eigenen Adreßraums bereit und sendet eine Antwort, die diese Seiten in Form von Flexpages enthält. Die in der Antwort enthaltenen Seiten werden vom Kern beim Empfang der Nachricht gemappt. Dann wird die verursachende Anweisung neu aufgesetzt.


Fußnoten:
  1. Der Kern bestimmt mit Hilfe der verschiedenen Map-Parameter genau die Seite innerhalb des Datenraums, an der der Fehler aufgetreten ist. Dazu verwendet er die folgende Formel: dataspace fault address = (page fault address - region base) + map offset

4.4 Clans and Chiefs

Ein wichtiger Aspekt bei der Implementation von Anwendungen ist die Durchsetzung einer auf die Anwendung zugeschnittenen Sicherheitspolitik. Einen ersten Ansatz hierfür bieten die L3-Konzepte Autonomie der Task und Integrität der Nachrichten.

Der L3-Kern bietet noch einen darüber hinausgehenden Mechanismus an. Angeregt vom subject restriction concept in Birlix [22] wurde das Konzept der Clans & Chiefs realisiert.

In Birlix ist es möglich, verdächtige Prozesse einzukapseln. Ihnen wird eine Liste aller von ihnen kontaktierten Prozesse zugeordnet, die in der Regel Server sind. Die Kommunikation der Prozesse wird dann anhand dieser Liste überwacht. Versucht ein Prozeß mit einem anderen zu kommunizieren, der nicht in der Liste steht, wird diese Kommunikation unterdrückt.

L3 realisiert hier ein allgemeineres Konzept. In Anlehnung an die schottischen Familienclans können Task zu Clans zusammengefaßt werden, die einen Chief besitzen.

Ein Clan ist eine Menge von Tasks, die von einem Chief kontrolliert werden. Innerhalb des Clans wird IPC zwischen Threads normal behandelt. Nachrichten, die jedoch die Grenzen des Clans überschreiten, werden über den Chief umgeleitet. Überschreiten heißt dabei sowohl Überschreiten der Grenze aus dem Clan heraus als auch in den Clan hinein.

Kommunikation über Clan-Grenzen hinweg

Eine solche Kommunikation könnte dann wie in Abbildung [hier] aussehen. Sendet eine Task R an eine Task S, die sich in einem anderen Clan befindet, kreuzt die Nachricht zwei Clan-Grenzen. Die Kommunikation läuft dann wie folgt ab:

  1. R sendet an Chief(R),
  2. Chief(R) sendet an Chief(S),
  3. Chief(S) sendet an S.

Der Chief kann dann die Nachricht in Bezug auf den Sender, den Empfänger, aber auch den Inhalt analysieren. Entsprechend der dabei gewonnenen Kentnisse hat er die Möglichkeit:

Der Chief kann bei den gegebenen Einschränkungen jeden beliebigen Algorithmus zur Kontrolle der Kommunikation seines Clans verwenden. Damit ist es möglich, eine auf die spezielle Anwendung zugeschnittene Sicherheitspolitik auf User-Level zu implementieren. Dann fungieren Clans als Schutzdomänen auf einem höheren Niveau.

In [23] sind weiterführende Ausführungen zu diesem Thema zu finden. Dort wird unter anderem auch erläutert, wie das Verhältnis von Vertrauenswürdigkeit und Integrität des Nachrichtenaustausches auf der einen und die Möglichkeit, Nachrichten zu fälschen, auf der anderen Seite zu bewerten ist. Weiterhin werden Möglichkeiten aufgezeigt, trotz der Fälschungsmöglichkeiten Informationen über die Vertrauenswürdigkeit des Absenders zu erhalten.


Fußnoten:
  1. bei Modifikation des Empfängers

Jean Wolter
14.11.1995