标签 WebAssembly 下的文章

使用 WebAssembly 开发有很多不同的方向,这取决于你已经知道的东西和你想建立的东西。

在过去的几十年里,Web 浏览器作为最流行的跨平台应用经久不衰。从另一个角度看浏览器,它是最受欢迎的应用交付平台之一。想想你使用的所有网站,它们取代了你过去用桌面上运行的软件进行的活动。你仍然在使用软件,但你是通过浏览器来访问它,而且是在别人的 Linux 服务器上运行。在优化我们所有人使用的软件的永恒努力中,软件开发世界早在 2019 年就引入了 WebAssembly,作为通过 Web 浏览器运行编译代码的一种方式。应用的性能比以往任何时候都要好,而且可以生成 WebAssembly 编码的语言远不只是通常的 PHP、Python 和 JavaScript。

一个目标和一种语言

关于 WebAssembly 的一个强大但也最令人困惑的地方是,“WebAssembly” 这个词既指一种语言,也指一个目标。WebAssembly 是一种汇编语言,但没有多少人选择直接用汇编写代码。即使是汇编语言,最终也会被转换为二进制格式,这也是计算机运行代码的要求。这种二进制格式也被称为 WebAssembly。不过这很好,因为这意味着你可以用你选择的语言来写一些最终以 WebAssembly 交付的东西,包括 C、C++、Rust、Javascript 和其他许多语言。

进入 WebAssembly 的途径是 Emscripten,这是一个 LLVM 编译器工具链,可以从你的代码中产生 WebAssembly。

安装 Emscripten

要在你的 Linux 或 macOS 电脑上安装 Emscripten,请使用 Git:

$ git clone https://github.com/emscripten-core/emsdk.git

改变目录进入 emsdk 目录并运行安装命令:

$ ./emsdk install latest
$ ./emsdk activate latest

Emscripten 工具链中的所有内容都安装在 emsdk 目录下,对系统的其他部分没有影响。由于这个原因,在使用 emsdk 之前,你必须 源引 source 它的环境:

$ source ./emsdk_env.sh

如果你打算经常使用 emsdk,你也可以在 .bashrc 中加入环境设置脚本。

要在 Windows 上安装 Emscripten,你可以在 WSL 环境下运行 Linux。

请访问 Emscripten 网站 了解更多安装信息。

Hello World

下面是一个用 C++ 编写的简单的 “Hello World” 应用。

#include <iostream>

using namespace std;

int main() {
    cout << "Hello world";
    return 0;
}

先把它作为你的系统的标准二进制文件来测试:

$ g++ hello.cpp -o world
$ ./world
Hello world

看到它像预期的那样工作,用 emcc 把它构建为 WebAssembly:

$ emcc hello.cpp -o world.html

最后,用 emrun 运行它:

$ emrun ./world.html

emrun 工具是一个用于本地测试的方便命令。当你在服务器上托管你的应用时,emrun 就没有必要了。

学习更多关于 WebAssembly 的知识

使用 WebAssembly 开发可以有很多不同的方向,这取决于你已经知道的东西和你想建立的东西。如果你了解 C 或 C++,那么你可以用这些来写你的项目。如果你正在学习 Rust,那么你可以使用 Rust。甚至 Python 代码也可以使用 Pyodide 模块来作为 WebAssembly 运行。你有很多选择,而且没有错误的开始方式(甚至有 COBOL 到 WebAssembly 的编译器)。如果你渴望开始使用 WebAssembly,

请下载我们免费的电子书

via: https://opensource.com/article/23/2/webassembly-guide

作者:Seth Kenlon 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

简介

正如我们 最近解释的,WebAssembly 是一种用于以任何语言编写的二进制格式的软件,旨在最终无需更改就能在任意平台运行。WebAssembly 的第一个应用是在 Web 浏览器中,以使网站更快、更具交互性。WebAssembly 有计划推向 Web 之外,从各种服务器到物联网(IoT),其创造了很多机会,但也存在很多安全问题。这篇文章是对这些问题和 WebAssembly 安全模型的一篇介绍性概述。

WebAssembly 跟 JavaScript 很像

在 Web 浏览器内部,WebAssembly 模块由执行 JavaScript 代码的同一 虚拟机 VM 管理。因此,WebAssembly 和 JavaScript 一样,造成的危害也是相同的,只是效率更高,更不易被察觉。由于 JavaScript 是纯文本,运行前需要浏览器编译,而 WebAssembly 是一种可立即运行的二进制格式,运行速度更快,也更难被扫描出(即使使用杀毒软件)其中的恶意指令。

WebAssembly 的这种 “代码混淆” 效果已经被用来弹出不请自来的广告,或打开假的 “技术支持” 窗口,要求提供敏感数据。另一个把戏则是自动将浏览器重定向到包含真正危险的恶意软件的 “落地” 页。

最后,就像 JavaScript 一样,WebAssembly 可能被用来 “窃取” 处理能力而不是数据。2019 年,对 150 个不同的 WASM 模块的分析 发现,其中约 32% 被用于加密货币挖掘。

WebAssembly 沙盒和接口

WebAssembly 代码在一个由虚拟机(而不是操作系统)管理的 沙盒 中封闭运行。这使它无法看到主机,也无法直接与主机交互。对系统资源(文件、硬件或互联网连接)的访问只能通过该虚拟机提供的 WebAssembly 系统接口 WebAssembly System Interface (WASI) 进行。

WASI 不同于大多数其他应用程序编程接口(API),它具有独特的安全特性,真正推动了 WASM 在传统服务器和 边缘 Edge 计算场景中的采用,这将是下一篇文章的主题。在这里,可以说,当从 Web 迁移到其他环境时,它的安全影响会有很大的不同。现代 Web 浏览器是极其复杂的软件,但它是建立在数十年的经验和数十亿人的日常测试之上的。与浏览器相比,服务器或物联网(IoT)设备几乎是未知领域。这些平台的虚拟机将需要扩展 WASI,因此,肯定会带来新的安全挑战。

WebAssembly 中的内存和代码管理

与普通的编译程序相比,WebAssembly 应用程序对内存的访问非常受限,对它们自己也是如此。WebAssembly 代码不能直接访问尚未调用的函数或变量,不能跳转到任意地址,也不能将内存中的数据作为字节码指令执行。

在浏览器内部,WASM 模块只能获得一个连续字节的全局数组( 线性内存 linear memory )进行操作。WebAssembly 可以直接读写该区域中的任意位置,或者请求增加其大小,但仅此而已。这个 线性内存 linear memory 也与包含其实际代码、执行堆栈、当然还有运行 WebAssembly 的虚拟机的区域分离。对于浏览器来说,所有这些数据结构都是普通的 JavaScript 对象,使用标准过程与所有其他对象隔离。

结果还好,但不完美

所有这些限制使得 WebAssembly 模块很难做出不当行为,但也并非不可能。

沙盒化的内存使 WebAssembly 几乎不可能接触到 外部 的东西,也使操作系统更难防止 内部 发生不好的事情。传统的内存监测机制,比如 堆栈金丝雀 Stack Canaries 能注意到是否有代码试图扰乱它不应该接触的对象,但在这里没用

事实上,WebAssembly 只能访问自己的 线性内存 linear memory ,但可以直接访问,这也可能为攻击者的行为 提供便利。有了这些约束和对模块源代码的访问,就更容易猜测覆盖哪些内存位置可能造成最大的破坏。破坏局部变量似乎也是 可能的,因为它们停留在 线性内存 linear memory 中的无监督堆栈中。

2020 年的一篇关于 WebAssembly 的二进制安全性 的论文指出,WebAssembly 代码仍然可以在设定的常量内存中覆盖字符串文字。同一篇论文描述了在三个不同的平台(浏览器、Node.JS 上的服务端应用程序,和独立 WebAssembly 虚拟机的应用程序)上,WebAssembly 可能比编译为原生二进制文件时更不安全的其他方式。建议进一步阅读此主题。

通常,认为 WebAssembly 只能破坏其自身沙盒中的内容的想法可能会产生误导。WebAssembly 模块为调用它们的 JavaScript 代码做繁重的工作,每次都会交换变量。如果模块在这些变量中的任意一处写入不安全的调用 WebAssembly 的 JavaScript 代码,就 导致崩溃或数据泄露。

未来的方向

WebAssembly 的两个新出现的特性:并发 和内部垃圾收集,肯定会影响其安全性(如何影响以及影响多少,现在下结论还为时过早)。

并发允许多个 WebAssembly 模块在同一个虚拟机中并行。目前,只有通过 JavaScript web workers 才能实现这一点,但更好的机制正在开发中。安全方面,他们可能会带来 以前不需要的大量的代码,也就是更多出错的方法。

为了提高性能和安全性,我们需要一个 本地的垃圾收集器,但最重要的是,要在经过良好测试的浏览器的 Java 虚拟机之外使用 WebAssembly,因为这些虚拟机无论如何都会在自己内部收集所有的垃圾。当然,甚至这个新代码也可能成为漏洞和攻击的另一个入口。

往好处想,使 WebAssembly 比现在更安全的通用策略也是存在的。再次引用 这篇文章,这些策略包括:编译器改进、栈/堆和常量数据的 分离 的线性存储机制,以及避免使用 不安全的语言(如 C)编译 WebAssembly 模块代码。

本文 WebAssembly 安全的现在和未来 首次发表在 Linux 基金会 - 培训


via: https://www.linux.com/news/webassembly-security-now-and-in-the-future/

作者:Dan Brown 选题:lujun9972 译者:hanszhao80 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

谷歌正式推出“切换到安卓”应用

据消息,传闻已久的针对 iOS 用户的“切换到安卓”应用开始在苹果应用商店面向公众逐步推出。该应用帮助用户将重要数据,如联系人、日历、照片和视频等从 iPhone 迁移到新的安卓设备。除了移动数据,该应用还提供了关于传输过程的其他说明,比如如何取消 iMessage 的注册,以便在新的安卓设备上继续收到短信。

老王点评:虽然看起来像是互相抢用户,但是其实这对于用户来说可以打破供应商锁定。

谷歌在 2021 年发现 58 个已被黑客利用的零日漏洞

据消息,谷歌 Project Zero 团队发布公告称,去年创历史记录地发现了 58 个零日漏洞。自 2014 年成立以来,Project Zero 检测和披露的零日漏洞的最高数量出现在 2015 年,共有 28 个。这可能代表着网络攻击数量上升,但 Project Zero 表示,更可能是因为他们改进了对零日漏洞的检测和报告。因此,尽管检测到的零日漏洞大幅增加,你的在线安全似乎并不比前几年更危险,至少在涉及零日漏洞时是这样。

老王点评:希望是检测技术的提高,而不是恶意攻击者更猖獗。

WebAssembly 2.0 工作草案发布

据消息,W3C 公布了 WebAssembly 2.0 公共工作草案。WebAssembly 是 W3C 的标准,是一种用于网络和其他地方的可执行程序的可移植二进制代码格式。本次草案带来了 WebAssembly 2.0 的核心规范、JavaScript 接口和 Web API 的公共工作草案。

老王点评:我觉得 WebAssembly 叫好不叫座,我似乎从未在哪个网站见过它。

雅虎可能又要被卖了

据消息人士透露,美国移动运营商 Verizon 正考虑出售旗下媒体业务,该业务包括多个互联网早期的知名品牌,如雅虎和 AOL。Verizon 目前正逐步剥离媒体资产,放弃了向在线广告业务的进军,进一步专注于移动通信业务,

去年,Verizon 已经将互联网媒体赫芬顿邮报出售给 BuzzFeed,并于 2019 年出售了轻博客平台 Tumblr。2017 年,Verizon 以约 45 亿美元的价格收购了雅虎的互联网资产,此前还于 2015 年以约 44 亿美元的价格收购了 AOL。

当年的互联网一代巨头,一时传奇,如今只能算作资产卖来卖去。

奇虎 360 发现一个潜伏多年的 Linux 后门

后门 3 月 25 日首次被发现,虽然早在 2018 年就已经发现了样本。该后门有 12 项功能,包括渗出和窃取数据、文件和插件管理和报告设备信息等。但是大多数病毒检测引擎尚不能发现该后门。该 Linux 恶意软件改变了它对加密的使用,这包括 ZLIB 压缩和 AES、异或和密钥轮转的组合,因而很难被发现。360 表示,他们不知道该恶意软件的“真正目的”,除了专注于破坏 Linux 系统。

专门潜伏在 Linux 上的后门,但是 Linux 上往往没有任何反病毒和木马的软件。

微软加入推进 WebAssembly 的字节码联盟

字节码联盟旨在将 WebAssembly 从浏览器和 JavaScript 扩展到桌面和移动平台的本地应用程序。它是由英特尔、Mozilla、RedHat 于 2019 年组建的,谷歌和 ARM 也是其成员。字节码联盟得到了四个主要浏览器供应商中三个的支持,只缺 Safari 背后的苹果了。

WebAssembly 也承诺可以让开发者编写一个应用程序,在浏览器之外的多个操作系统上运行。微软的加入,使 C# 和 .NET 开发人员可以使用 WebAssembly 构建在浏览器中运行的应用程序,以及可以构建原生的 iOS 和 Android 应用。

这种中间字节码的方式其实并不是什么新发明,不知道 WebAssembly 和以前的方案有什么突破,能否取得成功?

通过这个分步教程,开始用人类可读的文本编写 WebAssembly。

 title=

WebAssembly 是一种字节码格式,几乎所有的浏览器 都可以将它编译成其宿主操作系统的机器代码。除了 JavaScript 和 WebGL 之外,WebAssembly 还满足了将应用移植到浏览器中以实现平台独立的需求。作为 C++ 和 Rust 的编译目标,WebAssembly 使 Web 浏览器能够以接近原生的速度执行代码。

当谈论 WebAssembly 应用时,你必须区分三种状态:

  1. 源码(如 C++ 或 Rust): 你有一个用兼容语言编写的应用,你想把它在浏览器中执行。
  2. WebAssembly 字节码: 你选择 WebAssembly 字节码作为编译目标。最后,你得到一个 .wasm 文件。
  3. 机器码(opcode): 浏览器加载 .wasm 文件,并将其编译成主机系统的相应机器码。

WebAssembly 还有一种文本格式,用人类可读的文本表示二进制格式。为了简单起见,我将其称为 WASM-text。WASM-text 可以比作高级汇编语言。当然,你不会基于 WASM-text 来编写一个完整的应用,但了解它的底层工作原理是很好的(特别是对于调试和性能优化)。

本文将指导你在 WASM-text 中创建经典的 “Hello World” 程序。

创建 .wat 文件

WASM-text 文件通常以 .wat 结尾。第一步创建一个名为 helloworld.wat 的空文本文件,用你最喜欢的文本编辑器打开它,然后粘贴进去:

(module
    ;; 从 JavaScript 命名空间导入
    (import  "console"  "log" (func  $log (param  i32  i32))) ;; 导入 log 函数
    (import  "js"  "mem" (memory  1)) ;; 导入 1 页 内存(64kb)
   
    ;; 我们的模块的数据段
    (data (i32.const 0) "Hello World from WebAssembly!")
   
    ;; 函数声明:导出 helloWorld(),无参数
    (func (export  "helloWorld")
        i32.const 0  ;; 传递偏移 0 到 log
        i32.const 29  ;; 传递长度 29 到 log(示例文本的字符串长度)
        call  $log
        )
)

WASM-text 格式是基于 S 表达式的。为了实现交互,JavaScript 函数用 import 语句导入,WebAssembly 函数用 export 语句导出。在这个例子中,从 console 模块中导入 log 函数,它需要两个类型为 i32 的参数作为输入,以及一页内存(64KB)来存储字符串。

字符串将被写入偏移量 为 0 的数据段。数据段是你的内存的 叠加投影 overlay ,内存是在 JavaScript 部分分配的。

函数用关键字 func 标记。当进入函数时,栈是空的。在调用另一个函数之前,函数参数会被压入栈中(这里是偏移量和长度)(见 call $log)。当一个函数返回一个 f32 类型时(例如),当离开函数时,一个 f32 变量必须保留在栈中(但在本例中不是这样)。

创建 .wasm 文件

WASM-text 和 WebAssembly 字节码是 1:1 对应的,这意味着你可以将 WASM-text 转换成字节码(反之亦然)。你已经有了 WASM-text,现在将创建字节码。

转换可以通过 WebAssembly Binary Toolkit(WABT)来完成。从该链接克隆仓库,并按照安装说明进行安装。

建立工具链后,打开控制台并输入以下内容,将 WASM-text 转换为字节码:

wat2wasm helloworld.wat -o helloworld.wasm

你也可以用以下方法将字节码转换为 WASM-text:

wasm2wat helloworld.wasm -o helloworld_reverse.wat

一个从 .wasm 文件创建的 .wat 文件不包括任何函数或参数名称。默认情况下,WebAssembly 用它们的索引来识别函数和参数。

编译 .wasm 文件

目前,WebAssembly 只与 JavaScript 共存,所以你必须编写一个简短的脚本来加载和编译 .wasm 文件并进行函数调用。你还需要在 WebAssembly 模块中定义你要导入的函数。

创建一个空的文本文件,并将其命名为 helloworld.html,然后打开你喜欢的文本编辑器并粘贴进去:

<!DOCTYPE  html>
<html>
  <head>
    <meta  charset="utf-8">
    <title>Simple template</title>
  </head>
  <body>
    <script>
   
      var memory = new  WebAssembly.Memory({initial:1});

      function  consoleLogString(offset, length) {
        var  bytes = new  Uint8Array(memory.buffer, offset, length);
        var  string = new  TextDecoder('utf8').decode(bytes);
        console.log(string);
      };

      var  importObject = {
        console: {
          log:  consoleLogString
        },
        js : {
          mem:  memory
        }
      };
     
      WebAssembly.instantiateStreaming(fetch('helloworld.wasm'), importObject)
      .then(obj  => {
        obj.instance.exports.helloWorld();
      });
     
    </script>
  </body>
</html>

WebAssembly.Memory(...) 方法返回一个大小为 64KB 的内存页。函数 consoleLogString 根据长度和偏移量从该内存页读取一个字符串。这两个对象作为 importObject 的一部分传递给你的 WebAssembly 模块。

在你运行这个例子之前,你可能必须允许 Firefox 从这个目录中访问文件,在地址栏输入 about:config,并将 privacy.file_unique_origin 设置为 true

 title=

注意: 这样做会使你容易受到 CVE-2019-11730 安全问题的影响。

现在,在 Firefox 中打开 helloworld.html,按下 Ctrl+K 打开开发者控制台。

 title=

了解更多

这个 Hello World 的例子只是 MDN 的 了解 WebAssembly 文本格式 文档中的教程之一。如果你想了解更多关于 WebAssembly 的知识以及它的工作原理,可以看看这些文档。


via: https://opensource.com/article/21/3/hello-world-webassembly

作者:Stephan Avenwedde 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

了解在 Firefox 上运行 WebAssembly 的机会和局限性。

 title=

WebAssembly 是一种可移植的执行格式,由于它能够以近乎原生的速度在浏览器中执行应用而引起了人们的极大兴趣。WebAssembly 本质上有一些特殊的属性和局限性。但是,通过将其与其他技术结合,将出现全新的可能性,尤其是与浏览器中的游戏有关的可能性。

本文介绍了在 Firefox 上运行 WebAssembly 的概念、可能性和局限性。

沙盒

WebAssembly 有 严格的安全策略。 WebAssembly 中的程序或功能单元称为模块。每个模块实例都运行在自己的隔离内存空间中。因此,即使同一个网页加载了多个模块,它们也无法访问另一个模块的虚拟地址空间。设计上,WebAssembly 还考虑了内存安全性和控制流完整性,这使得(几乎)确定性的执行成为可能。

Web API

通过 JavaScript Web API 可以访问多种输入和输出设备。根据这个 提案,将来可以不用绕道到 JavaScript 来访问 Web API。C++ 程序员可以在 Emscripten.org 上找到有关访问 Web API 的信息。Rust 程序员可以使用 rustwasm.github.io 中写的 wasm-bindgen 库。

文件输入/输出

因为 WebAssembly 是在沙盒环境中执行的,所以当它在浏览器中执行时,它无法访问主机的文件系统。但是,Emscripten 提供了虚拟文件系统形式的解决方案。

Emscripten 使在编译时将文件预加载到内存文件系统成为可能。然后可以像在普通文件系统上一样从 WebAssembly 应用中读取这些文件。这个 教程 提供了更多信息。

持久化数据

如果你需要在客户端存储持久化数据,那么必须通过 JavaScript Web API 来完成。请参考 Mozilla 开发者网络(MDN)关于 浏览器存储限制和过期标准 的文档,了解不同方法的详细信息。

内存管理

WebAssembly 模块作为 堆栈机 在线性内存上运行。这意味着堆内存分配等概念是没有的。然而,如果你在 C++ 中使用 new 或者在 Rust 中使用 Box::new,你会期望它会进行堆内存分配。将堆内存分配请求转换成 WebAssembly 的方式在很大程度上依赖于工具链。你可以在 Frank Rehberger 关于 WebAssembly 和动态内存 的文章中找到关于不同工具链如何处理堆内存分配的详细分析。

游戏!

WebGL 结合使用时,WebAssembly 的执行速度很高,因此可以在浏览器中运行原生游戏。大型专有游戏引擎 Unity虚幻 4 展示了 WebGL 可以实现的功能。也有使用 WebAssembly 和 WebGL 接口的开源游戏引擎。这里有些例子:

有关 WebAssembly 的更多信息

WebAssembly 是一项很有前途的技术,我相信我们将来会越来越多地看到它。除了在浏览器中执行之外,WebAssembly 还可以用作可移植的执行格式。Wasmer 容器主机使你可以在各种平台上执行 WebAssembly 代码。

如果你需要更多的演示、示例和教程,请看一下这个 WebAssembly 主题集合。Mozilla 的 游戏和示例合集 并非全是 WebAssembly,但仍然值得一看。


via: https://opensource.com/article/21/3/webassembly-firefox

作者:Stephan Avenwedde 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出