mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-12-22 19:30:05 +00:00
Proof-of-concept, default-permit seccomp-bpf sandbox
Can be disabled by adding -DCONFIG_NOSANDBOX to CXXFLAGS.
This commit is contained in:
parent
05d6174351
commit
3c1e08372d
2
Makefile
2
Makefile
@ -48,6 +48,7 @@ CXXSRC=\
|
||||
src/db/shard.cpp\
|
||||
src/db/player.cpp\
|
||||
src/db/email.cpp\
|
||||
src/sandbox/seccomp.cpp\
|
||||
src/Chat.cpp\
|
||||
src/CustomCommands.cpp\
|
||||
src/Entities.cpp\
|
||||
@ -88,6 +89,7 @@ CXXHDR=\
|
||||
src/servers/Monitor.hpp\
|
||||
src/db/Database.hpp\
|
||||
src/db/internal.hpp\
|
||||
src/sandbox/Sandbox.hpp\
|
||||
vendor/bcrypt/BCrypt.hpp\
|
||||
vendor/INIReader.hpp\
|
||||
vendor/JSON.hpp\
|
||||
|
@ -5,6 +5,9 @@
|
||||
# 3 = print all packets
|
||||
verbosity=1
|
||||
|
||||
# sandbox the process on supported platforms
|
||||
sandbox=true
|
||||
|
||||
# Login Server configuration
|
||||
[login]
|
||||
# must be kept in sync with loginInfo.php
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "Rand.hpp"
|
||||
|
||||
#include "settings.hpp"
|
||||
#include "sandbox/Sandbox.hpp"
|
||||
|
||||
#include "../version.h"
|
||||
|
||||
@ -94,11 +95,13 @@ int main() {
|
||||
#else
|
||||
initsignals();
|
||||
#endif
|
||||
Rand::init(getTime());
|
||||
settings::init();
|
||||
|
||||
std::cout << "[INFO] OpenFusion v" GIT_VERSION << std::endl;
|
||||
std::cout << "[INFO] Protocol version: " << PROTOCOL_VERSION << std::endl;
|
||||
std::cout << "[INFO] Intializing Packet Managers..." << std::endl;
|
||||
|
||||
Rand::init(getTime());
|
||||
TableData::init();
|
||||
PlayerManager::init();
|
||||
PlayerMovement::init();
|
||||
@ -138,6 +141,8 @@ int main() {
|
||||
|
||||
shardThread = new std::thread(startShard, (CNShardServer*)shardServer);
|
||||
|
||||
sandbox_start();
|
||||
|
||||
loginServer.start();
|
||||
|
||||
shardServer->kill();
|
||||
@ -152,7 +157,7 @@ int main() {
|
||||
// helper functions
|
||||
|
||||
std::string U16toU8(char16_t* src, size_t max) {
|
||||
src[max-1] = '\0'; // force a NULL terminatorstd::string U16toU8(char16_t* src) {
|
||||
src[max-1] = '\0'; // force a NULL terminator
|
||||
try {
|
||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
|
||||
std::string ret = convert.to_bytes(src);
|
||||
|
21
src/sandbox/Sandbox.hpp
Normal file
21
src/sandbox/Sandbox.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
// use the sandbox on supported platforms, unless disabled
|
||||
#if defined(__linux__) || defined(__OpenBSD__)
|
||||
|
||||
# if !defined(CONFIG_NOSANDBOX)
|
||||
void sandbox_start();
|
||||
# else
|
||||
|
||||
#include <iostream>
|
||||
|
||||
inline void sandbox_start() {
|
||||
std::cout << "[WARN] Built without a sandbox" << std::endl;
|
||||
}
|
||||
|
||||
# endif // CONFIG_NOSANDBOX
|
||||
|
||||
#else
|
||||
// stub for unsupported platforms
|
||||
inline void sandbox_start() {}
|
||||
#endif
|
102
src/sandbox/seccomp.cpp
Normal file
102
src/sandbox/seccomp.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#if defined(__linux__) && !defined(CONFIG_NOSANDBOX)
|
||||
|
||||
#include "core/Core.hpp" // mostly for ARRLEN
|
||||
#include "settings.hpp"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/ptrace.h>
|
||||
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/seccomp.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/audit.h>
|
||||
|
||||
// our own wrapper for the seccomp() syscall
|
||||
// TODO: should this be conditional on a feature check or something?
|
||||
static inline int seccomp(unsigned int operation, unsigned int flags, void *args) {
|
||||
return syscall(__NR_seccomp, operation, flags, args);
|
||||
}
|
||||
|
||||
/*
|
||||
* Macros borrowed from from https://outflux.net/teach-seccomp/
|
||||
* Relevant license:
|
||||
* https://source.chromium.org/chromium/chromium/src/+/master:LICENSE
|
||||
*/
|
||||
#define syscall_nr (offsetof(struct seccomp_data, nr))
|
||||
#define arch_nr (offsetof(struct seccomp_data, arch))
|
||||
|
||||
#if defined(__i386__)
|
||||
# define ARCH_NR AUDIT_ARCH_I386
|
||||
#elif defined(__x86_64__)
|
||||
# define ARCH_NR AUDIT_ARCH_X86_64
|
||||
#elif defined(__arm__)
|
||||
# define ARCH_NR AUDIT_ARCH_ARM
|
||||
#else
|
||||
# error "Seccomp-bpf sandbox unsupported on this architecture"
|
||||
#endif
|
||||
|
||||
#define VALIDATE_ARCHITECTURE \
|
||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, arch_nr), \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
|
||||
|
||||
#define EXAMINE_SYSCALL \
|
||||
BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr)
|
||||
|
||||
#define ALLOW_SYSCALL(name) \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
|
||||
|
||||
#define KILL_PROCESS \
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
|
||||
|
||||
#define DENY_SYSCALL(name) \
|
||||
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL_PROCESS)
|
||||
|
||||
static sock_filter filter[] = {
|
||||
VALIDATE_ARCHITECTURE,
|
||||
EXAMINE_SYSCALL,
|
||||
|
||||
// examples of undesirable syscalls
|
||||
DENY_SYSCALL(execve),
|
||||
DENY_SYSCALL(fork),
|
||||
DENY_SYSCALL(vfork),
|
||||
DENY_SYSCALL(clone),
|
||||
DENY_SYSCALL(connect),
|
||||
DENY_SYSCALL(listen),
|
||||
DENY_SYSCALL(bind),
|
||||
DENY_SYSCALL(kill),
|
||||
DENY_SYSCALL(settimeofday),
|
||||
// etc
|
||||
|
||||
// default-permit mode
|
||||
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
|
||||
};
|
||||
|
||||
static sock_fprog prog = {
|
||||
ARRLEN(filter), filter
|
||||
};
|
||||
|
||||
void sandbox_start() {
|
||||
if (!settings::SANDBOX) {
|
||||
std::cout << "[WARN] Running without a sandbox" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cout << "[INFO] Starting seccomp-bpf sandbox..." << std::endl;
|
||||
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
|
||||
perror("prctl");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, &prog) < 0) {
|
||||
perror("seccomp");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SANDBOX_SECCOMP
|
@ -7,6 +7,7 @@
|
||||
|
||||
// defaults :)
|
||||
int settings::VERBOSITY = 1;
|
||||
bool settings::SANDBOX = true;
|
||||
|
||||
int settings::LOGINPORT = 23000;
|
||||
bool settings::APPROVEALLNAMES = true;
|
||||
@ -77,6 +78,7 @@ void settings::init() {
|
||||
|
||||
APPROVEALLNAMES = reader.GetBoolean("", "acceptallcustomnames", APPROVEALLNAMES);
|
||||
VERBOSITY = reader.GetInteger("", "verbosity", VERBOSITY);
|
||||
SANDBOX = reader.GetBoolean("", "sandbox", SANDBOX);
|
||||
LOGINPORT = reader.GetInteger("login", "port", LOGINPORT);
|
||||
SHARDPORT = reader.GetInteger("shard", "port", SHARDPORT);
|
||||
DBSAVEINTERVAL = reader.GetInteger("login", "dbsaveinterval", DBSAVEINTERVAL);
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace settings {
|
||||
extern int VERBOSITY;
|
||||
extern bool SANDBOX;
|
||||
extern int LOGINPORT;
|
||||
extern bool APPROVEALLNAMES;
|
||||
extern int DBSAVEINTERVAL;
|
||||
|
Loading…
Reference in New Issue
Block a user