作者:Marco Fioretti
WebAssembly(Wasm)[1]是一种二进制软件格式,所有浏览器都可以在任何操作系统(OS)上直接、安全地[2]以接近原生的速度运行。然而,它最大的承诺是最终以同样的方式在任何地方[3]工作,从物联网设备和边缘服务器,到移动设备和传统桌面。这篇文章介绍了实现这一目标的主界面。本系列的下一篇文章将描述一些已经可用的、真实世界的相同接口的实现和应用程序。
为了安全和可移植,软件代码至少需要:
传统上,这些服务是由每种语言的“系统调用”库提供的,即软件程序可以使用的函数来要求其主机操作系统执行一些低级的或敏感的任务。当这些库遵循像POSIX[4]这样的标准时,任何编译器都可以自动将它们与源代码组合在一起,从而生成一个可以在某些操作系统和处理器组合上运行的二进制文件。
系统调用只能使源代码跨平台移植。尽管它们很有用,但它们仍然迫使开发人员生成特定于平台的可执行文件,而这些文件往往来自或多或少不同的源代码组合。
相反,WebAssembly 的目标是达到下一个层次:使用任何你想要的语言,然后编译一次,生成一个二进制文件,这个文件可以在任何识别 WebAssembly 的环境中安全地运行。
由于 WebAssembly 已经为所有主流浏览器“编译一次”,扩展其功能的最简单方法似乎是为每个目标环境创建一个完整的虚拟机(运行时),它提供 Wasm 模块期望从 Firefox 或 Chrome 获得的一切。
然而,这样的工作将非常复杂,而且在许多情况下(例如在物联网设备上),最重要的是根本没有必要,如果不是不可能的话。此外,有更好的方法来保护 Wasm 模块,而不是像今天的浏览器那样将它们丢弃在一刀切的沙箱中。
举一个实际的例子,只有当系统调用生成与平台相关的机器代码时,才能编写对网络摄像头或网站的访问,完全可移植的 Wasm 模块才能实现。
因此,从任何编程语言中获得这些模块的最实用的方法似乎就是WebAssembly System interface(WASI)项目[5]:只为一个显然是虚拟的,但却是完整的操作系统编写和编译代码。
一方面,WASI 给所有Wasm 运行时[6]的开发人员提供了一个单一的操作系统来模拟。另一方面,WASI 给所有编程语言提供了一组系统调用来与同一个操作系统对话。
这样,即使你在 10 个不同的平台上加载它,一个二进制 Wasm 模块调用一个特定的 WASI 函数仍然会每次从启动它的运行时获得一个不同的二进制对象。但由于所有这些对象都将以完全相同的方式与单个 Wasm 模块交互,所以这并不重要!
这种方法也适用于 WebAssembly 的第一个用例,即 web 浏览器中的 JavaScript 虚拟机。要运行使用 WASI 调用的 Wasm 模块,这些机器应该只加载相应库的 JavaScript 版本。
这种操作系统级的模拟也比简单的沙箱更安全。使用 WASI,任何运行时都可以实现每个系统调用的不同版本——具有不同的安全特权——只要它们都符合规范。然后,运行时可以将它启动的每个 Wasm 模块的每个实例放入一个单独的沙箱中,只包含该特定实例真正需要的最小、最不受特权限制的函数组合。
这种“最小特权原则”或“基于能力的安全模型[7]”在 WASI 中随处可见。WASI 运行时可以将“开放”系统调用的实例传递到沙箱中,该实例只能打开运行时本身预先选定的特定文件或文件夹。与传统的文件权限,甚至 chroot 系统相比,这是一种更健壮、更细粒度的程序控制。
就编码而言,几乎所有程序都需要诸如文件、文件夹、网络连接或时间等基本管理功能。因此,相应的 WASI 接口被设计得尽可能类似于它们的 POSIX 对等物,并且全部打包到一个“WASI-core”模块中,每个符合 WASI 的运行时都必须包含这个模块。
libc 标准 C 库的一个版本,使用 wasi-core 函数重写,已经可用了,据它的开发人员[8]说,它已经“足够稳定,可以用于许多目的”。
WASI 包括的或将来将包括的所有其他虚拟接口都被标准化并打包为单独的模块,而无需强制任何运行时支持所有这些模块。在下一篇文章中,我们将看到这些 WASI 组件目前是如何被使用的。
文章最初在Linux Foundation Training[9]发布。
[1]
WebAssembly(Wasm): https://training.linuxfoundation.org/announcements/an-introduction-to-webassembly/
[2]
安全地: https://training.linuxfoundation.org/announcements/webassembly-security-now-and-in-the-future/
[3]
任何地方: https://webassembly.org/docs/non-web/
[4]
POSIX: https://www.gnu.org/software/libc/manual/html_node/POSIX.html#POSIX
[5]
WebAssembly System interface(WASI)项目: https://hacks.mozilla.org/2019/03/standardizing-wasi-a-webassembly-system-interface/
[6]
Wasm 运行时: https://github.com/appcypher/awesome-wasm-runtimes
[7]
基于能力的安全模型: https://github.com/WebAssembly/WASI/blob/main/docs/WASI-overview.md#capability-oriented
[8]
据它的开发人员: https://github.com/WebAssembly/wasi-libc
[9]
Linux Foundation Training: https://training.linuxfoundation.org/announcements/wasi-bringing-webassembly-way-beyond-browsers/