Extend and embed
Author a backend
Implement the ABI 10 lifecycle, capability vocabulary, filesystem semantics and descriptor contract.A backend implements maelys_executor_backend_ops_t and is registered with
maelys_executor_register_backend().
ABI 10 lifecycle, target compatibility and budgets
probe -> probe_target(TargetSpec) -> prepare(request, plan) -> artifact -> spawn
-> instance
|
+-> artifact_release exactly onceprobereports only guarantees enforced on the running host.probe_targetevaluates target kind/platform separately from MIR capability bits and returns stable evidence bound into selection and the artifact.preparestarts no workload and copies, validates or pins everything the artifact needs. Failure leaves no resource behind.- after successful prepare, the core calls
artifact_releaseexactly once, whether spawn succeeds or fails. spawnconsumes the immutable artifact and either returns one complete instance or leaves no process, descriptor or handle behind.- returned stream descriptors belong to Executor immediately.
waithonors its timeout.status.exitedmeans the lifecycle domain tracked by that backend is empty.stopis non-blocking and idempotent.releaseis local-only: it neither signals nor waits.
The ops table must outlive the executor. Context ownership transfers only after
successful registration and only when destroy_context is supplied.
abi_version is checked before any ops field is used. Target-aware probing
remains mandatory in ABI 10 and every backend must implement it. ABI 10 also
carries the normalized root mode, exact ephemeral scratch ceiling and terminal
cleanup outcome.
An ABI 2 backend is therefore rejected with a diagnostic instead of being
interpreted through the wrong layout.
Capability vocabulary
Capabilities describe guarantees, not implementation technologies:
PROCESS_CONFINEMENT: the isolation policy follows descendants;PROCESS_TREE_LIFECYCLE: wait/stop cover descendants even after session or process-group escape;FS_ACCESS_RULES: READ and WRITE rule lowering;FS_DENY_READ: explicit DENY lowering where DENY wins over every allow;FS_VIEW_MAPPINGandFS_TMPFS: view construction;NETWORK_NONE: no ambient external network path;NETWORK_IP_NONE: no ambient IP path; pathname-addressed Unix sockets deliberately exposed by a filesystem mapping may remain reachable;NETWORK_EXTERNAL_CHANNEL: ambient networking is denied and the borrowed Unix datagram channel frommaelys_execution_request_external_channel_fd()is inherited as child fd 4;NETWORK_MEDIATED_PROXY: the backend admits only the execution-scoped proxy endpoint supplied by the request and prevents workload-created sockets from reaching another host channel. Bubblewrap realizes this with an internal loopback relay in a fresh network namespace; Seatbelt lowers the endpoint to one exact loopback-port rule. The capability does not imply that the backend authenticates or evaluates destinations: those guarantees belong to Egress;FS_PROTECT_CREATE: an absent denied path cannot be created.
Never advertise a capability merely because a primitive exists. Selection is fail-closed, but prepare may still reject an individual plan that cannot be represented safely on the current host.
The exact built-in masks and the additional per-plan restrictions are listed
in backend-capabilities.md. In particular,
apple-container and apple-container-bubblewrap accept OCI targets only;
the latter advertises recursive READ/WRITE rules but deliberately omits DENY,
PROTECT_CREATE and an inner syscall filter.
Filesystem semantics
READ grants read. WRITE grants read and write. Allow rules are additive; DENY subtracts both read and write and always wins, independent of insertion order. LITERAL matches one vnode; RECURSIVE matches the path and descendants.
MISSING_ERROR rejects an absent path. MISSING_SKIP omits it.
MISSING_PROTECT_CREATE is valid only for DENY and requires a separate backend
capability. No built-in backend currently advertises that capability.
The canonical plan sort is for hashing and deterministic compilation. It never defines authorization precedence.
Returned descriptors
Every active stream descriptor returned by spawn is blocking, close-on-exec
and distinct from every other returned descriptor; inactive entries are -1.
The protocol stream is a SOCK_STREAM socket. It has SO_NOSIGPIPE on systems
that provide the option; other systems must be compatible with a
MSG_NOSIGNAL write path. The core validates these properties before exposing
an instance. An invalid instance is forcibly stopped and boundedly waited; a
cleanup failure is reported as a containment failure, never hidden behind a
layout diagnostic.
For NETWORK_EXTERNAL_CHANNEL, prepare must duplicate the borrowed request
fd into its immutable artifact and spawn must map it to
MAELYS_EXECUTOR_EXTERNAL_CHANNEL_FD (4). The fd is blocking, close-on-exec,
connected AF_UNIX/SOCK_DGRAM; it is not an ambient network capability. The
backend must prevent ordinary network creation while preserving fd 4.
Launcher acceptance
For direct POSIX execution, a successful spawn means the target image was
accepted by posix_spawn. For wrapper backends such as Bubblewrap and
sandbox-exec, it means the trusted launcher image was accepted; a later
launcher setup or target-exec error is observed through wait and diagnostics.
spawn_timeout_ms is retained for remote/helper backends but is not a hard
interruptible deadline for the local posix_spawn substrate in 0.18.0.
Local process backends own their child wait status. Embedders must not install
SA_NOCLDWAIT or reap Executor children from an application-wide SIGCHLD
handler; doing so makes the backend return an explicit wait error.