Allow host runtimes to bypass the native builder sandbox

This commit is contained in:
2026-11-12 09:32:30 +00:00
parent 0b79bb4227
commit a0bb71b175
11 changed files with 197 additions and 84 deletions
+6 -3
View File
@@ -289,7 +289,7 @@ mod tests {
let _ = started_tx.send(());
let _ = finish_rx.recv();
}));
let runtime = super::super::Runtime::with_compiler(world, compiler)?;
let runtime = super::super::Runtime::with_compiler(world, compiler, Default::default())?;
started_rx.await?;
let command_runtime = runtime.clone();
let mut command = tokio::spawn(async move {
@@ -353,7 +353,8 @@ mod tests {
wat::parse_str(r#"(module (memory (export "memory") 1) (func (export "_start")))"#)?,
)?;
compiler.get(parent).await?;
let runtime = super::super::Runtime::with_compiler(world, compiler.clone())?;
let runtime =
super::super::Runtime::with_compiler(world, compiler.clone(), Default::default())?;
let deadline = Deadline::new(Duration::ZERO);
let request = |name: &str| Request {
program: name.into(),
@@ -471,7 +472,9 @@ mod tests {
finish_rx.recv().unwrap();
}));
// Startup returns while the compiler remains blocked behind the test gate.
let runtime = super::super::Runtime::with_compiler(world, compiler.clone()).unwrap();
let runtime =
super::super::Runtime::with_compiler(world, compiler.clone(), Default::default())
.unwrap();
started_rx.await.unwrap();
let background = compiler.clone();
let precompile = tokio::spawn(async move { background.get(bytes).await });
+38 -9
View File
@@ -154,20 +154,36 @@ struct Started {
output: Option<DuplexStream>,
error: Option<DuplexStream>,
}
/// Host-only switches for native builder execution. Defaults retain namespace isolation.
#[derive(Clone, Copy, Debug, Default)]
pub struct RuntimeOptions {
pub no_builder_sandbox: bool,
}
impl Runtime {
pub fn open(path: &Path) -> anyhow::Result<Arc<Self>> {
Self::new(World::open(path)?)
}
pub fn new(world: World) -> anyhow::Result<Arc<Self>> {
Self::with_compiler(world, cache::shared()?)
Self::new_with_options(world, RuntimeOptions::default())
}
pub fn new_with_options(world: World, options: RuntimeOptions) -> anyhow::Result<Arc<Self>> {
Self::with_compiler(world, cache::shared()?, options)
}
/// Open an independent engine using an explicit shared disk cache.
pub fn new_with_cache(world: World, directory: &Path) -> anyhow::Result<Arc<Self>> {
Self::with_compiler(world, cache::Compiler::new(directory)?)
Self::with_compiler(
world,
cache::Compiler::new(directory)?,
RuntimeOptions::default(),
)
}
fn with_compiler(world: World, compiler: Arc<cache::Compiler>) -> anyhow::Result<Arc<Self>> {
fn with_compiler(
world: World,
compiler: Arc<cache::Compiler>,
options: RuntimeOptions,
) -> anyhow::Result<Arc<Self>> {
let cred = Arc::new(crate::cred::Cred::open(&world.host_dir)?);
Self::with_hooks(world, compiler, cred, default_script(), None)
Self::with_hooks(world, compiler, cred, default_script(), None, options)
}
/// Share credentials and the host API router with the host's other subsystems.
pub fn new_with_hooks(
@@ -176,7 +192,16 @@ impl Runtime {
script: Arc<dyn crate::cred::script::Script>,
router: Option<Router>,
) -> anyhow::Result<Arc<Self>> {
Self::with_hooks(world, cache::shared()?, cred, script, router)
Self::new_with_hooks_and_options(world, cred, script, router, RuntimeOptions::default())
}
pub fn new_with_hooks_and_options(
world: World,
cred: Arc<crate::cred::Cred>,
script: Arc<dyn crate::cred::script::Script>,
router: Option<Router>,
options: RuntimeOptions,
) -> anyhow::Result<Arc<Self>> {
Self::with_hooks(world, cache::shared()?, cred, script, router, options)
}
fn with_hooks(
world: World,
@@ -184,6 +209,7 @@ impl Runtime {
cred: Arc<crate::cred::Cred>,
script: Arc<dyn crate::cred::script::Script>,
router: Option<http::Router>,
options: RuntimeOptions,
) -> anyhow::Result<Arc<Self>> {
let router = match router {
Some(api) => api,
@@ -195,10 +221,13 @@ impl Runtime {
)?),
};
router.attach_journal(world.root.journal());
let _ = router.builder.set(Arc::new(crate::builder::Builder::new(
world.root.clone(),
&world.host_dir,
)?));
let _ = router
.builder
.set(Arc::new(crate::builder::Builder::new_with_options(
world.root.clone(),
&world.host_dir,
options.no_builder_sandbox,
)?));
let network = Arc::new(net::NetPolicy::open(&world.host_dir)?);
let engine = compiler.engine.clone();
let alive = Arc::new(AtomicBool::new(true));