WebAssembly System Interface (WASI)
[Stabil: 1 - Experimentell]
Stabil: 1 Stabilität: 1 - Experimentell
Das Modul node:wasi
bietet derzeit nicht die umfassenden Dateisystemsicherheitseigenschaften, die von einigen WASI-Laufzeiten bereitgestellt werden. Eine vollständige Unterstützung für sichere Dateisystem-Sandboxing kann in Zukunft implementiert werden oder auch nicht. Vertrauen Sie in der Zwischenzeit nicht darauf, nicht vertrauenswürdigen Code auszuführen.
Quellcode: lib/wasi.js
Die WASI-API bietet eine Implementierung der WebAssembly System Interface-Spezifikation. WASI ermöglicht WebAssembly-Anwendungen den Zugriff auf das zugrunde liegende Betriebssystem über eine Sammlung von POSIX-ähnlichen Funktionen.
import { readFile } from 'node:fs/promises'
import { WASI } from 'node:wasi'
import { argv, env } from 'node:process'
const wasi = new WASI({
version: 'preview1',
args: argv,
env,
preopens: {
'/local': '/some/real/path/that/wasm/can/access',
},
})
const wasm = await WebAssembly.compile(await readFile(new URL('./demo.wasm', import.meta.url)))
const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject())
wasi.start(instance)
'use strict'
const { readFile } = require('node:fs/promises')
const { WASI } = require('node:wasi')
const { argv, env } = require('node:process')
const { join } = require('node:path')
const wasi = new WASI({
version: 'preview1',
args: argv,
env,
preopens: {
'/local': '/some/real/path/that/wasm/can/access',
},
})
;(async () => {
const wasm = await WebAssembly.compile(await readFile(join(__dirname, 'demo.wasm')))
const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject())
wasi.start(instance)
})()
Um das obige Beispiel auszuführen, erstellen Sie eine neue WebAssembly-Textformatdatei namens demo.wat
:
(module
;; Importieren Sie die erforderliche fd_write WASI-Funktion, die die angegebenen IO-Vektoren nach stdout schreibt
;; Die Funktionssignatur für fd_write lautet:
;; (File Descriptor, *iovs, iovs_len, nwritten) -> Gibt die Anzahl der geschriebenen Bytes zurück
(import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
(memory 1)
(export "memory" (memory 0))
;; Schreibe 'hello world\n' in den Speicher bei einem Offset von 8 Bytes
;; Beachten Sie die nachgestellte Newline, die erforderlich ist, damit der Text angezeigt wird
(data (i32.const 8) "hello world\n")
(func $main (export "_start")
;; Erstellen eines neuen IO-Vektors im linearen Speicher
(i32.store (i32.const 0) (i32.const 8)) ;; iov.iov_base - Dies ist ein Zeiger auf den Start der Zeichenfolge 'hello world\n'
(i32.store (i32.const 4) (i32.const 12)) ;; iov.iov_len - Die Länge der Zeichenfolge 'hello world\n'
(call $fd_write
(i32.const 1) ;; file_descriptor - 1 für stdout
(i32.const 0) ;; *iovs - Der Zeiger auf das iov-Array, das an Speicherstelle 0 gespeichert ist
(i32.const 1) ;; iovs_len - Wir geben 1 Zeichenfolge aus, die in einem iov gespeichert ist - also eins.
(i32.const 20) ;; nwritten - Ein Ort im Speicher, um die Anzahl der geschriebenen Bytes zu speichern
)
drop ;; Verwirft die Anzahl der geschriebenen Bytes vom oberen Rand des Stacks
)
)
Verwenden Sie wabt, um .wat
in .wasm
zu kompilieren.
wat2wasm demo.wat
Sicherheit
[Verlauf]
Version | Änderungen |
---|---|
v21.2.0, v20.11.0 | Klarstellung der WASI-Sicherheitseigenschaften. |
v21.2.0, v20.11.0 | Hinzugefügt in: v21.2.0, v20.11.0 |
WASI bietet ein auf Fähigkeiten basierendes Modell, durch das Anwendungen ihre eigenen benutzerdefinierten env
, preopens
, stdin
, stdout
, stderr
und exit
-Fähigkeiten erhalten.
Das aktuelle Node.js-Bedrohungsmodell bietet keine sichere Sandboxing-Umgebung, wie sie in einigen WASI-Laufzeitumgebungen vorhanden ist.
Obwohl die Fähigkeitsfunktionen unterstützt werden, bilden sie kein Sicherheitsmodell in Node.js. Zum Beispiel kann das Dateisystem-Sandboxing mit verschiedenen Techniken umgangen werden. Das Projekt untersucht, ob diese Sicherheitsgarantien in der Zukunft hinzugefügt werden können.
Klasse: WASI
Hinzugefügt in: v13.3.0, v12.16.0
Die Klasse WASI
bietet die WASI-Systemaufruf-API und zusätzliche Komfortmethoden für die Arbeit mit WASI-basierten Anwendungen. Jede WASI
-Instanz repräsentiert eine eigene Umgebung.
new WASI([optionen])
[Verlauf]
Version | Änderungen |
---|---|
v20.1.0 | Standardwert von returnOnExit auf true geändert. |
v20.0.0 | Die Option version ist jetzt erforderlich und hat keinen Standardwert. |
v19.8.0 | Feld version zu Optionen hinzugefügt. |
v13.3.0, v12.16.0 | Hinzugefügt in: v13.3.0, v12.16.0 |
optionen
<Object>args
<Array> Ein Array von Zeichenketten, die die WebAssembly-Anwendung als Befehlszeilenargumente sehen wird. Das erste Argument ist der virtuelle Pfad zum WASI-Befehl selbst. Standard:[]
.env
<Object> Ein Objekt ähnlich wieprocess.env
, das die WebAssembly-Anwendung als ihre Umgebung sehen wird. Standard:{}
.preopens
<Object> Dieses Objekt repräsentiert die lokale Verzeichnisstruktur der WebAssembly-Anwendung. Die String-Schlüssel vonpreopens
werden als Verzeichnisse innerhalb des Dateisystems behandelt. Die entsprechenden Werte inpreopens
sind die tatsächlichen Pfade zu diesen Verzeichnissen auf dem Hostrechner.returnOnExit
<boolean> Standardmäßig gibtwasi.start()
zurück, wenn WASI-Anwendungen__wasi_proc_exit()
aufrufen, und zwar mit dem angegebenen Exit-Code, anstatt den Prozess zu beenden. Wenn diese Option auffalse
gesetzt wird, wird der Node.js-Prozess stattdessen mit dem angegebenen Exit-Code beendet. Standard:true
.stdin
<integer> Der Dateideskriptor, der als Standardeingabe in der WebAssembly-Anwendung verwendet wird. Standard:0
.stdout
<integer> Der Dateideskriptor, der als Standardausgabe in der WebAssembly-Anwendung verwendet wird. Standard:1
.stderr
<integer> Der Dateideskriptor, der als Standardfehlerausgabe in der WebAssembly-Anwendung verwendet wird. Standard:2
.version
<string> Die angeforderte Version von WASI. Derzeit werden nur die Versionenunstable
undpreview1
unterstützt. Diese Option ist obligatorisch.
wasi.getImportObject()
Hinzugefügt in: v19.8.0
Gibt ein Importobjekt zurück, das an WebAssembly.instantiate()
übergeben werden kann, wenn keine anderen WASM-Importe benötigt werden, die über die von WASI bereitgestellten hinausgehen.
Wenn die Version unstable
an den Konstruktor übergeben wurde, wird Folgendes zurückgegeben:
{ wasi_unstable: wasi.wasiImport }
Wenn die Version preview1
an den Konstruktor übergeben wurde oder keine Version angegeben wurde, wird Folgendes zurückgegeben:
{ wasi_snapshot_preview1: wasi.wasiImport }
wasi.start(instance)
Hinzugefügt in: v13.3.0, v12.16.0
instance
<WebAssembly.Instance>
Versucht, die Ausführung von instance
als WASI-Befehl zu starten, indem der Export _start()
aufgerufen wird. Wenn instance
keinen _start()
-Export enthält oder instance
einen _initialize()
-Export enthält, wird eine Ausnahme ausgelöst.
start()
erfordert, dass instance
einen WebAssembly.Memory
mit dem Namen memory
exportiert. Wenn instance
keinen memory
-Export hat, wird eine Ausnahme ausgelöst.
Wenn start()
mehr als einmal aufgerufen wird, wird eine Ausnahme ausgelöst.
wasi.initialize(instance)
Hinzugefügt in: v14.6.0, v12.19.0
instance
<WebAssembly.Instance>
Versucht, instance
als WASI-Reaktor zu initialisieren, indem der Export _initialize()
aufgerufen wird, falls vorhanden. Wenn instance
einen _start()
-Export enthält, wird eine Ausnahme ausgelöst.
initialize()
erfordert, dass instance
einen WebAssembly.Memory
mit dem Namen memory
exportiert. Wenn instance
keinen memory
-Export hat, wird eine Ausnahme ausgelöst.
Wenn initialize()
mehr als einmal aufgerufen wird, wird eine Ausnahme ausgelöst.
wasi.wasiImport
Hinzugefügt in: v13.3.0, v12.16.0
wasiImport
ist ein Objekt, das die WASI-Systemaufruf-API implementiert. Dieses Objekt sollte als wasi_snapshot_preview1
-Import während der Instanziierung einer WebAssembly.Instance
übergeben werden.