feat: refactor, drop LD_PRELOAD method
This commit is contained in:
parent
b6e7a328ff
commit
ae91f2c3f5
@ -3,6 +3,10 @@ project(woj_sandbox C)
|
|||||||
|
|
||||||
set(CMAKE_C_STANDARD 23)
|
set(CMAKE_C_STANDARD 23)
|
||||||
|
|
||||||
|
# Check IPO
|
||||||
|
include(CheckIPOSupported)
|
||||||
|
check_ipo_supported(RESULT ipo_result OUTPUT ipo_output)
|
||||||
|
|
||||||
# Handle __FILE__ in logging
|
# Handle __FILE__ in logging
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fmacro-prefix-map=${CMAKE_SOURCE_DIR}=.")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fmacro-prefix-map=${CMAKE_SOURCE_DIR}=.")
|
||||||
|
|
||||||
@ -19,30 +23,22 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libseccomp/include)
|
|||||||
|
|
||||||
# Targets
|
# Targets
|
||||||
add_library(woj_sandbox SHARED ${PROJECT_SOURCE_DIR}/library.c ${PROJECT_SOURCE_DIR}/inject.c ${SRC_FILES})
|
add_library(woj_sandbox SHARED ${PROJECT_SOURCE_DIR}/library.c ${PROJECT_SOURCE_DIR}/inject.c ${SRC_FILES})
|
||||||
add_executable(woj_launcher ${PROJECT_SOURCE_DIR}/launcher.c)
|
add_executable(woj_launcher ${PROJECT_SOURCE_DIR}/library.c ${PROJECT_SOURCE_DIR}/launcher.c ${SRC_FILES})
|
||||||
add_executable(woj_launcher2 ${PROJECT_SOURCE_DIR}/library.c ${PROJECT_SOURCE_DIR}/launcher.c ${SRC_FILES})
|
|
||||||
add_executable(woj_test ${PROJECT_SOURCE_DIR}/test.c)
|
add_executable(woj_test ${PROJECT_SOURCE_DIR}/test.c)
|
||||||
|
|
||||||
# Link seccomp
|
set(TARGETS woj_sandbox woj_launcher)
|
||||||
target_link_libraries(woj_sandbox ${CMAKE_SOURCE_DIR}/libseccomp/src/.libs/libseccomp.a)
|
|
||||||
target_link_libraries(woj_launcher ${CMAKE_SOURCE_DIR}/libseccomp/src/.libs/libseccomp.a)
|
|
||||||
target_link_libraries(woj_launcher2 ${CMAKE_SOURCE_DIR}/libseccomp/src/.libs/libseccomp.a)
|
|
||||||
|
|
||||||
# Disable symbol export
|
foreach (TARGET ${TARGETS})
|
||||||
set_target_properties(woj_sandbox PROPERTIES C_VISIBILITY_PRESET hidden)
|
# Link seccomp
|
||||||
set_property(TARGET woj_sandbox APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--version-script=${VERSION_SCRIPT}")
|
target_link_libraries(${TARGET} ${CMAKE_SOURCE_DIR}/libseccomp/src/.libs/libseccomp.a)
|
||||||
set_target_properties(woj_sandbox PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
|
|
||||||
|
|
||||||
set_target_properties(woj_launcher2 PROPERTIES C_VISIBILITY_PRESET hidden)
|
# Disable symbol export
|
||||||
set_property(TARGET woj_launcher2 APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--version-script=${VERSION_SCRIPT}")
|
set_target_properties(${TARGET} PROPERTIES C_VISIBILITY_PRESET hidden)
|
||||||
set_target_properties(woj_launcher2 PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
|
set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--version-script=${VERSION_SCRIPT}")
|
||||||
|
set_target_properties(${TARGET} PROPERTIES LINK_DEPENDS ${VERSION_SCRIPT})
|
||||||
|
|
||||||
# Optimization
|
# Optimization
|
||||||
include(CheckIPOSupported)
|
if (ipo_result)
|
||||||
check_ipo_supported(RESULT ipo_result OUTPUT ipo_output)
|
set_property(TARGET ${TARGET} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||||
if (ipo_result)
|
endif ()
|
||||||
set_property(TARGET woj_sandbox PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
endforeach (TARGET)
|
||||||
set_property(TARGET woj_launcher PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
|
||||||
else ()
|
|
||||||
message(WARNING "IPO is not supported: ${ipo_output}")
|
|
||||||
endif ()
|
|
||||||
|
2
inject.c
2
inject.c
@ -1,3 +1,3 @@
|
|||||||
#include "library.h"
|
#include "library.h"
|
||||||
|
|
||||||
static __attribute__((constructor)) void inject(void) { setup_all(); }
|
static __attribute__((constructor(102))) void inject(void) { setup_all(); }
|
||||||
|
60
launcher.c
60
launcher.c
@ -1,8 +1,6 @@
|
|||||||
#include "launcher.h"
|
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "sandbox.h"
|
|
||||||
#include "utils/log.h"
|
#include "utils/log.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -24,7 +22,6 @@ void print_help(char *self) {
|
|||||||
LOG_WARN(" --memory_limit memory limit in MB");
|
LOG_WARN(" --memory_limit memory limit in MB");
|
||||||
LOG_WARN(" --nproc_limit number of processes limit");
|
LOG_WARN(" --nproc_limit number of processes limit");
|
||||||
LOG_WARN(" --time_limit time limit in ms");
|
LOG_WARN(" --time_limit time limit in ms");
|
||||||
LOG_WARN(" --sandbox_path path to sandbox");
|
|
||||||
LOG_WARN(" --sandbox_template sandbox template");
|
LOG_WARN(" --sandbox_template sandbox template");
|
||||||
LOG_WARN(" --sandbox_action sandbox action");
|
LOG_WARN(" --sandbox_action sandbox action");
|
||||||
LOG_WARN(" --file_input path to input file");
|
LOG_WARN(" --file_input path to input file");
|
||||||
@ -39,7 +36,6 @@ void parse(int argc, char *argv[]) {
|
|||||||
[CFG_MEMORY_LIMIT] = {"memory_limit", required_argument, NULL, 0},
|
[CFG_MEMORY_LIMIT] = {"memory_limit", required_argument, NULL, 0},
|
||||||
[CFG_NPROC_LIMIT] = {"nproc_limit", required_argument, NULL, 0},
|
[CFG_NPROC_LIMIT] = {"nproc_limit", required_argument, NULL, 0},
|
||||||
[CFG_TIME_LIMIT] = {"time_limit", required_argument, NULL, 0},
|
[CFG_TIME_LIMIT] = {"time_limit", required_argument, NULL, 0},
|
||||||
[CFG_SANDBOX_PATH] = {"sandbox_path", required_argument, NULL, 0},
|
|
||||||
[CFG_SANDBOX_TEMPLATE] = {"sandbox_template", required_argument, NULL, 0},
|
[CFG_SANDBOX_TEMPLATE] = {"sandbox_template", required_argument, NULL, 0},
|
||||||
[CFG_SANDBOX_ACTION] = {"sandbox_action", required_argument, NULL, 0},
|
[CFG_SANDBOX_ACTION] = {"sandbox_action", required_argument, NULL, 0},
|
||||||
[CFG_FILE_INPUT] = {"file_input", required_argument, NULL, 0},
|
[CFG_FILE_INPUT] = {"file_input", required_argument, NULL, 0},
|
||||||
@ -74,53 +70,6 @@ void parse(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void launch_child() {
|
void launch_child() {
|
||||||
char *args[] = {config[CFG_PROGRAM], NULL};
|
|
||||||
char *env[8];
|
|
||||||
|
|
||||||
/* build env */ {
|
|
||||||
env[0] = malloc(sizeof("LD_PRELOAD=") + strlen(config[CFG_SANDBOX_PATH]) + 1);
|
|
||||||
sprintf(env[0], "LD_PRELOAD=%s", config[CFG_SANDBOX_PATH]);
|
|
||||||
|
|
||||||
env[1] = malloc(sizeof(LIMIT_MEMORY "=") + strlen(config[CFG_MEMORY_LIMIT]) + 1);
|
|
||||||
sprintf(env[1], LIMIT_MEMORY "=%s", config[CFG_MEMORY_LIMIT]);
|
|
||||||
|
|
||||||
env[2] = malloc(sizeof(LIMIT_NPROC "=") + strlen(config[CFG_NPROC_LIMIT]) + 1);
|
|
||||||
sprintf(env[2], LIMIT_NPROC "=%s", config[CFG_NPROC_LIMIT]);
|
|
||||||
|
|
||||||
env[3] = malloc(sizeof(LIMIT_TIME "=") + strlen(config[CFG_TIME_LIMIT]) + 1);
|
|
||||||
sprintf(env[3], LIMIT_TIME "=%s", config[CFG_TIME_LIMIT]);
|
|
||||||
|
|
||||||
env[4] = malloc(sizeof(SANDBOX_TEMPLATE "=") + strlen(config[CFG_SANDBOX_TEMPLATE]) + 1);
|
|
||||||
sprintf(env[4], SANDBOX_TEMPLATE "=%s", config[CFG_SANDBOX_TEMPLATE]);
|
|
||||||
|
|
||||||
env[5] = malloc(sizeof(SANDBOX_ACTION "=") + strlen(config[CFG_SANDBOX_ACTION]) + 1);
|
|
||||||
sprintf(env[5], SANDBOX_ACTION "=%s", config[CFG_SANDBOX_ACTION]);
|
|
||||||
|
|
||||||
env[6] = malloc(sizeof(SANDBOX_EXE_PATH "=") + strlen(config[CFG_PROGRAM]) + 1);
|
|
||||||
sprintf(env[6], SANDBOX_EXE_PATH "=%s", config[CFG_PROGRAM]);
|
|
||||||
|
|
||||||
env[7] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* build stdin */ {
|
|
||||||
int fd = open(config[CFG_FILE_INPUT], O_RDONLY);
|
|
||||||
dup2(fd, STDIN_FILENO);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* build stdout */ {
|
|
||||||
int fd = open(config[CFG_FILE_OUTPUT], O_WRONLY | O_CREAT, 0644);
|
|
||||||
dup2(fd, STDOUT_FILENO);
|
|
||||||
close(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
execve(config[CFG_PROGRAM], args, env);
|
|
||||||
}
|
|
||||||
|
|
||||||
void launch_child2() {
|
|
||||||
// TODO: glibc compiled program has a very annoying setup process
|
|
||||||
LOG_WARN("launch_child2 is not implemented yet");
|
|
||||||
|
|
||||||
char *args[] = {config[CFG_PROGRAM], NULL};
|
char *args[] = {config[CFG_PROGRAM], NULL};
|
||||||
|
|
||||||
/* build stdin */ {
|
/* build stdin */ {
|
||||||
@ -160,14 +109,7 @@ int main(int argc, char *argv[]) {
|
|||||||
exit(ERR_FORK);
|
exit(ERR_FORK);
|
||||||
|
|
||||||
} else if (child == 0) { // Program
|
} else if (child == 0) { // Program
|
||||||
if (!setup_all) {
|
launch_child();
|
||||||
LOG_INFO("Using preload sandbox");
|
|
||||||
launch_child();
|
|
||||||
} else {
|
|
||||||
LOG_INFO("Using inplace sandbox");
|
|
||||||
launch_child2();
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_ERR("Failed to execute child program");
|
LOG_ERR("Failed to execute child program");
|
||||||
exit(ERR_EXEC);
|
exit(ERR_EXEC);
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ enum ConfigIndex {
|
|||||||
CFG_MEMORY_LIMIT = 0,
|
CFG_MEMORY_LIMIT = 0,
|
||||||
CFG_NPROC_LIMIT,
|
CFG_NPROC_LIMIT,
|
||||||
CFG_TIME_LIMIT,
|
CFG_TIME_LIMIT,
|
||||||
CFG_SANDBOX_PATH,
|
|
||||||
CFG_SANDBOX_TEMPLATE,
|
CFG_SANDBOX_TEMPLATE,
|
||||||
CFG_SANDBOX_ACTION,
|
CFG_SANDBOX_ACTION,
|
||||||
CFG_FILE_INPUT,
|
CFG_FILE_INPUT,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "rules/lang.h"
|
|
||||||
#include "sandbox.h"
|
#include "sandbox.h"
|
||||||
#include "utils/log.h"
|
#include "utils/log.h"
|
||||||
|
|
||||||
@ -33,7 +32,6 @@ void setup_all(void) {
|
|||||||
config[CFG_PROGRAM] = getenv(SANDBOX_EXE_PATH);
|
config[CFG_PROGRAM] = getenv(SANDBOX_EXE_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
register_lang_c_cpp();
|
|
||||||
setup_rlimit(config);
|
setup_rlimit(config);
|
||||||
setup_seccomp(config);
|
setup_seccomp(config);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
#ifndef WOJ_SANDBOX_LANG_H
|
|
||||||
#define WOJ_SANDBOX_LANG_H
|
|
||||||
|
|
||||||
void register_lang_c_cpp(void);
|
|
||||||
|
|
||||||
#endif // WOJ_SANDBOX_LANG_H
|
|
@ -1,36 +1,20 @@
|
|||||||
#include "../sandbox.h"
|
|
||||||
#include "lang.h"
|
|
||||||
#include "rules.h"
|
#include "rules.h"
|
||||||
|
|
||||||
#include <seccomp.h>
|
#include <seccomp.h>
|
||||||
|
|
||||||
void setup_lang_c_cpp(scmp_filter_ctx ctx) {
|
void setup_lang_c_cpp(scmp_filter_ctx ctx) {
|
||||||
|
// some more syscall(s) that glibc uses
|
||||||
int white[] = {
|
int white[] = {
|
||||||
SCMP_SYS(read), // 0
|
|
||||||
SCMP_SYS(write), // 1
|
|
||||||
SCMP_SYS(close), // 3
|
|
||||||
SCMP_SYS(fstat), // 5
|
|
||||||
SCMP_SYS(lseek), // 8
|
|
||||||
SCMP_SYS(mmap), // 9
|
|
||||||
SCMP_SYS(munmap), // 11
|
|
||||||
SCMP_SYS(brk), // 12
|
|
||||||
SCMP_SYS(pread64), // 17
|
|
||||||
SCMP_SYS(getpid), // 39
|
|
||||||
SCMP_SYS(clone), // 56
|
SCMP_SYS(clone), // 56
|
||||||
|
SCMP_SYS(arch_prctl), // 158
|
||||||
SCMP_SYS(futex), // 202
|
SCMP_SYS(futex), // 202
|
||||||
SCMP_SYS(newfstatat), // 262
|
SCMP_SYS(set_tid_address), // 218
|
||||||
SCMP_SYS(clock_gettime), // 228
|
|
||||||
SCMP_SYS(clock_getres), // 229
|
|
||||||
SCMP_SYS(clock_nanosleep), // 230
|
|
||||||
SCMP_SYS(exit_group), // 231
|
SCMP_SYS(exit_group), // 231
|
||||||
SCMP_SYS(set_robust_list), // 273
|
SCMP_SYS(set_robust_list), // 273
|
||||||
SCMP_SYS(get_robust_list), // 274
|
SCMP_SYS(get_robust_list), // 274
|
||||||
|
SCMP_SYS(rseq), // 334
|
||||||
};
|
};
|
||||||
int white_len = sizeof(white) / sizeof(white[0]);
|
ADD_RULE_LIST(white, SCMP_ACT_ALLOW);
|
||||||
|
|
||||||
for (int i = 0; i < white_len; i++) {
|
|
||||||
add_syscall_nr(white[i], ctx, SCMP_ACT_ALLOW);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rule lang_c_rule = {
|
struct rule lang_c_rule = {
|
||||||
@ -43,7 +27,7 @@ struct rule lang_cpp_rule = {
|
|||||||
.setup = setup_lang_c_cpp,
|
.setup = setup_lang_c_cpp,
|
||||||
};
|
};
|
||||||
|
|
||||||
void register_lang_c_cpp(void) {
|
void __attribute__((constructor(101))) register_lang_c_cpp(void) {
|
||||||
register_rule(&lang_c_rule);
|
register_rule(&lang_c_rule);
|
||||||
register_rule(&lang_cpp_rule);
|
register_rule(&lang_cpp_rule);
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "rules.h"
|
#include "rules.h"
|
||||||
#include "../err.h"
|
#include "../err.h"
|
||||||
#include "../sandbox.h"
|
|
||||||
#include "../utils/log.h"
|
#include "../utils/log.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -10,16 +10,50 @@ LIST_HEAD(seccomp_rules);
|
|||||||
|
|
||||||
void register_rule(struct rule *rule) { list_add(&rule->list, &seccomp_rules); }
|
void register_rule(struct rule *rule) { list_add(&rule->list, &seccomp_rules); }
|
||||||
|
|
||||||
void setup_self(scmp_filter_ctx ctx, const char *exe_path) {
|
void setup_common(scmp_filter_ctx ctx, const char *exe_path) {
|
||||||
// allow to execute self
|
// allow to execute self
|
||||||
add_syscall_nr_arg(SCMP_SYS(execve), ctx, SCMP_ACT_ALLOW, 1, &SCMP_A0(SCMP_CMP_EQ, (scmp_datum_t)exe_path));
|
add_syscall_nr_arg(SCMP_SYS(execve), ctx, SCMP_ACT_ALLOW, 1, &SCMP_A0(SCMP_CMP_EQ, (scmp_datum_t)exe_path));
|
||||||
|
|
||||||
|
// allow to read files - do not allow write, readwrite, append, create
|
||||||
|
add_syscall_nr_arg(SCMP_SYS(open), ctx, SCMP_ACT_ALLOW, 1,
|
||||||
|
&SCMP_A1(SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_EXCL, 0));
|
||||||
|
add_syscall_nr_arg(SCMP_SYS(openat), ctx, SCMP_ACT_ALLOW, 1,
|
||||||
|
&SCMP_A2(SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_EXCL, 0));
|
||||||
|
|
||||||
|
// prlimit64(302) - disallow new_limit
|
||||||
|
add_syscall_nr_arg(SCMP_SYS(prlimit64), ctx, SCMP_ACT_ALLOW, 1, &SCMP_A2(SCMP_CMP_NE, 0));
|
||||||
|
|
||||||
|
// some commonly used syscall(s)
|
||||||
|
int white[] = {
|
||||||
|
SCMP_SYS(read), // 0
|
||||||
|
SCMP_SYS(write), // 1
|
||||||
|
SCMP_SYS(close), // 3
|
||||||
|
SCMP_SYS(fstat), // 5
|
||||||
|
SCMP_SYS(lseek), // 8
|
||||||
|
SCMP_SYS(mmap), // 9
|
||||||
|
SCMP_SYS(mprotect), // 10
|
||||||
|
SCMP_SYS(munmap), // 11
|
||||||
|
SCMP_SYS(brk), // 12
|
||||||
|
SCMP_SYS(pread64), // 17
|
||||||
|
SCMP_SYS(writev), // 20
|
||||||
|
SCMP_SYS(access), // 21
|
||||||
|
SCMP_SYS(nanosleep), // 35
|
||||||
|
SCMP_SYS(getpid), // 39
|
||||||
|
SCMP_SYS(clock_gettime), // 228
|
||||||
|
SCMP_SYS(clock_getres), // 229
|
||||||
|
SCMP_SYS(clock_nanosleep), // 230
|
||||||
|
SCMP_SYS(newfstatat), // 262
|
||||||
|
SCMP_SYS(getrandom), // 318
|
||||||
|
|
||||||
|
};
|
||||||
|
ADD_RULE_LIST(white, SCMP_ACT_ALLOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_rule(const char *name, scmp_filter_ctx ctx, const char *exe_path) {
|
void setup_rule(const char *name, scmp_filter_ctx ctx, const char *exe_path) {
|
||||||
struct list_head *current;
|
struct list_head *current;
|
||||||
struct rule *rule;
|
struct rule *rule;
|
||||||
|
|
||||||
setup_self(ctx, exe_path);
|
setup_common(ctx, exe_path);
|
||||||
|
|
||||||
list_for_each(current, &seccomp_rules) {
|
list_for_each(current, &seccomp_rules) {
|
||||||
rule = list_entry(current, struct rule, list);
|
rule = list_entry(current, struct rule, list);
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
#ifndef WOJ_SANDBOX_RULES_H
|
#ifndef WOJ_SANDBOX_RULES_H
|
||||||
#define WOJ_SANDBOX_RULES_H
|
#define WOJ_SANDBOX_RULES_H
|
||||||
|
|
||||||
|
#include "../sandbox.h"
|
||||||
#include "../utils/list.h"
|
#include "../utils/list.h"
|
||||||
|
|
||||||
#include "seccomp.h"
|
#include "seccomp.h"
|
||||||
|
|
||||||
|
#define ADD_RULE_LIST(white_list, act) \
|
||||||
|
do { \
|
||||||
|
int white_len = sizeof(white_list) / sizeof(white_list[0]); \
|
||||||
|
for (int i = 0; i < white_len; i++) add_syscall_nr(white_list[i], ctx, act); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
struct rule {
|
struct rule {
|
||||||
char *name;
|
char *name;
|
||||||
void (*setup)(scmp_filter_ctx);
|
void (*setup)(scmp_filter_ctx);
|
||||||
|
Loading…
Reference in New Issue
Block a user