diff options
| author | Riley Beckett <rbeckettvt@gmail.com> | 2026-07-27 01:01:18 -0400 |
|---|---|---|
| committer | Riley Beckett <rbeckettvt@gmail.com> | 2026-07-27 01:01:18 -0400 |
| commit | 7eb17df0a722c251f0697821b20450e1478142f3 (patch) | |
| tree | 6da85851403f2b9f487e53f1d0db7926ab9c6196 /snag/src/sandboxing.c | |
| parent | 3f50d3c69750e059939c10b44755d329be65a47e (diff) | |
add some sandboxing code
Diffstat (limited to 'snag/src/sandboxing.c')
| -rw-r--r-- | snag/src/sandboxing.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/snag/src/sandboxing.c b/snag/src/sandboxing.c new file mode 100644 index 0000000..5edc6ce --- /dev/null +++ b/snag/src/sandboxing.c @@ -0,0 +1,101 @@ +#define _GNU_SOURCE +#include "landlock_signatures.h" +#include "util.h" +#include "sandboxing.h" +#include <errno.h> +#include <fcntl.h> +#include <string.h> +#include <sys/prctl.h> +#include <linux/prctl.h> + +int create_new_landlock_ruleset(struct landlock_ruleset_attr* ruleset_attr) { + + int abi = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION); + print("landlock abi version: %d\n", abi); + if (abi < 0) { + /* Degrades gracefully if Landlock is not handled. */ + print("landlock is not enabled, sandboxing will not work\n"); + return -1; + } + switch (abi) { + case 1: + /* Removes LANDLOCK_ACCESS_FS_REFER for ABI < 2 */ + ruleset_attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER; + case 2: + /* Removes LANDLOCK_ACCESS_FS_TRUNCATE for ABI < 3 */ + ruleset_attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_TRUNCATE; + case 3: + /* Removes network support for ABI < 4 */ + ruleset_attr->handled_access_net &= + ~(LANDLOCK_ACCESS_NET_BIND_TCP | + LANDLOCK_ACCESS_NET_CONNECT_TCP); + case 4: + /* Removes LANDLOCK_ACCESS_FS_IOCTL_DEV for ABI < 5 */ + ruleset_attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV; + case 5: + /* Removes LANDLOCK_SCOPE_* for ABI < 6 */ + ruleset_attr->scoped &= ~(LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET | + LANDLOCK_SCOPE_SIGNAL); + case 6 ... 8: + /* Removes LANDLOCK_ACCESS_FS_RESOLVE_UNIX for ABI < 9 */ + ruleset_attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_RESOLVE_UNIX; + } + + int ruleset_fd = landlock_create_ruleset(ruleset_attr, sizeof(*ruleset_attr), 0); + if (ruleset_fd < 0) { + print("Failed to create landlock ruleset: %s", strerror(errno)); + return -1; + } + return ruleset_fd; +} + +bool landlock_add_path_rule(int landlock_fd, const struct landlock_ruleset_attr* ruleset_attr, const char* path, struct landlock_path_beneath_attr* path_beneath) { + path_beneath->allowed_access &= ruleset_attr->handled_access_fs; + if (path_beneath->allowed_access) { + path_beneath->parent_fd = open(path, O_PATH | O_CLOEXEC); + if (path_beneath->parent_fd < 0) { + print("Failed to open file %s: %s\n", path, strerror(errno)); + return false; + } + int err = landlock_add_rule(landlock_fd, LANDLOCK_RULE_PATH_BENEATH, path_beneath, 0); + close(path_beneath->parent_fd); + if (err) { + print("Failed to update ruleset: %s\n", strerror(errno)); + return false; + } + } + return true; +} + +bool landlock_enforce(int landlock_fd) { + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { + print("Failed to restrict privileges: %s\n", strerror(errno)); + return false; + } + uint32_t restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON | LANDLOCK_RESTRICT_SELF_TSYNC; + int abi = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION); + switch (abi) { + case 1 ... 6: + /* Removes logging flags for ABI < 7 */ + restrict_flags &= ~(LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF | + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON | + LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF); + case 7: + /* + * Removes multithreaded enforcement flag for ABI < 8 + * + * WARNING: Without this flag, calling landlock_restrict_self(2) is + * only equivalent if the calling process is single-threaded. Below + * ABI v8 (and as of ABI v8, when not using this flag), a Landlock + * policy would only be enforced for the calling thread and its + * children (and not for all threads, including parents and siblings). + */ + restrict_flags &= ~LANDLOCK_RESTRICT_SELF_TSYNC; + } + + if (landlock_restrict_self(landlock_fd, restrict_flags)) { + print("Failed to enforce ruleset: %s\n", strerror(errno)); + return false; + } + close(landlock_fd); +} |
