Interface Système WebAssembly (WASI)
[Stable: 1 - Expérimental]
Stable: 1 Stability: 1 - Expérimental
Le module node:wasi
ne fournit pas actuellement les propriétés de sécurité complètes du système de fichiers fournies par certains environnements d'exécution WASI. La prise en charge complète du sandboxing sécurisé du système de fichiers peut être implémentée ou non dans le futur. En attendant, ne comptez pas dessus pour exécuter du code non fiable.
Code Source: lib/wasi.js
L'API WASI fournit une implémentation de la spécification Interface Système WebAssembly. WASI donne aux applications WebAssembly l'accès au système d'exploitation sous-jacent via une collection de fonctions de type POSIX.
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);
})();
Pour exécuter l'exemple ci-dessus, créez un nouveau fichier de format texte WebAssembly nommé demo.wat
:
(module
;; Importe la fonction WASI fd_write requise qui écrira les vecteurs io donnés sur stdout
;; La signature de la fonction pour fd_write est :
;; (Descripteur de fichier, *iovs, iovs_len, nwritten) -> Renvoie le nombre d'octets écrits
(import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
(memory 1)
(export "memory" (memory 0))
;; Écrivez « hello world\n » dans la mémoire à un décalage de 8 octets
;; Notez le saut de ligne de fin qui est requis pour que le texte apparaisse
(data (i32.const 8) "hello world\n")
(func $main (export "_start")
;; Création d’un nouveau vecteur io dans la mémoire linéaire
(i32.store (i32.const 0) (i32.const 8)) ;; iov.iov_base - Il s'agit d'un pointeur vers le début de la chaîne « hello world\n »
(i32.store (i32.const 4) (i32.const 12)) ;; iov.iov_len - La longueur de la chaîne « hello world\n »
(call $fd_write
(i32.const 1) ;; file_descriptor - 1 pour stdout
(i32.const 0) ;; *iovs - Le pointeur vers le tableau iov, qui est stocké à l'emplacement mémoire 0
(i32.const 1) ;; iovs_len - Nous imprimons 1 chaîne stockée dans un iov - donc un.
(i32.const 20) ;; nwritten - Un endroit en mémoire pour stocker le nombre d'octets écrits
)
drop ;; Ignore le nombre d'octets écrits du haut de la pile
)
)
Utilisez wabt pour compiler .wat
en .wasm
wat2wasm demo.wat
Sécurité
[Historique]
Version | Modifications |
---|---|
v21.2.0, v20.11.0 | Clarification des propriétés de sécurité de WASI. |
v21.2.0, v20.11.0 | Ajouté dans : v21.2.0, v20.11.0 |
WASI fournit un modèle basé sur les capacités grâce auquel les applications reçoivent leurs propres capacités personnalisées env
, preopens
, stdin
, stdout
, stderr
et exit
.
Le modèle de menace actuel de Node.js ne fournit pas de sandboxing sécurisé comme c'est le cas dans certains environnements d'exécution WASI.
Bien que les fonctionnalités de capacité soient prises en charge, elles ne constituent pas un modèle de sécurité dans Node.js. Par exemple, le sandboxing du système de fichiers peut être contourné à l'aide de diverses techniques. Le projet étudie la possibilité d'ajouter ces garanties de sécurité à l'avenir.
Classe : WASI
Ajouté dans : v13.3.0, v12.16.0
La classe WASI
fournit l'API d'appel système WASI et des méthodes de commodité supplémentaires pour travailler avec des applications basées sur WASI. Chaque instance WASI
représente un environnement distinct.
new WASI([options])
[Historique]
Version | Modifications |
---|---|
v20.1.0 | La valeur par défaut de returnOnExit est passée à true. |
v20.0.0 | L'option version est désormais obligatoire et n'a pas de valeur par défaut. |
v19.8.0 | Champ version ajouté aux options. |
v13.3.0, v12.16.0 | Ajouté dans : v13.3.0, v12.16.0 |
options
<Object>args
<Array> Un tableau de chaînes que l'application WebAssembly verra comme arguments de ligne de commande. Le premier argument est le chemin d'accès virtuel à la commande WASI elle-même. Par défaut :[]
.env
<Object> Un objet similaire àprocess.env
que l'application WebAssembly verra comme son environnement. Par défaut :{}
.preopens
<Object> Cet objet représente la structure de répertoire locale de l'application WebAssembly. Les clés de chaîne depreopens
sont traitées comme des répertoires dans le système de fichiers. Les valeurs correspondantes danspreopens
sont les chemins réels vers ces répertoires sur la machine hôte.returnOnExit
<boolean> Par défaut, lorsque les applications WASI appellent__wasi_proc_exit()
,wasi.start()
renverra le code de sortie spécifié au lieu de mettre fin au processus. Définir cette option surfalse
entraînera la fermeture du processus Node.js avec le code de sortie spécifié à la place. Par défaut :true
.stdin
<integer> Le descripteur de fichier utilisé comme entrée standard dans l'application WebAssembly. Par défaut :0
.stdout
<integer> Le descripteur de fichier utilisé comme sortie standard dans l'application WebAssembly. Par défaut :1
.stderr
<integer> Le descripteur de fichier utilisé comme erreur standard dans l'application WebAssembly. Par défaut :2
.version
<string> La version de WASI demandée. Actuellement, les seules versions prises en charge sontunstable
etpreview1
. Cette option est obligatoire.
wasi.getImportObject()
Ajouté dans: v19.8.0
Renvoie un objet importable qui peut être passé à WebAssembly.instantiate()
si aucun autre import WASM n'est nécessaire au-delà de ceux fournis par WASI.
Si la version unstable
a été passée au constructeur, elle renverra:
{ wasi_unstable: wasi.wasiImport }
Si la version preview1
a été passée au constructeur ou si aucune version n'a été spécifiée, elle renverra:
{ wasi_snapshot_preview1: wasi.wasiImport }
wasi.start(instance)
Ajouté dans: v13.3.0, v12.16.0
instance
<WebAssembly.Instance>
Tente de commencer l'exécution de instance
en tant que commande WASI en invoquant son exportation _start()
. Si instance
ne contient pas d'exportation _start()
, ou si instance
contient une exportation _initialize()
, une exception est levée.
start()
exige que instance
exporte un WebAssembly.Memory
nommé memory
. Si instance
n'a pas d'exportation memory
, une exception est levée.
Si start()
est appelé plus d'une fois, une exception est levée.
wasi.initialize(instance)
Ajouté dans: v14.6.0, v12.19.0
instance
<WebAssembly.Instance>
Tente d'initialiser instance
en tant que réacteur WASI en invoquant son exportation _initialize()
, si elle est présente. Si instance
contient une exportation _start()
, une exception est levée.
initialize()
exige que instance
exporte un WebAssembly.Memory
nommé memory
. Si instance
n'a pas d'exportation memory
, une exception est levée.
Si initialize()
est appelé plus d'une fois, une exception est levée.
wasi.wasiImport
Ajouté dans: v13.3.0, v12.16.0
wasiImport
est un objet qui implémente l'API d'appel système WASI. Cet objet doit être passé en tant qu'importation wasi_snapshot_preview1
lors de l'instanciation d'un WebAssembly.Instance
.