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