-
Notifications
You must be signed in to change notification settings - Fork 19
rsandbox: RPython-style compile-time sandbox for pyre (#285) #304
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| # Sandbox compile-out fence. | ||
| # | ||
| # This config is applied ONLY by the dedicated sandbox clippy CI job, which | ||
| # points clippy at this directory via `CLIPPY_CONF_DIR`. Normal builds and | ||
| # normal `cargo clippy` never discover it (it is not an ancestor of any crate), | ||
| # so day-to-day development is unaffected. | ||
| # | ||
| # It forbids raw host-OS access in the `--features sandbox` build of the | ||
| # untrusted interpreter. Under sandbox every mediated OS call must go through | ||
| # `crate::host_seam::ops::*`, which marshals the request to the trusted | ||
| # controller; a direct `std::fs`/`std::env`/`std::io` stdio/`std::process`/ | ||
| # `std::net` call would bypass the seam and escape the sandbox. Because clippy | ||
| # only sees code that actually compiles under the feature set, the | ||
| # `#[cfg(not(feature = "sandbox"))]` real-syscall paths are invisible here — a | ||
| # clean run therefore proves no raw host call survives in sandbox-live code. | ||
| # | ||
| # The trusted controller lives in the separate `pyre-sandbox` crate and is not | ||
| # linted by this job (it lints `-p pyre-interpreter` only). | ||
|
|
||
| disallowed-methods = [ | ||
| # Filesystem entry points | ||
| { path = "std::fs::read", reason = "raw host FS read; route through crate::host_seam::ops" }, | ||
| { path = "std::fs::write", reason = "raw host FS write; route through crate::host_seam::ops" }, | ||
| { path = "std::fs::read_to_string", reason = "raw host FS read; route through crate::host_seam::ops" }, | ||
| { path = "std::fs::read_link", reason = "raw host FS access; route through crate::host_seam::ops" }, | ||
| { path = "std::fs::read_dir", reason = "raw host FS listdir; route through crate::host_seam::ops" }, | ||
| { path = "std::fs::metadata", reason = "raw host FS stat; route through crate::host_seam::ops" }, | ||
| { path = "std::fs::symlink_metadata", reason = "raw host FS lstat; route through crate::host_seam::ops" }, | ||
| { path = "std::fs::canonicalize", reason = "raw host FS access; route through crate::host_seam::ops" }, | ||
| { path = "std::fs::remove_file", reason = "host FS mutation is forbidden in the sandbox" }, | ||
| { path = "std::fs::remove_dir", reason = "host FS mutation is forbidden in the sandbox" }, | ||
| { path = "std::fs::remove_dir_all", reason = "host FS mutation is forbidden in the sandbox" }, | ||
| { path = "std::fs::create_dir", reason = "host FS mutation is forbidden in the sandbox" }, | ||
| { path = "std::fs::create_dir_all", reason = "host FS mutation is forbidden in the sandbox" }, | ||
| { path = "std::fs::rename", reason = "host FS mutation is forbidden in the sandbox" }, | ||
| { path = "std::fs::copy", reason = "host FS mutation is forbidden in the sandbox" }, | ||
| { path = "std::fs::hard_link", reason = "host FS mutation is forbidden in the sandbox" }, | ||
| { path = "std::fs::set_permissions", reason = "host FS mutation is forbidden in the sandbox" }, | ||
| # Process environment | ||
| { path = "std::env::var", reason = "raw process env; route through crate::host_seam::ops::getenv" }, | ||
| { path = "std::env::var_os", reason = "raw process env; route through crate::host_seam::ops::getenv" }, | ||
| { path = "std::env::vars", reason = "raw process env; route through crate::host_seam::ops::envitems" }, | ||
| { path = "std::env::vars_os", reason = "raw process env; route through crate::host_seam::ops::envitems" }, | ||
| { path = "std::env::set_var", reason = "host env mutation is forbidden in the sandbox" }, | ||
| { path = "std::env::remove_var", reason = "host env mutation is forbidden in the sandbox" }, | ||
| { path = "std::env::current_dir", reason = "raw host cwd; route through crate::host_seam::ops::getcwd" }, | ||
| { path = "std::env::set_current_dir", reason = "host cwd mutation is forbidden in the sandbox" }, | ||
| { path = "std::env::current_exe", reason = "leaks the real executable path; forbidden in the sandbox" }, | ||
| { path = "std::env::temp_dir", reason = "leaks a real host path; forbidden in the sandbox" }, | ||
| # Standard streams (the marshalling pipe is the only sanctioned raw stdio) | ||
| { path = "std::io::stdout", reason = "raw stdout; route through crate::host_seam::ops::write" }, | ||
| { path = "std::io::stderr", reason = "raw stderr; route through crate::host_seam::ops::write" }, | ||
| { path = "std::io::stdin", reason = "raw stdin; mediated by the controller" }, | ||
| { path = "std::io::_print", reason = "print!/println! writes real stdout; route through the host_seam" }, | ||
| { path = "std::io::_eprint", reason = "eprint!/eprintln! writes real stderr; route through the host_seam" }, | ||
| # Process control | ||
| { path = "std::process::exit", reason = "raw process exit; the controller owns process lifetime" }, | ||
| { path = "std::process::abort", reason = "raw process abort; the controller owns process lifetime" }, | ||
| ] | ||
|
|
||
| disallowed-types = [ | ||
| { path = "std::fs::File", reason = "raw host file handle; route file I/O through crate::host_seam::ops" }, | ||
| { path = "std::fs::OpenOptions", reason = "raw host file open; route through crate::host_seam::ops::open" }, | ||
| { path = "std::process::Command", reason = "process spawn is forbidden in the sandbox" }, | ||
| { path = "std::net::TcpStream", reason = "raw network; use the mediated tcp:// controller path" }, | ||
| { path = "std::net::TcpListener", reason = "raw network listen is forbidden in the sandbox" }, | ||
| { path = "std::net::UdpSocket", reason = "raw network is forbidden in the sandbox" }, | ||
| ] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,10 @@ description = "Python bytecode interpreter for pyre" | |
| [features] | ||
| default = ["host_env"] | ||
| host_env = ["dep:rustpython-host_env"] | ||
| # RPython-style sandbox: route every OS call through host_seam's marshalling | ||
| # trampoline instead of the real syscall. Implies host_env (same call surface, | ||
| # swapped bodies); the real-vs-trampoline choice lives only inside host_seam. | ||
| sandbox = ["host_env", "dep:pyre-sandbox"] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Because Useful? React with 👍 / 👎. |
||
| cranelift = ["majit-metainterp/cranelift"] | ||
| dynasm = ["majit-metainterp/dynasm"] | ||
| # Embed the pure-Python stdlib closure needed for `import re` into the binary | ||
|
|
@@ -35,6 +39,7 @@ num-integer = { workspace = true } | |
| pymath = { workspace = true } | ||
| sre-engine = { workspace = true } | ||
| rustpython-host_env = { workspace = true, optional = true } | ||
| pyre-sandbox = { workspace = true, optional = true } | ||
| libc = { workspace = true } | ||
| siphasher = { workspace = true } | ||
| caseless = { workspace = true } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the new sandbox feature enables
host_env,read_source_line()still compiles itsrustpython_host_env::fs::read_to_string(filename)branch and is not routed through the sandbox SourceProvider. A sandboxed program can set an arbitrary traceback filename, e.g. viacompile(..., "/etc/passwd", "exec"), then raise an exception and have the child read and print host file lines on stderr; with seccomp enabled the same path would die on the raw open instead of producing a normal sandbox error. Please gate this host_env path out under sandbox or read traceback lines through the seam.Useful? React with 👍 / 👎.