Skip to content

Feat/control socket introspection#153

Open
sachin2605 wants to merge 2 commits into
multikernel:mainfrom
bytehooks:feat/control-socket-introspection
Open

Feat/control socket introspection#153
sachin2605 wants to merge 2 commits into
multikernel:mainfrom
bytehooks:feat/control-socket-introspection

Conversation

@sachin2605

Copy link
Copy Markdown
Contributor

No description provided.

sachin2605 and others added 2 commits July 19, 2026 11:46
Add a per-sandbox Unix control socket under /dev/shm/sandlock-$UID/<name>/
that serves introspection requests.  Each sandbox gets a runtime directory
containing a `pid` file and a `control.sock` Unix socket.

CLI changes:
- `sandlock list` → `sandlock ps` (NAME/PID/UPTIME/CMD columns via /proc)
- `sandlock config <name>` queries the control socket for effective policy
  (JSON or --toml output)
- `sandlock kill <name>` reads pid from the per-sandbox pid file
- Removed network_registry.rs and all network.json references
- Removed --name incompatibility with --no-supervisor

Core changes:
- New `control` module: runtime dir helpers, control loop (tokio task),
  wire protocol (4-byte BE length + JSON, v:1, verb:config), SO_PEERCRED
  audit, stale-dir pruning via kill(pid,0) liveness check
- `profile.rs`: added Serialize to all section structs; added reverse
  serializer (sandbox_to_profile, sandbox_to_toml, sandbox_to_json,
  format_net_rule, format_http_rule, bind_ports_to_specs, time_start_str)
- `seccomp/state.rs`: added DeniedSet::denied_paths() accessor
- `sandbox.rs`: Runtime gains control_handle + control_dir fields; control
  socket setup in do_create_stdio (supervisor path) + pid-file-only for
  no_supervisor; control loop spawned after notif startup; cleanup in
  wait() and Drop

Wire protocol: 4-byte big-endian length prefix + UTF-8 JSON.
Request: {"v":1,"verb":"config","args":{}}
Response: {"v":1,"ok":true,"data":{...ProfileInput...}}

🤖 Generated with [Pochi](https://getpochi.com) | [Task](multikernel#68)

Co-Authored-By: Pochi <noreply@getpochi.com>
Add 10 integration tests in sandlock-core exercising the control socket
wire protocol (list, config, prune stale dirs, serializer round-trips).
Add 8 CLI integration tests for ps, config, kill, and help commands.
Make control socket setup best-effort (warn instead of fail) so nested
sandboxes where /dev/shm is restricted by outer landlock still work.

Update README.md: replace `sandlock list` with `sandlock ps`, add
`sandlock config` examples, update port virtualization section.

🤖 Generated with [Pochi](https://getpochi.com) | [Task](multikernel#68)

Co-Authored-By: Pochi <noreply@getpochi.com>
@congwang-mk

congwang-mk commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Thanks for the PR!

Just design-level review. Layering looks right: control.rs holding the dir helpers, server loop, and client helper means the CLI has no duplicated wire logic. Dedicated tokio task instead of folding accept() into the notify loop is the correct answer to RFC open question 2. Snapshot + read-dynamic-denies-at-request-time correctly avoids the stale-file problem the RFC calls out.

Five things worth resolving before merge:

1. pid file and socket refer to different processes. setup_runtime_dir(name, pid) gets the forked child pid, but the socket is served by the supervisor. ps liveness, kill, UPTIME, and CMD all key off the child; config keys off the supervisor. If the supervisor dies while the child lives, the sandbox still lists but config fails with a raw connect error. Write both pids, or pick one and document which.

2. Name collision silently destroys a live sandbox. setup_runtime_dir does an unconditional remove_dir_all. Two sandboxes named web: the second wipes the first's pid file and socket, the first disappears from ps, kill web hits the second, and the second's Drop removes the dir while the first is still running. Needs a liveness check and a hard error on collision.

3. Pruning races startup. list_live_sandboxes deletes any dir without a parseable pid file. setup_runtime_dir creates the dir, then writes pid, then binds. A concurrent sandlock ps in that window deletes the runtime dir of a sandbox that is coming up fine. Fix with temp+rename for the pid file, or only prune dirs past a minimum age.

4. The 64 KB cap is client-side only. send_control_request rejects responses over 65536 bytes; the server never caps what it writes. A policy with many fs rules produces a config that is sent successfully and cannot be read. Cap both ends or neither.

5. No opt-out. Every Sandbox, including embedded users who never asked for introspection, now creates a /dev/shm dir and a tokio task, with best-effort failures going to stderr. Worth a builder knob, particularly for nested-sandbox and library contexts where that warning is pure noise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants