Browser vertrauen Code, der Mediendateien von Fremden parst, und Angreifer haben diese Formate wiederholt gegen Speicherfehler von Decodern ausgenutzt. Mozilla hatte Rust fast sieben Jahre lang gesponsert, eine Sprache, die als sichere Alternative zu C++ konzipiert wurde, doch Mitte 2016 war davon nichts in Firefox ausgeliefert; die sicherheitsorientierte Sprache musste sich erst in einem riesigen, leistungskritischen C++-Browser beweisen.
Die naheliegenden Wege zum Schutz der Nutzer reichten alle nicht aus. Den C++-Parser zu patchen bedeutete, jede neue Schwachstelle für immer verteidigen zu müssen; ihn zu sandboxen verringerte den Wirkungsradius, ohne die Fehlerklasse zu beseitigen; und den gesamten Browser in Rust neu zu schreiben war ein mehrjähriges Glücksspiel, das das Produkt unterwegs beschädigen würde. Das Media-Playback-Team von Mozilla wählte stattdessen ein begrenztes, sicherheitskritisches Stück: den MP4-Metadaten-Parser, der auf nicht vertrauenswürdigen Webmedien läuft.
Ralph Giles und Matthew Gregan schrieben einen reinen Rust-Ersatz für diesen Parser, machten ihn über eine C-API zugänglich, sodass der umgebende C++-Build unverändert blieb, und verifizierten, dass er identische Ergebnisse lieferte wie der ersetzte Code. Firefox 48 brachte ihn dann auf alle Desktop-Plattformen und stellte damit erstmals Produktions-Rust vor Hunderte Millionen Nutzer, wobei Android-Unterstützung als Nächstes geplant war.
Der Pilot funktionierte, weil er eine Ideologie in Belege verwandelte. Die Regeln von Rust zur Kompilierzeit beseitigten die Speicherfehlerklasse für diese Komponente, statt eine weitere Verteidigungsschicht hinzuzufügen, und die Firefox-Telemetrie verzeichnete null Probleme bei mehr als einer Milliarde Nutzungen des neuen Codes. Mozilla nannte es den ersten Schritt, nicht das Ende: eine bewährte Vorlage – die riskanteste begrenzte Komponente ersetzen, Gleichwertigkeit nachweisen, ausliefern und messen – für die größere Migration, die noch bevorstand.
Beginne die Migration beim Parser, der nicht vertrauenswürdige Daten verarbeitet
Beim Medien-Parsing treffen nicht vertrauenswürdige Bytes auf nativen Code, daher zielte der Pilot auf das größte verbleibende Risiko pro Zeile
Ein eigenständiger Parser hat eine klar abgrenzbare, testbare Grenze: identische Ausgabe wie die C++-Komponente ließ sich prüfen
Speichersicherheit zur Kompilierzeit beseitigte die gesamte Fehlerklasse, statt eine weitere Verteidigungsschicht hinzuzufügen
Null Telemetrieprobleme bei einer Milliarde Nutzungen verwandelten eine Sprachwette in einen messbaren Produktionsnachweis
Die Bereitstellung von Rust über eine C-API ermöglichte die Auslieferung des Parsers, ohne den übrigen C++-Build zu stören
Neue Technologie in eine gewachsene Codebasis zu bringen ist eine Transplantation, keine Neuschreibung: Wähle die riskanteste Komponente mit einer testbaren Grenze, liefere sie aus und lass die Produktionsdaten den Fall für mehr belegen
Firefox 48 brachte den ersten Produktions-Rust zu allen Desktop-Nutzern, und Mozilla behandelte diesen Meilenstein als Eröffnungszug statt als Abschluss: Das Oxidation-Wiki bildete ab, welche Rust-Funktionen wann auf welcher Plattform Einzug halten würden, und Bugzilla 1284816 verfolgte das Ziel, Rust zu einem erforderlichen Teil des Firefox-Builds zu machen. Ein Speichermangel-Absturz, der während der Einführung entdeckt wurde, wurde für Firefox 48 behoben, indem auf eine fehlertolerante Thread-Builder-API umgestellt wurde, die einen Fehler zurückgibt, statt abzustürzen. Derselbe Weg – begrenzte speichersichere Ersetzungen, durch Telemetrie belegt – wurde zur Blaupause für die Rust-Komponenten, die folgten.
DEN BELEGEN FOLGEN
Die Quellen
- Shipping Rust in Firefox Mozilla Hacks · hacks.mozilla.org ·
- mozilla/mp4parse-rust — Parser for ISO Base Media Format aka video/mp4 written in Rust GitHub · github.com