#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+) * Linux seccomp user-notify when Landlock is missing (Android/Termux, * older kernels): a supervisor thread checks the path of every * write-type syscall and IPv4/IPv6 sockets are refused. Guards * against mistakes, not hostile code (the path is checked before * the kernel reads it again). * 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_SECCOMP } cst_sandbox_kind_t; /* What this process can use; cached. CST_SANDBOX=off|0|none forces NONE, * CST_SANDBOX=landlock|seccomp allows only that kind. */ int cst_sandbox_probe(void); /* Drops the cache and probes again (tests that change CST_SANDBOX). */ int cst_sandbox_reprobe(void); /* "landlock" | "seatbelt" | "seccomp" | "none" */ const char *cst_sandbox_name(int kind); /* 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 */ void *sc; /* seccomp: filter program and supervisor thread */ } 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. 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