Skip to content

feat(seccomp): ExtraHandler — user-supplied syscall handlers#20

Open
dzerik wants to merge 1 commit intomultikernel:mainfrom
dzerik:feature/extra-handlers
Open

feat(seccomp): ExtraHandler — user-supplied syscall handlers#20
dzerik wants to merge 1 commit intomultikernel:mainfrom
dzerik:feature/extra-handlers

Conversation

@dzerik
Copy link
Copy Markdown

@dzerik dzerik commented Apr 24, 2026

Summary

Adds a public extension point for downstream crates that need to register their own seccomp-notification handlers alongside sandlock's builtin chroot/cow/procfs/network/port_remap logic.

Motivation. Downstream crates that want to intercept additional syscalls in the same supervisor task as sandlock's builtins have no clean way to do it today — one SECCOMP_FILTER_FLAG_NEW_LISTENER per process means a single listener, so a second supervisor cannot run alongside. The only alternative is forking sandlock or patching notif::supervisor wholesale.

API.

  • New type dispatch::ExtraHandler { syscall_nr, handler }.
  • New entry Sandbox::run_with_extra_handlers(policy, cmd, extras).
  • Existing Sandbox::run() delegates to it with empty extras — zero behaviour change for current callers.

Ordering contract (documented + tested).

  • Builtins register first (chroot path normalization, COW, procfs, …).
  • Extras appended last, in the Vec order.
  • Chain stops at first non-Continue — user handlers cannot subvert builtin confinement.

Docs.

  • docs/extension-handlers.md: design rationale, security boundary, panics policy, non-goals, downstream sketch.
  • crates/sandlock-core/examples/openat_audit.rs: runnable example.

Minor bump 0.6 → 0.7 suggested.

Test plan

  • 4 new unit tests in dispatch::extra_handler_tests (ctor, insertion order, append-after-builtin, empty-extras nop) — passing
  • All 215 unit tests pass
  • Example openat_audit.rs runs against a python3 -c guest

Adds a public extension point for downstream crates that need to
register their own seccomp-notification handlers alongside sandlock's
builtin chroot/cow/procfs/network/port_remap logic.

Motivation: downstream crates that want to intercept additional
syscalls in the same supervisor task as sandlock's builtins have no
clean way to do it today — one SECCOMP_FILTER_FLAG_NEW_LISTENER per
process means a single listener, so a second supervisor cannot run
alongside.  The only alternative is forking sandlock or patching
notif::supervisor wholesale.

API:
- New type dispatch::ExtraHandler { syscall_nr, handler }.
- New entry Sandbox::run_with_extra_handlers(policy, cmd, extras).
- Existing Sandbox::run() delegates to it with empty extras — zero
  behaviour change for current callers.

Ordering contract (documented + tested):
- Builtins register first (chroot path normalization, COW, procfs, …).
- Extras appended last, in the Vec order.
- Chain stops at first non-Continue — user handlers cannot subvert
  builtin confinement.

Internals:
- build_dispatch_table now takes Vec<ExtraHandler> and drains it into
  register() calls after builtins.
- notif::supervisor signature extended to accept extras and pass them
  through.  sandbox.rs moves self.extra_handlers via std::mem::take
  on spawn (HandlerFn is Box<dyn Fn> — not Clone).

Docs:
- docs/extension-handlers.md: design rationale, security boundary,
  panics policy, non-goals, downstream sketch.
- crates/sandlock-core/examples/openat_audit.rs: runnable example.

Tests:
- 4 unit tests on dispatch::extra_handler_tests (ctor, insertion
  order, append-after-builtin, empty-extras nop).  All 215 unit
  tests pass.

Minor bump 0.6 → 0.7 suggested.

Signed-off-by: dzerik <dzerik@gmail.com>
@dzerik dzerik force-pushed the feature/extra-handlers branch from 5f2b730 to 71c5724 Compare April 24, 2026 14:00
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.

1 participant