Wenn das Kernel-Gedächnis streikt…, Teil 2

17. August 2010

In seinem ersten Artikel rund um die Probleme, die den oft so gefürchteten „Blue Screen of Death“ auslösen, hat unser Experte Ron Stock erläutert, welche Schwierigkeiten in den Hauptspeicherbereichen, die direkt dem Kernel zugeordnet sind, auftauchen können. Zudem hat er die grundlegende Architektur der beteiligten Speicher-Pools vorgestellt. In diesem zweiten Teil geht er genauer auf die Arbeit mit dem sogenannten Special-Pool ein – eines der wichtigsten Werkzeuge des Microsoft Support Teams.

Bild 1.Eine Möglichkeit den Special-Pool im System zu aktivieren: Die GUI-Version des Werkzeugs „Global Flags“ wird mit den Windows Debugging Tools auf ein System gebracht.

Nachdem wir im ersten Teil unseres Artikels einige der Probleme rund um den Kernel-Hauptspeicher vorgestellt haben, möchte der Autor in diesem Teil noch genauer auf den bereitsvorgestellten Special-Pool eingehen. Wir haben diesen Special-Pool, der bereits mit Windows NT und dem Service Pack 4 eingeführt wurde, schon in unserem ersten Artikel vorgestellt: Er dient dazu, „bösartige“ oder auch nur beschädigte Treiber, die Speicherbereiche korrumpieren, in Echtzeit zu fangen.

Dies geschieht dabei mittels sogenannten Schutzseiten (guard pages), die rund um den allokierten Bereich aufgestellt werden. Dieses Mechanismus beruht auf der Idee, dass man Treiber, die über den von ihnen reservierten Speicherplatz hinausschreiben, auf diese Weise dazu zwingt, in diese Schutzseiten hineinzuschreiben. Das würde das System zu einem sofortigen Absturz bringen, bei dem sich dann definitiv der schuldige Treiber ganz oben auf dem Stack befindet. Damit besitzt der Administrator dann aber einen eindeutigen Beweis, welcher Treiber die Probleme verursacht: Die Amerikaner nennen diesen Ansatz sehr bildhaft den „smoking gun approach“ – der Böse wird also noch mit dem rauchenden Revolver in der Hand erwischt.

Der Special-Pool: Der Fänger im Speicher

Damit der Special-Pool diese Aufgabe aber auch wirklich ausführen kann, mussten zunächst einige Änderungen im Speichermodell vorgenommen werden. Wenn ein Treiber mittels des Special-Pools beobachtet und verfolgt wird, werden seine Ressourcenzuteilungen (Allokationen) nicht mehr gemeinsam mit denen anderer Treiber auf einer 4 KByte angelegt. Vielmehr wird dieser Allokation nun eine komplette 4 KByte Seite zugeteilt, an deren oberen Ende dann der Pufferspeicher des Treibers gesetzt wird. Die Absicht dahinter: Der Treiber soll später „erwischt“ werden, wenn er über diese Allokation hinaus liest oder schreibt und dabei in die nächste nicht zugeteilte Schutzseite hineingerät. Diese „Überlauf-Bedingung“ wird dann die Schutzseite erreichen und einen entsprechenden Blue-Screen-Absturz auslösen:

Bug Check 0xCD: PAGE_FAULT_BEYOND_END_OF_ALLOCATION

Schaut sich der Administrator danach dann den Memory-Dump genauer an, so sollte sich der Treiber zeigen, der über seinen allokierten Bereich hinausgeschrieben hat. Der Rest der Seite, der den Pufferbereich beinhaltet, ist in diesem Fall mit einer zufälligen Bit-Muster-Signatur gefüllt. Diese erscheinen den meisten Systemprofis zwar zunächst einmal als ziemlich uninteressant, doch dienen auch sie einem sinnvollen Zweck.

Wenn der Speichermanager den zugeteilten Bereich wieder freigibt, untersucht er das gesamte Bit-Muster, wobei er nach Änderungen in der Signatur sucht. Findet er heraus, dass in dieser Signatur auch nur ein einziges Bit überschrieben wurde, so hält der Memory Manager die Maschine mit der folgenden Meldung an:

Bug Check 0xC1: SPECIAL_POOL_DETECTED_MEMORY_CORRUPTION.

Wurde in diesem Bit-Muster eine Beschädigung gefunden, so kann diese für eine sogenannte “underrun condition“ sprechen. In solchen Fällen wird in der Regel dazu geraten, ein spezielles Flag zu setzen, wodurch eine Überwachung solcher „underrun“-Vorfälle möglich wird. Dabei wird die zuvor geschilderte Situation umgekehrt: Der Treiber-Puffer wird an den Anfang der Seite geladen, während danach das Bit-Muster folgt, das bis zum Ende der Seite
reicht. Dabei hofft man darauf, dass auf diese Weise ein Lese- oder Schreibzugriff gefunden wird, der zu früh zugreift und dadurch die Schutzseite vor dem allokierten Bereich trifft.

Bild 1.Eine Möglichkeit den Special-Pool im System zu aktivieren: Die GUI-Version des Werkzeugs „Global Flags“ wird mit den Windows Debugging Tools auf ein System gebracht.

Aufstellen der Falle: Methoden, um den Special-Pool zu starten

Dem Administrator stehen diverser Methoden zur Verfügung, um den Special-Pool in Betrieb zu nehmen. Wer den „historischen Weg“ wählen möchte, kann es durch einen direkten Eingriff in die Registry erreichen. Dazu muss er in der Registry den Wert „PoolTagOverruns“ im folgenden Unterschlüssel hinzufügen:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management

Bekommt dieser dann den Wert „1“ zugewiesen, so wird die Entdeckung von „overrun“-Konditionen ermöglicht, während ein Wert „0“ an dieser Stelle die Überwachung der „underrun“-Bedingung ermöglicht. Im gleichen Unterschlüssel der Registry kann dann auch „PoolTag“ eingetragen werden. Diesem Wert kann dann der „Tag“ mitgegeben werden, der verfolgt werden soll. Bei der Eingabe dieses Wertes besitzt der Administrator große Freiheiten und kann hier auch sogenannte Wildcards einsetzen.

Deshalb raten die Profis von Microsoft in all jenen Fällen, in denen es zunächst
nicht feststellbar ist welcher „Tag“ das Problem verursacht, an dieser Stelle den
hexadezimalen Wert 0x2a zu verwenden, der dem ASCII-Äquivalent für das Zeichen „*“ entspricht. So kann man dann die „Tags“ aller Treiber überwachen. An dieser Stelle ist ein Hinweis besonders wichtig: Da es sich beim Special-Pool-Speicher um eine begrenzte Ressource handelt, werden nicht alle Zuweisungen in diesem Bereich allokiert. Zudem ist es auch eine ziemlich kostspielige Ressource, da der Memory-Verwalter für den Puffer eine komplette 4 KByte große Speicherseite plus zwei zusätzliche virtuelle nicht zugängliche Schutzseiten reserviert. Deshalb raten die Experten davon ab, diesen Modus noch weiter zu verwenden, wenn die Hauptursache der Memory-Korruption bereits bekannt ist.

Ein weiteres Werkzeug zum Anschalten des Special-Pools trägt die Bezeichnung „Global Flags“ (Gflags). Es wird bei der Installation der Windows Debugging Tools mit auf das System gebracht. Dieses Programm stellt dabei sowohl eine GUI-gestützte als auch eine reine Kommandozeilen-Version zur Verfügung und wird mit einer umfangreichen Hilfedatei ausgeliefert. Der Special-Pool wird bei dieser Software auf dem Tabulator „System Registry“ eingeschaltet (Bild 1), wenn der Administrator die GUI-Version einsetzt. Dies geschieht, im dem der Administrator wie in Bild 1 gezeigt den „Tag“ eingibt, den es zu überwachen gilt. Eine weitere Option ermöglicht es dann, zwischen der Überprüfung auf einen „overrun“ oder einen „underrun“ zu unterscheiden. Die Auswahl geschieht jeweils durch einen Radio-Button, mit „Verify End“ für die „overruns“ und „Verify Start“ für die Überwachung auf „underruns“.

Mit diesem Werkzeug ist es zwar ebenfalls möglich, mit Hilfe von Wildcards nach „Tags“ zu suchen, es steht aber kein Weg zur Verfügung, dem Tool eine Liste von „Tags“ zu übergeben. Allerdings stellt es dem Administrator eine Möglichkeit zur Verfügung, Zuweisungen mittels ihrer Größe zu verfolgen und zu finden, indem er anstelle des aus bis zu vier Zeichen bestehenden „Tags“ die Größe der Zuweisung als hexadezimalen Wert eingibt. Die Praxis zeigt allerdings, dass diese Vorgehensweise nicht so gut ist, da nun alle Treiber mit dieser allokierten Größe überwacht werden.

Bild 2. Der Treiber-Überprüfungsmanager: Er ermöglicht eine Auswahl des zu untersuchenden Treibers. Durch Auswahl dieser Option kann der Administrator dann sehr viel genauer festlegen, welcher spezifischen Treiber in diesem Fall überwacht werden soll.

Beide dieser gerade vorgestellten Methoden verlangen einen Reboot, was sich in der Praxis ebenfalls als schlecht erweisen kann, wenn beispielsweise ein Produktions-Server untersucht werden soll, der nicht einfach heruntergefahren werden kann. Aber es gibt auch eine gute Nachricht: Mit allen Windows-Systemen mit einer Kernel-Version ab 6.0 (Windows Vista und später) können auch Kernel-Flags zum Einsatz kommen, um den Special-Pool einzuschalten. Dabei ist dann auch kein Reboot nötig, allerdings sind diese Änderungen nach einem Reboot wieder ausgeschaltet.

Wer einen solchen Kernel-Flag mit Hilfe der Kommandozeilen-Version von Gflags einstellen will, kann den Special-Pool direkt „on-the-fly“ anschalten, indem er das Kommando mit dem Schalter „/k“ unterstützt durch die Option „+spp“ aufruft. Der nachfolgende Aufruf zeigt ein Kommando, dass dazu dient allokierte Bereiche mit der Größe 30 bis zum nächsten Reboot zu überwachen:

Gflags /k +spp 0x30

Mehr Informationen über vielen Möglichkeiten des Kommandos „Global Flags“ finden Administratoren in der umfangreichen Hilfedatei dieses Tools.

Ein weiteres Werkzeug, das der Microsoft-Support häufig einsetzt um den Special-Pool einzuschalten, ist der „Driver Verifier“, der bei den deutschen Windows-Versionen die Bezeichnung Treiber-Überprüfungsmanager (Bild 2) trägt. Ron Stock nennt dieses Programm sein Lieblings-Tool, weil es nicht nur über weitaus feiner einzustellende Optionen verfügt als die anderen Werkzeuge, sondern auch mit einigen Hilfedateien und „Wizards“ ausgestattet ist. Weiterhin sind die zuvor erwähnten Werkzeuge leider nur dazu in der Lage, einen einzelnen Treiber oder einen Wildcard-Begriff zurzeit zu bearbeiten. Der Treiber-Überprüfungsmanager stellt dem Administrator hingegen eine Liste von Treibern zur Auswahl zur Verfügung.

Wenn es also darum geht, den Überprüfungsmanager zusammen mit dem Special-Pool einzusetzen, um eine Kernel-Memory-Korruption zu untersuchen, so hat sich die folgenden Vorgehensweise nach Erfahrung des Autors bewährt:

•    Start des Treiber-Überprüfungsmanagers durch Eingabe von „verifier.exe“ an der Kommandozeile des jeweiligen Systems.

•    Wenn das Tool startet, sollte der Auswahlpunkt „Benutzerdefinierte Einstellung erstellen (für Entwickler) gewählt werden.

•    Danach im nächsten Fenster den Eintrag „Einstellungen aus Liste auswählen“ verwenden und

•    in der Liste der Eintrag „Spezieller Pool“ markieren. Nach einem Klick auf „Weiter“ erscheint eine Anzeige wie im Bild 2, die eine Auswahl des zu untersuchenden Treibers ermöglicht. Durch Auswahl dieser Option kann der Administrator dann sehr viel genauer festlegen, welcher spezifischen Treiber in diesem Fall überwacht werden soll.

Nach einem Reboot wird der Server nun so lange arbeiten, bis der Special-Pool einen Treiber „einfängt“, der den Pool beschädigt. Danach sollte ein Speicherauszug den entsprechenden Treiber auf dem Stack anzeigen. Es ist bei einem solchen Einsatz besonders wichtig, dass der Systemverwalter nach Abschluss seiner Untersuchungen den Überprüfungsmanager durch die entsprechende Option im Wizard der Software auch wieder ausschaltet.

Zum Abschluss: Einige Warnung und eine Anmerkung

Wie unsere beiden Artikel gezeigt haben, kann der Einsatz des Special-Pools sehr nützlich sein, wenn es darum geht Probleme im Bereich des Kernel-Speichers zu finden – aber auch dieses Werkzeug ist auf keinen Fall perfekt. So können Fälle auftreten, in denen das Timing des Systems durch den Einsatz von Special-Pool verändert wird, so dass ein Problem nicht mehr reproduzierbar ist. In anderen Fällen ist es durchaus passiert, dass der Special-Pool den Schuldigen während des Boot-Vorganges der Maschine abgefangen hat. Das hat dann das System dazu veranlasst, abzustürzen bevor überhaupt eine Anmeldung an ihm möglich war.

Man sollte sich in diesem Zusammenhang immer wieder vor Augen führen, dass es die Aufgabe des Special-Pools ist, die Maschine zum Absturz zu bringen und dabei den verantwortlichen Treiber auf dem Stack zu präsentieren. Wenn das allerdings vorzeitig passiert, kann es durchaus vorkommen, dass die abstürzende Maschine den Systemverwalter daran hindert, den Special-Pool abzuschalten. Diese Situation ändert das gesamte Szenario dann dahingehend, dass es sich danach um ein kritisches nicht mehr den Boot-Vorgang betreffendes Problem handelt! Die sogenannte „Last Known Good“-Option kann dann noch helfen, indem sie die Registry-Einträge dann wieder auf die vorherigen Einstellung zurücksetzt.

Das Werkzeug besitzt aber noch einen weiteren Nachteil: Durch seinen Einsatz kann nämlich durchaus etwas auftauchen, was im amerikanischen Sprachgebrauch gerne „Red Herring“-Effekt genannt wird und in Prinzip eine Täuschung oder ein Ablenkungsmanöver bezeichnet.

So kann es durchaus passieren, dass der Einsatz des Special-Pools Fehler in anderen Treiber aufdeckt, die Memory-Beschädigungen hervorrufen würden, aber normalerweise im Produktionsbetrieb keine Instabilitäten verursachen. Solche Entdeckungen sind zwar grundsätzlich keine schlechte Sache, aber sie können natürlich die eigentliche Suche deutlich verzögern oder den Administrator zu der falschen Annahme verleiten, er habe bereits den Schuldigen gefunden, bevor der wirkliche Verursacher der Probleme ausgemacht ist.

Insgesamt konnten wir mit diesen zwei Artikeln natürlich nur die Oberfläche dieser Problematik anreißen: So haben wir in diesem Zusammenhang noch nicht einmal die Vorgehensweise erläutern können, die nötig ist um die richtigen „Tags“ für die Untersuchung mittels des Special Pools herauszusuchen. Allein dieses Thema würde einen weiteren sehr umfangreichen Artikel füllen können. In vielen Fällen ist es in der Praxis leider wirklich so, dass diese Fehlersuche ganz ähnlich dem Debugging häufig mehr Kunst als Wissenschaft ist. Man kann aber ohne Zweifel sagen, dass für viele Fälle aus der täglichen Praxis der Special-Pool das Werkzeug des Microsoft Support Teams ist, das entscheidend dazu beiträgt, diese Probleme zu lösen.

Ron Stock/ fms

Lesen Sie auch