Sandbox.jl Documentation
Sandbox.jl
provides basic containerization tools for running Linux guests on a variety of platforms.
Index
Sandbox.BinFmtRegistration
Sandbox.BinFmtRegistration
Sandbox.SandboxConfig
Sandbox.SandboxExecutor
Sandbox.build_docker_image
Sandbox.check_binfmt_misc_loaded
Sandbox.default_persist_root_dirs
Sandbox.export_docker_image
Sandbox.get_kernel_version
Sandbox.get_loaded_modules
Sandbox.getgid
Sandbox.getuid
Sandbox.is_ecryptfs
Sandbox.load_env_pref
Sandbox.max_directory_ctime
Sandbox.pull_docker_image
Sandbox.read_binfmt_misc_registrations
Sandbox.realpath_stem
Sandbox.register_requested_formats!
Sandbox.register_string
Sandbox.uname
Sandbox.with_executor
Sandbox.write_binfmt_misc_registration!
Types
Sandbox.BinFmtRegistration
— TypeBinFmtRegistration
Provides a structured view of a binfmt_misc
interpreter registration. Note that only "magic" matching rules are allowed, we do not support "extension" matching rules.
Sandbox.BinFmtRegistration
— MethodBinFmtRegistration(file::String)
Reads a binfmt_misc
registration in from disk, if it cannot be parsed (because it is malformed, or uses unsupported features) it an ArgumentError
will be thrown.
Sandbox.SandboxConfig
— TypeSandboxConfig(read_only_maps, read_write_maps, env)
Sandbox executors require a configuration to set up the environment properly.
read_only_maps
: Directories that are mapped into the sandbox as read-only mappings.- Specified as pairs, e.g.
sandbox_path => host_path
. All paths must be absolute. - Must always include a mapping for root, e.g.
"/" => rootfs_path
.
- Specified as pairs, e.g.
read_write_maps
: Directories that are mapped into the sandbox as read-write mappings.- Specified as pairs, e.g.
sandbox_path => host_path
. All paths must be absolute. - Note that some executors may not show perfect live updates; consistency is guaranteed only after execution is finished.
- Specified as pairs, e.g.
env
: Dictionary mapping of environment variables that should be set within the sandbox.entrypoint
: Executable that gets passed the actual command being run.- This is a path within the sandbox, and must be absolute.
- Defaults to
nothing
, which causes the command to be executed directly.
pwd
: Set the working directory of the command that will be run.- This is a path within the sandbox, and must be absolute.
persist
: Tell the executor object to persist changes made to the rootfs.- This is a boolean value, it is up to interpretation by the executor.
- Persistence is a property of an individual executor and changes live only as long as the executor object itself.
- You cannot transfer persistent changes from one executor to another.
multiarch
: Request multiarch executable support- This is an array of
Platform
objects - Sandbox will ensure that interpreters (such as
qemu-*-static
binaries) are available for each platform. - Requesting multiarch support for a platform that we don't support results in an
ArgumentError
.
- This is an array of
uid
andgid
: Numeric user and group identifiers to spawn the sandboxed process as.- By default, these are both
0
, signifyingroot
inside the sandbox.
- By default, these are both
stdin
,stdout
,stderr
: input/output streams for the sandboxed process.- Can be any kind of
IO
,TTY
,devnull
, etc...
- Can be any kind of
hostname
: Set the hostname within the sandbox, defaults to the current hostnameverbose
: Set whether the sandbox construction process should be more or less verbose.
Sandbox.SandboxExecutor
— TypeSandboxExecutor
This represents the base type for all execution backends within this package. Valid concrete subtypes must implement at least the following methods:
T()
: no-argument constructor to ready an execution engine with all defaults.executor_available(::DataType{T})
: Checks whether executor typeT
is available on this system. For example,UserNamespacesExecutor
s are only available on Linux, and even then only on certain kernels. Availablility checks may run a program to determine whether that executor is actually available.build_executor_command(exe::T, config::SandboxConfig, cmd::Cmd)
: Builds theCmd
object that, when run, executes the user's desired command within the given sandbox. Theconfig
object contains all necessary metadata such as shard mappings, environment variables,stdin
/stdout
/stderr
redirection, etc...cleanup(exe::T)
: Cleans up any persistent data storage that this executor may have built up over the course of its execution.
Note that while you can manually construct and cleanup an executor, it is recommended that users instead make use of the with_executor()
convenience function:
with_executor(UnprivilegedUserNamespacesExecutor) do exe
run(exe, config, ...)
end
Functions
Sandbox.build_docker_image
— Methodbuild_docker_image(root_path::String)
Docker doesn't like volume mounts within volume mounts, like we do with sandbox
. So we do things "the docker way", where we construct a rootfs docker image, then mount things on top of that, with no recursive mounting. We cut down on unnecessary work somewhat by quick-scanning the directory for changes and only rebuilding if changes are detected.
Sandbox.check_binfmt_misc_loaded
— Methodcheck_binfmt_misc_loaded()
Check that the binfmt_misc
kernel module is loaded and enabled.
Sandbox.default_persist_root_dirs
— Methoddefault_persist_root_dirs()
Returns the default list of directories that should be attempted to be used as persistence storage. Influenced by the SANDBOX_PERSISTENCE_DIR
environment variable, as well as the persist_dir
preference. The last place searched by default is the persist_dirs
scratch space.
Sandbox.export_docker_image
— Functionexport_docker_image(image::String,
output_dir::String = <default scratch location>;
verbose::Bool = false,
force::Bool = false)
Exports the given docker image name to the requested output directory. Useful for pulling down a known good rootfs image from Docker Hub, for future use by Sandbox executors. If force
is set to true, will overwrite a pre-existing directory, otherwise will silently return.
Sandbox.get_kernel_version
— Methodget_kernel_version(;verbose::Bool = false)
Use uname()
to get the kernel version and parse it out as a VersionNumber
, returning nothing
if parsing fails or this is not Linux
.
Sandbox.get_loaded_modules
— Methodget_loaded_modules()
Returns a list of modules currently loaded by the system. On non-Linux platforms, returns an empty list.
Sandbox.getgid
— Methodgetgid()
Wrapper around libc's getgid()
function
Sandbox.getuid
— Methodgetuid()
Wrapper around libc's getuid()
function
Sandbox.is_ecryptfs
— Methodis_ecryptfs(path::AbstractString; verbose::Bool=false)
Checks to see if the given path
(or any parent directory) is placed upon an ecryptfs
mount. This is known not to work on current kernels, see this bug for more details: https://bugzilla.kernel.org/show_bug.cgi?id=197603
This method returns whether it is encrypted or not, and what mountpoint it used to make that decision.
Sandbox.load_env_pref
— Methodload_env_pref(env_var, prefs_name, default)
Many pieces of Sandbox.jl
functionality can be controlled either through environment variables or preferences. This utility function makes it easy to check first the environment, then preferences, finally falling back to the default. Additionally, it memoizes the result in a caching dictionary.
Sandbox.max_directory_ctime
— Methodmax_directory_ctime(prefix::String)
Takes the stat()
of all files in a directory root, keeping the maximum ctime, recursively. Comparing just this value allows for quick directory change detection.
Sandbox.pull_docker_image
— Functionpull_docker_image(image::String,
output_dir::String = <default scratch location>;
platform::String = "",
verbose::Bool = false,
force::Bool = false)
Pulls and saves the given docker image name to the requested output directory. Useful for pulling down a known good rootfs image from Docker Hub, for future use by Sandbox executors. If force
is set to true, will overwrite a pre-existing directory, otherwise will silently return. Optionally specify the platform of the image with platform
.
Sandbox.read_binfmt_misc_registrations
— Methodread_binfmt_misc_registrations()
Return a list of BinFmtRegistration
objects, one per readable registration, as found sitting in /proc/sys/fs/binfmt_misc/*
. Registrations that cannot be parsed are silently ignored.
Sandbox.realpath_stem
— Methodrealpath_stem(path::AbstractString)
Given a path, return the realpath
of it. If it does not exist, try to resolve the realpath
of its containing directory, then append the tail portion onto the end of that resolved stem. This iterates until we find a stem that can be resolved.
This allows for resolving directory symlinks halfway through a path, while not requiring that the final path leaf exist at the time of calling realpath_stem()
. Of course, if the final path leaf is itself a symlink, this will not work correctly, so this should be considered a "best effort" function.
Internally, we use this to attempt to discover the actual mountpoint a mapping is or will be stored on.
Sandbox.register_requested_formats!
— Methodregister_requested_formats(formats::Vector{BinFmtRegistration})
Given the list of binfmt_misc
formats, check the currently-registered formats through read_binfmt_misc_registrations()
, check to see if any in formats
are not yet registered, and if they are not, call write_binfmt_misc_registration!()
to register it with an artifact-sourced qemu-*-static
binary.
Sandbox.register_string
— Methodregister_string(reg::BinFmtRegistration)
Constructs the string used to register a binfmt_misc
registration with the register
file endpoint within /proc/sys/fs/binfmt_misc/register
. To actually register the interpreter, use write_binfmt_misc_registration()
.
Sandbox.uname
— Methoduname()
On Linux systems, return the strings returned by the uname()
function in libc.
Sandbox.with_executor
— Methodwith_executor(f::Function, ::Type{<:SandboxExecutor} = preferred_executor(); kwargs...)
Sandbox.write_binfmt_misc_registration!
— Methodwrite_binfmt_misc_registration(reg::BinFmtRegistration)
Write a binfmt_misc
registration out to the kernel's register
file endpoint. Requires sudo
privileges.