Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 940031

Summary: www-client/firefox: wire up wasm (rlbox) sandboxing
Product: Gentoo Linux Reporter: Sam James <sam>
Component: Current packagesAssignee: Mozilla Gentoo Team <mozilla>
Status: RESOLVED FIXED    
Severity: normal CC: and, herrtimson, w12101111
Priority: Normal Keywords: PullRequest
Version: unspecified   
Hardware: All   
OS: Linux   
See Also: https://github.com/gentoo/gentoo/pull/39343
Whiteboard:
Package list:
Runtime testing required: ---

Description Sam James archtester Gentoo Infrastructure gentoo-dev Security 2024-09-22 06:50:06 UTC
See https://hacks.mozilla.org/2020/02/securing-firefox-with-webassembly/ for background.

I thought I'd filed a bug for this before but I can't find it. I know juippis and I have discussed it before.

Anyway, in the ebuild right now, we pass --without-wasm-sandboxed-libraries because some work is needed to figure out how to wire up a wasm toolchain.

Unfortunately, GCC doesn't (yet?) have a wasm backend, so this will be a Clang-only feature (although it might be fine to mix w/ GCC builds).

Looking at Fedora's spec file:
```
# Created by:
# git clone --recursive https://github.com/WebAssembly/wasi-sdk.git
# cd wasi-sdk && git-archive-all --force-submodules wasi-sdk-20.tar.gz	
Source50:       wasi-sdk-20.tar.gz
[...]
 
# We need to create the wasi.patch with the correct path to the wasm libclang_rt.
%if %{with wasi_sdk}
export LIBCLANG_RT=`pwd`/wasi-sdk-20/build/compiler-rt/lib/wasi/libclang_rt.builtins-wasm32.a; cat %{SOURCE49} | envsubst > %{_sourcedir}/wasi.patch
%patch -P80 -p1 -b .wasi
%endif
[...]
	
#WASI SDK
%if %{with wasi_sdk}
pushd wasi-sdk-20
NINJA_FLAGS=-v CC=clang CXX=clang++ env -u CFLAGS -u CXXFLAGS -u FFLAGS -u VALFLAGS -u RUSTFLAGS -u LDFLAGS -u LT_SYS_LIBRARY_PATH make package
popd
%endif
# ^ with wasi_sdk

%if %{with wasi_sdk}
echo "ac_add_options --with-wasi-sysroot=`pwd`/wasi-sdk-20/build/install/opt/wasi-sdk/share/wasi-sysroot" >> .mozconfig
%else
echo "ac_add_options --without-sysroot" >> .mozconfig
echo "ac_add_options --without-wasm-sandboxed-libraries" >> .mozconfig
%endif
```

... which doesn't look too bad. Just filing this bug either as notes for myself to tackle or if someone else wants to.
Comment 1 Sam James archtester Gentoo Infrastructure gentoo-dev Security 2024-09-22 06:50:42 UTC
I should say: the key bit of info here is that because we force-on all LLVM targets in Gentoo (which we should really try fix but it's a pain), our Clang already supports wasm. So it's in theory just about wiring up in FF with the SDK.
Comment 2 Joonas Niilola gentoo-dev 2024-09-22 07:11:46 UTC
Yeah, I didn't want to become a maintainer of an extra toolchain bit for this. Been thinking about the Fedora way, but I do wonder how it affects overall build time of Firefox. And Fedora does use GCC to build Firefox, no idea if the wasm thing works with it at all (also the wasm bits are pushed by someone else than the main maintainer of Firefox in Fedora).

Food for thought, though, for sure.
Comment 3 12101111 2024-10-17 17:39:53 UTC
I have been enable rlbox for several weaks and don't have any issue.

The only thing required is a WASI toolchain.

A WASI toolchain contains those components

1. LLVM/Clang/LLD. They are already required for firefox (unless USE=-clang)
2. compiler-rt for wasm32-wasi target.
3. wasi-libc for wasm32-wasi target. (https://github.com/WebAssembly/wasi-libc)
4. libc++abi/libc++ for wasm32-wasi target.
(llvm-libunwind is not needed and don't support WASI)

wasi-sdk (https://github.com/WebAssembly/wasi-sdk) provide some script to compile them. You can download binary release from https://github.com/WebAssembly/wasi-sdk/releases , include whole toolchain(1+2+3+4), wasi-sysroot (3+4) and libclang_rt.builtins-wasm32-wasi (2).

wasi-sdk is not needed if you want to assemble a WASI toolchain from source. My toolchain is compiled using crossdev.

WASI has many target triples, include wasm32-wasi, wasm32-wasi-threads  wasm32-wasip1, wasm32-wasip1-threads, wasm32-wasip2. wasm32-wasip1 is the new name for wasm32-wasi and every thing except name is identical. wasm32-wasip2 is for version 0.2 of WASI. *-threads are targets support multi-thread and pthread API. See https://blog.rust-lang.org/2024/04/09/updates-to-rusts-wasi-targets.html for the rename stuff. Firefox currently use the old wasm32-wasi target, but this may change in the future.

Firefox build system will enable rlbox by default, and pass --without-wasm-sandboxed-libraries will disable it. 

Firefox build system can't find WASI compiler and sysroot by default. Pass WASM_CC and WASM_CXX for compiler, and --with-wasi-sysroot= for sysroot.

Firefox build system will check the WASI compiler using those c/c++ code:

```c++
#include <cstring>
int main(void){ ; return 0; }
```
The command is `clang++-19 --target=wasm32-wasi conftest.cpp --sysroot=$sysroot -c`

```c
#include <time.h>
int main(void){ ; return 0; }
```
The command is `clang-19 -std=gnu99 --target=wasm32-wasi conftest.c -Werror -D_WASI_EMULATED_PROCESS_CLOCKS -lwasi-emulated-process-clocks --sysro
ot=$sysroot`

If enable USE=clang and system clang have config in /etc/clang/cross/wasm32-wasi.cfg, WASM_CC and WASM_CXX is not needed.

/etc/clang/cross/wasm32-wasi.cfg:
```
--rtlib=compiler-rt
--sysroot=/usr/wasm32-wasi
--target=wasm32-wasi
--unwindlib=none
-fuse-ld=lld
```

Note 1: Before LLVM 19, compiler-rt don't normalize the triple and install path, and clang can't find it if wasm32-wasi is used as triple.

For example, the cmake script install compiler-rt of wasm32-wasi to /usr/lib/clang/18/lib/wasm32-wasi/libclang_rt.builtins.a, but clang try to find it in /usr/lib/clang/18/lib/wasm32-unknown-wasi/libclang_rt.builtins.a

See: https://github.com/llvm/llvm-project/
commit/9cb9a97e44130e17e96f994c3e594aba69ea1ad5

So LLVM 19 is required if not patched.

Note 2: How to compile WASI runtimes using crossdev.

1. crossdev -L wasm32-wasi

It should failed with "error: Target architecture not supported by installed LLVM toolchain".

2. In CROSSDEV_OVERLAY, remove cross_llvm-wasm32-wasi/linux-headers, link clang-crossdev-wrappers, compiler-rt and wasi-libc to my overlay.

3. emerge cross_llvm-wasm32-wasi/clang-crossdev-wrappers cross_llvm-wasm32-wasi/compiler-rt cross_llvm-wasm32-wasi/wasi-libc

4. edit /usr/wasm32-wasi/etc/portage/profile/make.defaults

```
ARCH="wasm32"
KERNEL="-linux wasi"
ELIBC="wasi"
AR=llvm-ar
AS=wasm32-wasi-as
CC="wasm32-wasi-clang"
CPP="wasm32-wasi-cpp"
CROSS_COMPILE="wasm32-wasi-"
```

ARCH/KERNEL/ELIBC is not supported by current gentoo tree, so the name is arbitrary

/usr/wasm32-wasi/etc/portage/profile/use.force

```
-kernel_linux
wasi
```

/usr/wasm32-wasi/etc/portage/profile/package.provided

```
sys-devel/llvm-19.1.2
sys-devel/clang-19.1.2
```

/usr/wasm32-wasi/etc/portage/package.accept_keywords

```
sys-libs/libcxxabi ~*
sys-libs/libcxx ~*
```

edit /usr/wasm32-wasi/etc/portage/repos.conf, add my overlay

5. wasm32-wasi-emerge libcxxabi libcxx
6. Test c/c++ programs

hello.c
```
#include <stdio.h>
int main() {
    printf("Hello world!\n");
    return 0;
}
```

hello.cpp
```
#include <iostream>
int main() {
  std::cout << "Gentoo Linux Clang/LLVM/LLD toolchain for WASI!" << std::endl;
  return 0;
}
```

`wasm32-wasi-clang hello.c -o hello.wasm`
`wasm32-wasi-clang++ hello.cpp -o hello-cpp.wasm`

You need a wasm runtime to run WASI program. 

dev-util/wasm3 and dev-util/wasmer don't works as the version in Gentoo are old and not compitable with current wasm features. See https://blog.rust-lang.org/2024/09/24/webassembly-targets-change-in-default-target-features.html

Install wasmtime using cargo: `cargo install wasmtime-cli`

`wasmtime hello-cpp.wasm` should output `Gentoo Linux Clang/LLVM/LLD toolchain for WASI!`

Ebuild needed:

https://github.com/12101111/overlay/blob/master/www-client/firefox/firefox-131.0.3.ebuild
https://github.com/12101111/overlay/blob/master/sys-devel/clang-crossdev-wrappers/clang-crossdev-wrappers-19.ebuild
https://github.com/12101111/overlay/blob/master/dev-libs/wasi-libc/wasi-libc-9999.ebuild
https://github.com/12101111/overlay/blob/master/sys-libs/compiler-rt/compiler-rt-19.1.2.ebuild
https://github.com/12101111/overlay/blob/master/sys-libs/libcxxabi/libcxxabi-19.1.2.ebuild
https://github.com/12101111/overlay/blob/master/sys-libs/libcxx/libcxx-19.1.2.ebuild
https://github.com/12101111/overlay/blob/master/eclass/cmake.eclass

The cmake.eclass and LLVM runtimes ebuild changes are also contain crossdev support for mingw32-llvm, which is needed by wine on aarch64 (also works on x86-64 with wow64). Therefore, the maintenance burden is mainly on wasi-libc.
Comment 4 Sam James archtester Gentoo Infrastructure gentoo-dev Security 2024-10-18 10:38:02 UTC
(In reply to 12101111 from comment #3)
> I have been enable rlbox for several weaks and don't have any issue.
> 

Thank you for the detailed summary! It's helpful.

I should say a few things:
1) I'm willing to help maintain the relevant parts if I need to;
2) I'd really like to avoid needing users to run `crossdev`. See the approach we take w/ bpf-toolchain and mingw64-toolchain;
3) I think we should consider doing the Fedora-style approach at first and then iterate on it, rather than having a huge amonut of work to do upfront.
Comment 5 Larry the Git Cow gentoo-dev 2024-11-16 13:12:32 UTC
The bug has been closed via the following commit(s):

https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=352d3c1982a73e40da5dd7161207e6973c001413

commit 352d3c1982a73e40da5dd7161207e6973c001413
Author:     Joonas Niilola <juippis@gentoo.org>
AuthorDate: 2024-11-16 12:27:41 +0000
Commit:     Joonas Niilola <juippis@gentoo.org>
CommitDate: 2024-11-16 13:11:49 +0000

    www-client/firefox: enable wasm on 132.0.2
    
     - Adds "wasm" support to compile certain third-party libraries with
       WebAssembly using Mozilla's RLBox.
     - It requires an external wasi toolchain which is not packaged in Gentoo (and
       I didn't wish to become a maintainer of a new toolchain), therefore the
       ebuild currently downloads and uses a pre-built package directly from
       upstream. They only provide pre-built packages for amd64 (x86_64) and arm64.
       This is the first step to getting wasm sandboxed libraries to work in
       Gentoo, work isn't finished but good enough to be shipped.
       Currently system-graphite2 doesn't work with wasm, but building Firefox
       doesn't require any user action related to this.
    
     - Also disconnect clang pgo toolchain check from lld - it's probably a remnant
       from times when lto was required to build with pgo.
    
    Closes: https://bugs.gentoo.org/940031
    Signed-off-by: Joonas Niilola <juippis@gentoo.org>
    Closes: https://github.com/gentoo/gentoo/pull/39343

 www-client/firefox/Manifest               |  3 ++
 www-client/firefox/firefox-132.0.2.ebuild | 60 ++++++++++++++++++++++++-------
 www-client/firefox/metadata.xml           |  3 +-
 3 files changed, 53 insertions(+), 13 deletions(-)
Comment 6 and 2024-11-29 09:53:34 UTC
Can we rename USE flag "wasm" to "wasm-sandbox" or "wasm-sandbox-3rdparty"?
Comment 7 Joonas Niilola gentoo-dev 2024-11-29 11:17:46 UTC
(In reply to and from comment #6)
> Can we rename USE flag "wasm" to "wasm-sandbox" or "wasm-sandbox-3rdparty"?

Yeah, I honestly did try to think the best use flag name for it. "wasm-sandbox-3rdparty" while the most descriptive and accurate, the use flag becomes a bit hideous. "wasm-sandbox" I did consider and I like. 

The "sandbox" part makes it seem like it's something everyone would want, while reality is the wasm procedure only applies to a handful of libraries. So the impact is not as big as people think. And rumors say there is a performance hit when enabling wasm - this is something I'm going to investigate with better time. All this meaning I actually wanted as low adoption rate as possible, to see if there are bugs, and to figure whether it really has a noticeable performance impact on users. I was going to default it on with '+wasm' when it was deemed to work.

But could you open a new bug for the name change and let other (interested) people weigh in, I'll change the use flag on next version bump most likely. Or 134.0/128.6.0.
Comment 8 Joonas Niilola gentoo-dev 2024-11-29 11:20:47 UTC
(In reply to Joonas Niilola from comment #7)
> But could you open a new bug for the name change and let other (interested)
> people weigh in, I'll change the use flag on next version bump most likely.
> Or 134.0/128.6.0.

(also so I don't end up forgetting this, I don't actively monitor closed bugs)