docs: reframe x/elevate as sandbox escape hatch, not privilege escalation
The purpose is to run steps outside the Landlock sandbox, not to gain privileges. Clarify the constraint (kernel-enforced, must reach an external process), reframe the minimal example and superpowerd walkthrough accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2eefe5a01d
commit
1de43c1105
|
|
@ -208,8 +208,11 @@ Outputs to stdout, making it composable with other pipeline stages.
|
|||
|
||||
## x/elevate
|
||||
|
||||
Elevation plugin invoked by `execute_code` when a step is marked `elevated: true`.
|
||||
Runs the command outside the sandbox and returns its output.
|
||||
Sandbox escape hatch invoked by `execute_code` when a step is marked `elevated: true`.
|
||||
The Landlock sandbox is enforced at the kernel level — certain operations (filesystem
|
||||
paths outside the sandbox config, specific syscalls) are simply blocked regardless of
|
||||
what the code does. `x/elevate` provides a controlled way to run those steps outside
|
||||
the sandbox entirely, without changing user privileges.
|
||||
|
||||
### Interface
|
||||
|
||||
|
|
@ -225,38 +228,45 @@ script must:
|
|||
- Write combined stdout/stderr to its own stdout
|
||||
- Exit with the command's exit code (non-zero is treated as failure)
|
||||
|
||||
That's the entire contract. Any script that satisfies it is a valid elevation backend.
|
||||
That's the entire contract. Any script that satisfies it is a valid backend.
|
||||
|
||||
The plugin is looked up in `OLLIE_PLUGINS_PATH` (first colon-separated entry) if set,
|
||||
otherwise in `~/.config/ollie/scripts/x/`. Override via env to use a different location
|
||||
without modifying the installed scripts.
|
||||
|
||||
### The constraint
|
||||
|
||||
Because Landlock is kernel-enforced, the backend cannot simply exec the command inside
|
||||
the sandboxed process — the restrictions apply regardless. The command must reach a
|
||||
process that was spawned outside of landrun entirely. The only viable pattern is to
|
||||
forward the command to an external daemon over a socket or pipe, where that daemon runs
|
||||
in an unsandboxed context and sends the result back.
|
||||
|
||||
### Minimal example
|
||||
|
||||
The simplest possible backend — unsandboxed exec, no privilege escalation:
|
||||
The simplest possible backend — direct exec, no sandbox. Suitable for development or
|
||||
environments where the sandbox itself is not in use:
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
# x/elevate: run command outside the sandbox with no additional privileges.
|
||||
# x/elevate: run command outside the sandbox (no landrun in this environment).
|
||||
shift # drop the '--'
|
||||
exec sh -c "$1"
|
||||
```
|
||||
|
||||
This is useful for development or environments where the sandbox is the only
|
||||
restriction that needs lifting.
|
||||
|
||||
### superpowerd example
|
||||
|
||||
The default `x/elevate` uses superpowerd as the elevation backend. superpowerd is a
|
||||
hypothetical privilege broker: it holds a session token,
|
||||
receives `ExecuteCommand` requests over a Unix socket, and runs them with the
|
||||
permissions granted to the session.
|
||||
The default `x/elevate` uses superpowerd as its backend. superpowerd is a hypothetical
|
||||
external command broker: a daemon running outside any sandbox that receives
|
||||
`ExecuteCommand` requests over a Unix socket, runs them, and returns the result. This
|
||||
satisfies the constraint above — the command executes in the daemon's process, which
|
||||
was never wrapped by landrun.
|
||||
|
||||
**How it works, step by step:**
|
||||
|
||||
1. If `SUPERPOWERD_SESSION_TOKEN` is not in the environment, the script re-execs itself
|
||||
under `superpowers run-session`, which acquires a token and re-runs the script inside
|
||||
a privileged session context:
|
||||
under `superpowers run-session`, which registers a session with the daemon and
|
||||
re-runs the script with the token set:
|
||||
|
||||
```python
|
||||
if "SUPERPOWERD_SESSION_TOKEN" not in os.environ:
|
||||
|
|
@ -288,21 +298,13 @@ permissions granted to the session.
|
|||
4. The response's `stdout`, `stderr`, and `exit_code` are forwarded back to
|
||||
`execute_code`.
|
||||
|
||||
|
||||
### Custom backends
|
||||
|
||||
Replace `~/.config/ollie/scripts/x/elevate` with any executable that satisfies the
|
||||
interface. The key constraint: the backend must run the command in a process that was
|
||||
spawned **outside** the landrun sandbox. Landlock restrictions are enforced at the
|
||||
kernel level — running `sudo` or `doas` inside a sandboxed process does not escape
|
||||
them. The only way out is to hand the command to a process that was never wrapped by
|
||||
landrun in the first place, which is exactly what superpowerd does via its Unix socket.
|
||||
|
||||
The superpowerd pattern (separate privileged daemon, commands sent over a socket) is
|
||||
the right model for any custom backend.
|
||||
Any daemon-and-socket design works. The daemon must be running outside landrun; the
|
||||
`x/elevate` script is the bridge between the sandboxed agent and that daemon.
|
||||
|
||||
**Disabling elevation:** replace `x/elevate` with a script that exits non-zero.
|
||||
Steps marked `elevated: true` will then fail rather than run unsandboxed:
|
||||
Steps marked `elevated: true` will fail rather than escape the sandbox:
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
|
|
|
|||
Loading…
Reference in New Issue