feat: tiny sandbox
This commit is contained in:
commit
228c7b653f
14
.clang-format
Normal file
14
.clang-format
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
|
||||
AlignConsecutiveAssignments: Consecutive
|
||||
AlignConsecutiveBitFields: AcrossEmptyLinesAndComments
|
||||
AlignConsecutiveDeclarations: Consecutive
|
||||
AlignEscapedNewlines: Left
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortIfStatementsOnASingleLine: true
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
ColumnLimit: 80
|
||||
IndentWidth: 4
|
||||
UseTab: Never
|
||||
SeparateDefinitionBlocks: Leave
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/cmake-build-*
|
||||
/build
|
||||
/libseccomp
|
||||
*.out
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
1
.idea/.name
Normal file
1
.idea/.name
Normal file
@ -0,0 +1 @@
|
||||
woj_sandbox
|
7
.idea/codeStyles/Project.xml
Normal file
7
.idea/codeStyles/Project.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<clangFormatSettings>
|
||||
<option name="ENABLED" value="true" />
|
||||
</clangFormatSettings>
|
||||
</code_scheme>
|
||||
</component>
|
5
.idea/codeStyles/codeStyleConfig.xml
Normal file
5
.idea/codeStyles/codeStyleConfig.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
10
.idea/misc.xml
Normal file
10
.idea/misc.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
||||
<component name="CidrRootsConfiguration">
|
||||
<excludeRoots>
|
||||
<file path="$PROJECT_DIR$/build" />
|
||||
<file path="$PROJECT_DIR$/libseccomp" />
|
||||
</excludeRoots>
|
||||
</component>
|
||||
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/woj-sandbox.iml" filepath="$PROJECT_DIR$/.idea/woj-sandbox.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
2
.idea/woj-sandbox.iml
Normal file
2
.idea/woj-sandbox.iml
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module classpath="CMake" type="CPP_MODULE" version="4" />
|
22
CMakeLists.txt
Normal file
22
CMakeLists.txt
Normal file
@ -0,0 +1,22 @@
|
||||
cmake_minimum_required(VERSION 3.23)
|
||||
project(woj_sandbox C)
|
||||
|
||||
set(CMAKE_C_STANDARD 23)
|
||||
|
||||
file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/*.c ${PROJECT_SOURCE_DIR}/rules/*.c ${PROJECT_SOURCE_DIR}/utils/*.c)
|
||||
list(FILTER SRC_FILES EXCLUDE REGEX ".*test\\.c$")
|
||||
|
||||
set(VERSION_SCRIPT ${PROJECT_SOURCE_DIR}/version_script.txt)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libseccomp/include)
|
||||
|
||||
add_library(woj_sandbox SHARED ${SRC_FILES})
|
||||
add_executable(woj_sandbox_test ${PROJECT_SOURCE_DIR}/test.c ${SRC_FILES})
|
||||
|
||||
target_link_libraries(woj_sandbox ${CMAKE_SOURCE_DIR}/libseccomp/src/.libs/libseccomp.a)
|
||||
target_link_libraries(woj_sandbox_test ${CMAKE_SOURCE_DIR}/libseccomp/src/.libs/libseccomp.a)
|
||||
|
||||
set_target_properties(woj_sandbox PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||
set_property(TARGET woj_sandbox APPEND_STRING
|
||||
PROPERTY LINK_FLAGS " -Wl,--version-script=${VERSION_SCRIPT}")
|
||||
set_target_properties(woj_sandbox PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
|
11
build_libseccomp.sh
Executable file
11
build_libseccomp.sh
Executable file
@ -0,0 +1,11 @@
|
||||
VERSION=v2.5.4
|
||||
if [ -d ./libseccomp ]; then exit 0; fi
|
||||
|
||||
set -x
|
||||
|
||||
git clone https://github.com/seccomp/libseccomp.git &>/dev/null
|
||||
cd libseccomp || exit 1
|
||||
git checkout $VERSION &>/dev/null
|
||||
./autogen.sh &>/dev/null
|
||||
./configure --enable-shared=no &>/dev/null
|
||||
make -j &>/dev/null
|
12
err.h
Normal file
12
err.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef WOJ_SANDBOX_ERR_H
|
||||
#define WOJ_SANDBOX_ERR_H
|
||||
|
||||
// Error Code
|
||||
#define ERR_SECCOMP_ENV 10
|
||||
#define ERR_SECCOMP_INIT 11
|
||||
#define ERR_SECCOMP_RESOLVE 12
|
||||
#define ERR_SECCOMP_LOAD 13
|
||||
#define ERR_UNSETENV 14
|
||||
#define ERR_NO_RULE_FOUND 15
|
||||
|
||||
#endif // WOJ_SANDBOX_ERR_H
|
9
library.c
Normal file
9
library.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include "rules/lang.h"
|
||||
#include "sandbox.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
static __attribute__((constructor)) void inject(void) {
|
||||
LOG_INFO("Setting up...");
|
||||
register_lang_c();
|
||||
setup_seccomp();
|
||||
}
|
6
rules/lang.h
Normal file
6
rules/lang.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef WOJ_SANDBOX_LANG_H
|
||||
#define WOJ_SANDBOX_LANG_H
|
||||
|
||||
void register_lang_c(void);
|
||||
|
||||
#endif // WOJ_SANDBOX_LANG_H
|
22
rules/lang_c.c
Normal file
22
rules/lang_c.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "../sandbox.h"
|
||||
#include "lang.h"
|
||||
#include "rules.h"
|
||||
|
||||
#include <seccomp.h>
|
||||
|
||||
void setup_lang_c(scmp_filter_ctx ctx) {
|
||||
int white[] = {SCMP_SYS(read), SCMP_SYS(write), SCMP_SYS(getpid),
|
||||
SCMP_SYS(futex), SCMP_SYS(exit_group), SCMP_SYS(newfstatat)};
|
||||
int white_len = sizeof(white) / sizeof(white[0]);
|
||||
|
||||
for (int i = 0; i < white_len; i++) {
|
||||
add_syscall_nr(white[i], ctx, SCMP_ACT_ALLOW);
|
||||
}
|
||||
}
|
||||
|
||||
struct rule lang_c_rule = {
|
||||
.name = "lang_c",
|
||||
.setup = setup_lang_c,
|
||||
};
|
||||
|
||||
void register_lang_c(void) { register_rule(&lang_c_rule); }
|
35
rules/rules.c
Normal file
35
rules/rules.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include "rules.h"
|
||||
#include "../err.h"
|
||||
#include "../utils/log.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
LIST_HEAD(seccomp_rules);
|
||||
|
||||
void register_rule(struct rule *rule) { list_add(&rule->list, &seccomp_rules); }
|
||||
|
||||
void setup_rule(char *name, scmp_filter_ctx ctx) {
|
||||
struct list_head *current;
|
||||
struct rule *rule;
|
||||
list_for_each(current, &seccomp_rules) {
|
||||
rule = list_entry(current, struct rule, list);
|
||||
if (strcmp(rule->name, name) == 0) {
|
||||
rule->setup(ctx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG_ERR("No rule found for %s", name);
|
||||
dump_rules();
|
||||
exit(ERR_NO_RULE_FOUND);
|
||||
}
|
||||
|
||||
void dump_rules(void) {
|
||||
struct list_head *current;
|
||||
struct rule *rule;
|
||||
LOG_INFO("Available Rules:");
|
||||
list_for_each(current, &seccomp_rules) {
|
||||
rule = list_entry(current, struct rule, list);
|
||||
LOG_INFO("> %s", rule->name);
|
||||
}
|
||||
}
|
18
rules/rules.h
Normal file
18
rules/rules.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef WOJ_SANDBOX_RULES_H
|
||||
#define WOJ_SANDBOX_RULES_H
|
||||
|
||||
#include "../utils/list.h"
|
||||
|
||||
#include "seccomp.h"
|
||||
|
||||
struct rule {
|
||||
char *name;
|
||||
void (*setup)(scmp_filter_ctx);
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
void register_rule(struct rule *rule);
|
||||
void setup_rule(char *name, scmp_filter_ctx ctx);
|
||||
void dump_rules(void);
|
||||
|
||||
#endif // WOJ_SANDBOX_RULES_H
|
78
sandbox.c
Normal file
78
sandbox.c
Normal file
@ -0,0 +1,78 @@
|
||||
#include "sandbox.h"
|
||||
#include "err.h"
|
||||
#include "rules/rules.h"
|
||||
#include "utils/log.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void add_syscall_nr(int syscall_nr, scmp_filter_ctx ctx, uint32_t action) {
|
||||
if (seccomp_rule_add_exact(ctx, action, syscall_nr, 0)) {
|
||||
LOG_ERR("Failed to add syscall %d", syscall_nr);
|
||||
seccomp_release(ctx);
|
||||
exit(ERR_SECCOMP_RESOLVE);
|
||||
}
|
||||
}
|
||||
|
||||
void add_syscall_name(const char *syscall_name, scmp_filter_ctx ctx,
|
||||
uint32_t action) {
|
||||
int syscall_nr = seccomp_syscall_resolve_name(syscall_name);
|
||||
if (syscall_nr == __NR_SCMP_ERROR) {
|
||||
LOG_ERR("Failed to resolve syscall %s", syscall_name);
|
||||
seccomp_release(ctx);
|
||||
exit(ERR_SECCOMP_RESOLVE);
|
||||
}
|
||||
|
||||
add_syscall_nr(syscall_nr, ctx, action);
|
||||
}
|
||||
|
||||
void setup_seccomp(void) {
|
||||
LOG_INFO("Setting seccomp rules...");
|
||||
|
||||
char *template = getenv(SANDBOX_TEMPLATE);
|
||||
char *action = getenv(SANDBOX_ACTION);
|
||||
|
||||
bool kill = true;
|
||||
if (action && strncmp(action, "log", sizeof("log")) == 0) {
|
||||
kill = false;
|
||||
}
|
||||
|
||||
if (kill && !template) {
|
||||
LOG_ERR("Environment variable %s required", SANDBOX_TEMPLATE);
|
||||
dump_rules();
|
||||
exit(ERR_SECCOMP_ENV);
|
||||
}
|
||||
|
||||
scmp_filter_ctx ctx =
|
||||
seccomp_init(kill ? SCMP_ACT_KILL_PROCESS : SCMP_ACT_LOG);
|
||||
if (!ctx) {
|
||||
LOG_ERR("Failed to init seccomp context");
|
||||
exit(ERR_SECCOMP_INIT);
|
||||
}
|
||||
|
||||
setup_rule(template, ctx);
|
||||
|
||||
#define UNSETENV(name) \
|
||||
do { \
|
||||
if (unsetenv(name)) { \
|
||||
LOG_ERR("Failed to unset environment variable %s", name); \
|
||||
seccomp_release(ctx); \
|
||||
exit(ERR_UNSETENV); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
UNSETENV(SANDBOX_TEMPLATE);
|
||||
UNSETENV(SANDBOX_ACTION);
|
||||
|
||||
#undef UNSETENV
|
||||
|
||||
if (seccomp_load(ctx)) {
|
||||
LOG_ERR("Failed to load seccomp context");
|
||||
seccomp_release(ctx);
|
||||
exit(ERR_SECCOMP_LOAD);
|
||||
}
|
||||
seccomp_release(ctx);
|
||||
|
||||
LOG_INFO("Preload Done");
|
||||
}
|
16
sandbox.h
Normal file
16
sandbox.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef WOJ_SANDBOX_SANDBOX_H
|
||||
#define WOJ_SANDBOX_SANDBOX_H
|
||||
|
||||
#include <seccomp.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Configuration Environment Variables
|
||||
#define SANDBOX_TEMPLATE "SANDBOX_TEMPLATE"
|
||||
#define SANDBOX_ACTION "SANDBOX_ACTION"
|
||||
|
||||
void setup_seccomp(void);
|
||||
void add_syscall_name(const char *syscall_name, scmp_filter_ctx ctx,
|
||||
uint32_t action);
|
||||
void add_syscall_nr(int syscall_nr, scmp_filter_ctx ctx, uint32_t action);
|
||||
|
||||
#endif // WOJ_SANDBOX_SANDBOX_H
|
9
test.c
Normal file
9
test.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include "utils/log.h"
|
||||
|
||||
int main() {
|
||||
char buf[128];
|
||||
scanf("%s", buf);
|
||||
printf("Hello %s\n", buf);
|
||||
|
||||
return 0;
|
||||
}
|
21
utils/list.h
Normal file
21
utils/list.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef WOJ_SANDBOX_LIST_H
|
||||
#define WOJ_SANDBOX_LIST_H
|
||||
|
||||
struct list_head {
|
||||
struct list_head *next;
|
||||
};
|
||||
|
||||
#define LIST_HEAD(name) struct list_head name = {&(name)};
|
||||
|
||||
static inline void list_add(struct list_head *new, struct list_head *head) {
|
||||
new->next = head->next;
|
||||
head->next = new;
|
||||
}
|
||||
|
||||
#define list_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
|
||||
|
||||
#endif // WOJ_SANDBOX_LIST_H
|
24
utils/log.h
Normal file
24
utils/log.h
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef WOJ_SANDBOX_LOG_H
|
||||
#define WOJ_SANDBOX_LOG_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// Log
|
||||
#define COLOR_RED "\x1B[1;31m"
|
||||
#define COLOR_YELLOW "\x1B[1;33m"
|
||||
#define COLOR_GREEN "\x1B[1;32m"
|
||||
#define COLOR_STDOUT_RESET "\x1B[0m"
|
||||
|
||||
#define _LOG(color, level, fmt, ...) \
|
||||
do { \
|
||||
fprintf(stderr, \
|
||||
color "[" level "](%d)(%s:%d): " fmt COLOR_STDOUT_RESET "\n", \
|
||||
getpid(), __FILE__, __LINE__, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define LOG_INFO(fmt, ...) _LOG(COLOR_GREEN, "info", fmt, ##__VA_ARGS__)
|
||||
#define LOG_WARN(fmt, ...) _LOG(COLOR_YELLOW, "warn", fmt, ##__VA_ARGS__)
|
||||
#define LOG_ERR(fmt, ...) _LOG(COLOR_RED, "err", fmt, ##__VA_ARGS__)
|
||||
|
||||
#endif // WOJ_SANDBOX_LOG_H
|
3
version_script.txt
Normal file
3
version_script.txt
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
local: seccomp_*;
|
||||
};
|
Loading…
Reference in New Issue
Block a user