You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

164 lines
7.5 KiB

# WASI: WebAssembly System Interface
WebAssembly System Interface, or WASI, is a new family of API's being
designed by the [Wasmtime] project to propose as a standard engine-independent
non-Web system-oriented API for WebAssembly. Initially, the focus is on
WASI Core, an API module that covers files, networking, and a few other
things. Additional modules are expected to be added in the future.
WebAssembly is designed to run well on the Web, however it's
[not limited to the Web](https://github.com/WebAssembly/design/blob/master/NonWeb.md).
The core WebAssembly language is independent of its surrounding
environment, and WebAssembly interacts with the outside world
exclusively through APIs. On the Web, it naturally uses the
existing Web APIs provided by browsers. However outside of
browsers, there's currently no standard set of APIs that
WebAssembly programs can be written to. This makes it difficult to
create truly portable non-Web WebAssembly programs.
WASI is an initiative to fill this gap, with a clean set of APIs
which can be implemented on multiple platforms by multiple engines,
and which don't depend on browser functionality (although they
still can run in browsers; see below).
## Capability-Oriented
The design follows
[CloudABI](https://cloudabi.org/)'s
(and in turn
[Capsicum](https://www.cl.cam.ac.uk/research/security/capsicum/))'s concept of
[capability-based security](https://en.wikipedia.org/wiki/Capability-based_security),
which fits well into WebAssembly's sandbox model. Files,
directories, network sockets, and other resources are identified
by UNIX-like file descriptors, which are indices into external
tables whose elements represent capabilities. Similar to how core
WebAssembly provides no ability to access the outside world without
calling imported functions, WASI APIs provide no ability to access
the outside world without an associated capability.
For example, instead of a typical
[open](http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html)
system call, WASI provides an
[openat](https://linux.die.net/man/2/openat)-like
system call, requiring the calling process to have a file
descriptor for a directory that contains the file, representing the
capability to open files within that directory. (These ideas are
common in capability-based systems.)
However, the WASI libc implementation still does provide an
implementation of open, by taking the approach of
[libpreopen](https://github.com/musec/libpreopen).
Programs may be granted capabilities for directories on launch, and
the library maintains a mapping from their filesystem path to the
file descriptor indices representing the associated capabilities.
When a program calls open, they look up the file name in the map,
and automatically supply the appropriate directory capability. It
also means WASI doesn't require the use of CloudABI's `program_main`
construct. This eases porting of existing applications without
compromising the underlying capability model. See the diagram below
for how libpreopen fits into the overall software architecture.
WASI also automatically provides file descriptors for standard
input and output, and WASI libc provides a normal `printf`. In
general, WASI is aiming to support a fairly full-featured libc
implementation, with the current implementation work being based on
[musl](http://www.musl-libc.org/).
## Portable System Interface for WebAssembly
WASI is being designed from the ground up for WebAssembly, with
sandboxing, portability, and API tidiness in mind, making natural
use of WebAssembly features such as i64, import functions with
descriptive names and typed arguments, and aiming to avoid being
tied to a particular implementation.
We'll often call functions in these APIs "syscalls", because they
serve an analogous purpose to system calls in native executables.
However, they're just functions that are provided by the
surrounding environment that can do I/O on behalf of the program.
WASI is starting with a basic POSIX-like set of syscall functions,
though adapted to suit the needs of WebAssembly, such as in
excluding functions such as fork and exec which aren't easily
implementable in some of the places people want to run WebAssembly,
and such as in adopting a capabilities-oriented design.
And, as WebAssembly grows support for
[host bindings](https://github.com/webassembly/host-bindings)
and related features, capabilities can evolve to being represented
as opaque, unforgeable
[reference typed values](https://github.com/WebAssembly/reference-types),
which can allow for finer-grained control over capabilities, and
make the API more accessible beyond the C-like languages that
POSIX-style APIs are typically aimed at.
## WASI Software Architecture
To facilitate use of the WASI API, a libc
implementation called WASI libc is being developed, which presents
a relatively normal musl-based libc interface, implemented on top
of a libpreopen-like layer and a system call wrapper layer (derived
from the "bottom half" of
[cloudlibc](https://github.com/NuxiNL/cloudlibc)).
The system call wrapper layer makes calls to the actual WASI
implementation, which may map these calls to whatever the
surrounding environment provides, whether it's native OS resources,
JS runtime resources, or something else entirely.
[This libc is part of a "sysroot"](https://github.com/WebAssembly/reference-sysroot),
which is a directory containing compiled libraries and C/C++ header
files providing standard library and related facilities laid out in
a standard way to allow compilers to use it directly.
With the [LLVM 8.0](http://llvm.org/)
release, the WebAssembly backend is now officially stable, but LLVM
itself doesn't provide a libc - a standard C library, which you
need to build anything with clang. This is what the WASI-enabled
sysroot provides, so the combination of clang in LLVM 8.0 and the
new WASI-enabled sysroot provides usable Rust and C compilation
environments that can produce wasm modules that can be run in
[Wasmtime] with WASI support, in browsers with the WASI polyfill,
and in the future other engines as well.
![WASI software architecture diagram](wasi-software-architecture.png "WASI software architecture diagram")
## Future Evolution
The first version of WASI is relatively simple, small, and
POSIX-like in order to make it easy for implementers to prototype
it and port existing code to it, making it a good way to start
building momentum and allow us to start getting feedback based on
experience.
Future versions will change based on experience
and feedback with the first version, and add features to address
new use cases. They may also see significant architectural
changes. One possibility is that this API could
evolve into something like
[Fuchsia](https://en.wikipedia.org/wiki/Google_Fuchsia)'s
low-level APIs, which are more complex and abstract, though also
more capable.
We also expect that whatever WASI evolves into in the future, it
should be possible to implement this initial API as a library
on top.
## Can WASI apps run on the Web?
Yes! We have a polyfill which implements WASI and runs in browsers.
At the WebAssembly level, WASI is just a set of callable functions that
can be imported by a .wasm module, and these imports can be implemented
in a variety of ways, including by a JavaScript polyfill library running
within browsers.
And in the future, it's possible that
[builtin modules](https://github.com/tc39/ecma262/issues/395)
could take these ideas even further allowing easier and tighter
integration between .wasm modules importing WASI and the Web.
## Work in Progress
WASI is currently experimental. Feedback is welcome!
[Wasmtime]: https://github.com/bytecodealliance/wasmtime