Handling untrustworthy data in non-trivial ways is a major source of security bugs, and it‘s therefore against Chromium’s security policies to do it in the Browser or Gpu process unless you are working in a memory-safe language.
Rust provides a cross-platform memory-safe language so that all platforms can handle untrustworthy data directly from a privileged process, without the performance overheads and complexity of a utility process.
The Rust toolchain is enabled for and supports all platforms and development environments that are supported by the Chromium project. The first milestone to include full production-ready support was M119.
Rust is approved by Chrome ATLs for production use in certain third-party scenarios.
For questions or help, reach out to rust-dev@chromium.org or #rust on the Chromium Slack.
If you use VSCode, we have additional advice below.
Third-party libraries are pulled from crates.io, but Chromium does not use Cargo as a build system.
All third-party crates need to go through third-party review. See //docs/adding_to_third_party.md for instructions on how to have a library reviewed.
The //third_party/rust/chromium_crates_io/Cargo.toml file defines the set of crates depended on from first-party code. Any transitive dependencies will be found from those listed there. The file is a standard Cargo.toml file, though the crate itself is never built, it is only used to collect dependencies through the [dependencies] section.
These instructions require the presence of nightly cargo which is normally found in //third_party/rust-toolchain/bin. But on Mac Arm it is missing, and will need to be installed separately with rustup install nightly and added to the PATH environment.
To use a third-party crate “bar” version 3 from first party code:
src/ dir of Chromium.//third_party/rust/chromium_crates_io/Cargo.toml:vpython3 ./tools/crates/run_gnrt.py add foo to add the latest version of foo.vpython3 ./tools/crates/run_gnrt.py add foo@1.2.3 to add a specific version of foo.cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt add foo./tools/crates/run_gnrt.py vendor to download the new crate.cargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt vendor//third_party/rust/chromium_crates_io/patches for the crates. If a patch can not apply, the crate's download will be cancelled and an error will be printed. See patching errors below for how to resolve this.git add -f third_party/rust/chromium_crates_io/vendor-f is important, as files may be skipped otherwise from a .gitignore inside the crate."test" group in //third_party/rust/chromium_crates_io/gnrt_config.toml:[crate.foo] group = "test"
BUILD.gn file for the new crate:vpython3 ./tools/crates/run_gnrt.py gencargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gencargo vet:cargo vet if it's not yet installed:./tools/crates/run_cargo.py install --git https://github.com/mozilla/cargo-vet cargo-vet--git to install cargo-vet from HEAD in order to use the --cargo-arg argument which is not released yet../tools/crates/run_cargo.py -Zunstable-options -C third_party/rust/chromium_crates_io/ vet check --cargo-arg=-Zbindeps --no-registry-suggestionscheck fails, then there are missing audits, which need to be added to //third_party/rust/chromium_crates_io/supply-chain/audits.toml.audits.toml.audit.toml should be part of the submitted CL so that cargo vet will continue to pass after the CL lands.unsafe usage then Security experts will need to audit the “ub-risk” level. Mark any unsafe usage with TODO code review comments, and include a link to it in the request for third-party and security review.To enable a feature “spaceships” in the crate, change the entry in //third_party/rust/chromium_crates_io/Cargo.toml to include the feature:
[dependencies] bar = { version = "3", features = [ "spaceships" ] }
You may patch a crate in tree, but save any changes made into a diff file in a //third_party/rust/chromium_crates_io/patches/ directory for the crate. The diff file should be generated by git-format-patch each new patch numbered consecutively so that they can be applied in order. For example, these files might exist if the “foo” crate was patched with a couple of changes:
//third_party/rust/chromium_crates_io/patches/foo/patches/0001-Edit-the-Cargo-toml.diff //third_party/rust/chromium_crates_io/patches/foo/patches/0002-Other-changes.diff
The recommended procedure to create such patches is:
git format-patch <unpatched version> to generate the patch filesgit cl upload doing soIf gnrt vendor fails to apply a patch for a crate, it will cancel the download of that crate rather than leave it in a broken state. To recreate patches, first get a pristine copy of the crate by using the --no-patches argument:
vpython3 ./tools/crates/run_gnrt.py vendor --no-patches=<CRATE_NAME>To verify the patches work, remove the vendored crate directory in //third_party/rust/chromium_crates_io/vendor/, named after the crate name and version. Then run the vendor action without --no-patches which will download the crate and apply the patches:
vpython3 ./tools/crates/run_gnrt.py vendorIf a shipping library needs security review (has any unsafe), and the review finds it‘s not satisfying the rule of 2, then move it to the "sandbox" group in //third_party/rust/chromium_crates_io/gnrt_config.toml to make it clear it can’t be used in a privileged process:
[crate.foo] group = "sandbox"
If a transitive dependency moves from "safe" to "sandbox" and causes a dependency chain across the groups, it will break the gnrt vendor step. You will need to fix the new crate so that it's deemed safe in unsafe review, or move the other dependent crates out of "safe" as well by setting their group in gnrt_config.toml.
To update crates to their latest minor versions:
src/ dir of Chromium.//third_party/rust/chromium_crates_io/Cargo.lock.vpython3 ./tools/crates/run_gnrt.py updatecargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt update./tools/crates/run_gnrt.py vendorcargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt vendorgit add -f third_party/rust/chromium_crates_io/vendor-f is important, as files may be skipped otherwise from a .gitignore inside the crate.//third_party/rust/chromium_crates_io/patches was updated as part of vendoring, then reapply patches to it://third_party/rust/chromium_crates_io directory../apply_patches.sh (this currently requires linux).BUILD.gn filesvpython3 ./tools/crates/run_gnrt.py gencargo run --release --manifest-path tools/crates/gnrt/Cargo.toml --target-dir out/gnrt gengit add -f third_party/rustThe directory structure for a crate “foo” version 3.4.2 is:
//third_party/
rust/
foo/ (for the "foo" crate)
v3/ (version 3.4.2 maps to the v3 epoch)
BUILD.gn (generated by gnrt gen)
README.chromium (generated by gnrt vendor)
chromium_crates_io/
vendor/
foo-3.4.2 (crate sources downloaded from crates.io)
patches/
foo/ (patches for the "foo" crate)
0001-Edit-the-Cargo-toml.diff
0002-Other-changes.diff
Cargo.toml
Cargo.lock
gnrt_config.toml
Most Rust libraries will need a more C++-friendly API written on top of them in order to generate C++ bindings to them. The wrapper library can be placed in //third_party/rust/<cratename>/<epoch>/wrapper or at another single place that all C++ goes through to access the library. The CXX is used to generate bindings between C++ and Rust.
See //third_party/rust/serde_json_lenient/v0_1/wrapper/ and //components/qr_code_generator for examples.
Rust libraries should use the rust_static_library GN template (not the built-in rust_library) to integrate properly into the mixed-language Chromium build and get the correct compiler options applied to them.
The CXX tool is used for generating C++ bindings to Rust code. Since it requires explicit declarations in Rust, an wrapper shim around a pure Rust library is needed. Add these Rust shims that contain the CXX bridge macro to the cxx_bindings GN variable in the rust_static_library to have CXX generate a C++ header for that file. To include the C++ header file, rooted in the gen output directory, use
#include "the/path/to/the/rust/file.rs.h"
rust-analyzer extension for VSCode, rather than earlier forms of Rust support.gn with the --export-rust-project flag, such as: gn gen out/Release --export-rust-project.ln -s out/Release/rust-project.json rust-project.jsonrust-project.json and use this to give you rich browsing, autocompletion, type annotations etc. for all the Rust within the Chromium codebase..vscode/settings.json in the Chromium checkout:{
// The rest of the settings...
"rust-analyzer.cargo.extraEnv": {
"PATH": "../../third_party/rust-toolchain/bin:$PATH",
}
}
This assumes you are working with an output directory like out/Debug which has two levels; adjust the number of .. in the path according to your own setup.If you are building a throwaway or experimental tool, you might like to use pure cargo tooling rather than gn and ninja. Even then, you may choose to restrict yourself to the toolchain and crates that are already approved for use in Chromium.
Here's how.
export PATH_TO_CHROMIUM_SRC=~/chromium/src mkdir my-rust-tool cd my-rust-tool mkdir .cargo cat <<END > .cargo/config.toml [source.crates-io] replace-with = "vendored-sources" [source.vendored-sources] directory = "$PATH_TO_CHROMIUM_SRC/third_party/rust/chromium_crates_io/vendor" END $PATH_TO_CHROMIUM_SRC/third_party/rust-toolchain/bin/cargo init --offline $PATH_TO_CHROMIUM_SRC/third_party/rust-toolchain/bin/cargo run --offline
Most cargo tooling works well with this setup; one exception is cargo add, but you can still add dependencies manually to your Cargo.toml:
[dependencies] log = "0.4"