Skip to content

WebAssembly System Interface (WASI)

[Stabile: 1 - Sperimentale]

Stabile: 1 Stabilità: 1 - Sperimentale

Il modulo node:wasi non fornisce attualmente le proprietà complete di sicurezza del file system offerte da alcuni runtime WASI. Il supporto completo per la sandbox sicura del file system potrebbe essere o meno implementato in futuro. Nel frattempo, non fare affidamento su di esso per eseguire codice non attendibile.

Codice sorgente: lib/wasi.js

L'API WASI fornisce un'implementazione della specifica WebAssembly System Interface. WASI fornisce alle applicazioni WebAssembly l'accesso al sistema operativo sottostante tramite una raccolta di funzioni di tipo POSIX.

js
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)
js
'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)
})()

Per eseguire l'esempio precedente, creare un nuovo file in formato testo WebAssembly denominato demo.wat:

text
(module
    ;; Importa la funzione WASI fd_write richiesta che scriverà i vettori di I/O dati su stdout
    ;; La firma della funzione per fd_write è:
    ;; (File Descriptor, *iovs, iovs_len, nwritten) -> Restituisce il numero di byte scritti
    (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))

    (memory 1)
    (export "memory" (memory 0))

    ;; Scrive 'hello world\n' in memoria a un offset di 8 byte
    ;; Si noti il carattere di nuova riga finale richiesto affinché il testo appaia
    (data (i32.const 8) "hello world\n")

    (func $main (export "_start")
        ;; Creazione di un nuovo vettore di I/O nella memoria lineare
        (i32.store (i32.const 0) (i32.const 8))  ;; iov.iov_base - Questo è un puntatore all'inizio della stringa 'hello world\n'
        (i32.store (i32.const 4) (i32.const 12))  ;; iov.iov_len - La lunghezza della stringa 'hello world\n'

        (call $fd_write
            (i32.const 1) ;; file_descriptor - 1 per stdout
            (i32.const 0) ;; *iovs - Il puntatore alla matrice iov, che è memorizzato nella posizione di memoria 0
            (i32.const 1) ;; iovs_len - Stiamo stampando 1 stringa memorizzata in un iov - quindi uno.
            (i32.const 20) ;; nwritten - Un posto in memoria per memorizzare il numero di byte scritti
        )
        drop ;; Elimina il numero di byte scritti dalla cima dello stack
    )
)

Utilizzare wabt per compilare .wat in .wasm

bash
wat2wasm demo.wat

Sicurezza

[Cronologia]

VersioneModifiche
v21.2.0, v20.11.0Chiarificazione delle proprietà di sicurezza WASI.
v21.2.0, v20.11.0Aggiunto in: v21.2.0, v20.11.0

WASI fornisce un modello basato sulle capacità attraverso il quale alle applicazioni vengono fornite le proprie capacità personalizzate env, preopens, stdin, stdout, stderr ed exit.

L'attuale modello di minacce di Node.js non fornisce una sandbox sicura come quella presente in alcuni runtime WASI.

Sebbene le funzionalità di capacità siano supportate, non costituiscono un modello di sicurezza in Node.js. Ad esempio, la sandbox del file system può essere elusa con varie tecniche. Il progetto sta esplorando la possibilità di aggiungere queste garanzie di sicurezza in futuro.

Classe: WASI

Aggiunto in: v13.3.0, v12.16.0

La classe WASI fornisce l'API delle chiamate di sistema WASI e metodi aggiuntivi per lavorare con applicazioni basate su WASI. Ogni istanza WASI rappresenta un ambiente distinto.

new WASI([options])

[Cronologia]

VersioneModifiche
v20.1.0Il valore predefinito di returnOnExit è stato modificato in true.
v20.0.0L'opzione version è ora obbligatoria e non ha un valore predefinito.
v19.8.0Campo version aggiunto alle opzioni.
v13.3.0, v12.16.0Aggiunto in: v13.3.0, v12.16.0
  • options <Oggetto>
    • args <Array> Una matrice di stringhe che l'applicazione WebAssembly vedrà come argomenti della riga di comando. Il primo argomento è il percorso virtuale del comando WASI stesso. Predefinito: [].
    • env <Oggetto> Un oggetto simile a process.env che l'applicazione WebAssembly vedrà come il suo ambiente. Predefinito: {}.
    • preopens <Oggetto> Questo oggetto rappresenta la struttura della directory locale dell'applicazione WebAssembly. Le chiavi stringa di preopens sono trattate come directory all'interno del file system. I valori corrispondenti in preopens sono i percorsi reali di quelle directory sulla macchina host.
    • returnOnExit <booleano> Per impostazione predefinita, quando le applicazioni WASI chiamano __wasi_proc_exit(), wasi.start() restituirà il codice di uscita specificato invece di terminare il processo. Impostando questa opzione su false, il processo Node.js terminerà con il codice di uscita specificato. Predefinito: true.
    • stdin <intero> Il descrittore del file utilizzato come input standard nell'applicazione WebAssembly. Predefinito: 0.
    • stdout <intero> Il descrittore del file utilizzato come output standard nell'applicazione WebAssembly. Predefinito: 1.
    • stderr <intero> Il descrittore del file utilizzato come errore standard nell'applicazione WebAssembly. Predefinito: 2.
    • version <stringa> La versione di WASI richiesta. Attualmente le uniche versioni supportate sono unstable e preview1. Questa opzione è obbligatoria.

wasi.getImportObject()

Aggiunto in: v19.8.0

Restituisce un oggetto di importazione che può essere passato a WebAssembly.instantiate() se non sono necessarie altre importazioni WASM oltre a quelle fornite da WASI.

Se la versione unstable è stata passata al costruttore, restituirà:

json
{ wasi_unstable: wasi.wasiImport }

Se la versione preview1 è stata passata al costruttore o non è stata specificata alcuna versione, restituirà:

json
{ wasi_snapshot_preview1: wasi.wasiImport }

wasi.start(instance)

Aggiunto in: v13.3.0, v12.16.0

Prova ad iniziare l'esecuzione di instance come comando WASI invocando la sua esportazione _start(). Se instance non contiene un'esportazione _start(), o se instance contiene un'esportazione _initialize(), viene sollevata un'eccezione.

start() richiede che instance esporti una WebAssembly.Memory denominata memory. Se instance non ha un'esportazione memory, viene sollevata un'eccezione.

Se start() viene chiamato più di una volta, viene sollevata un'eccezione.

wasi.initialize(instance)

Aggiunto in: v14.6.0, v12.19.0

Prova ad inizializzare instance come reattore WASI invocando la sua esportazione _initialize(), se presente. Se instance contiene un'esportazione _start(), viene sollevata un'eccezione.

initialize() richiede che instance esporti una WebAssembly.Memory denominata memory. Se instance non ha un'esportazione memory, viene sollevata un'eccezione.

Se initialize() viene chiamato più di una volta, viene sollevata un'eccezione.

wasi.wasiImport

Aggiunto in: v13.3.0, v12.16.0

wasiImport è un oggetto che implementa l'API delle chiamate di sistema WASI. Questo oggetto dovrebbe essere passato come importazione wasi_snapshot_preview1 durante l'istanza di una WebAssembly.Instance.