2 Punkte von GN⁺ 2024-03-27 | 1 Kommentare | Auf WhatsApp teilen

Die Geschichte des Hubris-Bugs: Wer hat den Netzwerk-Switch getötet?

  • Was ist Hubris?

    • Hubris ist ein Betriebssystem für tief eingebettete Systeme und wurde für Computer entwickelt, die nicht als Computer wahrgenommen werden, etwa im Inneren einer Tastatur.
    • Es wurde entwickelt, um alle Aufgaben zu erledigen, die nötig sind, um die großen Prozessoren in einem Oxide Rack zu starten.
    • Hubris ist ziemlich einzigartig; die für diese Geschichte relevanten Aspekte werden weiter unten erklärt.
  • Der Tatort

    • Arjen Roodselaar, ein Kollege bei Oxide, der für die Firmware des Netzwerk-Switches zuständig ist, testete Änderungen an der Power-Sequenz und der Taktkonfiguration.
    • Nach einer kleinen Änderung ließ sich der Switch plötzlich nicht mehr einschalten.
    • Teile der Firmware reagierten noch, aber der kritische Teil, der die Reihenfolge der Stromversorgung steuert, war stehen geblieben.
  • Mehr aus begrenztem RAM herausholen

    • Die günstigen Mikrocontroller, auf denen Hubris läuft, verfügen über sehr begrenztes RAM und Flash.
    • Hubris besteht aus vielen separat kompilierten Programmen, die Aufgaben genannt werden, und hat daher einen etwas höheren Ressourcenbedarf als andere Betriebssysteme.
    • Kollege Matt Keeter hatte das System kürzlich intelligenter gemacht, sodass es mehrere Bereiche in Zweierpotenzgrößen nutzt, um Aufgaben möglichst dicht zu packen.
  • Die rauchende Waffe

    • Arjen untersuchte den ausgefallenen Netzwerk-Switch mit Humility, dem Debugger für Hubris.
    • Mit dem Befehl humility tasks ließ er sich die Liste der auf dem Prozessor laufenden Aufgaben und ihre Statusinformationen ausgeben.
    • Dabei stellte er fest, dass die Aufgabe für die Power-Sequenz wegen eines Speicherfehlers bereits 115-mal neu gestartet worden war.
  • Rust-Borrows in Hubris-IPC über Aufgaben hinweg erweitern

    • Hubris-Aufgaben können sich über IPC gegenseitig Nachrichten senden.
    • Diese Nachrichten sehen Funktionsaufrufen sehr ähnlich und verhalten sich auch so.
    • Wenn eine Aufgabe Speicher an eine andere Aufgabe ausleiht, darf sie dabei nicht versuchen, Speicher auszuleihen, den sie tatsächlich nicht besitzt.
  • Wenn Features angreifen

    • Zwei Features können zusammen zu einem Bug werden.
    • Das Packen von Aufgaben arbeitet im Build-System opportunistisch.
    • Wenn sich die Größe von Aufgabe A geringfügig ändert, kann sich dadurch die Lage der MPU-Regionsgrenze einer nicht verwandten Aufgabe B verschieben.
  • Ein Anruf aus dem Inneren!

    • Der Algorithmus für den Speicherschutz musste geändert werden.
    • Ausgeliehener Speicher muss eine MPU-Region überschreiten dürfen.
  • Mit Hubris scheitern

    • Mehrere Dinge, die beim Systemausfall nicht passiert sind.
    • Der defekte Netzwerk-Switch konnte in drei Stunden repariert werden.
    • Dabei halfen Fehlerisolation, sicheres Fehlschlagen, sicherer Shared Memory, das gemeinsame Design von Kernel und Debugger, die Einfachheit von Entwurf und Implementierung sowie die enge, nicht-hierarchische Zusammenarbeit im Team.

Meinung von GN⁺

  • Dieser Artikel zeigt anhand der Suche und Behebung eines Bugs im Betriebssystem Hubris, wie wichtig robustes Softwaredesign selbst in komplexen Systemen ist.
  • Der Prozess der Fehlerfindung und -behebung unterstreicht, wie wichtig Teamarbeit und effiziente Debugging-Werkzeuge bei der Lösung komplexer Probleme im Software Engineering sind.
  • Er zeigt außerdem, wie entscheidend Isolations- und Fehlermanagement-Funktionen in Systemen wie Hubris sind. Sie können Stabilität und Wartbarkeit eines Systems erheblich verbessern.
  • Der Artikel veranschaulicht zudem, wie mit der sicheren Programmiersprache Rust Speichersicherheit gewährleistet und die Zahl von Bugs minimiert werden kann. In Systemen mit Rust treten solche Bug-Typen selten auf, was zeigt, wie wirksam Rusts Garantien zur Speichersicherheit in der Praxis sind.
  • Ähnliche Projekte oder Produkte mit vergleichbaren Funktionen sind seL4, FreeRTOS und Zephyr; dabei handelt es sich jeweils um Betriebssysteme für eingebettete Systeme mit unterschiedlichen Zielen und Eigenschaften.
  • Wer Systeme wie Hubris einführt, sollte Faktoren wie Speicherbeschränkungen, Aufgabenverwaltung und das Design des IPC-Mechanismus berücksichtigen. Zu den Vorteilen solcher Systeme zählen robustes Systemdesign und sichere Speicherverwaltung, während die Komplexität des Systems und die Lernkurve zu den Nachteilen gehören können.

1 Kommentare

 
GN⁺ 2024-03-27
Hacker-News-Kommentare
  • Review des Hubris-Kernel-Codes

    • Ich habe den Kernel-Code von Hubris eine halbe Stunde lang gelesen, und er ist sehr klar und gut geschrieben. Er hebt sich deutlich von dem komplexen C-Code mit Makros, zweibuchstabigen Variablennamen und wenigen Kommentaren ab, den ich früher gesehen habe. Ich empfehle ihn als gute Lektüre vor dem Schlafengehen.
  • Lob für die Stellenanzeige

    • Das ist eine der besten Stellenanzeigen, die ich je gesehen habe. Der Übergang zur Kultur wirkt natürlich und endet mit „Wir stellen ein“. Es ist sogar eine hervorragende Post-Mortem-Analyse, die auch Entwickler auf Anwendungsebene verstehen können. Ich lerne gerade Rust und war deshalb auf solche Inhalte vorbereitet. Außerdem ist es immer eine Freude, die Arbeit anderer zu sehen, die ihren Code ausführlich kommentiert haben.
  • Code-Review und Vorschlag

    • Eine kurze Anmerkung zum Code: Da es sich nicht um ein Detail einer bestimmten Funktion handelt, sondern um einen Kommentar zur Invariante eines Feldes, die alle Autoren respektieren und alle Leser nutzen können, wäre es gut, dies zum Docstring von TaskDesc::regions hinzuzufügen.
  • Einschätzung des Debugging-Prozesses

    • Der Beitrag liefert eine tiefgehende Analyse zum Debugging eines komplexen Problems, und dass der Rest des Systems stabil blieb, ist ein Beleg für die hochwertige Engineering-Arbeit des Oxide-Teams. Das hat mich persönlich inspiriert, bei der Arbeit ähnliche Techniken anzuwenden.
  • Interesse an der Kultur des Oxide-Teams

    • Das Engineering-Team von Oxide ist intern nicht abgeschottet und hat eine Kultur, die Offenheit, Neugier und Kommunikation fördert und Abwehrhaltung, Empire Building und Gatekeeping unterdrückt. Sie haben daran gearbeitet, diese Kultur zu schaffen und zu bewahren, und man kann das an der horizontalen Organisation über Bereiche hinweg erkennen, die andere Organisationen jeweils als eigenes Team bezeichnen würden. Ich würde gern mehr über die Motivation und die konkreten Umsetzungsdetails hinter dem Aufbau einer solchen Kultur erfahren. Gibt es Nachteile dabei, in einer Organisation „Offenheit, Neugier und Kommunikation“ zu fördern, oder Fälle, in denen man sich für ein strengeres hierarchisches System entscheidet? Es scheint mir, dass ein Organigramm strategisch festgelegt werden sollte, aber die Trade-offs dabei sind mir nicht ganz klar.
  • Link zu weiterführenden Informationen

    • Vorabinformationen lassen sich über den angegebenen Link finden.
  • Mitgefühl für Probleme beim Debugging

    • Ich kann nachvollziehen, dass zufällige Abstürze, die verschwinden, sobald man Debugging-Code hinzufügt, die schlimmsten sind.
  • Vorschlag zum Umgang mit der Hardware

    • Es wird erwähnt, dass man mehr als acht Regionen unterstützen könnte, indem man die Hardware wie einen Software-Fill-TLB behandelt.
  • Lob für die Arbeit von Oxide

    • Es wird Staunen über die Arbeit ausgedrückt, die Oxide leistet.
  • Reaktion auf den Namen des Betriebssystems

    • Es wird Überraschung und eine Reaktion darauf ausgedrückt, dass das Betriebssystem Hubris genannt wurde.