Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 940031 - www-client/firefox: wire up wasm (rlbox) sandboxing
Summary: www-client/firefox: wire up wasm (rlbox) sandboxing
Status: CONFIRMED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal
Assignee: Mozilla Gentoo Team
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-09-22 06:50 UTC by Sam James
Modified: 2024-10-18 10:38 UTC (History)
2 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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.