Abstrakte Wikipedia/Anmerkungen zu WebAssembly
Abstrakte Wikipedia |
---|
(Diskussion) |
Allgemein |
Entwicklungsplan |
|
Anmerkungen, Entwürfe, Diskussionen |
|
Beispiele und Modelle |
Datenwerkzeuge |
Historisch |
Dies ist eine Sammlung von Anmerkungen zu WebAssembly (im Folgenden WASM), zum WebAssembly System Interface (im Folgenden WASI), der aktuellen Integration dieser Technologien in Wikifunctions und einer Reihe von Gedanken zu alternativen Designs, die wir in Zukunft untersuchen könnten.
WASM, WASI, Was und Warum
WASM ist eine Assembler-ähnliche Sprache. Sie wird als Compiler-Ziel für mehrere Programmiersprachen unterstützt, darunter C und Rust. WASM-Code kann in den meisten modernen Browsern ausgeführt werden. Er kann auch als eigenständige Anwendung über eine WASM-Laufzeitumgebung ausgeführt werden. Es gibt mehrere WASM-Laufzeiten; wir haben wasmtime
ausprobiert, verwenden jetzt aber ausschließlich wasmedge
.
WASI ermöglicht WASM die Interaktion mit einem Betriebssystem. WASM selbst bietet einige Funktionen für häufige Vorgänge — Dateien lesen / schreiben, Netzwerkverbindungen, etc — die nicht nativ implementiert sind, sondern explizit an die entsprechenden Systemaufrufe eines Betriebssystems angehängt werden müssen. WASI tut dies, indem es selektiven Zugriff auf bestimmte Systemaufrufe bietet. wasmedge
verfügt wie die meisten WASM-Laufzeiten über eine integrierte WASI-Erweiterung.
Die Wikifunctions-Ausführer laufen derzeit in WASM-Laufzeiten. Nach Gesprächen mit Sicherheit und SRE einigte sich das Team Abstrakte Wikipedia darauf, WASM-Laufzeiten als schnelle und relativ unaufdringliche Möglichkeit zu verwenden, um einige gängige Angriffsmethoden im Zusammenhang mit der Ausführung von beliebigem Code anzugehen (wofür die Ausführer entwickelt wurden). Dies ist keine perfekte Lösung, aber andere Lösungen hätten entweder potenziell unsichere Änderungen von anderen Teams erfordert (z. B. Änderungen an Blubber, um die Ausführung des AW-Auswerter-Dienstes als Wurzel zu ermöglichen) oder große und problematische Änderungen am Auswerter-Dienst selbst (z. B. die Umwandlung des Auswerters in einen einzelnen, lang laufenden Dienst anstelle eines einfachen und kurzlebigen Dienstes plus damit verbundene Änderungen zur Koordination asynchroner Aufrufe, Implementierung einer Wiederholungslogik, Neustart des Ausführer-Prozesses bei Fehlern, etc.). Deshalb wurde WASM als unkomplizierte Lösung vereinbart, die den Sicherheits- und Infrastrukturbeschränkungen entspricht.
Aktueller Status
Für Python und JavaScript haben wir uns auf ein ähnliches Muster geeinigt. Wir erstellen den Interpreter für jede Programmiersprache aus dem Quellcode. Der Interpreter ist eine .wasm-Binärdatei, die mit einer WASM-Laufzeitumgebung (in diesem Fall wasmedge
) ausgeführt werden kann. Aus Performancegründen kompilieren wir diese Binärdatei (ebenfalls mit wasmedge
), wenn wir das Bild des Auswerter-Dienstes erstellen.
WASM-Laufzeitumgebungen für diese Programmiersprachen sind leichter in Hipster-Implementierungen zu finden. Daher verwenden wir für Python RustPython (der Standard-Interpreter ist CPython). Für JavaScript verwenden wir wasmedge-quickjs, das JavaScript mit der QuickJS-Engine implementiert (anstelle der häufigeren V8).
Alternativen und Ideen für die Zukunft (JavaScript)
quickjs-emscripten
quickjs-emscripten
wurde speziell für die Ausführung von nicht vertrauenswürdigem Code entwickelt. Sein Ausführungsmodell ähnelt oberflächlich dem Berechnungsgraph von TensorFlow. Der QuickJS-Interpreter wird in einem isolierten Kontext ausgeführt. Daten werden zwischen dem Haupt-JS-Prozess und diesem Kontext per Vorwärtsdeklaration übergeben. Anschließend führt eine sichere eval()
-Funktion beliebige Berechnungen über diese Daten innerhalb des isolierten Kontexts aus. Dann werden die zurückgegebenen Werte aus dem Kontext "ausgepackt" und im Hauptprozess angezeigt.
Du kannst hier
einen früheren Versuch sehen, diesen Ansatz zu verwenden. Leider handelt es sich dabei um eine relativ unbekannte Bibliothek mit wenig Support und ihre WASM-Laufzeitumgebung verfügt nicht über das von uns gewünschte Sicherheitsprofil (zumindest nicht von Haus aus), sodass wir diesen Ansatz aufgegeben haben.
Javy
Javy
funktioniert, indem JavaScript-Code in WASM transpiliert wird, der dann über wasmedge
oder eine andere WASM-Laufzeitumgebung ausgeführt werden kann. Dieser Ansatz könnte daher möglicherweise schneller sein, da wir den Ausführer-Code direkt in WASM transpilieren können und nur der von der Community beigesteuerte Code in einer eval()
-Anweisung "langsam" ausgeführt wird.
Dieser Ansatz leidet ein wenig unter der Modularität. Er setzt voraus, dass jedes Modul als .wit-Datei verpackt wird, es gibt jedoch starke Einschränkungen hinsichtlich dessen, was exportiert werden kann. Insbesondere können Module keine Funktionen exportieren, die Argumente oder Rückgabewerte haben. Wenn jedoch die Geschwindigkeit ein Problem darstellt, sollten wir uns möglicherweise erneut Javy ansehen. Wenn .wit-Importe bis dahin noch nicht ausgereift sind, können wir die Modularitätsprobleme mit rollupjs
umgehen.
cloudflare/workerd
Cloudflares workerd
wurde entwickelt, um dasselbe Problem zu lösen, das uns dazu veranlasst hat, WASM in Wikifunctions einzuführen: Es handelt sich um eine serverseitige WASM-Laufzeitumgebung für JavaScript, und genau das implementiert Wikifunctions jetzt. Ein potenzieller Vorteil hierbei ist, dass workerd
die bekanntere V8-Engine verwendet (die anderen hier erwähnten Lösungen verwenden QuickJS). Allerdings ist workerd
extrem schwergewichtig, sodass es zu umständlich erschien, es als ersten Versuch zu integrieren, um JS auf WASM auszuführen.
Zusätzliche Ressourcen
Diese Zusammenfassung der QuickJS-Spezifikation und C-APIs war sehr hilfreich.