Sandbox.jl Documentation

Sandbox.jl provides basic containerization tools for running Linux guests on a variety of platforms.

Index

Types

Sandbox.BinFmtRegistrationType
BinFmtRegistration

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.

source
Sandbox.BinFmtRegistrationMethod
BinFmtRegistration(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.

source
Sandbox.SandboxConfigType
SandboxConfig(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.
  • 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.
  • 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.
  • uid and gid: Numeric user and group identifiers to spawn the sandboxed process as.

    • By default, these are both 0, signifying root inside the sandbox.
  • stdin, stdout, stderr: input/output streams for the sandboxed process.

    • Can be any kind of IO, TTY, devnull, etc...
  • hostname: Set the hostname within the sandbox, defaults to the current hostname

  • verbose: Set whether the sandbox construction process should be more or less verbose.

source
Sandbox.SandboxExecutorType
SandboxExecutor

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 type T is available on this system. For example, UserNamespacesExecutors 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 the Cmd object that, when run, executes the user's desired command within the given sandbox. The config 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
source

Functions

Sandbox.build_docker_imageMethod
build_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.

source
Sandbox.default_persist_root_dirsMethod
default_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.

source
Sandbox.export_docker_imageFunction
export_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.

source
Sandbox.get_kernel_versionMethod
get_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.

source
Sandbox.get_loaded_modulesMethod
get_loaded_modules()

Returns a list of modules currently loaded by the system. On non-Linux platforms, returns an empty list.

source
Sandbox.is_ecryptfsMethod
is_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.

source
Sandbox.load_env_prefMethod
load_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.

source
Sandbox.max_directory_ctimeMethod
max_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.

source
Sandbox.pull_docker_imageFunction
pull_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.

source
Sandbox.read_binfmt_misc_registrationsMethod
read_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.

source
Sandbox.realpath_stemMethod
realpath_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.

source
Sandbox.register_requested_formats!Method
register_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.

source
Sandbox.register_stringMethod
register_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().

source
Sandbox.unameMethod
uname()

On Linux systems, return the strings returned by the uname() function in libc.

source