Open nikomatsakis opened 3 months ago
This issue is intended for status updates only.
For general questions or comments, please contact the owner(s) directly.
Have been looking into different sandbox runtime choices. Here is a simple version of the comparison of three potential choices:
CAP_PERFMON
CAP_NET_ADMIN
CAP_SYS_ADMIN
or CAP_BPF
for loading eBPF programs, unless unprivileged eBPF is enabledmounts
in config.json
cargo run ubuntu:latest
to run docker image!?), and is not really portable.wasmtime --dir
.There are prior research on cross-over between each of these options. I've been busy these two weeks. Will update a more detail post for prior arts afterward.
The biggest challenge I am seeing now is spawning external processes. Most build script usages invoke some external binaries, like pkg-config
for building *-sys
crates, or protoc
for generating protobuf bindings. If process spawning is that common, we need to find a way to provide a fine-grained permission granting scheme. I don't want it to see an βall-or-nothingβ mechanism when process spawning is needed.
The other huge headache is setting library search paths. We cannot know every possible path of system libraries ahead of time, but we need to grant access to the runtime.
None.
None.
Having a family urgency. I will be back after RustConf.
Building a workable version of wasm-based build script (not yet done). There are some technical difficulties. Not blocking but need to be addressed.
wasm32-wasip1
is not shipped by default; we need to rustup target add wasm32-wasip1
to build wasm.--target
flag is provided. Not providing --target wasm32-wasip1
means no target information available. AFAIK, this is already an issue of artifact-dependencies, e.g., https://github.com/rust-lang/cargo/issues/10444 and https://github.com/rust-lang/cargo/issues/11260.In order to make the development independent of Cargo, RUSTC_WRAPPER
was the first approach I tried, though it still lacks some extension point in Cargo:
RUSTC_WRAPPER
can only intercept rustc
invocations.target.runner
is available but for cargo test
and cargo run
only.Some compatibility issues came up when integrating with Cargo:
artifact-dependencies
can compile build script to any other platform, making it challenging to handle.None.
None.
Have a working-in-process pull request in https://github.com/weihanglo/cargo/pull/66.
Let me copy some texts from there :)
As you can see, we can easily swap to any sandbox runner with a custom target.
We use wasm32-wasip1
above as an example,
as it is the one with smaller footprint, very cross-platform, and pretty popular in the Rust community.
However, it turns out that `wasm32-wasip1 doesn't support POSIX process spawning.
Use cases of process spawning in build scripts are essential, such as
pkg-config
to find system libraries.cargo metadata
to get crate metadata.git
.According to the design axioms,
Restrcting process spawning is the top one axiom.
We made that with wasm32-wasip1
,
but have no way to opt-out.
This contradicts to the "ensuring -sys
crates be built" axiom.
As a result, it is unlikely to use wasm32-wasip1
as a default sandbox environment with this experiment.
Have talked to some other folks, there are some potential route we could take if we chose wasi as a default sandbox environment.
build-rs
crate to the rescueThe Cargo team recently adopted the build-rs
crate.
It is going to be the official crate providing API for writing build scripts.
We could take the advantage of it, telling everyone instead of using std::process::Command
, use something like build_rs::Command
. So that Cargo could have a full control over how a build script spawning processes.
While it sounds ideal, this doesn't help the current situation because
build-rs
in build scripts may increase build time; people may refuse to use.There was a discussion in the GSoC "sandboxed proc-macro with wasm" about shipping a custom verion of the standard library for sandboxed wasm. For Cargo's build script, we could potentially ship a wasm32-wasi-cargo
target. The std in this custom target could intercept any exec
call or process spawning. Then it calls back to the host process (which is Cargo in our case) to determine how to handle process execution. The host process could either reject, or run the external program and post back the result.
This idea sounds pretty hacky and need more investigations of the communication mechanism between the host process and the wasm runtime. Perhaps via sockets, The WebAssembly Component Model, other host function call mechanism. There is also WASIX project which supprots fork
/exec
though it is currently not a WASI standard not even a proposal.
Since one of major design space is the user interafce of sandbox configuration, we could leave off sandbox runtimes and explore more on the configuration side.
We could, for example, use docker or eBPF as a temporary default runtime, and explore how the configuration should look like. We may want to take a look at the configuration of Cackle-rs as a starting point. By doing so, we wouldn't block on waiting for wasm runtime to being more mature.
Summary
Explore different strategies for sandboxing build script executions in Cargo.
Tasks and status