#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../logger.h" #include "../utils.h" #include "../random.h" #include "sandbox-linux.h" /* TODO: make a whitelist approach. So far we simply blacklist * obvious systemcalls. To whitelist, we need to analyse our * dependencies (http library, sqlite wrapper, sqlite lib etc.) */ bool SandboxLinux::enableForInit() { umask(0027); struct qssb_policy policy = {0}; int blacklisted_syscalls[] = {QSSB_SYS(execveat), QSSB_SYS(execve), -1}; policy.blacklisted_syscalls = blacklisted_syscalls; policy.no_new_privs = 1; int result = qssb_enable_policy(&policy); if(result != 0) { Logger::error() << "Failed to install sandboxing policy (init): " << result; return false; } return true; } bool SandboxLinux::enablePreWorker(std::vector fsPaths) { std::sort(fsPaths.begin(), fsPaths.end(), [](const std::string &a, const std::string &b) { return a.length() < b.length(); }); struct qssb_path_policy *policies = new qssb_path_policy[fsPaths.size()]; for(unsigned int i = 0; i < fsPaths.size(); i++) { policies[i].next = policies + (i + 1); policies[i].mountpoint = fsPaths[i].c_str(); policies[i].policy = QSSB_MOUNT_ALLOW_READ | QSSB_MOUNT_ALLOW_WRITE; } policies[fsPaths.size() - 1].next = NULL; struct qssb_policy policy = {0}; policy.path_policies = policies; policy.namespace_options |= QSSB_UNSHARE_MOUNT; policy.namespace_options |= QSSB_UNSHARE_USER; int blacklisted_syscalls[] = {QSSB_SYS(execveat), QSSB_SYS(execve), -1}; policy.blacklisted_syscalls = blacklisted_syscalls; int result = qssb_enable_policy(&policy); if(result != 0) { Logger::error() << "Failed to install sandboxing policy (preworker): %i" << result; return false; } delete[] policies; return true; } bool SandboxLinux::supported() { std::fstream stream; stream.open("/proc/sys/kernel/unprivileged_userns_clone"); if(stream.is_open()) { std::string str; stream >> str; if(str[0] == '0') { Logger::error() << "Please write '1' to /proc/sys/kernel/unprivileged_userns_clone in order to enable " "sandboxing support on this system"; return false; } } return true; } bool SandboxLinux::enableForWorker() { struct qssb_policy policy = {0}; policy.drop_caps = 1; policy.not_dumpable = 1; policy.no_new_privs = 1; /* TODO: as said, a whitelist approach is better. As such, this list is bound to be incomplete in the * sense that more could be listed here and some critical ones are probably missing */ int blacklisted_syscalls[] = {QSSB_SYS(setuid), QSSB_SYS(connect), QSSB_SYS(chroot), QSSB_SYS(pivot_root), QSSB_SYS(mount), QSSB_SYS(setns), QSSB_SYS(unshare), QSSB_SYS(ptrace), QSSB_SYS(personality), QSSB_SYS(prctl), -1}; policy.blacklisted_syscalls = blacklisted_syscalls; if(qssb_enable_policy(&policy) != 0) { Logger::error() << "Sandbox: Activation of seccomp blacklist failed!"; return false; } return true; }