#ifndef CST_SANDBOX_H #define CST_SANDBOX_H /* * OS sandbox for run_shell: reads and exec stay allowed everywhere, writes * are limited to the workspace, the temp dir, /dev/null and /dev/tty, and * the network is cut where the OS can do it. * Linux Landlock (network needs ABI 4, kernel 6.7+) * macOS sandbox_init (Seatbelt profile) * other none: callers fall back to rule-based approval */ #include "os_compat.h" #include #ifdef __cplusplus extern "C" { #endif typedef enum { CST_SANDBOX_NONE = 0, CST_SANDBOX_LANDLOCK, CST_SANDBOX_SEATBELT } cst_sandbox_kind_t; /* What this process can use; cached. CST_SANDBOX=0 forces NONE. */ int cst_sandbox_probe(void); const char *cst_sandbox_name(int kind); /* "landlock" | "seatbelt" | "none" */ /* Landlock ABI version (0 when unavailable); ≥4 also blocks TCP. */ int cst_sandbox_landlock_abi(void); typedef struct { int kind; int ruleset_fd; /* Landlock, built in the parent */ char *profile; /* Seatbelt */ } cst_sandbox_plan_t; /* Parent side: build the policy. Returns 0, or -1 (plan->kind = NONE). */ int cst_sandbox_prepare(const char *workspace, const char *tmpdir, cst_sandbox_plan_t *plan); /* Child side, after fork and before exec (os_run_capture_ex hook): * async-signal-safe for Landlock. Returns 0 when confined. */ int cst_sandbox_enter(void *plan); void cst_sandbox_release(cst_sandbox_plan_t *plan); /* `sh -c cmd` confined to workspace (+ temp dir). Fails closed: if the * policy cannot be applied the command does not run (exit 126). */ int cst_sandbox_run_shell(const char *workspace, const char *cmd, size_t max_out, os_run_result_t *r); /* Output of a failed sandboxed run that looks like the sandbox got in the * way (EACCES / EPERM / EROFS / blocked network). */ int cst_sandbox_blocked(const char *out, size_t n, int exit_code); #ifdef __cplusplus } #endif #endif