Skip to content

Go support: a CLI wrapper library, or just usage docs/examples? #76

@solarhell

Description

@solarhell

Context

I'd like to help Go users adopt sandlock and want to check the maintainers'
preference before opening a PR.

From reading the tree, the binding surface is the C ABI (libsandlock_ffi.so,
crate-type = ["cdylib", ...]), and the Python SDK is a ctypes layer over it.
A Go SDK would naturally be cgo over the same .so.

The question

For the common case — "run an untrusted command under a policy" — Go users
are already well served by shelling out to the sandlock CLI via os/exec
(idiomatic in Go, no cgo, trivial cross-compile). A thin Go wrapper around the
CLI would add type-safe config, --status-fd exit/signal handling, and
context.Context timeouts — but it's convenience, not new capability.

So I'm unsure which is actually wanted:

  1. A small pure-Go wrapper library (exec-based, no cgo) — ergonomic typed
    API mapping to CLI flags, captures stdout/stderr, parses --status-fd.
  2. Just Go usage docs + examples showing how to drive the CLI from
    os/exec directly — lowest maintenance, may be all Go users need.
  3. A real cgo/FFI SDK — only this can expose what the CLI fundamentally
    cannot (see below).

Where the CLI is genuinely not enough

The capability that would justify an SDK (vs. exec'ing the CLI) is in-process
/ dynamic control that the CLI doesn't expose. Concrete example —
command-level allow/deny (e.g. allow ls/cat, deny curl):

  • Via CLI you can only do path-level control through Landlock FS execute
    permission (LANDLOCK_ACCESS_FS_EXECUTE) — i.e. only grant read/exec on the
    binaries you want runnable.
  • argv-level decisions ("allow this command, deny that one, inspect
    arguments") require intercepting execve in policy_fn (TOCTOU-safe argv
    freeze), which is FFI-only — there's no CLI flag for it.

Other FFI-only powers in the same bucket: confine() (apply Landlock to the
current process in-place), run_with_handlers, checkpoint/fork/gather.

So: an exec wrapper covers ~90% of cases cheaply; the remaining 10% is exactly
the part that needs cgo.

What I'm proposing

I'm happy to implement (1) or (2) — whichever you prefer — and add a Go CI job
(needs: rust, builds the CLI, runs go test on ubuntu). I'd lean toward (2)
or a minimal (1), keeping (3) as a possible follow-up if there's demand for the
dynamic features.

Questions for maintainers:

  • Which of 1/2/3 fits the project's direction?
  • If a library: module path github.com/multikernel/sandlock/go (subdir +
    go/vX.Y.Z tags), or a separate sandlock-go repo?

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions