/// Wrap a binary in a sandbox. This sandbox is not meant for security, so there
/// are no guarantees that it's impossible (or even necessarily difficult) to
/// break out of - but it is designed to be annoying and/or obvious to escape,
/// so as to encourage safe + hermetic code in certain contexts.
Wrap a binary in a sandbox. This sandbox is not meant for security, so there
are no guarantees that it's impossible (or even necessarily difficult) to
break out of - but it is designed to be annoying and/or obvious to escape,
so as to encourage safe + hermetic code in certain contexts.
Wrap a binary in a sandbox . This sandbox is not meant for security so there are no guarantees that it ' s impossible ( or even necessarily difficult ) to break out of - but it is designed to be annoying and / or obvious to escape so as to encourage safe + hermetic code in certain contexts .
pub fn sandbox<S: AsRef<OsStr>>(binary: S, opts: SandboxOpts) -> Result<Command> {
    let root = tempfile::tempdir().context("while creating tmpdir for root")?;
    let root_path = root.path().to_path_buf();
    let mut ro_files = opts.ro_files;
    ro_files.extend(
        so_dependencies(binary.as_ref())?
            .into_iter()
            .map(|p| (p.clone(), p)),
    );
    let mut cmd = std::process::Command::new(binary);
    unsafe {
        cmd.pre_exec(move || {
            unshare(
                CloneFlags::CLONE_NEWUSER
                    | CloneFlags::CLONE_NEWNS
                    | CloneFlags::CLONE_NEWNET
                    | CloneFlags::CLONE_NEWCGROUP
                    | CloneFlags::CLONE_NEWUTS,
                // CLONE_NEWPID causes hang for some reason, but it shouldn't
                // really matter
            )?;
            for (src, dst) in &ro_files {
                let dst = root_path.join(dst.strip_prefix("/").unwrap());
                std::fs::create_dir_all(dst.parent().unwrap())?;
                std::fs::File::create(&dst)?;
                mount::<_, _, str, str>(
                    Some(src),
                    &dst,
                    None,
                    MsFlags::MS_BIND | MsFlags::MS_RDONLY,
                    None,
                )?;
            }
            // mount the tmpdir as the root of the sandboxed container
            mount::<_, _, str, str>(
                Some(&root_path),
                "/",
                None,
                MsFlags::MS_BIND | MsFlags::MS_RDONLY,
                None,
            )?;
            Ok(())
        });
    }
    Ok(Command {
        _root: root,
        inner: cmd,
    })
}
pub fn sandbox < S : AsRef < OsStr > > ( binary : S , opts : SandboxOpts ) -> Result < Command > { let root = tempfile :: tempdir ( ) . context ( " " ) ? ; let root_path = root . path ( ) . to_path_buf ( ) ; let mut ro_files = opts . ro_files ; ro_files . extend ( so_dependencies ( binary . as_ref ( ) ) ? . into_iter ( ) . map ( | p | ( p . clone ( ) , p ) ) , ) ; let mut cmd = std :: process :: Command :: new ( binary ) ; unsafe { cmd . pre_exec ( move | | { unshare ( CloneFlags :: CLONE_NEWUSER | CloneFlags :: CLONE_NEWNS | CloneFlags :: CLONE_NEWNET | CloneFlags :: CLONE_NEWCGROUP | CloneFlags :: CLONE_NEWUTS , // CLONE_NEWPID causes hang for some reason, but it shouldn't // really matter ) ? ; for ( src , dst ) in & ro_files { let dst = root_path . join ( dst . strip_prefix ( " " ) . unwrap ( ) ) ; std :: fs :: create_dir_all ( dst . parent ( ) . unwrap ( ) ) ? ; std :: fs :: File :: create ( & dst ) ? ; mount :: < _ , _ , str , str > ( Some ( src ) , & dst , None , MsFlags :: MS_BIND | MsFlags :: MS_RDONLY , None , ) ? ; } // mount the tmpdir as the root of the sandboxed container mount :: < _ , _ , str , str > ( Some ( & root_path ) , " " , None , MsFlags :: MS_BIND | MsFlags :: MS_RDONLY , None , ) ? ; Ok ( ( ) ) } ) ; } Ok ( Command { _root : root , inner : cmd , } ) }
Wrap a binary in a sandbox.
Wrap a binary in a sandbox .
binary
S
opts
SandboxOpts