mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Enable V8 sandboxing for source-built builds (#21146)
## Summary
This is the first PR in the V8 in-process sandboxing rollout.
It adds the build-system and Rust feature plumbing needed to support
sandboxed V8 builds, then enables sandboxing by default for the
source-built Bazel V8 path that we control directly. It deliberately
keeps the published `rusty_v8` artifact workflows on their current
non-sandboxed contract so this PR can land and ship independently before
we change any released artifacts.
## Rollout plan
- [x] **PR 1: land sandbox plumbing and default source-built Bazel V8 to
sandboxed mode**
- [ ] **PR 2: publish sandbox-enabled release artifacts and add
compatibility validation**
- Produce sandboxed artifact pairs for every released Cargo target that
does not already use the source-built Bazel path.
- Add CI coverage that consumes those sandboxed artifacts and verifies:
- `codex-v8-poc` reports sandbox enabled
- `codex-code-mode` builds/tests against the sandboxed path
- [ ] **PR 3: switch release consumers to sandboxed artifacts by
default**
- Update released artifact selectors/checksums.
- Enable the Rust `v8_enable_sandbox` feature in the default release
path.
- Make the sandboxed artifact family the normal path for published
builds.
- [ ] **PR 4: remove rollout-only compatibility paths**
- Remove the temporary non-sandbox release compatibility config once the
new default has shipped and baked.
- Keep the invariant tests permanently.
This commit is contained in:
committed by
GitHub
Unverified
parent
bb2257e3f5
commit
36460387ec
@@ -183,5 +183,15 @@ common:ci-v8 --build_metadata=TAG_os=linux
|
||||
common:ci-v8 --config=remote
|
||||
common:ci-v8 --strategy=remote
|
||||
|
||||
# Source-built Bazel V8 artifacts use the in-process sandbox by default. This
|
||||
# does not affect Cargo's default prebuilt rusty_v8 path.
|
||||
common --@v8//:v8_enable_pointer_compression=True
|
||||
common --@v8//:v8_enable_sandbox=True
|
||||
|
||||
# Keep currently published rusty_v8 release artifacts non-sandboxed until the
|
||||
# artifact migration ships matching Rust feature selection for Cargo consumers.
|
||||
common:v8-release-compat --@v8//:v8_enable_pointer_compression=False
|
||||
common:v8-release-compat --@v8//:v8_enable_sandbox=False
|
||||
|
||||
# Optional per-user local overrides.
|
||||
try-import %workspace%/user.bazelrc
|
||||
|
||||
@@ -63,8 +63,10 @@ def bazel_output_files(
|
||||
platform: str,
|
||||
labels: list[str],
|
||||
compilation_mode: str = "fastbuild",
|
||||
bazel_configs: list[str] | None = None,
|
||||
) -> list[Path]:
|
||||
expression = "set(" + " ".join(labels) + ")"
|
||||
bazel_configs = bazel_configs or []
|
||||
result = subprocess.run(
|
||||
[
|
||||
"bazel",
|
||||
@@ -72,6 +74,7 @@ def bazel_output_files(
|
||||
"-c",
|
||||
compilation_mode,
|
||||
f"--platforms=@llvm//platforms:{platform}",
|
||||
*[f"--config={config}" for config in bazel_configs],
|
||||
"--output=files",
|
||||
expression,
|
||||
],
|
||||
@@ -87,7 +90,9 @@ def bazel_build(
|
||||
platform: str,
|
||||
labels: list[str],
|
||||
compilation_mode: str = "fastbuild",
|
||||
bazel_configs: list[str] | None = None,
|
||||
) -> None:
|
||||
bazel_configs = bazel_configs or []
|
||||
subprocess.run(
|
||||
[
|
||||
"bazel",
|
||||
@@ -95,6 +100,7 @@ def bazel_build(
|
||||
"-c",
|
||||
compilation_mode,
|
||||
f"--platforms=@llvm//platforms:{platform}",
|
||||
*[f"--config={config}" for config in bazel_configs],
|
||||
*labels,
|
||||
],
|
||||
cwd=ROOT,
|
||||
@@ -106,13 +112,14 @@ def ensure_bazel_output_files(
|
||||
platform: str,
|
||||
labels: list[str],
|
||||
compilation_mode: str = "fastbuild",
|
||||
bazel_configs: list[str] | None = None,
|
||||
) -> list[Path]:
|
||||
outputs = bazel_output_files(platform, labels, compilation_mode)
|
||||
outputs = bazel_output_files(platform, labels, compilation_mode, bazel_configs)
|
||||
if all(path.exists() for path in outputs):
|
||||
return outputs
|
||||
|
||||
bazel_build(platform, labels, compilation_mode)
|
||||
outputs = bazel_output_files(platform, labels, compilation_mode)
|
||||
bazel_build(platform, labels, compilation_mode, bazel_configs)
|
||||
outputs = bazel_output_files(platform, labels, compilation_mode, bazel_configs)
|
||||
missing = [str(path) for path in outputs if not path.exists()]
|
||||
if missing:
|
||||
raise SystemExit(f"missing built outputs for {labels}: {missing}")
|
||||
@@ -187,8 +194,9 @@ def single_bazel_output_file(
|
||||
platform: str,
|
||||
label: str,
|
||||
compilation_mode: str = "fastbuild",
|
||||
bazel_configs: list[str] | None = None,
|
||||
) -> Path:
|
||||
outputs = ensure_bazel_output_files(platform, [label], compilation_mode)
|
||||
outputs = ensure_bazel_output_files(platform, [label], compilation_mode, bazel_configs)
|
||||
if len(outputs) != 1:
|
||||
raise SystemExit(f"expected exactly one output for {label}, found {outputs}")
|
||||
return outputs[0]
|
||||
@@ -198,11 +206,17 @@ def merged_musl_archive(
|
||||
platform: str,
|
||||
lib_path: Path,
|
||||
compilation_mode: str = "fastbuild",
|
||||
bazel_configs: list[str] | None = None,
|
||||
) -> Path:
|
||||
llvm_ar = single_bazel_output_file(platform, LLVM_AR_LABEL, compilation_mode)
|
||||
llvm_ranlib = single_bazel_output_file(platform, LLVM_RANLIB_LABEL, compilation_mode)
|
||||
llvm_ar = single_bazel_output_file(platform, LLVM_AR_LABEL, compilation_mode, bazel_configs)
|
||||
llvm_ranlib = single_bazel_output_file(
|
||||
platform,
|
||||
LLVM_RANLIB_LABEL,
|
||||
compilation_mode,
|
||||
bazel_configs,
|
||||
)
|
||||
runtime_archives = [
|
||||
single_bazel_output_file(platform, label, compilation_mode)
|
||||
single_bazel_output_file(platform, label, compilation_mode, bazel_configs)
|
||||
for label in MUSL_RUNTIME_ARCHIVE_LABELS
|
||||
]
|
||||
|
||||
@@ -233,11 +247,13 @@ def stage_release_pair(
|
||||
target: str,
|
||||
output_dir: Path,
|
||||
compilation_mode: str = "fastbuild",
|
||||
bazel_configs: list[str] | None = None,
|
||||
) -> None:
|
||||
outputs = ensure_bazel_output_files(
|
||||
platform,
|
||||
[release_pair_label(target)],
|
||||
compilation_mode,
|
||||
bazel_configs,
|
||||
)
|
||||
|
||||
try:
|
||||
@@ -254,7 +270,7 @@ def stage_release_pair(
|
||||
staged_library = output_dir / staged_archive_name(target, lib_path)
|
||||
staged_binding = output_dir / f"src_binding_release_{target}.rs"
|
||||
source_archive = (
|
||||
merged_musl_archive(platform, lib_path, compilation_mode)
|
||||
merged_musl_archive(platform, lib_path, compilation_mode, bazel_configs)
|
||||
if is_musl_archive_target(target, lib_path)
|
||||
else lib_path
|
||||
)
|
||||
@@ -293,6 +309,12 @@ def parse_args() -> argparse.Namespace:
|
||||
stage_release_pair_parser.add_argument("--platform", required=True)
|
||||
stage_release_pair_parser.add_argument("--target", required=True)
|
||||
stage_release_pair_parser.add_argument("--output-dir", required=True)
|
||||
stage_release_pair_parser.add_argument(
|
||||
"--bazel-config",
|
||||
action="append",
|
||||
default=[],
|
||||
dest="bazel_configs",
|
||||
)
|
||||
stage_release_pair_parser.add_argument(
|
||||
"--compilation-mode",
|
||||
default="fastbuild",
|
||||
@@ -330,6 +352,7 @@ def main() -> int:
|
||||
target=args.target,
|
||||
output_dir=Path(args.output_dir),
|
||||
compilation_mode=args.compilation_mode,
|
||||
bazel_configs=args.bazel_configs,
|
||||
)
|
||||
return 0
|
||||
if args.command == "resolved-v8-crate-version":
|
||||
|
||||
@@ -25,7 +25,10 @@ TOP_LEVEL_NAME_EXCEPTIONS = {
|
||||
UTILITY_NAME_EXCEPTIONS = {
|
||||
"path-utils": "codex-utils-path",
|
||||
}
|
||||
MANIFEST_FEATURE_EXCEPTIONS = {}
|
||||
MANIFEST_FEATURE_EXCEPTIONS = {
|
||||
"codex-rs/code-mode/Cargo.toml": {"sandbox": ("v8/v8_enable_sandbox",)},
|
||||
"codex-rs/v8-poc/Cargo.toml": {"sandbox": ("v8/v8_enable_sandbox",)},
|
||||
}
|
||||
OPTIONAL_DEPENDENCY_EXCEPTIONS = set()
|
||||
INTERNAL_DEPENDENCY_FEATURE_EXCEPTIONS = {}
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ jobs:
|
||||
-c
|
||||
opt
|
||||
"--platforms=@llvm//platforms:${PLATFORM}"
|
||||
--config=v8-release-compat
|
||||
"${pair_target}"
|
||||
"${extra_targets[@]}"
|
||||
--build_metadata=COMMIT_SHA=$(git rev-parse HEAD)
|
||||
@@ -134,6 +135,7 @@ jobs:
|
||||
--platform "${PLATFORM}" \
|
||||
--target "${TARGET}" \
|
||||
--compilation-mode opt \
|
||||
--bazel-config v8-release-compat \
|
||||
--output-dir "dist/${TARGET}"
|
||||
|
||||
- name: Upload staged musl artifacts
|
||||
|
||||
@@ -105,6 +105,7 @@ jobs:
|
||||
bazel_args=(
|
||||
build
|
||||
"--platforms=@llvm//platforms:${PLATFORM}"
|
||||
--config=v8-release-compat
|
||||
"${pair_target}"
|
||||
"${extra_targets[@]}"
|
||||
--build_metadata=COMMIT_SHA=$(git rev-parse HEAD)
|
||||
@@ -127,6 +128,7 @@ jobs:
|
||||
python3 .github/scripts/rusty_v8_bazel.py stage-release-pair \
|
||||
--platform "${PLATFORM}" \
|
||||
--target "${TARGET}" \
|
||||
--bazel-config v8-release-compat \
|
||||
--output-dir "dist/${TARGET}"
|
||||
|
||||
- name: Upload staged musl artifacts
|
||||
|
||||
@@ -327,6 +327,18 @@ crate.annotation(
|
||||
"RUSTY_V8_SRC_BINDING_PATH": "$(execpath @v8_targets//:rusty_v8_binding_for_target)",
|
||||
},
|
||||
crate = "v8",
|
||||
# Keep the Rust feature aligned with the source-built Bazel artifacts.
|
||||
# Windows MSVC still consumes upstream non-sandboxed prebuilts.
|
||||
crate_features_select = {
|
||||
"aarch64-apple-darwin": ["v8_enable_sandbox"],
|
||||
"aarch64-pc-windows-gnullvm": ["v8_enable_sandbox"],
|
||||
"aarch64-unknown-linux-gnu": ["v8_enable_sandbox"],
|
||||
"aarch64-unknown-linux-musl": ["v8_enable_sandbox"],
|
||||
"x86_64-apple-darwin": ["v8_enable_sandbox"],
|
||||
"x86_64-pc-windows-gnullvm": ["v8_enable_sandbox"],
|
||||
"x86_64-unknown-linux-gnu": ["v8_enable_sandbox"],
|
||||
"x86_64-unknown-linux-musl": ["v8_enable_sandbox"],
|
||||
},
|
||||
gen_build_script = "on",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
|
||||
@@ -9,6 +9,9 @@ doctest = false
|
||||
name = "codex_code_mode"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
sandbox = ["v8/v8_enable_sandbox"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@ load("//:defs.bzl", "codex_rust_crate")
|
||||
codex_rust_crate(
|
||||
name = "v8-poc",
|
||||
crate_name = "codex_v8_poc",
|
||||
crate_features = select({
|
||||
"@rules_rs//rs/experimental/platforms/constraints:windows_msvc": [],
|
||||
"//conditions:default": ["sandbox"],
|
||||
}),
|
||||
deps_extra = ["@crates//:v8"],
|
||||
)
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@ license.workspace = true
|
||||
name = "codex_v8_poc"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
sandbox = ["v8/v8_enable_sandbox"]
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
|
||||
@@ -12,6 +12,17 @@ pub fn embedded_v8_version() -> &'static str {
|
||||
v8::V8::get_version()
|
||||
}
|
||||
|
||||
/// Returns whether the linked V8 library was built with the in-process sandbox.
|
||||
#[must_use]
|
||||
pub fn linked_v8_has_sandbox() -> bool {
|
||||
unsafe extern "C" {
|
||||
fn v8__V8__IsSandboxEnabled() -> bool;
|
||||
}
|
||||
|
||||
// `rusty_v8` exposes this symbol for its own sandbox verification tests.
|
||||
unsafe { v8__V8__IsSandboxEnabled() }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::assert_eq;
|
||||
@@ -53,6 +64,11 @@ mod tests {
|
||||
assert!(!super::embedded_v8_version().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sandbox_feature_matches_linked_v8() {
|
||||
assert_eq!(super::linked_v8_has_sandbox(), cfg!(feature = "sandbox"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn evaluates_integer_addition() {
|
||||
assert_eq!(evaluate_expression("1 + 2"), "3");
|
||||
|
||||
@@ -331,6 +331,7 @@ def codex_rust_crate(
|
||||
rust_test(
|
||||
name = unit_test_binary,
|
||||
crate = name,
|
||||
crate_features = crate_features,
|
||||
deps = all_crate_deps(normal = True, normal_dev = True) + maybe_deps + deps_extra,
|
||||
# Unit tests also compile to standalone Windows executables, so
|
||||
# keep their stack reserve aligned with binaries and integration
|
||||
|
||||
@@ -65,10 +65,19 @@ index 9648e4a..88efd41 100644
|
||||
":should_add_rdynamic": ["-rdynamic"],
|
||||
"//conditions:default": [],
|
||||
diff --git a/orig/v8-14.6.202.11/BUILD.bazel b/mod/v8-14.6.202.11/BUILD.bazel
|
||||
index 85f31b7..7314584 100644
|
||||
index 85f31b7..bbc351b 100644
|
||||
--- a/orig/v8-14.6.202.11/BUILD.bazel
|
||||
+++ b/mod/v8-14.6.202.11/BUILD.bazel
|
||||
@@ -303,7 +303,7 @@ v8_int(
|
||||
@@ -148,6 +148,8 @@ v8_flag(name = "v8_enable_trace_maps")
|
||||
|
||||
v8_flag(name = "v8_enable_v8_checks")
|
||||
|
||||
+v8_flag(name = "v8_enable_sandbox")
|
||||
+
|
||||
v8_flag(name = "v8_enable_verify_csa")
|
||||
|
||||
v8_flag(name = "v8_enable_verify_heap")
|
||||
@@ -303,7 +305,7 @@ v8_int(
|
||||
# If no explicit value for v8_enable_pointer_compression, we set it to 'none'.
|
||||
v8_string(
|
||||
name = "v8_enable_pointer_compression",
|
||||
@@ -77,7 +86,15 @@ index 85f31b7..7314584 100644
|
||||
)
|
||||
|
||||
# Default setting for v8_enable_pointer_compression.
|
||||
@@ -4077,28 +4077,14 @@ filegroup(
|
||||
@@ -503,6 +505,7 @@ v8_config(
|
||||
"v8_enable_slow_dchecks": "ENABLE_SLOW_DCHECKS",
|
||||
"v8_enable_runtime_call_stats": "V8_RUNTIME_CALL_STATS",
|
||||
"v8_enable_snapshot_native_code_counters": "V8_SNAPSHOT_NATIVE_CODE_COUNTERS",
|
||||
+ "v8_enable_sandbox": "V8_ENABLE_SANDBOX",
|
||||
"v8_enable_trace_maps": "V8_TRACE_MAPS",
|
||||
"v8_enable_turbofan": "V8_ENABLE_TURBOFAN",
|
||||
"v8_enable_v8_checks": "V8_ENABLE_CHECKS",
|
||||
@@ -4077,28 +4080,14 @@ filegroup(
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -112,7 +129,7 @@ index 85f31b7..7314584 100644
|
||||
)
|
||||
|
||||
filegroup(
|
||||
@@ -4405,6 +4391,20 @@ genrule(
|
||||
@@ -4405,6 +4394,20 @@ genrule(
|
||||
srcs = [
|
||||
"include/js_protocol.pdl",
|
||||
"src/inspector/inspector_protocol_config.json",
|
||||
@@ -133,7 +150,7 @@ index 85f31b7..7314584 100644
|
||||
],
|
||||
outs = [
|
||||
"include/inspector/Debugger.h",
|
||||
@@ -4426,15 +4426,19 @@ genrule(
|
||||
@@ -4426,15 +4429,19 @@ genrule(
|
||||
"src/inspector/protocol/Schema.cpp",
|
||||
"src/inspector/protocol/Schema.h",
|
||||
],
|
||||
@@ -157,7 +174,7 @@ index 85f31b7..7314584 100644
|
||||
],
|
||||
)
|
||||
|
||||
@@ -4448,6 +4451,15 @@ filegroup(
|
||||
@@ -4448,6 +4455,15 @@ filegroup(
|
||||
],
|
||||
)
|
||||
|
||||
@@ -173,7 +190,7 @@ index 85f31b7..7314584 100644
|
||||
filegroup(
|
||||
name = "d8_files",
|
||||
srcs = [
|
||||
@@ -4567,16 +4579,9 @@ cc_library(
|
||||
@@ -4567,16 +4583,9 @@ cc_library(
|
||||
],
|
||||
)
|
||||
|
||||
@@ -192,7 +209,8 @@ index 85f31b7..7314584 100644
|
||||
+ actual = "@simdutf//:simdutf",
|
||||
)
|
||||
|
||||
@@ -4593,7 +4598,7 @@ v8_library(
|
||||
v8_library(
|
||||
@@ -4593,7 +4602,7 @@ v8_library(
|
||||
copts = ["-Wno-implicit-fallthrough"],
|
||||
icu_deps = [
|
||||
":icu/generated_torque_definitions_headers",
|
||||
@@ -201,7 +219,7 @@ index 85f31b7..7314584 100644
|
||||
],
|
||||
icu_srcs = [
|
||||
":generated_regexp_special_case",
|
||||
@@ -4608,7 +4613,7 @@ v8_library(
|
||||
@@ -4608,7 +4617,7 @@ v8_library(
|
||||
],
|
||||
deps = [
|
||||
":lib_dragonbox",
|
||||
@@ -210,7 +228,7 @@ index 85f31b7..7314584 100644
|
||||
":lib_fp16",
|
||||
":simdutf",
|
||||
":v8_libbase",
|
||||
@@ -4664,6 +4669,7 @@ alias(
|
||||
@@ -4664,6 +4673,7 @@ alias(
|
||||
alias(
|
||||
name = "core_lib_icu",
|
||||
actual = "icu/v8",
|
||||
@@ -218,7 +236,7 @@ index 85f31b7..7314584 100644
|
||||
)
|
||||
|
||||
v8_library(
|
||||
@@ -4715,7 +4721,7 @@ v8_binary(
|
||||
@@ -4715,7 +4725,7 @@ v8_binary(
|
||||
],
|
||||
deps = [
|
||||
":v8_libbase",
|
||||
|
||||
Vendored
+9
-2
@@ -3,14 +3,21 @@
|
||||
This directory wires the `v8` crate to exact-version Bazel inputs.
|
||||
Bazel consumer builds use:
|
||||
|
||||
- upstream `denoland/rusty_v8` release archives on Windows
|
||||
- source-built V8 archives on Darwin, GNU Linux, and musl Linux
|
||||
- upstream `denoland/rusty_v8` release archives on Windows MSVC
|
||||
- source-built V8 archives on Darwin, GNU Linux, musl Linux, and Windows GNU
|
||||
- `openai/codex` release assets for published musl release pairs
|
||||
|
||||
Cargo builds still use prebuilt `rusty_v8` archives by default. Only Bazel
|
||||
overrides `RUSTY_V8_ARCHIVE`/`RUSTY_V8_SRC_BINDING_PATH` in `MODULE.bazel` to
|
||||
select source-built local archives for its consumer builds.
|
||||
|
||||
Source-built Bazel V8 artifacts enable V8's in-process sandbox by default, and
|
||||
the Bazel `v8` crate feature selection tracks those targets. A full consumer
|
||||
rollout still needs matching sandbox-enabled archives for every non-source-built
|
||||
target. Until that artifact migration lands, the rusty_v8 publishing workflows
|
||||
use `--config=v8-release-compat` to preserve the current non-sandboxed release
|
||||
artifact contract.
|
||||
|
||||
Current pinned versions:
|
||||
|
||||
- Rust crate: `v8 = =146.4.0`
|
||||
|
||||
Reference in New Issue
Block a user